Merge pull request #70 from cosmos/pubkey-with-null-account
Let getMultisigAccount always return a pubkey
This commit is contained in:
@@ -6,7 +6,7 @@ import StackableContainer from "../layout/StackableContainer";
|
||||
interface Props {
|
||||
/** Addresses of the multisig members */
|
||||
members: string[];
|
||||
threshold: number;
|
||||
threshold: string;
|
||||
}
|
||||
|
||||
const MultisigMembers = (props: Props) => (
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import React from "react";
|
||||
import { MultisigThresholdPubkey } from "@cosmjs/amino";
|
||||
|
||||
import { DbSignature } from "../../types";
|
||||
import StackableContainer from "../layout/StackableContainer";
|
||||
import { AccountWithPubkey } from "../../lib/multisigHelpers";
|
||||
|
||||
interface Props {
|
||||
signatures: DbSignature[];
|
||||
account: AccountWithPubkey;
|
||||
pubkey: MultisigThresholdPubkey;
|
||||
}
|
||||
|
||||
const ThresholdInfo = ({ signatures, account }: Props) => (
|
||||
const ThresholdInfo = ({ signatures, pubkey }: Props) => (
|
||||
<StackableContainer lessPadding lessMargin>
|
||||
<h2>Signatures</h2>
|
||||
<StackableContainer lessPadding lessMargin lessRadius>
|
||||
@@ -21,7 +22,7 @@ const ThresholdInfo = ({ signatures, account }: Props) => (
|
||||
<div className="threshold">
|
||||
<div className="current">{signatures.length}</div>
|
||||
<div className="label divider">of</div>
|
||||
<div className="required">{account.pubkey.value.threshold}</div>
|
||||
<div className="required">{pubkey.value.threshold}</div>
|
||||
<div className="label">signatures complete</div>
|
||||
</div>
|
||||
</StackableContainer>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios from "axios";
|
||||
import { calculateFee } from "@cosmjs/stargate";
|
||||
import { Account, calculateFee } from "@cosmjs/stargate";
|
||||
import { Decimal } from "@cosmjs/math";
|
||||
import { assert } from "@cosmjs/utils";
|
||||
import React, { useState } from "react";
|
||||
@@ -10,11 +10,10 @@ import Button from "../inputs/Button";
|
||||
import Input from "../inputs/Input";
|
||||
import StackableContainer from "../layout/StackableContainer";
|
||||
import { checkAddress, exampleAddress } from "../../lib/displayHelpers";
|
||||
import { AccountWithPubkey } from "../../lib/multisigHelpers";
|
||||
|
||||
interface Props {
|
||||
address: string | null;
|
||||
accountOnChain: AccountWithPubkey | null;
|
||||
accountOnChain: Account | null;
|
||||
router: NextRouter;
|
||||
closeForm: () => void;
|
||||
}
|
||||
|
||||
+19
-16
@@ -1,7 +1,13 @@
|
||||
import axios from "axios";
|
||||
import { createMultisigThresholdPubkey, Pubkey, pubkeyToAddress } from "@cosmjs/amino";
|
||||
import {
|
||||
createMultisigThresholdPubkey,
|
||||
isMultisigThresholdPubkey,
|
||||
MultisigThresholdPubkey,
|
||||
pubkeyToAddress,
|
||||
} from "@cosmjs/amino";
|
||||
import { Account } from "@cosmjs/stargate";
|
||||
import { StargateClient } from "@cosmjs/stargate";
|
||||
import { assert } from "@cosmjs/utils";
|
||||
|
||||
/**
|
||||
* Turns array of compressed Secp256k1 pubkeys
|
||||
@@ -40,31 +46,31 @@ const createMultisigFromCompressedSecp256k1Pubkeys = async (
|
||||
return res.data.address;
|
||||
};
|
||||
|
||||
/** Like Account but with non-optional pubkey */
|
||||
export type AccountWithPubkey = Account & { readonly pubkey: Pubkey };
|
||||
|
||||
/**
|
||||
* This gets a multisigs account (pubkey, sequence, account number, etc) from
|
||||
* a node and/or the api 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
|
||||
* @return {object} The multisig account.
|
||||
* The public key should always be available, either on chain or in the app's database.
|
||||
* The account is only available when the there was any on-chain activity such as
|
||||
* receipt of tokens.
|
||||
*/
|
||||
const getMultisigAccount = async (
|
||||
address: string,
|
||||
client: StargateClient,
|
||||
): Promise<AccountWithPubkey | null> => {
|
||||
): Promise<[MultisigThresholdPubkey, Account | null]> => {
|
||||
// we need the multisig pubkeys to create transactions, if the multisig
|
||||
// is new, and has never submitted a transaction its pubkeys will not be
|
||||
// available from a node. If the multisig was created with this instance
|
||||
// of this tool its pubkey will be available in the fauna datastore
|
||||
const accountOnChain = await client.getAccount(address);
|
||||
const chainId = await client.getChainId();
|
||||
if (!accountOnChain) return null;
|
||||
|
||||
let pubkey: Pubkey;
|
||||
if (accountOnChain.pubkey) {
|
||||
let pubkey: MultisigThresholdPubkey;
|
||||
if (accountOnChain?.pubkey) {
|
||||
assert(
|
||||
isMultisigThresholdPubkey(accountOnChain.pubkey),
|
||||
"Pubkey on chain is not of type MultisigThreshold",
|
||||
);
|
||||
pubkey = accountOnChain.pubkey;
|
||||
} else {
|
||||
console.log("No pubkey on chain for: ", address);
|
||||
@@ -76,10 +82,7 @@ const getMultisigAccount = async (
|
||||
pubkey = JSON.parse(res.data.pubkeyJSON);
|
||||
}
|
||||
|
||||
return {
|
||||
...accountOnChain,
|
||||
pubkey: pubkey,
|
||||
};
|
||||
return [pubkey, accountOnChain];
|
||||
};
|
||||
|
||||
export { createMultisigFromCompressedSecp256k1Pubkeys, getMultisigAccount };
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { pubkeyToAddress, Pubkey } from "@cosmjs/amino";
|
||||
import { StargateClient } from "@cosmjs/stargate";
|
||||
import { pubkeyToAddress, Pubkey, MultisigThresholdPubkey } from "@cosmjs/amino";
|
||||
import { Account, StargateClient } from "@cosmjs/stargate";
|
||||
import { assert } from "@cosmjs/utils";
|
||||
import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { useAppContext } from "../../../context/AppContext";
|
||||
import Button from "../../../components/inputs/Button";
|
||||
import { AccountWithPubkey, getMultisigAccount } from "../../../lib/multisigHelpers";
|
||||
import { getMultisigAccount } from "../../../lib/multisigHelpers";
|
||||
import HashView from "../../../components/dataViews/HashView";
|
||||
import MultisigHoldings from "../../../components/dataViews/MultisigHoldings";
|
||||
import MultisigMembers from "../../../components/dataViews/MultisigMembers";
|
||||
@@ -30,7 +30,8 @@ const multipage = () => {
|
||||
const [showTxForm, setShowTxForm] = useState(false);
|
||||
const [holdings, setHoldings] = useState<Coin | null>(null);
|
||||
const [multisigAddress, setMultisigAddress] = useState("");
|
||||
const [accountOnChain, setAccountOnChain] = useState<AccountWithPubkey | null>(null);
|
||||
const [accountOnChain, setAccountOnChain] = useState<Account | null>(null);
|
||||
const [pubkey, setPubkey] = useState<MultisigThresholdPubkey>();
|
||||
const [accountError, setAccountError] = useState(null);
|
||||
const router = useRouter();
|
||||
|
||||
@@ -49,9 +50,10 @@ const multipage = () => {
|
||||
const client = await StargateClient.connect(state.chain.nodeAddress);
|
||||
assert(state.chain.denom, "denom missing");
|
||||
const tempHoldings = await client.getBalance(address, state.chain.denom);
|
||||
const tempAccountOnChain = await getMultisigAccount(address, client);
|
||||
setHoldings(tempHoldings);
|
||||
setAccountOnChain(tempAccountOnChain);
|
||||
const result = await getMultisigAccount(address, client);
|
||||
setPubkey(result[0]);
|
||||
setAccountOnChain(result[1]);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (error: any) {
|
||||
setAccountError(error.message);
|
||||
@@ -74,13 +76,10 @@ const multipage = () => {
|
||||
)}
|
||||
</h1>
|
||||
</StackableContainer>
|
||||
{accountOnChain && (
|
||||
{pubkey && (
|
||||
<MultisigMembers
|
||||
members={participantAddressesFromMultisig(
|
||||
accountOnChain.pubkey,
|
||||
state.chain.addressPrefix,
|
||||
)}
|
||||
threshold={accountOnChain.pubkey.value.threshold}
|
||||
members={participantAddressesFromMultisig(pubkey, state.chain.addressPrefix)}
|
||||
threshold={pubkey.value.threshold}
|
||||
/>
|
||||
)}
|
||||
{accountError && (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import axios from "axios";
|
||||
import React from "react";
|
||||
import { GetServerSideProps } from "next";
|
||||
import { StargateClient, makeMultisignedTx } from "@cosmjs/stargate";
|
||||
import { StargateClient, makeMultisignedTx, Account } from "@cosmjs/stargate";
|
||||
import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
@@ -12,7 +12,7 @@ import { DbSignature, DbTransaction } from "../../../../types";
|
||||
import { useAppContext } from "../../../../context/AppContext";
|
||||
import Button from "../../../../components/inputs/Button";
|
||||
import { findTransactionByID } from "../../../../lib/graphqlHelpers";
|
||||
import { AccountWithPubkey, getMultisigAccount } from "../../../../lib/multisigHelpers";
|
||||
import { getMultisigAccount } from "../../../../lib/multisigHelpers";
|
||||
import Page from "../../../../components/layout/Page";
|
||||
import StackableContainer from "../../../../components/layout/StackableContainer";
|
||||
import ThresholdInfo from "../../../../components/dataViews/ThresholdInfo";
|
||||
@@ -75,7 +75,8 @@ const transactionPage = ({
|
||||
const [broadcastError, setBroadcastError] = useState("");
|
||||
const [isBroadcasting, setIsBroadcasting] = useState(false);
|
||||
const [transactionHash, setTransactionHash] = useState(txHash);
|
||||
const [accountOnChain, setAccountOnChain] = useState<AccountWithPubkey | null>(null);
|
||||
const [accountOnChain, setAccountOnChain] = useState<Account | null>(null);
|
||||
const [pubkey, setPubkey] = useState<MultisigThresholdPubkey>();
|
||||
const [accountError, setAccountError] = useState(null);
|
||||
const txInfo: DbTransaction = (transactionJSON && JSON.parse(transactionJSON)) || null;
|
||||
const router = useRouter();
|
||||
@@ -95,8 +96,9 @@ const transactionPage = ({
|
||||
try {
|
||||
assert(state.chain.nodeAddress, "Node address missing");
|
||||
const client = await StargateClient.connect(state.chain.nodeAddress);
|
||||
const tempAccountOnChain = await getMultisigAccount(address, client);
|
||||
setAccountOnChain(tempAccountOnChain);
|
||||
const result = await getMultisigAccount(address, client);
|
||||
setPubkey(result[0]);
|
||||
setAccountOnChain(result[1]);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (error: any) {
|
||||
setAccountError(error.toString());
|
||||
@@ -150,11 +152,11 @@ const transactionPage = ({
|
||||
)}
|
||||
{transactionHash && <CompletedTransaction transactionHash={transactionHash} />}
|
||||
<TransactionInfo tx={txInfo} />
|
||||
{!transactionHash && accountOnChain && (
|
||||
<ThresholdInfo signatures={currentSignatures} account={accountOnChain} />
|
||||
{!transactionHash && pubkey && (
|
||||
<ThresholdInfo signatures={currentSignatures} pubkey={pubkey} />
|
||||
)}
|
||||
{accountOnChain &&
|
||||
currentSignatures.length >= parseInt(accountOnChain.pubkey.value.threshold, 10) &&
|
||||
{pubkey &&
|
||||
currentSignatures.length >= parseInt(pubkey.value.threshold, 10) &&
|
||||
!transactionHash && (
|
||||
<>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user