From 623b4ed8eeb56688e6e0d5187254a019b1674824 Mon Sep 17 00:00:00 2001 From: Eric Corson Date: Wed, 9 Oct 2024 05:54:38 +0100 Subject: [PATCH] feat: add rough form for IBC withdrawals (#1133) --- apps/namadillo/src/App/Ibc/IbcWithdraw.tsx | 155 ++++++++++++++++++++- 1 file changed, 153 insertions(+), 2 deletions(-) diff --git a/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx b/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx index 760440d2c..3f33187e7 100644 --- a/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx +++ b/apps/namadillo/src/App/Ibc/IbcWithdraw.tsx @@ -1,9 +1,160 @@ +import { Key as KeplrKey, Window as KeplrWindow } from "@keplr-wallet/types"; import { Panel } from "@namada/components"; +import { WindowWithNamada } from "@namada/types"; +import BigNumber from "bignumber.js"; +import { getSdkInstance } from "hooks"; +import { useAtomValue } from "jotai"; +import { useEffect, useState } from "react"; + +import { NamCurrency } from "App/Common/NamCurrency"; +import { NamInput } from "App/Common/NamInput"; +import { accountBalanceAtom, defaultAccountAtom } from "atoms/accounts"; +import { chainAtom, chainParametersAtom } from "atoms/chain"; +import { getFirstError } from "atoms/utils"; + +const keplr = (window as KeplrWindow).keplr!; +const namada = (window as WindowWithNamada).namada!; + +const keplrChain = "theta-testnet-001"; + +const buttonStyles = "bg-white my-2 p-2 block"; export const IbcWithdraw: React.FC = () => { + const [error, setError] = useState(""); + const [keplrAccount, setKeplrAccount] = useState(); + const [amount, setAmount] = useState(); + const [channel, setChannel] = useState(""); + + const namadaAccount = useAtomValue(defaultAccountAtom); + const balance = useAtomValue(accountBalanceAtom); + const namadaChain = useAtomValue(chainAtom); + const namadaChainParams = useAtomValue(chainParametersAtom); + + useEffect(() => { + const error = getFirstError( + namadaAccount, + balance, + namadaChain, + namadaChainParams + ); + setError(error ? error.message : ""); + }, [ + namadaAccount.isError, + balance.isError, + namadaChain.isError, + namadaChainParams.isError, + ]); + + const withErrorReporting = + (fn: () => Promise): (() => Promise) => + async () => { + try { + await fn(); + setError(""); + } catch (e) { + // eslint-disable-next-line no-console + console.log(e); + setError(e instanceof Error ? e.message : "unknown error"); + } + }; + + const getKeplrAccount = withErrorReporting(async () => { + const key = await keplr.getKey(keplrChain); + setKeplrAccount(key); + }); + + const submitIbcTransfer = withErrorReporting(async () => { + const wrapperTxProps = { + token: namadaChain.data!.nativeTokenAddress, + feeAmount: BigNumber(0), + gasLimit: BigNumber(1_000_000), + chainId: namadaChain.data!.chainId, + publicKey: namadaAccount.data!.publicKey, + }; + + const sdk = await getSdkInstance(); + const tx = await sdk.tx.buildIbcTransfer(wrapperTxProps, { + source: namadaAccount.data!.address, + receiver: keplrAccount!.bech32Address, + token: namadaChain.data!.nativeTokenAddress, + amount: amount!, + portId: "transfer", + channelId: channel, + timeoutHeight: undefined, + timeoutSecOffset: undefined, + shieldingData: undefined, + }); + + const signedTxBytes = await namada.sign({ + signer: namadaAccount.data!.address, + txs: [tx], + checksums: namadaChainParams.data!.checksums, + }); + + await sdk.rpc.broadcastTx(signedTxBytes![0], wrapperTxProps); + }); + return ( - -
IBC: Withdraw (WIP)
+ + {/* Error */} +

{error}

+ +
+ + {/* Namada account */} +

Namada account

+ {namadaAccount.isSuccess && typeof namadaAccount.data !== "undefined" && ( +

+ {namadaAccount.data.alias} {namadaAccount.data.address} +

+ )} + +
+ + {/* Balance */} +

Balance

+ {balance.isSuccess && } + +
+ + {/* Keplr address */} +

Keplr address

+ + + {keplrAccount && ( +

+ {keplrAccount.name} {keplrAccount.bech32Address} +

+ )} + +
+ + {/* Amount */} +

Amount to send

+ setAmount(e.target.value)} /> + +
+ + {/* Channel */} +

Channel

+ setChannel(e.target.value)} + /> + +
+ + {/* Submit IBC transfer */} +

Submit IBC transfer

+
); };