import axios from "axios"; import React from "react"; import { withRouter } from "next/router"; import { StargateClient } from "@cosmjs/stargate"; import Button from "../inputs/Button"; import { createMultisigFromCompressedSecp256k1Pubkeys } from "../../lib/multisigHelpers"; import Input from "../inputs/Input"; import StackableContainer from "../layout/StackableContainer"; import ThresholdInput from "../inputs/ThresholdInput"; let emptyPubKeyGroup = () => { return { address: "", compressedPubkey: "", keyError: "", isPubkey: false }; }; class MultiSigForm extends React.Component { constructor(props) { super(props); this.state = { pubkeys: [emptyPubKeyGroup(), emptyPubKeyGroup()], threshold: 2, processing: false, }; } handleChangeThreshold = (e) => { const threshold = e.target.value <= this.state.pubkeys.length ? e.target.value : this.state.pubkeys.length; this.setState({ threshold }); }; handleKeyGroupChange = (index, e) => { const { pubkeys } = this.state; pubkeys[index][e.target.name] = e.target.value; this.setState({ pubkeys }); }; handleAddKey = () => { this.setState({ pubkeys: this.state.pubkeys.concat(emptyPubKeyGroup()) }); }; handleRemove = (index) => { this.setState((prevState) => { const pubkeys = Array.from(prevState.pubkeys); pubkeys.splice(index, 1); const threshold = prevState.threshold > pubkeys.length ? pubkeys.length : prevState.threshold; return { pubkeys, threshold }; }); }; getPubkeyFromNode = async (address) => { const nodeAddress = process.env.NEXT_PUBLIC_NODE_ADDRESS; const client = await StargateClient.connect(nodeAddress); const accountOnChain = await client.getAccount(address); console.log(accountOnChain); if (!accountOnChain || !accountOnChain.pubkey) { throw new Error( "Account has no pubkey on chain, this address will need to send a transaction to appear on chain." ); } return accountOnChain.pubkey.value; }; handleKeyBlur = async (index, e) => { try { const { pubkeys } = this.state; let pubkey; // use pubkey console.log(pubkeys[index]); if (pubkeys[index].isPubkey) { pubkey = e.target.value; if (pubkey.length !== 44) { throw new Error("Invalid Secp256k1 pubkey"); } } else { // use address to fetch pubkey let address = e.target.value; if (address.length > 0) { pubkey = await this.getPubkeyFromNode(address); } } pubkeys[index].compressedPubkey = pubkey; pubkeys[index].keyError = ""; this.setState({ pubkeys }); } catch (error) { console.log(error); const { pubkeys } = this.state; pubkeys[index].keyError = error.message; this.setState({ pubkeys }); } }; handleCreate = async () => { this.setState({ processing: true }); const compressedPubkeys = this.state.pubkeys.map( (item) => item.compressedPubkey ); let multisigAddress; try { multisigAddress = await createMultisigFromCompressedSecp256k1Pubkeys( compressedPubkeys, parseInt(this.state.threshold, 10) ); this.props.router.push(`/multi/${multisigAddress}`); } catch (error) { console.log("Failed to creat multisig: ", error); } }; togglePubkey = (index) => { const { pubkeys } = this.state; pubkeys[index].isPubkey = !pubkeys[index].isPubkey; this.setState({ pubkeys }); }; render() { return ( <> Add the addresses that will make up this multisig. {this.state.pubkeys.map((pubkeyGroup, index) => ( {this.state.pubkeys.length > 2 && ( { this.handleRemove(index); }} > ✕ )} { this.handleKeyGroupChange(index, e); }} value={ pubkeyGroup.isPubkey ? pubkeyGroup.compressedPubkey : pubkeyGroup.address } label={ pubkeyGroup.isPubkey ? "Public Key (Secp256k1)" : "Address" } name={pubkeyGroup.isPubkey ? "compressedPubkey" : "address"} width="100%" placeholder={ pubkeyGroup.isPubkey ? "Akd/qKMWdZXyiMnSu6aFLpQEGDO0ijyal9mXUIcVaPNX" : "cosmos1vqpjljwsynsn58dugz0w8ut7kun7t8ls2qkmsq" } error={pubkeyGroup.keyError} onBlur={(e) => { this.handleKeyBlur(index, e); }} /> this.togglePubkey(index)} > Use {pubkeyGroup.isPubkey ? "Address" : "Public Key"} ))} This means that each transaction this multisig makes will require{" "} {this.state.threshold} of the members to sign it for it to be accepted by the validators. > ); } } export default withRouter(MultiSigForm);
Add the addresses that will make up this multisig.
This means that each transaction this multisig makes will require{" "} {this.state.threshold} of the members to sign it for it to be accepted by the validators.