From 9b7c304ebe855e53e2d4ff72a4e2905912cee8b0 Mon Sep 17 00:00:00 2001 From: klk1236 Date: Wed, 6 Jul 2022 18:25:08 +0400 Subject: [PATCH 01/30] Fixed where the keplr overides txn fees. --- components/forms/TransactionSigning.tsx | 3 +++ types/index.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/components/forms/TransactionSigning.tsx b/components/forms/TransactionSigning.tsx index 290d148..25dc3ed 100644 --- a/components/forms/TransactionSigning.tsx +++ b/components/forms/TransactionSigning.tsx @@ -33,6 +33,9 @@ const TransactionSigning = (props: Props) => { try { assert(state.chain.chainId, "chainId missing"); await window.keplr.enable(state.chain.chainId); + window.keplr.defaultOptions = { + sign: { preferNoSetFee: !0, preferNoSetMemo: !0, disableBalanceCheck: !0 }, + }; const tempWalletAccount = await window.keplr.getKey(state.chain.chainId); console.log(tempWalletAccount); const tempHasSigned = props.signatures.some( diff --git a/types/index.ts b/types/index.ts index 1d29077..f6e78f1 100644 --- a/types/index.ts +++ b/types/index.ts @@ -4,6 +4,9 @@ import { EncodeObject } from "@cosmjs/proto-signing"; declare global { interface Window { keplr: { + defaultOptions: { + sign: { preferNoSetFee: boolean; preferNoSetMemo: boolean; disableBalanceCheck: boolean }; + }; // eslint-disable-next-line @typescript-eslint/no-explicit-any enable: (chainId: string) => any; getKey: (chainId: string) => Promise; From 937b7846efbc3a2b648491c34132466323e5715a Mon Sep 17 00:00:00 2001 From: klk1236 Date: Thu, 7 Jul 2022 10:47:16 +0400 Subject: [PATCH 02/30] Setting keplr options true instead of !0. --- components/forms/TransactionSigning.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/forms/TransactionSigning.tsx b/components/forms/TransactionSigning.tsx index 25dc3ed..46d6a73 100644 --- a/components/forms/TransactionSigning.tsx +++ b/components/forms/TransactionSigning.tsx @@ -34,7 +34,7 @@ const TransactionSigning = (props: Props) => { assert(state.chain.chainId, "chainId missing"); await window.keplr.enable(state.chain.chainId); window.keplr.defaultOptions = { - sign: { preferNoSetFee: !0, preferNoSetMemo: !0, disableBalanceCheck: !0 }, + sign: { preferNoSetFee: true, preferNoSetMemo: true, disableBalanceCheck: true }, }; const tempWalletAccount = await window.keplr.getKey(state.chain.chainId); console.log(tempWalletAccount); From 9047d3c54d0adf6200f28f9edf00fc1e7b660783 Mon Sep 17 00:00:00 2001 From: klk1236 Date: Mon, 11 Jul 2022 16:32:23 +0400 Subject: [PATCH 03/30] added delegation txn support --- .gitignore | 5 +- components/dataViews/TransactionInfo.tsx | 40 ++++-- components/forms/DelegationForm.tsx | 158 +++++++++++++++++++++++ lib/displayHelpers.ts | 19 +++ pages/multi/[address]/index.tsx | 22 +++- 5 files changed, 228 insertions(+), 16 deletions(-) create mode 100644 components/forms/DelegationForm.tsx diff --git a/.gitignore b/.gitignore index 5e489ce..c7fbfeb 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,7 @@ yarn-debug.log* yarn-error.log* # Local Netlify folder -.netlify \ No newline at end of file +.netlify + +# IDE folder +.idea diff --git a/components/dataViews/TransactionInfo.tsx b/components/dataViews/TransactionInfo.tsx index 2abb112..482a53a 100644 --- a/components/dataViews/TransactionInfo.tsx +++ b/components/dataViews/TransactionInfo.tsx @@ -5,7 +5,7 @@ import { DbTransaction } from "../../types"; import { useAppContext } from "../../context/AppContext"; import HashView from "./HashView"; import StackableContainer from "../layout/StackableContainer"; -import { printableCoins } from "../../lib/displayHelpers"; +import { printableCoins, printableCoin } from "../../lib/displayHelpers"; interface Props { tx: DbTransaction; @@ -16,19 +16,33 @@ const TransactionInfo = (props: Props) => { return (
    - {props.tx.msgs && ( -
  • - -
    {printableCoins(props.tx.msgs[0].value.amount, state.chain)}
    -
  • + {props.tx.msgs && props.tx.msgs[0].typeUrl === "/cosmos.bank.v1beta1.MsgSend" && ( + <> +
  • + +
    {printableCoins(props.tx.msgs[0].value.amount, state.chain)}
    +
  • +
  • + +
    + +
    +
  • + )} - {props.tx.msgs && ( -
  • - -
    - -
    -
  • + {props.tx.msgs && props.tx.msgs[0].typeUrl === "/cosmos.staking.v1beta1.MsgDelegate" && ( + <> +
  • + +
    {printableCoin(props.tx.msgs[0].value.amount, state.chain)}
    +
  • +
  • + +
    + +
    +
  • + )} {props.tx.fee && ( <> diff --git a/components/forms/DelegationForm.tsx b/components/forms/DelegationForm.tsx new file mode 100644 index 0000000..bb5d31d --- /dev/null +++ b/components/forms/DelegationForm.tsx @@ -0,0 +1,158 @@ +import axios from "axios"; +import { Account, calculateFee } from "@cosmjs/stargate"; +import { Decimal } from "@cosmjs/math"; +import { assert } from "@cosmjs/utils"; +import React, { useState } from "react"; +import { withRouter, NextRouter } from "next/router"; +import { useAppContext } from "../../context/AppContext"; +import Button from "../inputs/Button"; +import Input from "../inputs/Input"; +import StackableContainer from "../layout/StackableContainer"; +import { checkValidatorAddress } from "../../lib/displayHelpers"; + +interface Props { + address: string | null; + accountOnChain: Account | null; + router: NextRouter; + closeForm: () => void; +} + +const DelegationForm = (props: Props) => { + const { state } = useAppContext(); + const [validatorAddress, setValidatorAddress] = useState(""); + const [amount, setAmount] = useState("0"); + 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 = (txValidatorAddress: string, txAmount: string, txGas: number) => { + const amountInAtomics = Decimal.fromUserInput( + txAmount, + Number(state.chain.displayDenomExponent), + ).atomics; + const msgDelegate = { + delegatorAddress: props.address, + validatorAddress: txValidatorAddress, + amount: { + amount: amountInAtomics, + denom: state.chain.denom, + }, + }; + const msg = { + typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", + value: msgDelegate, + }; + assert(gasPrice, "gasPrice missing"); + const fee = calculateFee(Number(txGas), gasPrice); + const { accountOnChain } = props; + assert(accountOnChain, "accountOnChain missing"); + return { + accountNumber: accountOnChain.accountNumber, + sequence: accountOnChain.sequence, + chainId: state.chain.chainId, + msgs: [msg], + fee: fee, + memo: memo, + }; + }; + + const handleCreate = async () => { + assert(state.chain.addressPrefix, "addressPrefix missing"); + const validatorAddressError = checkValidatorAddress( + validatorAddress, + state.chain.addressPrefix, + ); + if (validatorAddressError) { + setAddressError( + `Invalid address for network ${state.chain.chainId}: ${validatorAddressError}`, + ); + return; + } + + setProcessing(true); + const tx = createTransaction(validatorAddress, amount, gas); + console.log(tx, "tx data"); + const dataJSON = JSON.stringify(tx); + const res = await axios.post("/api/transaction", { dataJSON }); + console.log(dataJSON, "tx dataJSON", res); + const { transactionID } = res.data; + props.router.push(`${props.address}/transaction/${transactionID}`); + }; + + assert(state.chain.addressPrefix, "addressPrefix missing"); + + return ( + + +

    Create Delegation

    +
    + ) => setValidatorAddress(e.target.value)} + error={addressError} + placeholder={`E.g. cosmosvaloper1sjllsnramtg3ewxqwwrwjxfgc4n4ef9u2lcnj0`} + /> +
    +
    + ) => setAmount(e.target.value)} + /> +
    +
    + ) => + setGas(parseInt(e.target.value, 10)) + } + /> +
    +
    + +
    +
    + ) => setMemo(e.target.value)} + /> +
    +