moves multisig queries to client
to be able to use context-based chain info
This commit is contained in:
@@ -38,7 +38,7 @@ const createMultisigFromCompressedSecp256k1Pubkeys = async (
|
||||
|
||||
/**
|
||||
* This gets a multisigs account (pubkey, sequence, account number, etc) from
|
||||
* a node and/or the faunadb if the multisig was made on this app
|
||||
* a node and/or the api if the multisig was made on this app
|
||||
*
|
||||
* @param {string} address The multisig address
|
||||
* @param client A connected stargate cosmoshub client
|
||||
@@ -53,12 +53,12 @@ const getMultisigAccount = async (address, client) => {
|
||||
|
||||
if (!accountOnChain || !accountOnChain.pubkey) {
|
||||
console.log("No pubkey on chain for: ", address);
|
||||
const res = await getMultisig(address);
|
||||
const res = await axios.get(`/api/multisig/${address}`);
|
||||
|
||||
if (!res.data.data.getMultisig) {
|
||||
if (res.status !== 200) {
|
||||
throw new Error("Multisig has no pubkey on node, and was not created using this tool.");
|
||||
}
|
||||
const pubkey = JSON.parse(res.data.data.getMultisig.pubkeyJSON);
|
||||
const pubkey = JSON.parse(res.data.pubkeyJSON);
|
||||
|
||||
if (!accountOnChain) {
|
||||
accountOnChain = {};
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { getMultisig } from "../../../../lib/graphqlHelpers";
|
||||
|
||||
export default async function (req, res) {
|
||||
switch (req.method) {
|
||||
case "GET":
|
||||
try {
|
||||
const { multisigAddress } = req.query;
|
||||
console.log("Function `getMultisig` invoked", multisigAddress);
|
||||
const getRes = await getMultisig(multisigAddress);
|
||||
if (!getRes.data.data.getMultisig) {
|
||||
res.status(404).send("Multisig not found");
|
||||
return;
|
||||
}
|
||||
console.log("success", getRes.data.data.getMultisig);
|
||||
res.status(200).send(getRes.data.data.getMultisig);
|
||||
return;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(400).send(err.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// no route matched
|
||||
res.status(405).end();
|
||||
return;
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { pubkeyToAddress } from "@cosmjs/amino";
|
||||
import { StargateClient } from "@cosmjs/stargate";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { useAppContext } from "../../../context/AppContext";
|
||||
import Button from "../../../components/inputs/Button";
|
||||
import { getMultisigAccount } from "../../../lib/multisigHelpers";
|
||||
import HashView from "../../../components/dataViews/HashView";
|
||||
@@ -12,23 +13,6 @@ import Page from "../../../components/layout/Page";
|
||||
import StackableContainer from "../../../components/layout/StackableContainer";
|
||||
import TransactionForm from "../../../components/forms/TransactionForm";
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
try {
|
||||
const client = await StargateClient.connect(process.env.NEXT_PUBLIC_NODE_ADDRESS);
|
||||
const multisigAddress = context.params.address;
|
||||
const holdings = await client.getBalance(multisigAddress, process.env.NEXT_PUBLIC_DENOM);
|
||||
const accountOnChain = await getMultisigAccount(multisigAddress, client);
|
||||
return {
|
||||
props: { accountOnChain, holdings },
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return {
|
||||
props: { error: error.message },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function participantPubkeysFromMultisig(multisigPubkey) {
|
||||
return multisigPubkey.value.pubkeys;
|
||||
}
|
||||
@@ -40,28 +24,51 @@ function participantAddressesFromMultisig(multisigPubkey, addressPrefix) {
|
||||
}
|
||||
|
||||
const multipage = (props) => {
|
||||
const { state } = useAppContext();
|
||||
const [showTxForm, setShowTxForm] = useState(false);
|
||||
const [holdings, setHoldings] = useState("");
|
||||
const [accountOnChain, setAccountOnChain] = useState(null);
|
||||
const [accountError, setAccountError] = useState(null);
|
||||
const router = useRouter();
|
||||
const { address } = router.query;
|
||||
|
||||
useEffect(() => {
|
||||
if (router.query.address) {
|
||||
fetchMultisig(router.query.address);
|
||||
}
|
||||
}, [router.query.address]);
|
||||
|
||||
const fetchMultisig = async (address) => {
|
||||
try {
|
||||
const client = await StargateClient.connect(state.chain.nodeAddress);
|
||||
const tempHoldings = await client.getBalance(address, state.chain.denom);
|
||||
const tempAccountOnChain = await getMultisigAccount(address, client);
|
||||
setHoldings(tempHoldings);
|
||||
setAccountOnChain(tempAccountOnChain);
|
||||
} catch (error) {
|
||||
setAccountError(error.message);
|
||||
console.log("Account error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<StackableContainer base>
|
||||
<StackableContainer>
|
||||
<label>Multisig Address</label>
|
||||
<h1>
|
||||
<HashView hash={address} />
|
||||
<HashView hash={router.query.address} />
|
||||
</h1>
|
||||
</StackableContainer>
|
||||
{props.accountOnChain?.pubkey && (
|
||||
<MultisigMembers
|
||||
members={participantAddressesFromMultisig(
|
||||
props.accountOnChain?.pubkey,
|
||||
process.env.NEXT_PUBLIC_ADDRESS_PREFIX,
|
||||
accountOnChain?.pubkey,
|
||||
state.chain.addressPrefix,
|
||||
)}
|
||||
threshold={props.accountOnChain?.pubkey.value.threshold}
|
||||
/>
|
||||
)}
|
||||
{props.error && (
|
||||
{accountError && (
|
||||
<StackableContainer>
|
||||
<div className="multisig-error">
|
||||
<p>
|
||||
@@ -78,7 +85,7 @@ const multipage = (props) => {
|
||||
)}
|
||||
{showTxForm ? (
|
||||
<TransactionForm
|
||||
address={address}
|
||||
address={router.query.address}
|
||||
accountOnChain={props.accountOnChain}
|
||||
closeForm={() => {
|
||||
setShowTxForm(false);
|
||||
@@ -87,7 +94,7 @@ const multipage = (props) => {
|
||||
) : (
|
||||
<div className="interfaces">
|
||||
<div className="col-1">
|
||||
<MultisigHoldings holdings={props.holdings} />
|
||||
<MultisigHoldings holdings={holdings} />
|
||||
</div>
|
||||
<div className="col-2">
|
||||
<StackableContainer lessPadding>
|
||||
|
||||
@@ -2,9 +2,11 @@ import React from "react";
|
||||
import axios from "axios";
|
||||
import { StargateClient, makeMultisignedTx } from "@cosmjs/stargate";
|
||||
import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { fromBase64 } from "@cosmjs/encoding";
|
||||
|
||||
import { useAppContext } from "../../../../context/AppContext";
|
||||
import Button from "../../../../components/inputs/Button";
|
||||
import { findTransactionByID } from "../../../../lib/graphqlHelpers";
|
||||
import { getMultisigAccount } from "../../../../lib/multisigHelpers";
|
||||
@@ -16,17 +18,12 @@ import TransactionSigning from "../../../../components/forms/TransactionSigning"
|
||||
import CompletedTransaction from "../../../../components/dataViews/CompletedTransaction";
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
// get multisig account and transaction info
|
||||
const nodeAddress = process.env.NEXT_PUBLIC_NODE_ADDRESS;
|
||||
const client = await StargateClient.connect(nodeAddress);
|
||||
const multisigAddress = context.params.address;
|
||||
// get transaction info
|
||||
const transactionID = context.params.transactionID;
|
||||
let transactionJSON;
|
||||
let txHash;
|
||||
let accountOnChain;
|
||||
let signatures;
|
||||
try {
|
||||
accountOnChain = await getMultisigAccount(multisigAddress, client);
|
||||
console.log("Function `findTransactionByID` invoked", transactionID);
|
||||
const getRes = await findTransactionByID(transactionID);
|
||||
console.log("success", getRes.data);
|
||||
@@ -38,13 +35,10 @@ export async function getServerSideProps(context) {
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
multisigAddress,
|
||||
transactionJSON,
|
||||
txHash,
|
||||
accountOnChain,
|
||||
transactionID,
|
||||
signatures,
|
||||
nodeAddress,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -54,18 +48,42 @@ const transactionPage = ({
|
||||
transactionJSON,
|
||||
transactionID,
|
||||
signatures,
|
||||
accountOnChain,
|
||||
nodeAddress,
|
||||
txHash,
|
||||
}) => {
|
||||
const { state } = useAppContext();
|
||||
const [currentSignatures, setCurrentSignatures] = useState(signatures);
|
||||
const [broadcastError, setBroadcastError] = useState("");
|
||||
const [isBroadcasting, setIsBroadcasting] = useState(false);
|
||||
const [transactionHash, setTransactionHash] = useState(txHash);
|
||||
const [_holdings, setHoldings] = useState("");
|
||||
const [accountOnChain, setAccountOnChain] = useState(null);
|
||||
const [accountError, setAccountError] = useState(null);
|
||||
const txInfo = (transactionJSON && JSON.parse(transactionJSON)) || null;
|
||||
const router = useRouter();
|
||||
|
||||
const addSignature = (signature) => {
|
||||
setCurrentSignatures((prevState) => [...prevState, signature]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (router.query.address) {
|
||||
fetchMultisig(router.query.address);
|
||||
}
|
||||
}, [router.query.address]);
|
||||
|
||||
const fetchMultisig = async (address) => {
|
||||
try {
|
||||
const client = await StargateClient.connect(state.chain.nodeAddress);
|
||||
const tempHoldings = await client.getBalance(address, state.chain.denom);
|
||||
const tempAccountOnChain = await getMultisigAccount(address, client);
|
||||
setHoldings(tempHoldings);
|
||||
setAccountOnChain(tempAccountOnChain);
|
||||
} catch (error) {
|
||||
setAccountError(error.message);
|
||||
console.log("Account error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const broadcastTx = async () => {
|
||||
try {
|
||||
setIsBroadcasting(true);
|
||||
@@ -79,7 +97,7 @@ const transactionPage = ({
|
||||
bodyBytes,
|
||||
new Map(currentSignatures.map((s) => [s.address, fromBase64(s.signature)])),
|
||||
);
|
||||
const broadcaster = await StargateClient.connect(nodeAddress);
|
||||
const broadcaster = await StargateClient.connect(state.chain.nodeAddress);
|
||||
const result = await broadcaster.broadcastTx(
|
||||
Uint8Array.from(TxRaw.encode(signedTx).finish()),
|
||||
);
|
||||
@@ -100,13 +118,20 @@ const transactionPage = ({
|
||||
<StackableContainer>
|
||||
<h1>{transactionHash ? "Completed Transaction" : "In Progress Transaction"}</h1>
|
||||
</StackableContainer>
|
||||
|
||||
{accountError && (
|
||||
<StackableContainer>
|
||||
<div className="multisig-error">
|
||||
<p>Multisig address could not be found.</p>
|
||||
</div>
|
||||
</StackableContainer>
|
||||
)}
|
||||
{transactionHash && <CompletedTransaction transactionHash={transactionHash} />}
|
||||
<TransactionInfo tx={txInfo} />
|
||||
{!transactionHash && (
|
||||
{!transactionHash && accountOnChain && (
|
||||
<ThresholdInfo signatures={currentSignatures} account={accountOnChain} />
|
||||
)}
|
||||
{currentSignatures.length >= parseInt(accountOnChain.pubkey.value.threshold, 10) &&
|
||||
{accountOnChain &&
|
||||
currentSignatures.length >= parseInt(accountOnChain.pubkey.value.threshold, 10) &&
|
||||
!transactionHash && (
|
||||
<>
|
||||
<Button
|
||||
@@ -138,6 +163,12 @@ const transactionPage = ({
|
||||
font-family: monospace;
|
||||
max-width: 475px;
|
||||
}
|
||||
.multisig-error p {
|
||||
max-width: 550px;
|
||||
color: red;
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
`}</style>
|
||||
</Page>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user