From 56d884812b3f12a52895bc666cb25e6edbe6eba0 Mon Sep 17 00:00:00 2001 From: jeff <113397187+cyberhorsey@users.noreply.github.com> Date: Mon, 13 Mar 2023 20:47:15 -0700 Subject: [PATCH] feat(bridge-ui): custom recipient address (#13309) Co-authored-by: shadab-taiko <108871478+shadab-taiko@users.noreply.github.com> --- packages/bridge-ui/src/App.svelte | 9 ++++- .../src/components/form/BridgeForm.svelte | 13 +++++- .../bridge-ui/src/components/form/To.svelte | 40 +++++++++++++++++++ packages/bridge-ui/src/domain/bridge.ts | 1 + packages/bridge-ui/src/erc20/bridge.spec.ts | 4 +- packages/bridge-ui/src/erc20/bridge.ts | 14 +++---- packages/bridge-ui/src/eth/bridge.spec.ts | 4 +- packages/bridge-ui/src/eth/bridge.ts | 14 +++---- 8 files changed, 76 insertions(+), 23 deletions(-) create mode 100644 packages/bridge-ui/src/components/form/To.svelte diff --git a/packages/bridge-ui/src/App.svelte b/packages/bridge-ui/src/App.svelte index b407342520..a16c1ed7d5 100644 --- a/packages/bridge-ui/src/App.svelte +++ b/packages/bridge-ui/src/App.svelte @@ -146,6 +146,7 @@ const apiTxs = await $relayerApi.GetAllByAddress(userAddress); + const blockInfoMap = await $relayerApi.GetBlockInfo(); relayerBlockInfoMap.set(blockInfoMap); @@ -155,6 +156,13 @@ // return [tx.hash, tx]; // })) + // const updatedStorageTxs: BridgeTransaction[] = txs.filter((tx) => { + // if (apiTxs.find((apiTx) => apiTx.hash.toLowerCase() === tx.hash)) { + // return false; + // } + // return true; + // }); + const updatedStorageTxs: BridgeTransaction[] = txs.filter((tx) => { const blockInfo = blockInfoMap.get(tx.fromChainId); if (blockInfo?.latestProcessedBlock >= tx.receipt.blockNumber) { @@ -170,7 +178,6 @@ const tokens = await $tokenService.GetTokens(userAddress); userTokens.set(tokens); } - return store; }); pendingTransactions.subscribe((store) => { diff --git a/packages/bridge-ui/src/components/form/BridgeForm.svelte b/packages/bridge-ui/src/components/form/BridgeForm.svelte index 4486b1d2ea..95363a3f92 100644 --- a/packages/bridge-ui/src/components/form/BridgeForm.svelte +++ b/packages/bridge-ui/src/components/form/BridgeForm.svelte @@ -25,7 +25,6 @@ import { pendingTransactions, transactions as transactionsStore, - transactioner, } from '../../store/transactions'; import { ProcessingFeeMethod } from '../../domain/fee'; import Memo from './Memo.svelte'; @@ -39,6 +38,7 @@ import { fetchFeeData } from '@wagmi/core'; import { providers } from '../../store/providers'; import { checkIfTokenIsDeployedCrossChain } from '../../utils/checkIfTokenIsDeployedCrossChain'; + import To from './To.svelte'; let amount: string; let amountInput: HTMLInputElement; @@ -51,6 +51,8 @@ let loading: boolean = false; let isFaucetModalOpen: boolean = false; let memoError: string; + let to: string = ''; + let showTo: boolean = false; $: getUserBalance($signer, $token, $fromChain); @@ -222,6 +224,9 @@ try { loading = true; if (requiresAllowance) throw Error('requires additional allowance'); + if (showTo && !ethers.utils.isAddress(to)) { + throw Error('Invalid custom recipient address'); + } const amountInWei = ethers.utils.parseUnits(amount, $token.decimals); @@ -238,7 +243,7 @@ $fromChain, ); - const bridgeOpts = { + const bridgeOpts: BridgeOpts = { amountInWei: amountInWei, signer: $signer, tokenAddress: await addrForToken(), @@ -248,6 +253,7 @@ processingFeeInWei: getProcessingFee(), memo: memo, isBridgedTokenAlreadyDeployed, + to: showTo && to ? to : await $signer.getAddress(), }; const doesUserHaveEnoughBalance = await checkUserHasEnoughBalance( @@ -324,6 +330,7 @@ tokenVaultAddress: $chainIdToTokenVaultAddress.get($fromChain.id), processingFeeInWei: getProcessingFee(), memo: memo, + to: showTo && to ? to : await $signer.getAddress(), }); const requiredGas = gasEstimate.mul(feeData.gasPrice); const userBalance = await $signer.getBalance('latest'); @@ -421,6 +428,8 @@ bind:isOpen={isFaucetModalOpen} /> {/if} + + diff --git a/packages/bridge-ui/src/components/form/To.svelte b/packages/bridge-ui/src/components/form/To.svelte new file mode 100644 index 0000000000..09e455e56c --- /dev/null +++ b/packages/bridge-ui/src/components/form/To.svelte @@ -0,0 +1,40 @@ + + +
+ (tooltipOpen = true)}> + Custom Recipient + + + { + showTo = !showTo; + }} + bind:checked={showTo} /> +
+{#if showTo} + +{/if} + + + +

+ You can set a custom address as the recipient of your funds, instead of + your current wallet address. +

+
+
diff --git a/packages/bridge-ui/src/domain/bridge.ts b/packages/bridge-ui/src/domain/bridge.ts index b7b3798ea9..94e2d07bf7 100644 --- a/packages/bridge-ui/src/domain/bridge.ts +++ b/packages/bridge-ui/src/domain/bridge.ts @@ -26,6 +26,7 @@ type BridgeOpts = { tokenId?: string; memo?: string; isBridgedTokenAlreadyDeployed?: boolean; + to: string; }; type ClaimOpts = { diff --git a/packages/bridge-ui/src/erc20/bridge.spec.ts b/packages/bridge-ui/src/erc20/bridge.spec.ts index dfd79d301d..d430a096c3 100644 --- a/packages/bridge-ui/src/erc20/bridge.spec.ts +++ b/packages/bridge-ui/src/erc20/bridge.spec.ts @@ -53,6 +53,7 @@ const opts: BridgeOpts = { tokenVaultAddress: '0x456', processingFeeInWei: BigNumber.from(2), memo: 'memo', + to: '0x', }; const approveOpts: ApproveOpts = { @@ -198,7 +199,7 @@ describe('bridge tests', () => { expect(mockContract.sendERC20).toHaveBeenCalled(); expect(mockContract.sendERC20).toHaveBeenCalledWith( opts.toChainId, - '0xfake', + '0x', opts.tokenAddress, opts.amountInWei, BigNumber.from(2640000), @@ -228,6 +229,7 @@ describe('bridge tests', () => { fromChainId: mainnet.id, toChainId: taiko.id, tokenVaultAddress: '0x456', + to: await wallet.getAddress(), }; await bridge.Bridge(opts); diff --git a/packages/bridge-ui/src/erc20/bridge.ts b/packages/bridge-ui/src/erc20/bridge.ts index 0755fa9a6a..ea786e81f0 100644 --- a/packages/bridge-ui/src/erc20/bridge.ts +++ b/packages/bridge-ui/src/erc20/bridge.ts @@ -34,7 +34,7 @@ class ERC20Bridge implements Bridge { srcChainId: opts.fromChainId, destChainId: opts.toChainId, owner: owner, - to: owner, + to: opts.to, refundAddress: owner, depositValue: opts.amountInWei, callValue: 0, @@ -108,13 +108,11 @@ class ERC20Bridge implements Bridge { throw Error('token vault does not have required allowance'); } - const { contract, owner, message } = await ERC20Bridge.prepareTransaction( - opts, - ); + const { contract, message } = await ERC20Bridge.prepareTransaction(opts); const tx = await contract.sendERC20( message.destChainId, - owner, + message.to, opts.tokenAddress, opts.amountInWei, message.gasLimit, @@ -130,13 +128,11 @@ class ERC20Bridge implements Bridge { } async EstimateGas(opts: BridgeOpts): Promise { - const { contract, owner, message } = await ERC20Bridge.prepareTransaction( - opts, - ); + const { contract, message } = await ERC20Bridge.prepareTransaction(opts); const gasEstimate = await contract.estimateGas.sendERC20( message.destChainId, - owner, + message.to, opts.tokenAddress, opts.amountInWei, message.gasLimit, diff --git a/packages/bridge-ui/src/eth/bridge.spec.ts b/packages/bridge-ui/src/eth/bridge.spec.ts index f181822979..0a2ec53b27 100644 --- a/packages/bridge-ui/src/eth/bridge.spec.ts +++ b/packages/bridge-ui/src/eth/bridge.spec.ts @@ -84,6 +84,7 @@ describe('bridge tests', () => { tokenVaultAddress: '0x456', processingFeeInWei: BigNumber.from(2), memo: 'memo', + to: '0x', }; expect(mockSigner.getAddress).not.toHaveBeenCalled(); @@ -92,7 +93,7 @@ describe('bridge tests', () => { expect(mockSigner.getAddress).toHaveBeenCalled(); expect(mockContract.sendEther).toHaveBeenCalledWith( opts.toChainId, - wallet.getAddress(), + '0x', BigNumber.from(140000), opts.processingFeeInWei, wallet.getAddress(), @@ -115,6 +116,7 @@ describe('bridge tests', () => { fromChainId: mainnet.id, toChainId: taiko.id, tokenVaultAddress: '0x456', + to: await wallet.getAddress(), }; await bridge.Bridge(opts); diff --git a/packages/bridge-ui/src/eth/bridge.ts b/packages/bridge-ui/src/eth/bridge.ts index 936eceb4e9..eb97a3d5e9 100644 --- a/packages/bridge-ui/src/eth/bridge.ts +++ b/packages/bridge-ui/src/eth/bridge.ts @@ -35,7 +35,7 @@ class ETHBridge implements BridgeInterface { srcChainId: opts.fromChainId, destChainId: opts.toChainId, owner: owner, - to: owner, + to: opts.to, refundAddress: owner, depositValue: opts.amountInWei, callValue: 0, @@ -59,13 +59,11 @@ class ETHBridge implements BridgeInterface { } async Bridge(opts: BridgeOpts): Promise { - const { contract, owner, message } = await ETHBridge.prepareTransaction( - opts, - ); + const { contract, message } = await ETHBridge.prepareTransaction(opts); const tx = await contract.sendEther( message.destChainId, - owner, + message.to, message.gasLimit, message.processingFee, message.refundAddress, @@ -81,13 +79,11 @@ class ETHBridge implements BridgeInterface { } async EstimateGas(opts: BridgeOpts): Promise { - const { contract, owner, message } = await ETHBridge.prepareTransaction( - opts, - ); + const { contract, message } = await ETHBridge.prepareTransaction(opts); const gasEstimate = await contract.estimateGas.sendEther( message.destChainId, - owner, + message.to, message.gasLimit, message.processingFee, message.refundAddress,