add in faunadb and netlify
This commit is contained in:
@@ -17,3 +17,6 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Local Netlify folder
|
||||
.netlify
|
||||
@@ -58,12 +58,28 @@ class MultiSigForm extends React.Component {
|
||||
|
||||
handleCreate = async () => {
|
||||
this.setState({ processing: true });
|
||||
const res = await axios.post("/api/multiaddress", {
|
||||
members: this.state.pubkeys,
|
||||
threshold: this.state.threshold,
|
||||
const res = await axios.post("/.netlify/functions/create-multisig", {
|
||||
threshold: 3,
|
||||
sourceAddresses: [
|
||||
{
|
||||
nickname: "samtest",
|
||||
address: "cosmossam1",
|
||||
pubkey: "sampubkey",
|
||||
},
|
||||
{
|
||||
nickname: "samtest2",
|
||||
address: "cosmossam2",
|
||||
pubkey: "sampubkey",
|
||||
},
|
||||
{
|
||||
nickname: "samtest3",
|
||||
address: "cosmossam3",
|
||||
pubkey: "sampubkey",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
this.props.router.push(`/multi/${res.data}`);
|
||||
console.log(res);
|
||||
// this.props.router.push(`/multi/${res.data}`);
|
||||
};
|
||||
|
||||
render() {
|
||||
@@ -78,7 +94,7 @@ class MultiSigForm extends React.Component {
|
||||
</p>
|
||||
</StackableContainer>
|
||||
{this.state.pubkeys.map((pubkeyGroup, index) => (
|
||||
<StackableContainer lessPadding lessMargin>
|
||||
<StackableContainer lessPadding lessMargin key={index}>
|
||||
<div className="key-row">
|
||||
{this.state.pubkeys.length > 2 && (
|
||||
<button
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
type Multisig {
|
||||
threshold: Int!
|
||||
sourceAddresses: [SourceAddress]! @relation
|
||||
address: String
|
||||
nickname: String
|
||||
}
|
||||
|
||||
type SourceAddress {
|
||||
nickname: String
|
||||
address: String!
|
||||
pubkey: String!
|
||||
multisig: Multisig @relation
|
||||
}
|
||||
|
||||
type Transaction {
|
||||
multisigId: Multisig!
|
||||
signatures: [Signature] @relation
|
||||
toAddress: String!
|
||||
fromAddress: String!
|
||||
amount: Float!
|
||||
threshold: Int!
|
||||
txHash: String
|
||||
broadcastDate: String
|
||||
gas: Int!
|
||||
fee: Float
|
||||
JSON: String
|
||||
}
|
||||
|
||||
type Signature {
|
||||
transaction: Transaction! @relation
|
||||
JSON: String!
|
||||
sourceAddress: SourceAddress @relation
|
||||
}
|
||||
|
||||
type Query {
|
||||
getMultisig(address: String!): Multisig
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
|
||||
/* code from functions/todos-create.js */
|
||||
import faunadb from "faunadb"; /* Import faunaDB sdk */
|
||||
|
||||
/* configure faunaDB Client with our secret */
|
||||
const q = faunadb.query;
|
||||
const client = new faunadb.Client({
|
||||
secret: process.env.FAUNADB_SECRET,
|
||||
});
|
||||
|
||||
/* export our lambda function as named "handler" export */
|
||||
exports.handler = (event, context, callback) => {
|
||||
/* parse the string body into a useable JS object */
|
||||
const data = JSON.parse(event.body);
|
||||
console.log("Function `createMultisig` invoked", data);
|
||||
const multisig = {
|
||||
data: data,
|
||||
};
|
||||
/* construct the fauna query */
|
||||
return client
|
||||
.query(q.Create(q.Collection("Multisig"), multisig))
|
||||
.then((response) => {
|
||||
console.log("success", response);
|
||||
/* Success! return the response with statusCode 200 */
|
||||
return callback(null, {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify(response),
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("error", error);
|
||||
/* Error! return the error with statusCode 400 */
|
||||
return callback(null, {
|
||||
statusCode: 400,
|
||||
body: JSON.stringify(error),
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
# example netlify.toml
|
||||
[build]
|
||||
command = "next build"
|
||||
functions = "lambda-build"
|
||||
publish = ".next"
|
||||
|
||||
## Uncomment to use this redirect for Single Page Applications like create-react-app.
|
||||
## Not needed for static site generators.
|
||||
#[[redirects]]
|
||||
# from = "/*"
|
||||
# to = "/index.html"
|
||||
# status = 200
|
||||
|
||||
## (optional) Settings for Netlify Dev
|
||||
## https://github.com/netlify/cli/blob/master/docs/netlify-dev.md#project-detection
|
||||
#[dev]
|
||||
# command = "yarn start" # Command to start your dev server
|
||||
# port = 3000 # Port that the dev server will be listening on
|
||||
# publish = "dist" # Folder with the static content for _redirect file
|
||||
|
||||
## more info on configuring this file: https://www.netlify.com/docs/netlify-toml-reference/
|
||||
Generated
+5578
-19
File diff suppressed because it is too large
Load Diff
+22
-2
@@ -2,16 +2,36 @@
|
||||
"name": "create-next-example-app",
|
||||
"scripts": {
|
||||
"dev": "next",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
"build": "npm-run-all --parallel build:**",
|
||||
"build:app": "next build",
|
||||
"build:functions": "netlify-lambda build functions",
|
||||
"start": "npm-run-all --parallel start:app start:server",
|
||||
"start:app": "PORT=3000 node server.js",
|
||||
"start:server": "netlify-lambda serve lambda"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/proto-signing": "^0.24.0-alpha.26",
|
||||
"@cosmjs/stargate": "^0.24.0-alpha.26",
|
||||
"axios": "^0.21.1",
|
||||
"chalk": "^4.1.0",
|
||||
"faunadb": "^4.1.1",
|
||||
"next": "^10.0.7",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"uuid": "^8.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"express": "^4.17.1",
|
||||
"http-proxy-middleware": "^1.0.6",
|
||||
"netlify-lambda": "^2.0.3",
|
||||
"npm-run-all": "^4.1.5"
|
||||
},
|
||||
"proxy": {
|
||||
"/.netlify/functions": {
|
||||
"target": "http://localhost:9000",
|
||||
"pathRewrite": {
|
||||
"^/\\.netlify/functions": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
const { queries } = require("../../../database/connectDatabase");
|
||||
|
||||
const get = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
query: { uuid },
|
||||
} = req;
|
||||
|
||||
const multi = query.getMultiFromUUID.get(uuid);
|
||||
res.status(200).send(multi);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
export default (req, res) => {
|
||||
switch (req.method) {
|
||||
case "GET":
|
||||
get(req, res);
|
||||
break;
|
||||
default:
|
||||
res.status(404).send();
|
||||
}
|
||||
};
|
||||
@@ -1,92 +0,0 @@
|
||||
const gaiaWrap = require("../../../lib/gaiaWrap");
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
const { queries } = require("../../../database/connectDatabase");
|
||||
|
||||
const get = async (req, res) => {
|
||||
const allKeys = await gaiaWrap.listKeys();
|
||||
res.status(200).send(allKeys);
|
||||
};
|
||||
|
||||
const post = async (req, res) => {
|
||||
try {
|
||||
// req.body.members should have array of members:
|
||||
// members: [{nickname: 'Cyril', pubkey: ''}]
|
||||
// req.body.threshold should have integer <= members.length
|
||||
const { members, threshold } = req.body;
|
||||
|
||||
// for each member, create key and save to DB
|
||||
// have to do this sequentially/synchronously to avoid
|
||||
// locking up gaiacli
|
||||
const saveProms = [];
|
||||
let commaSepKeyNames = "";
|
||||
|
||||
for (var i = 0; i < members.length; i++) {
|
||||
const member = members[i];
|
||||
const keyname = await createAndSaveKey(member);
|
||||
|
||||
// combine keyNames into string for creating multisig key
|
||||
commaSepKeyNames += keyname;
|
||||
|
||||
if (i !== members.length - 1) {
|
||||
// not the last one so add a comma
|
||||
commaSepKeyNames += ",";
|
||||
}
|
||||
}
|
||||
|
||||
// create multisig key
|
||||
const multiName = uuidv4();
|
||||
await gaiaWrap.createMultiSigKey({
|
||||
multiName,
|
||||
commaSepKeyNames,
|
||||
threshold,
|
||||
});
|
||||
let multiAddress = await gaiaWrap.getMultiAddress({ keyName: multiName });
|
||||
|
||||
// save multisig
|
||||
const saveResult = queries.insertMultiKey.run({
|
||||
key_name: multiName,
|
||||
address: multiAddress,
|
||||
multi_threshold: threshold,
|
||||
multi_members: commaSepKeyNames,
|
||||
is_multi: 1,
|
||||
});
|
||||
|
||||
res.status(200).send(multiAddress);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
const createAndSaveKey = async (member) => {
|
||||
try {
|
||||
// create gaiacli key
|
||||
member.key_name = uuidv4();
|
||||
|
||||
await gaiaWrap.createKey({
|
||||
keyName: member.key_name,
|
||||
pubkey: member.pubkey,
|
||||
});
|
||||
|
||||
// save single key
|
||||
const saveResult = queries.insertSingleKey.run(member);
|
||||
|
||||
return member.key_name;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
export default (req, res) => {
|
||||
switch (req.method) {
|
||||
case "GET":
|
||||
get(req, res);
|
||||
break;
|
||||
case "POST":
|
||||
post(req, res);
|
||||
break;
|
||||
default:
|
||||
res.status(404).send();
|
||||
}
|
||||
};
|
||||
@@ -1,99 +0,0 @@
|
||||
const fs = require("fs");
|
||||
const gaiaWrap = require("../../../../lib/gaiaWrap");
|
||||
const path = require("path");
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
const { queries } = require("../../../../database/connectDatabase");
|
||||
|
||||
const get = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
query: { uuid },
|
||||
} = req;
|
||||
|
||||
// get corresponding multi record
|
||||
const transaction = queries.getTransactionForUUID.get(uuid);
|
||||
|
||||
if (!transaction) {
|
||||
res.status(404).send();
|
||||
} else {
|
||||
const multi = queries.getMultiFromUUID.get(transaction.multi_key_name);
|
||||
const signatures = JSON.parse(transaction.signatures);
|
||||
if (signatures.length < multi.multi_threshold) {
|
||||
res.status(400).send("Not enough signatures");
|
||||
} else {
|
||||
// create the files and multisign the tx
|
||||
const unsignedJsonPath = `${transaction.uuid}-unsigned.json`;
|
||||
fs.writeFileSync(unsignedJsonPath, transaction.unsigned);
|
||||
|
||||
const signatureFilePaths = [];
|
||||
for (var i = 0; i < signatures.length; i++) {
|
||||
const signature = signatures[i];
|
||||
const filePath = `${transaction.uuid}-sign${i}.json`;
|
||||
|
||||
fs.writeFileSync(filePath, JSON.stringify(signature));
|
||||
signatureFilePaths.push(filePath);
|
||||
}
|
||||
|
||||
let signedTransaction = await gaiaWrap.signMulti({
|
||||
keyName: multi.key_name,
|
||||
signatureFiles: signatureFilePaths,
|
||||
unsignedFile: unsignedJsonPath,
|
||||
});
|
||||
|
||||
signedTransaction = signedTransaction.replace(/(\r\n|\n|\r)/gm, "");
|
||||
|
||||
// save signed tx
|
||||
queries.updateTransactionSigned.run({
|
||||
uuid: transaction.uuid,
|
||||
signed: signedTransaction,
|
||||
});
|
||||
|
||||
// save signed transaction
|
||||
const signedTxPath = `${transaction.uuid}-signed.json`;
|
||||
fs.writeFileSync(signedTxPath, signedTransaction);
|
||||
|
||||
// broadcast tx
|
||||
const broadcastRes = await gaiaWrap.broadcastTX({
|
||||
txFilename: signedTxPath,
|
||||
});
|
||||
|
||||
queries.updateTransactionCompleted.run({
|
||||
completed_tx: broadcastRes,
|
||||
uuid: transaction.uuid,
|
||||
});
|
||||
|
||||
const updatedTransaction = queries.getTransactionForUUID.get(uuid);
|
||||
|
||||
res.status(200).send(updatedTransaction);
|
||||
|
||||
// delete unsigned and signatures
|
||||
fs.unlink(unsignedJsonPath, (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
for (var i = 0; i < signatureFilePaths.length; i++) {
|
||||
fs.unlink(signatureFilePaths[i], (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
export default (req, res) => {
|
||||
switch (req.method) {
|
||||
case "GET":
|
||||
get(req, res);
|
||||
break;
|
||||
default:
|
||||
res.status(404).send();
|
||||
}
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
const { queries } = require("../../../../database/connectDatabase");
|
||||
|
||||
const get = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
query: { uuid },
|
||||
} = req;
|
||||
|
||||
const transaction = query.getTransactionForUUID.get(uuid);
|
||||
res.status(200).send(transaction);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
const post = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
query: { uuid },
|
||||
} = req;
|
||||
|
||||
// req.body should have signature, a json object of the
|
||||
// signature for this transaction
|
||||
const { signature } = req.body;
|
||||
|
||||
// get corresponding transaction record
|
||||
const transaction = queries.getTransactionForUUID.get(uuid);
|
||||
|
||||
if (!transaction) {
|
||||
res.status(404).send();
|
||||
} else {
|
||||
// add signature to existing signatures and save
|
||||
transaction.signatures = transaction.signatures
|
||||
? JSON.parse(transaction.signatures)
|
||||
: [];
|
||||
|
||||
transaction.signatures.push(signature);
|
||||
queries.updateTransactionSignatures.run({
|
||||
signatures: JSON.stringify(transaction.signatures),
|
||||
uuid: transaction.uuid,
|
||||
});
|
||||
const updatedTransaction = queries.getTransactionForUUID.get(uuid);
|
||||
res.status(200).send(updatedTransaction);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
export default (req, res) => {
|
||||
switch (req.method) {
|
||||
case "POST":
|
||||
post(req, res);
|
||||
break;
|
||||
case "GET":
|
||||
post(req, res);
|
||||
break;
|
||||
default:
|
||||
res.status(404).send();
|
||||
}
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
const { queries } = require("../../../database/connectDatabase");
|
||||
|
||||
const post = async (req, res) => {
|
||||
try {
|
||||
// req.body should have unsignedJson, a json object of the
|
||||
// cosmos sdk standard send msg, and multiAddress, a string
|
||||
// with the address of the multisig that the tx is from
|
||||
const { unsignedJson, multiAddress } = req.body;
|
||||
|
||||
// get corresponding multi record
|
||||
const multi = queries.getMultiFromAddress.get(multiAddress);
|
||||
const transactionUUID = uuidv4();
|
||||
|
||||
const saveResult = queries.insertTransaction.run({
|
||||
multi_key_name: multi.key_name,
|
||||
unsigned: unsignedJson,
|
||||
uuid: transactionUUID,
|
||||
});
|
||||
|
||||
res.status(200).send(transactionUUID);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
export default (req, res) => {
|
||||
switch (req.method) {
|
||||
case "POST":
|
||||
post(req, res);
|
||||
break;
|
||||
default:
|
||||
res.status(404).send();
|
||||
}
|
||||
};
|
||||
@@ -21,7 +21,7 @@ const transactionPage = ({ transaction, multi }) => {
|
||||
<Page>
|
||||
<StackableContainer base>
|
||||
<StackableContainer>
|
||||
<h1>Un-broadcast Transaction</h1>
|
||||
<h1>In Progress Transaction</h1>
|
||||
</StackableContainer>
|
||||
<TransactionInfo tx={dummyTX} />
|
||||
<TransactionSigning />
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// server.js
|
||||
/* eslint-disable no-console */
|
||||
const express = require("express");
|
||||
const next = require("next");
|
||||
|
||||
const devProxy = {
|
||||
"/.netlify": {
|
||||
target: "http://localhost:9000",
|
||||
pathRewrite: { "^/.netlify/functions": "" },
|
||||
},
|
||||
};
|
||||
|
||||
const port = parseInt(process.env.PORT, 10) || 3000;
|
||||
const env = process.env.NODE_ENV;
|
||||
const dev = env !== "production";
|
||||
const app = next({
|
||||
dir: ".", // base directory where everything is, could move to src later
|
||||
dev,
|
||||
});
|
||||
|
||||
const handle = app.getRequestHandler();
|
||||
|
||||
let server;
|
||||
app
|
||||
.prepare()
|
||||
.then(() => {
|
||||
server = express();
|
||||
|
||||
// Set up the proxy.
|
||||
if (dev && devProxy) {
|
||||
const { createProxyMiddleware } = require("http-proxy-middleware");
|
||||
Object.keys(devProxy).forEach(function (context) {
|
||||
server.use(createProxyMiddleware(context, devProxy[context]));
|
||||
});
|
||||
}
|
||||
|
||||
// Default catch-all handler to allow Next.js to handle all other routes
|
||||
server.all("*", (req, res) => handle(req, res));
|
||||
|
||||
server.listen(port, (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console.log(`> Ready on port ${port} [${env}]`);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("An error occurred, unable to start the server");
|
||||
console.log(err);
|
||||
});
|
||||
Reference in New Issue
Block a user