diff --git a/components/forms/TransactionSigning.js b/components/forms/TransactionSigning.js index 5dc5ca07..4b8ae77a 100644 --- a/components/forms/TransactionSigning.js +++ b/components/forms/TransactionSigning.js @@ -1,8 +1,7 @@ import React, { useState, useEffect } from "react"; import axios from "axios"; import { toBase64 } from "@cosmjs/encoding"; -import { SigningStargateClient } from "@cosmjs/stargate"; - +import { AminoTypes, SigningStargateClient } from "@cosmjs/stargate"; import { useAppContext } from "../../context/AppContext"; import Button from "../inputs/Button"; import HashView from "../dataViews/HashView"; @@ -41,8 +40,42 @@ const TransactionSigning = (props) => { disableBalanceCheck: true, }, }; + const options = { + aminoTypes: new AminoTypes({ + "/cosmos.vesting.v1beta1.MsgCreateVestingAccount": { + aminoType: "cosmos-sdk/MsgCreateVestingAccount", + toAmino: ({ fromAddress, toAddress, amount, endTime, delayed }) => ({ + from_address: fromAddress, + to_address: toAddress, + amount: [...amount], + end_time: endTime, + delayed: delayed, + }), + fromAmino: ({ from_address, to_address, amount, end_time, delayed }) => ({ + fromAddress: from_address, + toAddress: to_address, + amount: [...amount], + endTime: end_time, + delayed: delayed, + }), + }, + "/cosmos.bank.v1beta1.MsgSend": { + aminoType: "cosmos-sdk/MsgSend", + toAmino: ({ fromAddress, toAddress, amount }) => ({ + from_address: fromAddress, + to_address: toAddress, + amount: [...amount], + }), + fromAmino: ({ from_address, to_address, amount }) => ({ + fromAddress: from_address, + toAddress: to_address, + amount: [...amount], + }), + }, + }), + }; const offlineSigner = window.getOfflineSignerOnlyAmino(state.chain.chainId); - const signingClient = await SigningStargateClient.offline(offlineSigner); + const signingClient = await SigningStargateClient.offline(offlineSigner, options); const signerData = { accountNumber: props.tx.accountNumber, sequence: props.tx.sequence, diff --git a/components/forms/VestingForm.js b/components/forms/VestingForm.js new file mode 100644 index 00000000..5dbf0d3d --- /dev/null +++ b/components/forms/VestingForm.js @@ -0,0 +1,163 @@ +import axios from "axios"; +import { calculateFee } from "@cosmjs/stargate"; +import { Decimal } from "@cosmjs/math"; +import React, { useState } from "react"; +import { withRouter } from "next/router"; + +import { useAppContext } from "../../context/AppContext"; +import Button from "../../components/inputs/Button"; +import Input from "../../components/inputs/Input"; +import StackableContainer from "../layout/StackableContainer"; +import { checkAddress, exampleAddress } from "../../lib/displayHelpers"; + +const VestingForm = (props) => { + const { state } = useAppContext(); + const [toAddress, setToAddress] = useState(""); + const [amount, setAmount] = useState("0"); + const [unixEpochTime, setUnixEpochTime] = useState("0"); + const [delayed, setDelayed] = useState(true); + const [memo, setMemo] = useState(""); + const [gas, setGas] = useState(200000); + const [gasPrice, _setGasPrice] = useState(state.chain.gasPrice); + const [_processing, setProcessing] = useState(false); + const [addressError, setAddressError] = useState(""); + + const createTransaction = (txToAddress, txAmount, txGas, txEndTime) => { + const amountInAtomics = Decimal.fromUserInput( + txAmount, + Number(state.chain.displayDenomExponent), + ).atomics; + const msgCreateVestingAccount = { + fromAddress: props.address, + toAddress: txToAddress, + endTime: txEndTime, + amount: [ + { + amount: amountInAtomics, + denom: state.chain.denom, + }, + ], + delayed: delayed, + }; + const msg = { + typeUrl: "/cosmos.vesting.v1beta1.MsgCreateVestingAccount", + value: msgCreateVestingAccount, + }; + const fee = calculateFee(Number(txGas), gasPrice); + return { + accountNumber: props.accountOnChain.accountNumber, + sequence: props.accountOnChain.sequence, + chainId: state.chain.chainId, + msgs: [msg], + fee: fee, + memo: memo, + }; + }; + + const handleCreate = async () => { + const toAddressError = checkAddress(toAddress, state.chain.addressPrefix); + if (toAddressError) { + setAddressError(`Invalid address for network ${state.chain.chainId}: ${toAddressError}`); + return; + } + + setProcessing(true); + const tx = createTransaction(toAddress, amount, gas, unixEpochTime); + console.log(tx); + const dataJSON = JSON.stringify(tx); + const res = await axios.post("/api/transaction", { dataJSON }); + const { transactionID } = res.data; + props.router.push(`${props.address}/transaction/${transactionID}`); + }; + + return ( + + +

Create New Vesting Account

+
+ setToAddress(e.target.value)} + error={addressError} + placeholder={`E.g. ${exampleAddress(0, state.chain.addressPrefix)}`} + /> +
+
+ setAmount(e.target.value)} + /> +
+
+ setUnixEpochTime(e.target.value)} + /> +
+
+ { + setDelayed(e.target.checked); + }} + /> +
+
+ setGas(e.target.value)} + /> +
+
+ +
+
+ setMemo(e.target.value)} + /> +
+