From bec2657993091b5d6a3df33cae9040981b3cb702 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 17 Jul 2023 19:34:50 +0200 Subject: [PATCH 01/67] minor change --- .../src/components/Bridge/AmountInput/Balance.svelte | 4 ++-- .../components/ChainSelector/ChainSelector.svelte | 4 ++-- .../bridge-ui-v2/src/components/Faucet/Faucet.svelte | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte index 18000188fa6..1c204943709 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte @@ -27,8 +27,8 @@ userAddress: account.address, chainId: srcChainId, }); - } catch (error) { - console.error(error); + } catch (err) { + console.error(err); errorComputingTokenBalance = true; } finally { computingTokenBalance = false; diff --git a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte index a95f2fcb20f..007d288f5ad 100644 --- a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte +++ b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte @@ -56,8 +56,8 @@ try { await switchNetwork({ chainId: chain.id }); closeModal(); - } catch (error) { - console.error(error); + } catch (err) { + console.error(err); if (error instanceof UserRejectedRequestError) { warningToast($t('messages.network.rejected')); diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index c1348c80eb3..b69cb192642 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -31,8 +31,8 @@ try { await switchNetwork({ chainId: +PUBLIC_L1_CHAIN_ID }); - } catch (error) { - console.error(error); + } catch (err) { + console.error(err); if (error instanceof UserRejectedRequestError) { warningToast($t('messages.network.rejected')); @@ -70,8 +70,8 @@ ); // TODO: pending transaction logic - } catch (error) { - console.error(error); + } catch (err) { + console.error(err); // const { cause } = error as Error; } finally { @@ -100,8 +100,8 @@ try { await checkMintable(token, network); mintButtonEnabled = true; - } catch (error) { - console.error(error); + } catch (err) { + console.error(err); const { cause } = error as Error; From 3a84b4fd726147ee142dc64362fc10789ebb3cf7 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 00:41:31 +0200 Subject: [PATCH 02/67] wip --- packages/bridge-ui-v2/src/app.config.ts | 4 + .../Bridge/AmountInput/AmountInput.svelte | 15 ++++ .../src/components/Bridge/state.ts | 7 +- .../bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 78 +++++++++++++++++++ .../bridge-ui-v2/src/libs/bridge/types.ts | 71 +++++++++++++++++ 5 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts create mode 100644 packages/bridge-ui-v2/src/libs/bridge/types.ts diff --git a/packages/bridge-ui-v2/src/app.config.ts b/packages/bridge-ui-v2/src/app.config.ts index 5584560c844..cc0e4c917ee 100644 --- a/packages/bridge-ui-v2/src/app.config.ts +++ b/packages/bridge-ui-v2/src/app.config.ts @@ -8,3 +8,7 @@ export const processingFeeComponent = { closingDelayOptionClick: 300, intervalComputeRecommendedFee: 20000, }; + +export const bridge = { + nonOwnerGasLimit: BigInt(140000), +}; diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index d2cd50a02cc..0db5dbb8d4d 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -1,12 +1,26 @@
@@ -20,6 +34,7 @@ type="number" placeholder="0.01" min="0" + on:input={updateAmount} class="w-full input-box outline-none py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content" />
diff --git a/packages/bridge-ui-v2/src/components/Bridge/state.ts b/packages/bridge-ui-v2/src/components/Bridge/state.ts index 834e1045738..63435098002 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/state.ts +++ b/packages/bridge-ui-v2/src/components/Bridge/state.ts @@ -12,6 +12,7 @@ import type { Token } from '$libs/token'; // but once again, we don't need such level of security that we have to // prevent other components outside the Bridge from accessing this store. -export const selectedToken = writable>(); -export const destNetwork = writable>(); -export const processingFee = writable(); +export const selectedToken = writable>(null); +export const enteredAmount = writable(BigInt(0)); +export const destNetwork = writable>(null); +export const processingFee = writable(BigInt(0)); diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts new file mode 100644 index 00000000000..e163be6fabf --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -0,0 +1,78 @@ +import { getContract } from '@wagmi/core'; + +import { bridgeABI } from '$abi'; +import { bridge } from '$config'; +import { getLogger } from '$libs/util/logger'; + +import type { ETHBridgeArgs, Message } from './types'; + +const log = getLogger('ETHBridge'); + +export class ETHBridge { + private static async _prepareTransaction(args: ETHBridgeArgs) { + const { to, memo = '', amount, srcChainId, destChainId, walletClient, bridgeAddress, processingFee } = args; + + const bridgeContract = getContract({ + walletClient, + abi: bridgeABI, + address: bridgeAddress, + }); + + const owner = walletClient.account.address; + + // TODO: contract actually supports bridging to ourselves as well as + // to another address at the same time + const [depositValue, callValue] = + to.toLowerCase() === owner.toLowerCase() ? [amount, BigInt(0)] : [BigInt(0), amount]; + + const gasLimit = processingFee > 0 ? bridge.nonOwnerGasLimit : BigInt(0); + + const message: Message = { + to, + owner, + sender: owner, + refundAddress: owner, + + srcChainId, + destChainId, + + gasLimit, + callValue, + depositValue, + processingFee, + + memo, + data: '0x', + }; + + log('Preparing transaction with message', message); + + return { bridgeContract, owner, message }; + } + + // async estimateGas(args: ): Promise { + // const { contract, message } = await ETHBridge._prepareTransaction(opts); + + // const value = message.depositValue + // .add(message.processingFee) + // .add(message.callValue); + + // log(`Estimating gas for sendMessage. Value to send: ${value}`); + + // try { + // // See https://docs.ethers.org/v5/api/contract/contract/#contract-estimateGas + // const gasEstimate = await contract.estimateGas.sendMessage(message, { + // value, + // }); + + // log('Estimated gas', gasEstimate.toString()); + + // return gasEstimate; + // } catch (error) { + // console.error(error); + // throw new Error('failed to estimate gas for sendMessage', { + // cause: error, + // }); + // } + // } +} diff --git a/packages/bridge-ui-v2/src/libs/bridge/types.ts b/packages/bridge-ui-v2/src/libs/bridge/types.ts new file mode 100644 index 00000000000..b10399d153d --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/types.ts @@ -0,0 +1,71 @@ +import type { WalletClient } from '@wagmi/core'; +import type { Address } from 'abitype'; + +export enum BridgeType { + ETH = 'ETH', + + // https://ethereum.org/en/developers/docs/standards/tokens/erc-20/ + ERC20 = 'ERC20', + + // https://ethereum.org/en/developers/docs/standards/tokens/erc-721/ + ERC721 = 'ERC721', + + // https://ethereum.org/en/developers/docs/standards/tokens/erc-1155/ + ERC1155 = 'ERC1155', +} + +export type Message = { + // Message sender address (auto filled) + sender: Address; + // Source chain ID (auto filled) + srcChainId: number; + // Destination chain ID where the `to` address lives (auto filled) + destChainId: number; + // Owner address of the bridged asset. + owner: Address; + // Destination owner address + to: Address; + // Alternate address to send any refund. If blank, defaults to owner. + refundAddress: Address; + // Deposited Ether minus the processingFee. + depositValue: bigint; + // callValue to invoke on the destination chain, for ERC20 transfers. + callValue: bigint; + // Processing fee for the relayer. Zero if owner will process themself. + processingFee: bigint; + // gasLimit to invoke on the destination chain, for ERC20 transfers. + gasLimit: bigint; + // Message ID. Will be set in contract + id?: number; + // callData to invoke on the destination chain, for ERC20 transfers. + data?: string; + // Optional memo. + memo?: string; +}; + +export type ApproveArgs = { + amount: bigint; + tokenAddress: Address; + spenderAddress: Address; + walletClient: WalletClient; +}; + +export type BridgeArgs = { + to: Address; + srcChainId: number; + destChainId: number; + amount: bigint; + walletClient: WalletClient; + processingFee: bigint; + memo?: string; +}; + +export type ETHBridgeArgs = BridgeArgs & { + bridgeAddress: Address; +}; + +export type ERC20BridgeArgs = BridgeArgs & { + tokenAddress: Address; + tokenVaultAddress: Address; + isBridgedTokenAlreadyDeployed?: boolean; +}; From 82d6d88068d02fc6b3ea469c6ca44944427342a6 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 08:02:40 +0200 Subject: [PATCH 03/67] wip --- packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index e163be6fabf..895dd88780e 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -25,6 +25,7 @@ export class ETHBridge { const [depositValue, callValue] = to.toLowerCase() === owner.toLowerCase() ? [amount, BigInt(0)] : [BigInt(0), amount]; + // If there is a processing fee const gasLimit = processingFee > 0 ? bridge.nonOwnerGasLimit : BigInt(0); const message: Message = { From 8adfaeaedfc8dfa6619aef331488ad7327036c8e Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 10:58:37 +0200 Subject: [PATCH 04/67] wip --- packages/bridge-ui-v2/src/app.config.ts | 3 +- .../Bridge/AmountInput/AmountInput.svelte | 11 +++- .../Bridge/AmountInput/Balance.svelte | 7 ++- .../Bridge/ProcessingFee/NoneOption.svelte | 2 +- .../src/components/Faucet/Faucet.svelte | 10 ++-- .../src/libs/bridge/ERC20Bridge.ts | 59 +++++++++++++++++++ .../bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 38 +++--------- .../bridge-ui-v2/src/libs/bridge/types.ts | 27 ++++++--- .../bridge-ui-v2/src/libs/chain/chains.ts | 3 +- .../bridge-ui-v2/src/libs/token/getBalance.ts | 3 +- packages/bridge-ui-v2/src/libs/token/types.ts | 2 +- 11 files changed, 112 insertions(+), 53 deletions(-) create mode 100644 packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts diff --git a/packages/bridge-ui-v2/src/app.config.ts b/packages/bridge-ui-v2/src/app.config.ts index cc0e4c917ee..0c49606a95c 100644 --- a/packages/bridge-ui-v2/src/app.config.ts +++ b/packages/bridge-ui-v2/src/app.config.ts @@ -10,5 +10,6 @@ export const processingFeeComponent = { }; export const bridge = { - nonOwnerGasLimit: BigInt(140000), + noOwnerGasLimit: BigInt(140000), + noTokenDeployedGasLimit: BigInt(3000000), }; diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index 0db5dbb8d4d..03a74586c3a 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -1,14 +1,19 @@
- +
; + export let value: Maybe; + let computingTokenBalance = false; let errorComputingTokenBalance = false; @@ -21,7 +22,7 @@ errorComputingTokenBalance = false; try { - tokenBalance = await getTokenBalance({ + value = await getTokenBalance({ token, destChainId, userAddress: account.address, @@ -50,7 +51,7 @@ {:else} - {renderTokenBalance(tokenBalance)} + {renderTokenBalance(value)} {/if}
diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte index fb5dbd614f8..99af71c167a 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte @@ -1,5 +1,5 @@
diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 1aa4751af24..4e95732bad3 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -49,15 +49,11 @@ // A token and a source chain must be selected in order to be able to mint if (!selectedToken || !$network) return; - // ... and of course, our wallet must be connected - const walletClient = await getWalletClient(); - if (!walletClient) return; - // Let's begin the minting process minting = true; try { - const txHash = await mint(selectedToken, walletClient); + const txHash = await mint(selectedToken); successToast( $t('faucet.minting_tx', { @@ -98,7 +94,7 @@ reasonNotMintable = ''; try { - await checkMintable(token, network); + await checkMintable(token, network.id); mintButtonEnabled = true; } catch (err) { console.error(err); diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index eabb0154f28..9ac7401e892 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -4,11 +4,11 @@ import { bridgeABI, tokenVaultABI } from '$abi'; import { bridge } from '$config'; import { getLogger } from '$libs/util/logger'; -import type { ERC20BridgeArgs, Message, SendERC20Args } from './types'; +import type { Bridge, ERC20BridgeArgs, SendERC20Args } from './types'; const log = getLogger('ERC20Bridge'); -export class ERC20Bridge { +export class ERC20Bridge implements Bridge { private static async _prepareTransaction(args: ERC20BridgeArgs) { const { to, @@ -28,7 +28,7 @@ export class ERC20Bridge { address: tokenVaultAddress, }); - const refundAddress = walletClient.account.address + const refundAddress = walletClient.account.address; const gasLimit = !isTokenAlreadyDeployed ? BigInt(bridge.noTokenDeployedGasLimit) @@ -52,7 +52,7 @@ export class ERC20Bridge { return { tokenVaultContract, sendERC20Args }; } - static async estimateGas(args: ERC20BridgeArgs): Promise { + async estimateGas(args: ERC20BridgeArgs): Promise { const { tokenVaultContract, sendERC20Args } = await ERC20Bridge._prepareTransaction(args); return tokenVaultContract.estimateGas.sendERC20([...sendERC20Args]); } diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index 3225d9028dc..db8bb2fbe0c 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -4,11 +4,11 @@ import { bridgeABI } from '$abi'; import { bridge } from '$config'; import { getLogger } from '$libs/util/logger'; -import type { ETHBridgeArgs, Message } from './types'; +import type { Bridge, ETHBridgeArgs, Message } from './types'; const log = getLogger('ETHBridge'); -export class ETHBridge { +export class ETHBridge implements Bridge { private static async _prepareTransaction(args: ETHBridgeArgs) { const { to, memo = '', amount, srcChainId, destChainId, walletClient, bridgeAddress, processingFee } = args; @@ -52,7 +52,7 @@ export class ETHBridge { return { bridgeContract, message }; } - static async estimateGas(args: ETHBridgeArgs): Promise { + async estimateGas(args: ETHBridgeArgs): Promise { const { bridgeContract, message } = await ETHBridge._prepareTransaction(args); return bridgeContract.estimateGas.sendMessage([message]); } diff --git a/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts new file mode 100644 index 00000000000..1e5e8a6dd41 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts @@ -0,0 +1,30 @@ +import { getPublicClient, getWalletClient } from '@wagmi/core'; + +import { ETHBridge } from './ETHBridge'; +import type { Bridge, BridgeArgs } from './types'; + +export async function hasEnoughBalanceToBridge(bridge: Bridge, bridgeArgs: BridgeArgs) { + const walletClient = await getWalletClient(); + if (!walletClient) { + throw Error('wallet is not connected'); + } + + const userAddress = walletClient.account.address; + const publicClient = getPublicClient(); + + // Calculate the estimated cost of bridging + const estimatedGas = await bridge.estimateGas(bridgeArgs); + const gasPrice = await publicClient.getGasPrice(); + const estimatedCost = estimatedGas * gasPrice; + + const userBalance = await publicClient.getBalance({ address: userAddress }); + + let balanceAvailable = userBalance; + + if (bridge instanceof ETHBridge) { + // If it's ETH, we need to subtract the amount we're trying to bridge + balanceAvailable = userBalance - bridgeArgs.amount; + } + + return balanceAvailable > estimatedCost; +} diff --git a/packages/bridge-ui-v2/src/libs/bridge/index.ts b/packages/bridge-ui-v2/src/libs/bridge/index.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/bridge-ui-v2/src/libs/bridge/types.ts b/packages/bridge-ui-v2/src/libs/bridge/types.ts index 76d5f910922..f303e7578b6 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/types.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/types.ts @@ -46,14 +46,14 @@ export type Message = { // TokenVault sendERC20(...args) export type SendERC20Args = [ - bigint, // destChainId - Address, // to - Address, // token - bigint, // amount - bigint, // gasLimit - bigint, // processingFee - Address, // refundAddress - string, // memo + bigint, // destChainId + Address, // to + Address, // token + bigint, // amount + bigint, // gasLimit + bigint, // processingFee + Address, // refundAddress + string, // memo ]; // TODO: future sendToken(op: BridgeTransferOp) @@ -94,3 +94,7 @@ export type ERC20BridgeArgs = BridgeArgs & { tokenVaultAddress: Address; isTokenAlreadyDeployed?: boolean; }; + +export interface Bridge { + estimateGas(args: BridgeArgs): Promise; +} diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts index 3066604fa6c..146c490a1f0 100644 --- a/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts +++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts @@ -45,16 +45,20 @@ describe('checkMintable', () => { vi.mocked(getPublicClient).mockReturnValue(mockPublicClient); }); + beforeEach(() => { + vi.clearAllMocks(); + }); + it('should throw when wallet is not connected', async () => { vi.mocked(getWalletClient).mockResolvedValueOnce(null); try { - await checkMintable(BLLToken, mainnetChain); + await checkMintable(BLLToken, mainnetChain.id); expect.fail('should have thrown'); } catch (error) { const { cause } = error as Error; expect(cause).toBe(MintableError.NOT_CONNECTED); - expect(getWalletClient).toHaveBeenCalledWith({ chainId: mainnetChain.id }); + expect(getWalletClient).toHaveBeenCalled(); } }); @@ -62,7 +66,7 @@ describe('checkMintable', () => { vi.mocked(mockTokenContract.read.minters).mockResolvedValueOnce(true); try { - await checkMintable(BLLToken, mainnetChain); + await checkMintable(BLLToken, mainnetChain.id); expect.fail('should have thrown'); } catch (error) { const { cause } = error as Error; @@ -91,7 +95,7 @@ describe('checkMintable', () => { vi.mocked(mockPublicClient.getBalance).mockResolvedValueOnce(BigInt(100)); try { - await checkMintable(BLLToken, mainnetChain); + await checkMintable(BLLToken, mainnetChain.id); expect.fail('should have thrown'); } catch (error) { const { cause } = error as Error; @@ -117,7 +121,7 @@ describe('checkMintable', () => { vi.mocked(mockPublicClient.getBalance).mockResolvedValueOnce(BigInt(300)); try { - await checkMintable(BLLToken, mainnetChain); + await checkMintable(BLLToken, mainnetChain.id); } catch (error) { expect.fail('should not have thrown'); } diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts index 848de485316..5e78890bb24 100644 --- a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts +++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts @@ -6,15 +6,13 @@ import { freeMintErc20ABI } from '$abi'; import { MintableError, type Token } from './types'; // Throws an error if: -// 1. User is not connected to the network +// 1. Wallet is not connected // 2. User has already minted this token // 3. User has insufficient balance to mint this token -export async function checkMintable(token: Token, network: Chain) { - const chainId = network.id; - const walletClient = await getWalletClient({ chainId }); - +export async function checkMintable(token: Token, chainId: number) { + const walletClient = await getWalletClient(); if (!walletClient) { - throw Error(`user is not connected to ${network.name}`, { cause: MintableError.NOT_CONNECTED }); + throw Error(`wallet is not connected`, { cause: MintableError.NOT_CONNECTED }); } const tokenContract = getContract({ @@ -28,12 +26,13 @@ export async function checkMintable(token: Token, network: Chain) { const hasMinted = await tokenContract.read.minters([userAddress]); if (hasMinted) { - throw Error(`token ${token.symbol} has already been minted`, { cause: MintableError.TOKEN_MINTED }); + throw Error(`token already minted`, { cause: MintableError.TOKEN_MINTED }); } // Check whether the user has enough balance to mint. // Compute the cost of the transaction: - const publicClient = getPublicClient({ chainId }); + const publicClient = getPublicClient(); + const estimatedGas = await tokenContract.estimateGas.mint([userAddress]); const gasPrice = await publicClient.getGasPrice(); const estimatedCost = estimatedGas * gasPrice; @@ -41,7 +40,7 @@ export async function checkMintable(token: Token, network: Chain) { const userBalance = await publicClient.getBalance({ address: userAddress }); if (estimatedCost > userBalance) { - throw Error(`user has insufficient balance to mint ${token.symbol}: ${formatEther(userBalance)}`, { + throw Error('user has insufficient balance', { cause: MintableError.INSUFFICIENT_BALANCE, }); } diff --git a/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts b/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts index a6846bb2be6..7b9d00d2e70 100644 --- a/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts +++ b/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts @@ -68,7 +68,6 @@ describe('getBalance', () => { }); expect(fetchBalance).toHaveBeenCalledWith({ address: mockWalletClient.account.address, - chainId: Number(PUBLIC_L1_CHAIN_ID), token: BLLToken.addresses[PUBLIC_L1_CHAIN_ID], }); }); diff --git a/packages/bridge-ui-v2/src/libs/token/getBalance.ts b/packages/bridge-ui-v2/src/libs/token/getBalance.ts index d09257cecdb..f4715362bd5 100644 --- a/packages/bridge-ui-v2/src/libs/token/getBalance.ts +++ b/packages/bridge-ui-v2/src/libs/token/getBalance.ts @@ -20,7 +20,7 @@ export async function getBalance({ token, userAddress, chainId, destChainId }: G let tokenBalance: FetchBalanceResult | null = null; if (isETH(token)) { - tokenBalance = await fetchBalance({ address: userAddress, chainId }); + tokenBalance = await fetchBalance({ address: userAddress }); } else { // We are dealing with an ERC20 token. We need to first find out its address // on the current chain in order to fetch the balance. @@ -31,7 +31,6 @@ export async function getBalance({ token, userAddress, chainId, destChainId }: G // Wagmi is such an amazing library. We had to do this // more manually before. tokenBalance = await fetchBalance({ - chainId, address: userAddress, token: tokenAddress, }); diff --git a/packages/bridge-ui-v2/src/libs/token/mint.ts b/packages/bridge-ui-v2/src/libs/token/mint.ts index cfd35b3b331..302d1ab0c1e 100644 --- a/packages/bridge-ui-v2/src/libs/token/mint.ts +++ b/packages/bridge-ui-v2/src/libs/token/mint.ts @@ -1,4 +1,4 @@ -import { getContract, type WalletClient } from '@wagmi/core'; +import { getContract, getWalletClient, type WalletClient } from '@wagmi/core'; import { freeMintErc20ABI } from '$abi'; @@ -7,7 +7,12 @@ import type { Token } from './types'; const log = getLogger('token:mint'); -export async function mint(token: Token, walletClient: WalletClient) { +export async function mint(token: Token) { + const walletClient = await getWalletClient(); + if (!walletClient) { + throw Error('wallet is not connected'); + } + const tokenSymbol = token.symbol; const userAddress = walletClient.account.address; const chainId = walletClient.chain.id; From ccd044bac4c351290f7f276893eceb3090daa831 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 14:54:44 +0200 Subject: [PATCH 07/67] max button --- packages/bridge-ui-v2/src/app.config.ts | 4 + .../Bridge/AmountInput/AmountInput.svelte | 86 +++++++++++++++++-- .../Bridge/ProcessingFee/ProcessingFee.svelte | 20 ++--- .../src/components/Faucet/Faucet.svelte | 2 +- .../src/components/InputBox/InputBox.svelte | 11 ++- .../src/libs/bridge/ERC1155Bridge.ts | 7 ++ .../src/libs/bridge/ERC20Bridge.ts | 10 ++- .../src/libs/bridge/ERC721Bridge.ts | 7 ++ .../bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 15 +++- .../bridge-ui-v2/src/libs/bridge/bridges.ts | 12 +++ .../src/libs/bridge/estimateCostOfBridging.ts | 12 +++ .../libs/bridge/hasEnoughBalanceToBridge.ts | 22 ++--- .../bridge-ui-v2/src/libs/bridge/index.ts | 2 + .../src/libs/bridge/maxAmountToBridge | 0 .../bridge-ui-v2/src/libs/bridge/types.ts | 2 - .../src/libs/token/checkMintable.ts | 9 +- packages/bridge-ui-v2/src/libs/token/mint.ts | 8 +- .../bridge-ui-v2/src/libs/util/getWallet.ts | 11 +++ .../src/libs/util/truncateDecimal.ts | 4 + 19 files changed, 188 insertions(+), 56 deletions(-) create mode 100644 packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts create mode 100644 packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts create mode 100644 packages/bridge-ui-v2/src/libs/bridge/bridges.ts create mode 100644 packages/bridge-ui-v2/src/libs/bridge/estimateCostOfBridging.ts create mode 100644 packages/bridge-ui-v2/src/libs/bridge/maxAmountToBridge create mode 100644 packages/bridge-ui-v2/src/libs/util/getWallet.ts create mode 100644 packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts diff --git a/packages/bridge-ui-v2/src/app.config.ts b/packages/bridge-ui-v2/src/app.config.ts index 0c49606a95c..398f621f63d 100644 --- a/packages/bridge-ui-v2/src/app.config.ts +++ b/packages/bridge-ui-v2/src/app.config.ts @@ -13,3 +13,7 @@ export const bridge = { noOwnerGasLimit: BigInt(140000), noTokenDeployedGasLimit: BigInt(3000000), }; + +export const amountInputComponent = { + estimatedCostBridging: BigInt(136000000) +} diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index a570b32d1d8..975fc7abf3f 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -1,19 +1,28 @@
@@ -45,8 +108,15 @@ type="number" placeholder="0.01" min="0" + loading={computingMaxETH} on:input={updateAmount} + bind:this={inputBox} class="w-full input-box outline-none py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content" /> - +
diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte index 18b8fcb0994..47dc3807f93 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte @@ -29,7 +29,7 @@ let errorCalculatingEnoughEth = false; let modalOpen = false; - let customInput: InputBox; + let inputBox: InputBox; function closeModal() { // Let's check if we are closing with CUSTOM method selected and zero amount entered @@ -51,11 +51,11 @@ setTimeout(closeModal, processingFeeComponent.closingDelayOptionClick); } - function focusCustomInput() { - customInput?.focus(); + function focusInputBox() { + inputBox.focus(); } - function onCustomInputChange(event: Event) { + function onInputBoxChange(event: Event) { if (selectedFeeMethod !== ProcessingFeeMethod.CUSTOM) return; const input = event.target as HTMLInputElement; @@ -66,20 +66,20 @@ switch (method) { case ProcessingFeeMethod.RECOMMENDED: $processingFee = recommendedAmount; - customInput?.clear(); + inputBox?.clear(); break; case ProcessingFeeMethod.CUSTOM: // Get a previous value entered if exists, otherwise default to 0 - $processingFee = parseToWei(customInput?.value()); + $processingFee = parseToWei(inputBox?.getValue()); // We need to wait for Svelte to set the attribute `disabled` on the input // to false to be able to focus it - tick().then(focusCustomInput); + tick().then(focusInputBox); break; case ProcessingFeeMethod.NONE: $processingFee = BigInt(0); - customInput?.clear(); + inputBox?.clear(); break; } @@ -214,8 +214,8 @@ placeholder="0.01" disabled={selectedFeeMethod !== ProcessingFeeMethod.CUSTOM} class="w-full input-box outline-none p-6 pr-16 title-subsection-bold placeholder:text-tertiary-content" - on:input={onCustomInputChange} - bind:this={customInput} /> + on:input={onInputBoxChange} + bind:this={inputBox} /> ETH
diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 4e95732bad3..31380fc82c7 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -1,5 +1,5 @@ - + diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts new file mode 100644 index 00000000000..ddad81ecab1 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts @@ -0,0 +1,7 @@ +import type { Bridge } from './types'; + +export class ERC1155Bridge implements Bridge { + async estimateGas(): Promise { + return Promise.resolve(BigInt(0)); + } +} diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index 9ac7401e892..06adac8d72f 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -1,7 +1,8 @@ -import { getContract } from '@wagmi/core'; +import { getContract, getWalletClient } from '@wagmi/core'; -import { bridgeABI, tokenVaultABI } from '$abi'; +import { tokenVaultABI } from '$abi'; import { bridge } from '$config'; +import { getConnectedWallet } from '$libs/util/getWallet'; import { getLogger } from '$libs/util/logger'; import type { Bridge, ERC20BridgeArgs, SendERC20Args } from './types'; @@ -10,12 +11,13 @@ const log = getLogger('ERC20Bridge'); export class ERC20Bridge implements Bridge { private static async _prepareTransaction(args: ERC20BridgeArgs) { + const walletClient = await getConnectedWallet(); + const { to, memo = '', amount, destChainId, - walletClient, tokenAddress, processingFee, tokenVaultAddress, @@ -52,7 +54,7 @@ export class ERC20Bridge implements Bridge { return { tokenVaultContract, sendERC20Args }; } - async estimateGas(args: ERC20BridgeArgs): Promise { + async estimateGas(args: ERC20BridgeArgs) { const { tokenVaultContract, sendERC20Args } = await ERC20Bridge._prepareTransaction(args); return tokenVaultContract.estimateGas.sendERC20([...sendERC20Args]); } diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts new file mode 100644 index 00000000000..a9d03418e55 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts @@ -0,0 +1,7 @@ +import type { Bridge } from './types'; + +export class ERC721Bridge implements Bridge { + async estimateGas(): Promise { + return Promise.resolve(BigInt(0)); + } +} diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index db8bb2fbe0c..cb09d6aba25 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -2,6 +2,7 @@ import { getContract } from '@wagmi/core'; import { bridgeABI } from '$abi'; import { bridge } from '$config'; +import { getConnectedWallet } from '$libs/util/getWallet'; import { getLogger } from '$libs/util/logger'; import type { Bridge, ETHBridgeArgs, Message } from './types'; @@ -10,7 +11,9 @@ const log = getLogger('ETHBridge'); export class ETHBridge implements Bridge { private static async _prepareTransaction(args: ETHBridgeArgs) { - const { to, memo = '', amount, srcChainId, destChainId, walletClient, bridgeAddress, processingFee } = args; + const walletClient = await getConnectedWallet(); + + const { to, memo = '', amount, srcChainId, destChainId, bridgeAddress, processingFee } = args; const bridgeContract = getContract({ walletClient, @@ -52,8 +55,14 @@ export class ETHBridge implements Bridge { return { bridgeContract, message }; } - async estimateGas(args: ETHBridgeArgs): Promise { + async estimateGas(args: ETHBridgeArgs) { const { bridgeContract, message } = await ETHBridge._prepareTransaction(args); - return bridgeContract.estimateGas.sendMessage([message]); + const { depositValue, callValue, processingFee } = message; + + const value = depositValue + callValue + processingFee; + + log('Estimating gas for sendMessage call. Sending value', value); + + return bridgeContract.estimateGas.sendMessage([message], { value }); } } diff --git a/packages/bridge-ui-v2/src/libs/bridge/bridges.ts b/packages/bridge-ui-v2/src/libs/bridge/bridges.ts new file mode 100644 index 00000000000..8eefde0a6dd --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/bridges.ts @@ -0,0 +1,12 @@ +import { ERC20Bridge } from './ERC20Bridge'; +import { ERC721Bridge } from './ERC721Bridge'; +import { ERC1155Bridge } from './ERC1155Bridge'; +import { ETHBridge } from './ETHBridge'; +import type { Bridge, BridgeType } from './types'; + +export const bridges: Record = { + ETH: new ETHBridge(), + ERC20: new ERC20Bridge(), + ERC721: new ERC721Bridge(), + ERC1155: new ERC1155Bridge(), +}; diff --git a/packages/bridge-ui-v2/src/libs/bridge/estimateCostOfBridging.ts b/packages/bridge-ui-v2/src/libs/bridge/estimateCostOfBridging.ts new file mode 100644 index 00000000000..adcb8c81d74 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/estimateCostOfBridging.ts @@ -0,0 +1,12 @@ +import { getPublicClient } from '@wagmi/core'; + +import type { Bridge, BridgeArgs } from './types'; + +export async function estimateCostOfBridging(bridge: Bridge, bridgeArgs: BridgeArgs) { + const publicClient = getPublicClient(); + + // Calculate the estimated cost of bridging + const estimatedGas = await bridge.estimateGas(bridgeArgs); + const gasPrice = await publicClient.getGasPrice(); + return estimatedGas * gasPrice; +} diff --git a/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts index 1e5e8a6dd41..97eb14716e6 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts @@ -1,28 +1,24 @@ -import { getPublicClient, getWalletClient } from '@wagmi/core'; +import { getPublicClient } from '@wagmi/core'; +import { getConnectedWallet } from '$libs/util/getWallet'; + +import { estimateCostOfBridging } from './estimateCostOfBridging'; import { ETHBridge } from './ETHBridge'; import type { Bridge, BridgeArgs } from './types'; export async function hasEnoughBalanceToBridge(bridge: Bridge, bridgeArgs: BridgeArgs) { - const walletClient = await getWalletClient(); - if (!walletClient) { - throw Error('wallet is not connected'); - } + const walletClient = await getConnectedWallet(); - const userAddress = walletClient.account.address; - const publicClient = getPublicClient(); - - // Calculate the estimated cost of bridging - const estimatedGas = await bridge.estimateGas(bridgeArgs); - const gasPrice = await publicClient.getGasPrice(); - const estimatedCost = estimatedGas * gasPrice; + const estimatedCost = await estimateCostOfBridging(bridge, bridgeArgs); + const publicClient = getPublicClient(); + const userAddress = walletClient.account.address; const userBalance = await publicClient.getBalance({ address: userAddress }); let balanceAvailable = userBalance; if (bridge instanceof ETHBridge) { - // If it's ETH, we need to subtract the amount we're trying to bridge + // If dealing with ETH, we need to subtract the amount we're trying to bridge balanceAvailable = userBalance - bridgeArgs.amount; } diff --git a/packages/bridge-ui-v2/src/libs/bridge/index.ts b/packages/bridge-ui-v2/src/libs/bridge/index.ts index e69de29bb2d..12f1eaa2504 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/index.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/index.ts @@ -0,0 +1,2 @@ +export { bridges } from './bridges'; +export { hasEnoughBalanceToBridge } from './hasEnoughBalanceToBridge'; diff --git a/packages/bridge-ui-v2/src/libs/bridge/maxAmountToBridge b/packages/bridge-ui-v2/src/libs/bridge/maxAmountToBridge new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/bridge-ui-v2/src/libs/bridge/types.ts b/packages/bridge-ui-v2/src/libs/bridge/types.ts index f303e7578b6..78f70703849 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/types.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/types.ts @@ -72,7 +72,6 @@ export type ApproveArgs = { amount: bigint; tokenAddress: Address; spenderAddress: Address; - walletClient: WalletClient; }; export type BridgeArgs = { @@ -80,7 +79,6 @@ export type BridgeArgs = { srcChainId: number; destChainId: number; amount: bigint; - walletClient: WalletClient; processingFee: bigint; memo?: string; }; diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts index 5e78890bb24..fb1d63a790b 100644 --- a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts +++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts @@ -1,7 +1,7 @@ -import { type Chain, getContract, getPublicClient, getWalletClient } from '@wagmi/core'; -import { formatEther } from 'viem'; +import { getContract, getPublicClient, getWalletClient } from '@wagmi/core'; import { freeMintErc20ABI } from '$abi'; +import { getConnectedWallet } from '$libs/util/getWallet'; import { MintableError, type Token } from './types'; @@ -10,10 +10,7 @@ import { MintableError, type Token } from './types'; // 2. User has already minted this token // 3. User has insufficient balance to mint this token export async function checkMintable(token: Token, chainId: number) { - const walletClient = await getWalletClient(); - if (!walletClient) { - throw Error(`wallet is not connected`, { cause: MintableError.NOT_CONNECTED }); - } + const walletClient = await getConnectedWallet(); const tokenContract = getContract({ walletClient, diff --git a/packages/bridge-ui-v2/src/libs/token/mint.ts b/packages/bridge-ui-v2/src/libs/token/mint.ts index 302d1ab0c1e..8a20061d1ff 100644 --- a/packages/bridge-ui-v2/src/libs/token/mint.ts +++ b/packages/bridge-ui-v2/src/libs/token/mint.ts @@ -1,6 +1,7 @@ -import { getContract, getWalletClient, type WalletClient } from '@wagmi/core'; +import { getContract, getWalletClient } from '@wagmi/core'; import { freeMintErc20ABI } from '$abi'; +import { getConnectedWallet } from '$libs/util/getWallet'; import { getLogger } from '../util/logger'; import type { Token } from './types'; @@ -8,10 +9,7 @@ import type { Token } from './types'; const log = getLogger('token:mint'); export async function mint(token: Token) { - const walletClient = await getWalletClient(); - if (!walletClient) { - throw Error('wallet is not connected'); - } + const walletClient = await getConnectedWallet(); const tokenSymbol = token.symbol; const userAddress = walletClient.account.address; diff --git a/packages/bridge-ui-v2/src/libs/util/getWallet.ts b/packages/bridge-ui-v2/src/libs/util/getWallet.ts new file mode 100644 index 00000000000..d609ef62344 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/util/getWallet.ts @@ -0,0 +1,11 @@ +import { getWalletClient } from '@wagmi/core'; + +export async function getConnectedWallet() { + const walletClient = await getWalletClient(); + + if (!walletClient) { + throw Error('wallet is not connected'); + } + + return walletClient; +} diff --git a/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts b/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts new file mode 100644 index 00000000000..92b1c8af865 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts @@ -0,0 +1,4 @@ +export function truncateDecimal(num: number, decimalPlaces: number) { + const factor = 10 ** decimalPlaces + return Math.floor(num * factor) / factor +} From 0c49995fbdd0d0d786052dc66445efc0df21624b Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 14:59:46 +0200 Subject: [PATCH 08/67] wip --- packages/bridge-ui-v2/src/app.config.ts | 4 ++-- .../src/components/Bridge/AmountInput/AmountInput.svelte | 2 +- packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts | 2 +- packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/bridge-ui-v2/src/app.config.ts b/packages/bridge-ui-v2/src/app.config.ts index 398f621f63d..36e2e497ccc 100644 --- a/packages/bridge-ui-v2/src/app.config.ts +++ b/packages/bridge-ui-v2/src/app.config.ts @@ -15,5 +15,5 @@ export const bridge = { }; export const amountInputComponent = { - estimatedCostBridging: BigInt(136000000) -} + estimatedCostBridging: BigInt(136000000), +}; diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index 975fc7abf3f..db224e30ade 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -4,6 +4,7 @@ import { formatEther, parseUnits } from 'viem'; import { InputBox } from '$components/InputBox'; + import { amountInputComponent } from '$config'; import { bridges } from '$libs/bridge'; import { estimateCostOfBridging } from '$libs/bridge/estimateCostOfBridging'; import { ETHBridge } from '$libs/bridge/ETHBridge'; @@ -16,7 +17,6 @@ import { destNetwork, enteredAmount, processingFee, selectedToken } from '../state'; import Balance from './Balance.svelte'; - import { amountInputComponent } from '$config'; let inputId = `input-${uid()}`; let tokenBalance: FetchBalanceResult; diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index 06adac8d72f..753d29537c1 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -1,4 +1,4 @@ -import { getContract, getWalletClient } from '@wagmi/core'; +import { getContract } from '@wagmi/core'; import { tokenVaultABI } from '$abi'; import { bridge } from '$config'; diff --git a/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts b/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts index 92b1c8af865..bd3391864cb 100644 --- a/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts +++ b/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts @@ -1,4 +1,4 @@ export function truncateDecimal(num: number, decimalPlaces: number) { - const factor = 10 ** decimalPlaces - return Math.floor(num * factor) / factor + const factor = 10 ** decimalPlaces; + return Math.floor(num * factor) / factor; } From 2908484fb98ccbd5d15427b6047ea4b0be2b6338 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 16:16:20 +0200 Subject: [PATCH 09/67] wip --- packages/bridge-ui-v2/src/app.config.ts | 4 - .../Bridge/AmountInput/AmountInput.svelte | 113 ++++++++---------- .../src/components/InputBox/InputBox.svelte | 2 +- packages/bridge-ui-v2/src/i18n/en.json | 6 +- .../src/libs/bridge/getMaxToBridge.ts | 60 ++++++++++ .../libs/bridge/hasEnoughBalanceToBridge.ts | 11 +- .../bridge-ui-v2/src/libs/bridge/index.ts | 2 + .../src/libs/bridge/maxAmountToBridge | 0 .../src/libs/token/checkMintable.ts | 2 +- packages/bridge-ui-v2/src/libs/token/mint.ts | 2 +- 10 files changed, 125 insertions(+), 77 deletions(-) create mode 100644 packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts delete mode 100644 packages/bridge-ui-v2/src/libs/bridge/maxAmountToBridge diff --git a/packages/bridge-ui-v2/src/app.config.ts b/packages/bridge-ui-v2/src/app.config.ts index 36e2e497ccc..0c49606a95c 100644 --- a/packages/bridge-ui-v2/src/app.config.ts +++ b/packages/bridge-ui-v2/src/app.config.ts @@ -13,7 +13,3 @@ export const bridge = { noOwnerGasLimit: BigInt(140000), noTokenDeployedGasLimit: BigInt(3000000), }; - -export const amountInputComponent = { - estimatedCostBridging: BigInt(136000000), -}; diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index db224e30ade..6ac72fe4eb5 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -4,27 +4,48 @@ import { formatEther, parseUnits } from 'viem'; import { InputBox } from '$components/InputBox'; - import { amountInputComponent } from '$config'; - import { bridges } from '$libs/bridge'; - import { estimateCostOfBridging } from '$libs/bridge/estimateCostOfBridging'; - import { ETHBridge } from '$libs/bridge/ETHBridge'; - import type { ETHBridgeArgs } from '$libs/bridge/types'; - import { chainContractsMap, chains } from '$libs/chain'; - import { ETHToken, isETH, type Token } from '$libs/token'; + import { getMaxToBridge } from '$libs/bridge/getMaxToBridge'; import { uid } from '$libs/util/uid'; import { account } from '$stores/account'; import { network } from '$stores/network'; import { destNetwork, enteredAmount, processingFee, selectedToken } from '../state'; import Balance from './Balance.svelte'; + import { warningToast } from '$components/NotificationToast'; let inputId = `input-${uid()}`; let tokenBalance: FetchBalanceResult; let inputBox: InputBox; - let computingMaxETH = false; + let computingMaxAmount = false; + let errorAmount = false; + + // Handler for when the user leaves the amount input. + // Will inform the users if they have enough balance to bridge + // the amount they entered + async function checkAmount() { + if (!$selectedToken || !$network || !$account?.address) return; + + const maxAmount = await getMaxToBridge({ + token: $selectedToken, + balance: tokenBalance.value, + processingFee: $processingFee, + srcChainId: $network.id, + destChainId: $destNetwork?.id, + userAddress: $account.address, + amount: $enteredAmount, + }); + + if ($enteredAmount > maxAmount) { + errorAmount = true; + } + } + // Handle for when the user changes the amount input. + // Will update the entered amount in the store function updateAmount(event: Event) { + errorAmount = false; + if (!$selectedToken) return; const target = event.target as HTMLInputElement; @@ -41,58 +62,28 @@ $enteredAmount = amount; } + // We call this function when clicking on the "MAX" button async function useMaxAmount() { - if (!$selectedToken || !$network) return; - - if (isETH($selectedToken)) { - computingMaxETH = true; - - try { - // Let's estimate the cost of briding 1 ETH - // and then subtract it from the balance, - // minus the processing fee - - const ethBridge = bridges['ETH']; - const to = $account.address; - const srcChainId = $network.id; - - // If no destination chain is selected, grab another - // chain that's not the connected one - const destChainId = $destNetwork ? $destNetwork.id : chains.find((chain) => chain.id !== srcChainId)?.id; - - const amount = BigInt(1); // whatever amount just to get an estimation - const { bridgeAddress } = chainContractsMap[srcChainId.toString()]; - - const bridgeArgs = { - to, - amount, - srcChainId, - destChainId, - bridgeAddress, - processingFee: $processingFee, - } as ETHBridgeArgs; - - const estimatedCost = await estimateCostOfBridging(ethBridge, bridgeArgs); - const maxAmount = tokenBalance.value - $processingFee - estimatedCost; - - setETHAmount(maxAmount); - } catch (err) { - console.error(err); - - // Unfortunately something happened and we couldn't estimate the cost - // of bridging. Let's substract our own estimation - const maxAmount = tokenBalance.value - $processingFee - amountInputComponent.estimatedCostBridging; - - setETHAmount(maxAmount); - } finally { - computingMaxETH = false; - } - } else { - inputBox.setValue(tokenBalance.formatted); - - // Unfortunately setting the inputbox via API doesn't trigger - // the `input` event, so we need to manually update the amount - $enteredAmount = tokenBalance.value; + if (!$selectedToken || !$network || !$account?.address) return; + + computingMaxAmount = true; + + try { + const maxAmount = await getMaxToBridge({ + token: $selectedToken, + balance: tokenBalance.value, + processingFee: $processingFee, + srcChainId: $network.id, + destChainId: $destNetwork?.id, + userAddress: $account.address, + }); + + setETHAmount(maxAmount); + } catch (err) { + console.error(err); + warningToast($t('amount_input.button.failed_max')); + } finally { + computingMaxAmount = false; } } @@ -108,13 +99,13 @@ type="number" placeholder="0.01" min="0" - loading={computingMaxETH} + loading={computingMaxAmount} on:input={updateAmount} bind:this={inputBox} class="w-full input-box outline-none py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content" /> diff --git a/packages/bridge-ui-v2/src/components/InputBox/InputBox.svelte b/packages/bridge-ui-v2/src/components/InputBox/InputBox.svelte index 7e16595de59..dfeb441ce45 100644 --- a/packages/bridge-ui-v2/src/components/InputBox/InputBox.svelte +++ b/packages/bridge-ui-v2/src/components/InputBox/InputBox.svelte @@ -13,4 +13,4 @@ export const focus = () => input.focus(); - + diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index cc9e3ca9999..d96c75e14f4 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -84,7 +84,11 @@ "amount_input": { "label": "Amount", "balance": "Balance", - "button.max": "Max" + "button.max": "Max", + "button": { + "max": "Max", + "failed_max": "Coult not estimate max amount to bridge." + } }, "chain_selector": { diff --git a/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts new file mode 100644 index 00000000000..bb9f2ce5e82 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts @@ -0,0 +1,60 @@ +import type { Address } from 'viem'; + +import { bridge } from '$config'; +import { chainContractsMap, chains } from '$libs/chain'; +import { isETH, type Token } from '$libs/token'; +import { getLogger } from '$libs/util/logger'; + +import { bridges } from './bridges'; +import { estimateCostOfBridging } from './estimateCostOfBridging'; +import type { ETHBridgeArgs } from './types'; + +type GetMaxToBridgeArgs = { + token: Token; + balance: bigint; + srcChainId: number; + userAddress: Address; + processingFee: bigint; + destChainId?: number; + amount?: bigint; +}; + +const log = getLogger('getMaxToBridge'); + +export async function getMaxToBridge({ + token, + balance, + srcChainId, + userAddress, + processingFee, + destChainId, + amount, +}: GetMaxToBridgeArgs) { + if (isETH(token)) { + const to = userAddress; + const { bridgeAddress } = chainContractsMap[srcChainId.toString()]; + + const bridgeArgs = { + to, + srcChainId, + bridgeAddress, + processingFee, + + // If no amount passed in, use whatever just to get an estimation + amount: amount ?? BigInt(1), + + // If no destination chain is selected, find another chain to estimate + // TODO: we might want to really find a compatible chain to bridge to + destChainId: destChainId ?? chains.find((chain) => chain.id !== srcChainId)?.id, + } as ETHBridgeArgs; + + const estimatedCost = await estimateCostOfBridging(bridges.ETH, bridgeArgs); + + log('Estimated cost of bridging', estimatedCost, 'with argument', bridgeArgs, ); + + return balance - processingFee - estimatedCost; + } + + // For ERC20 tokens, we can bridge the whole balance + return balance; +} diff --git a/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts index 97eb14716e6..7fb713adbcc 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts @@ -1,19 +1,14 @@ -import { getPublicClient } from '@wagmi/core'; - -import { getConnectedWallet } from '$libs/util/getWallet'; +import { type Address, getPublicClient } from '@wagmi/core'; import { estimateCostOfBridging } from './estimateCostOfBridging'; import { ETHBridge } from './ETHBridge'; import type { Bridge, BridgeArgs } from './types'; -export async function hasEnoughBalanceToBridge(bridge: Bridge, bridgeArgs: BridgeArgs) { - const walletClient = await getConnectedWallet(); - +export async function hasEnoughBalanceToBridge(bridge: Bridge, bridgeArgs: BridgeArgs, address: Address) { const estimatedCost = await estimateCostOfBridging(bridge, bridgeArgs); const publicClient = getPublicClient(); - const userAddress = walletClient.account.address; - const userBalance = await publicClient.getBalance({ address: userAddress }); + const userBalance = await publicClient.getBalance({ address }); let balanceAvailable = userBalance; diff --git a/packages/bridge-ui-v2/src/libs/bridge/index.ts b/packages/bridge-ui-v2/src/libs/bridge/index.ts index 12f1eaa2504..7325863e4d3 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/index.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/index.ts @@ -1,2 +1,4 @@ export { bridges } from './bridges'; +export { estimateCostOfBridging } from './estimateCostOfBridging'; export { hasEnoughBalanceToBridge } from './hasEnoughBalanceToBridge'; +export * from './types'; diff --git a/packages/bridge-ui-v2/src/libs/bridge/maxAmountToBridge b/packages/bridge-ui-v2/src/libs/bridge/maxAmountToBridge deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts index fb1d63a790b..2c173659ea2 100644 --- a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts +++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts @@ -1,4 +1,4 @@ -import { getContract, getPublicClient, getWalletClient } from '@wagmi/core'; +import { getContract, getPublicClient } from '@wagmi/core'; import { freeMintErc20ABI } from '$abi'; import { getConnectedWallet } from '$libs/util/getWallet'; diff --git a/packages/bridge-ui-v2/src/libs/token/mint.ts b/packages/bridge-ui-v2/src/libs/token/mint.ts index 8a20061d1ff..c9585583711 100644 --- a/packages/bridge-ui-v2/src/libs/token/mint.ts +++ b/packages/bridge-ui-v2/src/libs/token/mint.ts @@ -1,4 +1,4 @@ -import { getContract, getWalletClient } from '@wagmi/core'; +import { getContract } from '@wagmi/core'; import { freeMintErc20ABI } from '$abi'; import { getConnectedWallet } from '$libs/util/getWallet'; From a222c3fd0ae8498ee49ec97a62028c85f1f0d64a Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 17:34:20 +0200 Subject: [PATCH 10/67] wip --- .../Bridge/AmountInput/AmountInput.svelte | 53 ++++++++++++------- .../src/components/InputBox/InputBox.svelte | 7 +-- .../src/libs/bridge/getMaxToBridge.ts | 3 +- .../bridge-ui-v2/src/libs/util/debounce.ts | 14 +++++ .../bridge-ui-v2/src/styles/components.css | 4 ++ 5 files changed, 57 insertions(+), 24 deletions(-) create mode 100644 packages/bridge-ui-v2/src/libs/util/debounce.ts diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index 6ac72fe4eb5..f1b8fe306b7 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -1,7 +1,7 @@ - + diff --git a/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts index bb9f2ce5e82..66ee66e1df9 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts @@ -45,12 +45,13 @@ export async function getMaxToBridge({ // If no destination chain is selected, find another chain to estimate // TODO: we might want to really find a compatible chain to bridge to + // if we have multiple layers destChainId: destChainId ?? chains.find((chain) => chain.id !== srcChainId)?.id, } as ETHBridgeArgs; const estimatedCost = await estimateCostOfBridging(bridges.ETH, bridgeArgs); - log('Estimated cost of bridging', estimatedCost, 'with argument', bridgeArgs, ); + log('Estimated cost of bridging', estimatedCost, 'with argument', bridgeArgs); return balance - processingFee - estimatedCost; } diff --git a/packages/bridge-ui-v2/src/libs/util/debounce.ts b/packages/bridge-ui-v2/src/libs/util/debounce.ts new file mode 100644 index 00000000000..75cdc862732 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/util/debounce.ts @@ -0,0 +1,14 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function debounce ReturnType>( + callback: T, + timeout: number, +): (...args: Parameters) => void { + let timer: ReturnType; + + return (...args: Parameters) => { + clearTimeout(timer); + timer = setTimeout(() => { + callback(...args); + }, timeout); + }; +} diff --git a/packages/bridge-ui-v2/src/styles/components.css b/packages/bridge-ui-v2/src/styles/components.css index 7b82bbfa2c6..bc172348a8d 100644 --- a/packages/bridge-ui-v2/src/styles/components.css +++ b/packages/bridge-ui-v2/src/styles/components.css @@ -86,6 +86,10 @@ focus:shadow-[0_0_0_3px_#E81899]; } + .input-box.error { + @apply !shadow-[0_0_0_3px_#F15C5D]; + } + /* Separatos */ .h-sep { @apply divider h-[1px] border-divider-border; From 626b9282f3bc64698e190d00f73d6fc4d1a85d9c Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 17:53:14 +0200 Subject: [PATCH 11/67] wip --- .../components/Bridge/AmountInput/AmountInput.svelte | 11 ++++++++++- packages/bridge-ui-v2/src/i18n/en.json | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index f1b8fe306b7..c67ffaba2e0 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -13,6 +13,7 @@ import Balance from './Balance.svelte'; import { warningToast } from '$components/NotificationToast'; import { debounce } from '$libs/util/debounce'; + import Icon from '$components/Icon/Icon.svelte'; let inputId = `input-${uid()}`; let tokenBalance: FetchBalanceResult; @@ -102,6 +103,7 @@ +
+ {#if errorAmount} - BAM!!! + +
+ +
+ {$t('amount_input.error.insufficient_balance')} +
+
{/if} diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index d96c75e14f4..56ab85e6681 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -84,11 +84,11 @@ "amount_input": { "label": "Amount", "balance": "Balance", - "button.max": "Max", "button": { "max": "Max", "failed_max": "Coult not estimate max amount to bridge." - } + }, + "error.insufficient_balance": "Insufficient balance" }, "chain_selector": { From 93ceb18e072e3b3696e61c45644e92f1867a64d1 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 18:35:20 +0200 Subject: [PATCH 12/67] wip --- .../Bridge/AmountInput/AmountInput.svelte | 24 +++++++++++++++---- .../bridge-ui-v2/src/styles/components.css | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index c67ffaba2e0..aeea3fc793b 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -1,7 +1,7 @@
diff --git a/packages/bridge-ui-v2/src/styles/components.css b/packages/bridge-ui-v2/src/styles/components.css index bc172348a8d..839066bb4d9 100644 --- a/packages/bridge-ui-v2/src/styles/components.css +++ b/packages/bridge-ui-v2/src/styles/components.css @@ -83,7 +83,7 @@ /* focus:border-[3px] */ /* focus:border-primary-border-accent */ - focus:shadow-[0_0_0_3px_#E81899]; + focus:!shadow-[0_0_0_3px_#E81899]; } .input-box.error { From 3d9bf59d780ae94835f7c10875fdb2c8a8a920bd Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:18:06 +0200 Subject: [PATCH 13/67] amount input validation --- .../Bridge/AmountInput/AmountInput.svelte | 15 +++++++++++---- .../src/libs/bridge/getMaxToBridge.ts | 1 - 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index aeea3fc793b..1a143cdb150 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -3,17 +3,17 @@ import { t } from 'svelte-i18n'; import { formatEther, parseUnits } from 'viem'; + import Icon from '$components/Icon/Icon.svelte'; import { InputBox } from '$components/InputBox'; + import { warningToast } from '$components/NotificationToast'; import { getMaxToBridge } from '$libs/bridge/getMaxToBridge'; + import { debounce } from '$libs/util/debounce'; import { uid } from '$libs/util/uid'; import { account } from '$stores/account'; import { network } from '$stores/network'; import { destNetwork, enteredAmount, processingFee, selectedToken } from '../state'; import Balance from './Balance.svelte'; - import { warningToast } from '$components/NotificationToast'; - import { debounce } from '$libs/util/debounce'; - import Icon from '$components/Icon/Icon.svelte'; let inputId = `input-${uid()}`; let tokenBalance: FetchBalanceResult; @@ -22,6 +22,9 @@ let computingMaxAmount = false; let errorAmount = false; + // Simple, let's get the max amount to bridge and see if it's less + // than what the user has entered. For ETH, will actually get an error + // when trying to get that max amount, if the user has entered too much ETH async function checkEnteredAmount() { if ( !$selectedToken || @@ -61,6 +64,8 @@ // We want to debounce this function for input events const debouncedCheckEnteredAmount = debounce(checkEnteredAmount, 300); + // Will trigger on input events. We update the entered amount + // and check it's validity function updateAmount(event: Event) { errorAmount = false; @@ -82,7 +87,10 @@ $enteredAmount = amount; } + // Will trigger when the user clicks on the "Max" button async function useMaxAmount() { + errorAmount = false; + if (!$selectedToken || !$network || !$account?.address) return; computingMaxAmount = true; @@ -98,7 +106,6 @@ }); setETHAmount(maxAmount); - checkEnteredAmount(); } catch (err) { console.error(err); warningToast($t('amount_input.button.failed_max')); diff --git a/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts index 66ee66e1df9..041567139a4 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts @@ -1,6 +1,5 @@ import type { Address } from 'viem'; -import { bridge } from '$config'; import { chainContractsMap, chains } from '$libs/chain'; import { isETH, type Token } from '$libs/token'; import { getLogger } from '$libs/util/logger'; From 1be938676fa292543f45b2c197f0502cc3d0cb51 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:21:47 +0200 Subject: [PATCH 14/67] minor change --- packages/bridge-ui-v2/src/libs/bridge/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/libs/bridge/types.ts b/packages/bridge-ui-v2/src/libs/bridge/types.ts index 78f70703849..7dd0f52172c 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/types.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/types.ts @@ -1,4 +1,3 @@ -import type { WalletClient } from '@wagmi/core'; import type { Address, Hex } from 'viem'; export enum BridgeType { From 8d5fbec53a322d5bb1eeb164f532279698fcc589 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:27:13 +0200 Subject: [PATCH 15/67] minor comment --- packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index cb09d6aba25..ddaeaa5437a 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -28,7 +28,8 @@ export class ETHBridge implements Bridge { const [depositValue, callValue] = to.toLowerCase() === owner.toLowerCase() ? [amount, BigInt(0)] : [BigInt(0), amount]; - // If there is a processing fee + // If there is a processing fee, use the specified message gas limit + // if not called by the owner const gasLimit = processingFee > 0 ? bridge.noOwnerGasLimit : BigInt(0); const message: Message = { From 535487433dfbc42b71ca9444acb66563ae0a82b5 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:29:38 +0200 Subject: [PATCH 16/67] minor TODO --- .../src/components/Bridge/AmountInput/AmountInput.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index 1a143cdb150..75f71980857 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -22,7 +22,7 @@ let computingMaxAmount = false; let errorAmount = false; - // Simple, let's get the max amount to bridge and see if it's less + // Let's get the max amount to bridge and see if it's less // than what the user has entered. For ETH, will actually get an error // when trying to get that max amount, if the user has entered too much ETH async function checkEnteredAmount() { @@ -116,6 +116,7 @@ // Let's also trigger the check when either the processingFee or // the selectedToken change and debounce it, just in case + // TODO: better way? maybe store.subscribe(), or different component $: $processingFee && $selectedToken && debouncedCheckEnteredAmount(); From 0be1db3e996b3ff2ef353e876caa0a5ffb9b6c0f Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:36:38 +0200 Subject: [PATCH 17/67] fix test --- .../components/ChainSelector/ChainSelector.svelte | 2 +- .../src/libs/token/checkMintable.test.ts | 15 +-------------- .../bridge-ui-v2/src/libs/token/checkMintable.ts | 5 ++--- packages/bridge-ui-v2/src/libs/token/mint.test.ts | 2 +- packages/bridge-ui-v2/src/libs/token/types.ts | 1 - 5 files changed, 5 insertions(+), 20 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte index 007d288f5ad..ae34f6184bd 100644 --- a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte +++ b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte @@ -59,7 +59,7 @@ } catch (err) { console.error(err); - if (error instanceof UserRejectedRequestError) { + if (err instanceof UserRejectedRequestError) { warningToast($t('messages.network.rejected')); } } finally { diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts index 146c490a1f0..503542c036e 100644 --- a/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts +++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts @@ -49,19 +49,6 @@ describe('checkMintable', () => { vi.clearAllMocks(); }); - it('should throw when wallet is not connected', async () => { - vi.mocked(getWalletClient).mockResolvedValueOnce(null); - - try { - await checkMintable(BLLToken, mainnetChain.id); - expect.fail('should have thrown'); - } catch (error) { - const { cause } = error as Error; - expect(cause).toBe(MintableError.NOT_CONNECTED); - expect(getWalletClient).toHaveBeenCalled(); - } - }); - it('should throw when user has already minted', async () => { vi.mocked(mockTokenContract.read.minters).mockResolvedValueOnce(true); @@ -100,7 +87,7 @@ describe('checkMintable', () => { } catch (error) { const { cause } = error as Error; expect(cause).toBe(MintableError.INSUFFICIENT_BALANCE); - expect(getPublicClient).toHaveBeenCalledWith({ chainId: mainnetChain.id }); + expect(getPublicClient).toHaveBeenCalled(); expect(mockTokenContract.estimateGas.mint).toHaveBeenCalledWith([mockWalletClient.account.address]); expect(mockPublicClient.getBalance).toHaveBeenCalledWith({ address: mockWalletClient.account.address }); } diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts index 2c173659ea2..2c91d47a4eb 100644 --- a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts +++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts @@ -6,9 +6,8 @@ import { getConnectedWallet } from '$libs/util/getWallet'; import { MintableError, type Token } from './types'; // Throws an error if: -// 1. Wallet is not connected -// 2. User has already minted this token -// 3. User has insufficient balance to mint this token +// 1. User has already minted this token +// 2. User has insufficient balance to mint this token export async function checkMintable(token: Token, chainId: number) { const walletClient = await getConnectedWallet(); diff --git a/packages/bridge-ui-v2/src/libs/token/mint.test.ts b/packages/bridge-ui-v2/src/libs/token/mint.test.ts index 379c5798d88..2be21d8334d 100644 --- a/packages/bridge-ui-v2/src/libs/token/mint.test.ts +++ b/packages/bridge-ui-v2/src/libs/token/mint.test.ts @@ -28,7 +28,7 @@ describe('mint', () => { vi.mocked(getContract).mockReturnValue(mockTokenContract); vi.mocked(mockTokenContract.write.mint).mockResolvedValue('0x123456'); - await expect(mint(BLLToken, mockWalletClient)).resolves.toEqual('0x123456'); + await expect(mint(BLLToken)).resolves.toEqual('0x123456'); expect(mockTokenContract.write.mint).toHaveBeenCalledWith([mockWalletClient.account.address]); }); }); diff --git a/packages/bridge-ui-v2/src/libs/token/types.ts b/packages/bridge-ui-v2/src/libs/token/types.ts index 5c66fd46aa9..230e5814d1d 100644 --- a/packages/bridge-ui-v2/src/libs/token/types.ts +++ b/packages/bridge-ui-v2/src/libs/token/types.ts @@ -14,7 +14,6 @@ export type TokenEnv = { }; export enum MintableError { - NOT_CONNECTED = 'NOT_CONNECTED', TOKEN_MINTED = 'TOKEN_MINTED', INSUFFICIENT_BALANCE = 'INSUFFICIENT_BALANCE', } From 8e51d03454e5d32588acad145cf45e7db20191a4 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:41:56 +0200 Subject: [PATCH 18/67] remove unnecessary file --- .../libs/bridge/hasEnoughBalanceToBridge.ts | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts diff --git a/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts deleted file mode 100644 index 7fb713adbcc..00000000000 --- a/packages/bridge-ui-v2/src/libs/bridge/hasEnoughBalanceToBridge.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { type Address, getPublicClient } from '@wagmi/core'; - -import { estimateCostOfBridging } from './estimateCostOfBridging'; -import { ETHBridge } from './ETHBridge'; -import type { Bridge, BridgeArgs } from './types'; - -export async function hasEnoughBalanceToBridge(bridge: Bridge, bridgeArgs: BridgeArgs, address: Address) { - const estimatedCost = await estimateCostOfBridging(bridge, bridgeArgs); - - const publicClient = getPublicClient(); - const userBalance = await publicClient.getBalance({ address }); - - let balanceAvailable = userBalance; - - if (bridge instanceof ETHBridge) { - // If dealing with ETH, we need to subtract the amount we're trying to bridge - balanceAvailable = userBalance - bridgeArgs.amount; - } - - return balanceAvailable > estimatedCost; -} From 5780ea5065365756f8288a06e8718a38d9a3a921 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:42:10 +0200 Subject: [PATCH 19/67] fix error --- packages/bridge-ui-v2/src/libs/bridge/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/libs/bridge/index.ts b/packages/bridge-ui-v2/src/libs/bridge/index.ts index 7325863e4d3..5187917dc4b 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/index.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/index.ts @@ -1,4 +1,3 @@ export { bridges } from './bridges'; export { estimateCostOfBridging } from './estimateCostOfBridging'; -export { hasEnoughBalanceToBridge } from './hasEnoughBalanceToBridge'; export * from './types'; From 3ba05aa1a6d953a04cae337ce72e8f74c51bbfd9 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:45:30 +0200 Subject: [PATCH 20/67] fix ts error --- packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 31380fc82c7..2b7e621a568 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -102,9 +102,6 @@ const { cause } = err as Error; switch (cause) { - case MintableError.NOT_CONNECTED: - reasonNotMintable = $t('faucet.warning.no_connected'); - break; case MintableError.INSUFFICIENT_BALANCE: reasonNotMintable = $t('faucet.warning.insufficient_balance'); break; From 9e499647704df9f4f45613eb12f311d6b34c5ad2 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:48:29 +0200 Subject: [PATCH 21/67] fix lint --- packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index ddaeaa5437a..45c54f813a9 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -28,7 +28,7 @@ export class ETHBridge implements Bridge { const [depositValue, callValue] = to.toLowerCase() === owner.toLowerCase() ? [amount, BigInt(0)] : [BigInt(0), amount]; - // If there is a processing fee, use the specified message gas limit + // If there is a processing fee, use the specified message gas limit // if not called by the owner const gasLimit = processingFee > 0 ? bridge.noOwnerGasLimit : BigInt(0); From c1f27b93bf691a8413517b10f5f7c1735bfe4c84 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 19:54:34 +0200 Subject: [PATCH 22/67] minor change --- .../src/components/Bridge/AmountInput/AmountInput.svelte | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index 75f71980857..02e08753648 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -53,8 +53,9 @@ } catch (err) { console.error(err); - // Viem might throw an error that contains the following message, indicating + // Viem will throw an error that contains the following message, indicating // that the user won't have enough to pay the transaction + // TODO: better way to handle this. Error codes? if (`${err}`.toLocaleLowerCase().match('transaction exceeds the balance')) { errorAmount = true; } @@ -128,7 +129,7 @@
Date: Wed, 19 Jul 2023 20:00:53 +0200 Subject: [PATCH 23/67] minor change --- packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index 753d29537c1..e9cca0ff5e5 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -56,6 +56,12 @@ export class ERC20Bridge implements Bridge { async estimateGas(args: ERC20BridgeArgs) { const { tokenVaultContract, sendERC20Args } = await ERC20Bridge._prepareTransaction(args); - return tokenVaultContract.estimateGas.sendERC20([...sendERC20Args]); + const [,,,,,processingFee] = sendERC20Args; + + const value = processingFee; + + log('Estimating gas for sendERC20 call. Sending value', value); + + return tokenVaultContract.estimateGas.sendERC20([...sendERC20Args], { value }); } } From 893b37e959242436bfa0f345f645b256140f964f Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 20:24:59 +0200 Subject: [PATCH 24/67] fix lint --- packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index e9cca0ff5e5..074bc062a27 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -56,7 +56,7 @@ export class ERC20Bridge implements Bridge { async estimateGas(args: ERC20BridgeArgs) { const { tokenVaultContract, sendERC20Args } = await ERC20Bridge._prepareTransaction(args); - const [,,,,,processingFee] = sendERC20Args; + const [, , , , , processingFee] = sendERC20Args; const value = processingFee; From b459d3958555dc088f146ada88acd10d4def3345 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 21:43:22 +0200 Subject: [PATCH 25/67] align to new design --- .../src/components/Bridge/Bridge.svelte | 2 +- .../Bridge/ProcessingFee/ProcessingFee.svelte | 36 +++++++++++++++---- packages/bridge-ui-v2/src/i18n/en.json | 4 +++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 770e2c091a4..b76eba55b09 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -61,7 +61,7 @@
-
diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte index 47dc3807f93..515dc7d000d 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte @@ -16,9 +16,11 @@ import { processingFee } from '../state'; import NoneOption from './NoneOption.svelte'; import RecommendedFee from './RecommendedFee.svelte'; + import { Button } from '$components/Button'; let dialogId = `dialog-${uid()}`; let selectedFeeMethod = ProcessingFeeMethod.RECOMMENDED; + let prevOptionSelected = ProcessingFeeMethod.RECOMMENDED; let recommendedAmount = BigInt(0); let calculatingRecommendedAmount = false; @@ -42,10 +44,20 @@ } function openModal() { + // Keep track of the selected method before opening the modal + // so if we cancel we can go back to the previous method + prevOptionSelected = selectedFeeMethod; + modalOpen = true; } - function closeOnOptionClick() { + function cancelModal() { + inputBox.clear(); + selectedFeeMethod = prevOptionSelected; + closeModalWithDelay(); + } + + function closeModalWithDelay() { // By adding delay there is enough time to see the selected option // before closing the modal. Better experience for the user. setTimeout(closeModal, processingFeeComponent.closingDelayOptionClick); @@ -122,7 +134,7 @@ {/if} - + {#if !hasEnoughEth} @@ -207,7 +219,7 @@ -
+
ETH
+ +
+ + +
diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index 56ab85e6681..3cb29e904c1 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -32,6 +32,10 @@ "custom": { "label": "Custom", "text": "Customize your processing fee" + }, + "button": { + "confirm": "Confirm", + "cancel": "Cancel" } }, From d67cc8eee0977937b61f4796019f7ebf16a9753e Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 19 Jul 2023 21:51:31 +0200 Subject: [PATCH 26/67] minor change --- .../src/components/Bridge/AmountInput/AmountInput.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte index 02e08753648..d9163922f05 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte @@ -138,8 +138,9 @@ on:input={updateAmount} bind:this={inputBox} class="w-full input-box outline-none py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content" /> +
diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte index 515dc7d000d..c7c4ba88ac0 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte @@ -4,6 +4,7 @@ import { formatEther } from 'viem'; import { Alert } from '$components/Alert'; + import { Button } from '$components/Button'; import { Icon } from '$components/Icon'; import { InputBox } from '$components/InputBox'; import { LoadingText } from '$components/LoadingText'; @@ -16,7 +17,6 @@ import { processingFee } from '../state'; import NoneOption from './NoneOption.svelte'; import RecommendedFee from './RecommendedFee.svelte'; - import { Button } from '$components/Button'; let dialogId = `dialog-${uid()}`; let selectedFeeMethod = ProcessingFeeMethod.RECOMMENDED; @@ -54,7 +54,7 @@ function cancelModal() { inputBox.clear(); selectedFeeMethod = prevOptionSelected; - closeModalWithDelay(); + closeModal(); } function closeModalWithDelay() { diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 2b7e621a568..a6fbdc75d07 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -145,7 +145,11 @@ {#if connected && wrongChain} - + +
+ +
diff --git a/packages/bridge-ui-v2/src/components/Bridge/SwitchChainsButton.svelte b/packages/bridge-ui-v2/src/components/Bridge/SwitchChainsButton.svelte index 18af65694e9..4c64c0ad7cd 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/SwitchChainsButton.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/SwitchChainsButton.svelte @@ -27,5 +27,5 @@ class="f-center rounded-full bg-secondary-icon w-[30px] h-[30px]" disabled={!$destNetwork} on:click={switchToDestChain}> - + diff --git a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte index ae34f6184bd..c08ccf8d167 100644 --- a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte +++ b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte @@ -13,7 +13,7 @@ import { uid } from '$libs/util/uid'; import { account } from '$stores/account'; - export let label: string; + export let label: string = ''; export let value: Maybe = null; export let switchWallet = false; export let readOnly = false; @@ -84,7 +84,10 @@
- + {#if label} + + {/if} + +
@@ -236,10 +236,10 @@ on:click={cancelModal} type="neutral" class="px-[28px] py-[10px] rounded-full w-auto bg-transparent !border border-primary-brand hover:border-primary-interactive-hover"> - {$t('processing_fee.button.cancel')} + {$t('common.cancel')}
diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte index 8f3e929b613..d95c9f4c189 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte @@ -1,28 +1,89 @@ - -
+
- Recipient address - TODO: add description about custom recipient + {$t('recipient.title')} + TODO: add description about processing fee
- -
-
- +
+ + + {#if $account?.address} + {shortenAddress($account.address, 15, 13)} + {:else} + {$t('recipient.placeholder')} + {/if} + + + + +
diff --git a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte index c08ccf8d167..9c67c41ba49 100644 --- a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte +++ b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte @@ -12,12 +12,15 @@ import { chains } from '$libs/chain'; import { uid } from '$libs/util/uid'; import { account } from '$stores/account'; + import { classNames } from '$libs/util/classNames'; export let label: string = ''; export let value: Maybe = null; export let switchWallet = false; export let readOnly = false; + let classes = classNames('ChainSelector', $$props.class); + let chainToIconMap: Record = { [PUBLIC_L1_CHAIN_ID]: EthIcon, [PUBLIC_L2_CHAIN_ID]: TaikoIcon, @@ -82,7 +85,7 @@ onDestroy(closeModal); -
+
{#if label} @@ -95,9 +98,9 @@ aria-haspopup="dialog" aria-controls={dialogId} aria-expanded={modalOpen} - class="px-2 py-[6px] body-small-regular bg-neutral-background rounded-md min-w-[150px]" + class="px-2 py-[10px] body-small-regular bg-neutral-background rounded-[10px] w-full" on:click={openModal}> -
+
{#if !value} {$t('chain_selector.placeholder')} {/if} diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index af62f785c4b..41ac32a8f95 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -16,6 +16,12 @@ } }, + "recipient": { + "title": "Recipient address", + "link": "Change recipient", + "placeholder": "Add custom recipient" + }, + "processing_fee": { "title": "Processing fee", "link": "Customize fee", @@ -32,10 +38,6 @@ "custom": { "label": "Custom", "text": "Customize your processing fee" - }, - "button": { - "confirm": "Confirm", - "cancel": "Cancel" } }, @@ -103,6 +105,20 @@ "currently_on": "You are currently on" }, + "chain": { + "to": "To", + "from": "From" + }, + + "wallet": { + "connect": "Connect wallet", + "status": { + "disconnected": "Disconnected", + "connected": "Connected", + "connecting": "Connecting" + } + }, + "messages": { "account": { "required": "Please connect your wallet.", @@ -118,21 +134,12 @@ } }, - "chain": { - "to": "To", - "from": "From" - }, - - "custom_recipient": { - "placeholder": "Add custom recipient" - }, - - "wallet": { - "connect": "Connect wallet", - "status": { - "disconnected": "Disconnected", - "connected": "Connected", - "connecting": "Connecting" - } + "common": { + "edit": "Edit", + "cancel": "Cancel", + "confirm": "Confirm", + "close": "Close", + "loading": "Loading", + "ok": "Ok" } } diff --git a/packages/bridge-ui-v2/src/libs/util/shortenAddress.test.ts b/packages/bridge-ui-v2/src/libs/util/shortenAddress.test.ts new file mode 100644 index 00000000000..e7181058e50 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/util/shortenAddress.test.ts @@ -0,0 +1,12 @@ +import { shortenAddress } from './shortenAddress'; + +it('should return string with prefix and suffix', () => { + const dummyAddress = '0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377'; + + expect(shortenAddress(dummyAddress)).toStrictEqual('0x63Fa…D377'); + expect(shortenAddress(dummyAddress, 10, 10)).toStrictEqual('0x63FaC920…52fe3BD377'); +}); + +it('should return 0x if empty', () => { + expect(shortenAddress('')).toBe('0x'); +}); diff --git a/packages/bridge-ui-v2/src/libs/util/shortenAddress.ts b/packages/bridge-ui-v2/src/libs/util/shortenAddress.ts new file mode 100644 index 00000000000..9e48ed36d81 --- /dev/null +++ b/packages/bridge-ui-v2/src/libs/util/shortenAddress.ts @@ -0,0 +1,7 @@ +export const shortenAddress = (address: string, charsStart = 6, charsEnd = 4, sep = '…') => { + if (!address) return '0x'; + return [ + address.slice(0, charsStart), + address.slice(-charsEnd) + ].join(sep) +}; From 6170b73ed20891cc99defe9f6a34f957c2f9cd21 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 20 Jul 2023 23:16:50 +0200 Subject: [PATCH 45/67] add FlatAlert component --- .../src/components/Alert/Alert.svelte | 24 +++---- .../src/components/Alert/FlatAlert.svelte | 47 ++++++++++++ .../src/components/Alert/index.ts | 1 + .../src/components/Alert/types.ts | 8 +++ .../components/Bridge/Amount/Amount.svelte | 71 +++++++++---------- .../Bridge/ProcessingFee/ProcessingFee.svelte | 8 +-- .../Bridge/Recipient/Recipient.svelte | 17 ++++- .../src/components/Bridge/state.ts | 1 + packages/bridge-ui-v2/src/i18n/en.json | 2 +- 9 files changed, 120 insertions(+), 59 deletions(-) create mode 100644 packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte create mode 100644 packages/bridge-ui-v2/src/components/Alert/types.ts diff --git a/packages/bridge-ui-v2/src/components/Alert/Alert.svelte b/packages/bridge-ui-v2/src/components/Alert/Alert.svelte index 8dff979fdfa..13844da0cd9 100644 --- a/packages/bridge-ui-v2/src/components/Alert/Alert.svelte +++ b/packages/bridge-ui-v2/src/components/Alert/Alert.svelte @@ -1,13 +1,11 @@
diff --git a/packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte b/packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte new file mode 100644 index 00000000000..b30a240f83a --- /dev/null +++ b/packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte @@ -0,0 +1,47 @@ + + +
+ +
+ {message} +
+
diff --git a/packages/bridge-ui-v2/src/components/Alert/index.ts b/packages/bridge-ui-v2/src/components/Alert/index.ts index e3f24bb7c75..5d62a66c910 100644 --- a/packages/bridge-ui-v2/src/components/Alert/index.ts +++ b/packages/bridge-ui-v2/src/components/Alert/index.ts @@ -1 +1,2 @@ export { default as Alert } from './Alert.svelte'; +export { default as FlatAlert } from './FlatAlert.svelte'; diff --git a/packages/bridge-ui-v2/src/components/Alert/types.ts b/packages/bridge-ui-v2/src/components/Alert/types.ts new file mode 100644 index 00000000000..67d1c895ef2 --- /dev/null +++ b/packages/bridge-ui-v2/src/components/Alert/types.ts @@ -0,0 +1,8 @@ +import type { IconType } from "$components/Icon"; + +export type AlertType = 'success' | 'warning' | 'error' | 'info'; + +export type AlertIconDetails = { + iconType: IconType; + iconFillClass: string; +}; diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte b/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte index 9775ac28559..5fffd287239 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte @@ -15,6 +15,7 @@ import { destNetwork, enteredAmount, processingFee, selectedToken } from '../state'; import Balance from './Balance.svelte'; + import { FlatAlert } from '$components/Alert'; let inputId = `input-${uid()}`; let tokenBalance: FetchBalanceResult; @@ -73,7 +74,7 @@ // Will trigger on input events. We update the entered amount // and check it's validity - function updateAmount(event: Event) { + function inputAmount(event: Event) { insufficientBalance = false; insufficientAllowance = false; @@ -139,42 +140,36 @@
-
- - - -
- - {#if insufficientBalance} - -
- -
- {$t('amount_input.error.insufficient_balance')} -
-
- {/if} - - {#if insufficientAllowance} -
- -
- {$t('amount_input.error.insufficient_allowance')} -
+
+
+ + +
- {/if} + + {#if insufficientBalance} + + {/if} + + {#if insufficientAllowance} + + {/if} +
diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte index a4c933a8737..902cfd30d8b 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte @@ -67,11 +67,11 @@ inputBox.focus(); } - function onInputBoxChange(event: Event) { + function inputProcessFee(event: Event) { if (selectedFeeMethod !== ProcessingFeeMethod.CUSTOM) return; - const input = event.target as HTMLInputElement; - $processingFee = parseToWei(input.value); + const { value } = event.target as HTMLInputElement; + $processingFee = parseToWei(value); } async function updateProcessingFee(method: ProcessingFeeMethod, recommendedAmount: bigint) { @@ -226,7 +226,7 @@ placeholder="0.01" disabled={selectedFeeMethod !== ProcessingFeeMethod.CUSTOM} class="w-full input-box outline-none p-6 pr-16 title-subsection-bold placeholder:text-tertiary-content" - on:input={onInputBoxChange} + on:input={inputProcessFee} bind:this={inputBox} /> ETH
diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte index d95c9f4c189..896ad8fb786 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte @@ -9,9 +9,14 @@ import { account } from '$stores/account'; import { shortenAddress } from '$libs/util/shortenAddress'; import { onMount } from 'svelte'; + import { recipientAddress } from '../state'; + import { isAddress } from 'viem'; let dialogId = `dialog-${uid()}`; + let modalOpen = false; + let invalidAddress = false; + let inputBox: InputBox; function closeModal() { @@ -31,8 +36,14 @@ inputBox.focus(); } - function onInputBoxChange(event: Event) { - const input = event.target as HTMLInputElement; + function inputRecipientAddress(event: Event) { + const { value } = event.target as HTMLInputElement; + if (isAddress(value)) { + invalidAddress = false; + $recipientAddress = value; + } else { + invalidAddress = true; + } } onMount(focusInputBox); @@ -69,7 +80,7 @@
diff --git a/packages/bridge-ui-v2/src/components/Bridge/state.ts b/packages/bridge-ui-v2/src/components/Bridge/state.ts index 63435098002..93d8eeca003 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/state.ts +++ b/packages/bridge-ui-v2/src/components/Bridge/state.ts @@ -16,3 +16,4 @@ export const selectedToken = writable>(null); export const enteredAmount = writable(BigInt(0)); export const destNetwork = writable>(null); export const processingFee = writable(BigInt(0)); +export const recipientAddress = writable(''); diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index 41ac32a8f95..696c2defdcb 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -19,7 +19,7 @@ "recipient": { "title": "Recipient address", "link": "Change recipient", - "placeholder": "Add custom recipient" + "placeholder": "Add custom recipient 0x…" }, "processing_fee": { From eac90abb9fc08c96862ec4878368757fb8118525 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 21 Jul 2023 11:25:37 +0200 Subject: [PATCH 46/67] recipient address --- .../components/Activities/Activities.svelte | 2 +- .../src/components/Bridge/Bridge.svelte | 2 +- .../Bridge/ProcessingFee/ProcessingFee.svelte | 2 + .../Bridge/Recipient/Recipient.svelte | 39 ++++++++++++++----- .../src/components/Faucet/Faucet.svelte | 2 +- packages/bridge-ui-v2/src/i18n/en.json | 8 ++-- 6 files changed, 40 insertions(+), 15 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Activities/Activities.svelte b/packages/bridge-ui-v2/src/components/Activities/Activities.svelte index 9e3633b7dc4..84c2b8b7123 100644 --- a/packages/bridge-ui-v2/src/components/Activities/Activities.svelte +++ b/packages/bridge-ui-v2/src/components/Activities/Activities.svelte @@ -9,7 +9,7 @@ import TableView from './TableView.svelte'; - +
diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 3ddb27abde3..b2424fd56bb 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -37,7 +37,7 @@ } - +
diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte index 902cfd30d8b..c86d94657f5 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte @@ -142,6 +142,8 @@

{$t('processing_fee.title')}

+

{$t('processing_fee.description')}

+
  • diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte index 896ad8fb786..e58f5e9b9b9 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte @@ -8,7 +8,6 @@ import { Icon } from '$components/Icon'; import { account } from '$stores/account'; import { shortenAddress } from '$libs/util/shortenAddress'; - import { onMount } from 'svelte'; import { recipientAddress } from '../state'; import { isAddress } from 'viem'; @@ -16,6 +15,7 @@ let modalOpen = false; let invalidAddress = false; + let prevRecipientAddress: string = ''; let inputBox: InputBox; @@ -29,15 +29,16 @@ function cancelModal() { inputBox.clear(); - closeModal(); - } - function focusInputBox() { - inputBox.focus(); + // Revert change of recipient address + $recipientAddress = prevRecipientAddress; + + closeModal(); } function inputRecipientAddress(event: Event) { const { value } = event.target as HTMLInputElement; + if (isAddress(value)) { invalidAddress = false; $recipientAddress = value; @@ -46,7 +47,24 @@ } } - onMount(focusInputBox); + function deleteRecipient() { + $recipientAddress = ''; // update state + inputBox.clear(); // update UI + } + + function modalOpenChange(open: boolean) { + if (open) { + // Save it in case we want to cancel + prevRecipientAddress = $recipientAddress; + + inputBox.setValue($recipientAddress); + inputBox.focus(); + } + } + + $: modalOpenChange(modalOpen); + + $: displayedRecipient = $recipientAddress || $account?.address;
    @@ -59,8 +77,8 @@
    - {#if $account?.address} - {shortenAddress($account.address, 15, 13)} + {#if displayedRecipient} + {shortenAddress(displayedRecipient, 15, 13)} {:else} {$t('recipient.placeholder')} {/if} @@ -74,7 +92,7 @@

    {$t('recipient.title')}

    - +

    {$t('recipient.description')}

    +
    diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 95216792d9d..09877bdd543 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -132,7 +132,7 @@ $: updateMintButtonState(selectedToken, $network); - +
    diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index f61a251524b..c5e4b9db9cd 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -9,7 +9,7 @@ "bridge": { "title": "Bridge", - "subtitle": "Send your assets across chains.", + "description": "Send your assets across chains.", "button": { "approve": "Approve", "bridge": "Bridge" @@ -18,12 +18,14 @@ "recipient": { "title": "Recipient address", + "description": "Customize the recipient address for your bridged tokens instead of using your current wallet address.", "link": "Change recipient", "placeholder": "Add custom recipient 0x…" }, "processing_fee": { "title": "Processing fee", + "description": "Some description about the processing fee", "link": "Customize fee", "recommended": { "label": "Recommended", @@ -47,7 +49,7 @@ "activities": { "title": "Activities", - "subtitle": "Track your bridge transactions here.", + "description": "Track your bridge transactions here.", "header": { "explorer": "Explorer link", "status": "Status" @@ -69,7 +71,7 @@ "faucet": { "title": "Faucet", - "subtitle": "Mint test tokens.", + "description": "Mint test tokens.", "minting_tx": "Transaction sent to mint {token} tokens. Click here to see it in the explorer.", "button": { "mint": "Mint", From 28364bcf5d4c68f5d7209cb9fada38685b284d57 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 21 Jul 2023 11:48:30 +0200 Subject: [PATCH 47/67] wip --- .../src/components/Bridge/Amount/Amount.svelte | 6 +++--- .../src/components/Bridge/Recipient/Recipient.svelte | 8 ++++---- packages/bridge-ui-v2/src/components/Bridge/state.ts | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte b/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte index 5fffd287239..1349ed0cc1c 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte @@ -13,7 +13,7 @@ import { account } from '$stores/account'; import { network } from '$stores/network'; - import { destNetwork, enteredAmount, processingFee, selectedToken } from '../state'; + import { destNetwork, enteredAmount, processingFee, recipientAddress, selectedToken } from '../state'; import Balance from './Balance.svelte'; import { FlatAlert } from '$components/Alert'; @@ -47,7 +47,7 @@ try { await checkBalanceToBridge({ - to: $account.address, + to: $recipientAddress || $account.address, token: $selectedToken, amount: $enteredAmount, balance: tokenBalance.value, @@ -103,7 +103,7 @@ try { const maxAmount = await getMaxAmountToBridge({ - to: $account.address, + to: $recipientAddress || $account.address, token: $selectedToken, balance: tokenBalance.value, processingFee: $processingFee, diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte index e58f5e9b9b9..ca2b769eea8 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte @@ -9,13 +9,13 @@ import { account } from '$stores/account'; import { shortenAddress } from '$libs/util/shortenAddress'; import { recipientAddress } from '../state'; - import { isAddress } from 'viem'; + import { isAddress, type Address } from 'viem'; let dialogId = `dialog-${uid()}`; let modalOpen = false; let invalidAddress = false; - let prevRecipientAddress: string = ''; + let prevRecipientAddress: Maybe
    = null; let inputBox: InputBox; @@ -48,8 +48,8 @@ } function deleteRecipient() { - $recipientAddress = ''; // update state inputBox.clear(); // update UI + $recipientAddress = null; // update state } function modalOpenChange(open: boolean) { @@ -57,7 +57,7 @@ // Save it in case we want to cancel prevRecipientAddress = $recipientAddress; - inputBox.setValue($recipientAddress); + inputBox.setValue($recipientAddress as string); inputBox.focus(); } } diff --git a/packages/bridge-ui-v2/src/components/Bridge/state.ts b/packages/bridge-ui-v2/src/components/Bridge/state.ts index 93d8eeca003..9e1bf2eaf21 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/state.ts +++ b/packages/bridge-ui-v2/src/components/Bridge/state.ts @@ -1,4 +1,4 @@ -import type { Chain } from '@wagmi/core'; +import type { Address, Chain } from '@wagmi/core'; import { writable } from 'svelte/store'; import type { Token } from '$libs/token'; @@ -16,4 +16,4 @@ export const selectedToken = writable>(null); export const enteredAmount = writable(BigInt(0)); export const destNetwork = writable>(null); export const processingFee = writable(BigInt(0)); -export const recipientAddress = writable(''); +export const recipientAddress = writable>(null); From 4eb1babb9b4f51df6661a7f088970d6a916dc22c Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 21 Jul 2023 12:12:24 +0200 Subject: [PATCH 48/67] wip --- .../src/components/Activities/Activities.svelte | 2 +- .../bridge-ui-v2/src/components/Bridge/Bridge.svelte | 2 +- .../Bridge/{Recipient => }/Recipient.svelte | 2 +- .../src/components/Bridge/Recipient/index.ts | 1 - .../src/components/ChainSelector/ChainSelector.svelte | 11 +++++++++-- .../bridge-ui-v2/src/components/Faucet/Faucet.svelte | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) rename packages/bridge-ui-v2/src/components/Bridge/{Recipient => }/Recipient.svelte (98%) delete mode 100644 packages/bridge-ui-v2/src/components/Bridge/Recipient/index.ts diff --git a/packages/bridge-ui-v2/src/components/Activities/Activities.svelte b/packages/bridge-ui-v2/src/components/Activities/Activities.svelte index 84c2b8b7123..c5549a215ea 100644 --- a/packages/bridge-ui-v2/src/components/Activities/Activities.svelte +++ b/packages/bridge-ui-v2/src/components/Activities/Activities.svelte @@ -11,7 +11,7 @@
    - +
    diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index b2424fd56bb..6c2fff4a576 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -14,7 +14,7 @@ import { Amount } from './Amount'; import { ProcessingFee } from './ProcessingFee'; - import { Recipient } from './Recipient'; + import Recipient from './Recipient.svelte'; import { destNetwork, selectedToken } from './state'; import SwitchChainsButton from './SwitchChainsButton.svelte'; diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte b/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte similarity index 98% rename from packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte rename to packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte index ca2b769eea8..d3f479fb475 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient/Recipient.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte @@ -8,7 +8,7 @@ import { Icon } from '$components/Icon'; import { account } from '$stores/account'; import { shortenAddress } from '$libs/util/shortenAddress'; - import { recipientAddress } from '../state'; + import { recipientAddress } from './state'; import { isAddress, type Address } from 'viem'; let dialogId = `dialog-${uid()}`; diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient/index.ts b/packages/bridge-ui-v2/src/components/Bridge/Recipient/index.ts deleted file mode 100644 index fc42fed1b79..00000000000 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as Recipient } from './Recipient.svelte'; diff --git a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte index 9c67c41ba49..d611c31b6b1 100644 --- a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte +++ b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte @@ -18,8 +18,15 @@ export let value: Maybe = null; export let switchWallet = false; export let readOnly = false; + export let small = false; let classes = classNames('ChainSelector', $$props.class); + let buttonClasses = classNames( + 'px-2 body-small-regular bg-neutral-background', + small ? 'py-[6px]' : 'py-[10px]', + small ? 'rounded-md' : 'rounded-[10px]', + small ? 'w-auto' : 'w-full', + ); let chainToIconMap: Record = { [PUBLIC_L1_CHAIN_ID]: EthIcon, @@ -98,9 +105,9 @@ aria-haspopup="dialog" aria-controls={dialogId} aria-expanded={modalOpen} - class="px-2 py-[10px] body-small-regular bg-neutral-background rounded-[10px] w-full" + class={buttonClasses} on:click={openModal}> -
    +
    {#if !value} {$t('chain_selector.placeholder')} {/if} diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 09877bdd543..27d32aec90d 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -135,7 +135,7 @@
    - +
    From 8db8e2ca1dbad63f171ea0954be085e62fa14172 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 21 Jul 2023 13:22:24 +0200 Subject: [PATCH 49/67] remove Balance component --- .../src/components/Alert/FlatAlert.svelte | 2 +- .../src/components/Alert/types.ts | 2 +- .../src/components/Bridge/Actions.svelte | 34 +++++ .../Bridge/{Amount => }/Amount.svelte | 139 +++++++++++------- .../components/Bridge/Amount/Balance.svelte | 57 ------- .../src/components/Bridge/Amount/index.ts | 1 - .../src/components/Bridge/Bridge.svelte | 16 +- .../src/components/Bridge/Recipient.svelte | 9 +- .../src/components/Bridge/state.ts | 20 ++- .../ChainSelector/ChainSelector.svelte | 4 +- .../src/libs/bridge/checkBalanceToBridge.ts | 2 + .../src/libs/util/shortenAddress.ts | 5 +- 12 files changed, 164 insertions(+), 127 deletions(-) create mode 100644 packages/bridge-ui-v2/src/components/Bridge/Actions.svelte rename packages/bridge-ui-v2/src/components/Bridge/{Amount => }/Amount.svelte (53%) delete mode 100644 packages/bridge-ui-v2/src/components/Bridge/Amount/Balance.svelte delete mode 100644 packages/bridge-ui-v2/src/components/Bridge/Amount/index.ts diff --git a/packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte b/packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte index b30a240f83a..6fc7fd4d029 100644 --- a/packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte +++ b/packages/bridge-ui-v2/src/components/Alert/FlatAlert.svelte @@ -2,7 +2,7 @@ import { classNames } from '$libs/util/classNames'; import { Icon } from '../Icon'; - import type { AlertType, AlertIconDetails } from './types'; + import type { AlertIconDetails, AlertType } from './types'; type AlertTypeDetails = AlertIconDetails & { textClass: string; diff --git a/packages/bridge-ui-v2/src/components/Alert/types.ts b/packages/bridge-ui-v2/src/components/Alert/types.ts index 67d1c895ef2..7a50f31c3e4 100644 --- a/packages/bridge-ui-v2/src/components/Alert/types.ts +++ b/packages/bridge-ui-v2/src/components/Alert/types.ts @@ -1,4 +1,4 @@ -import type { IconType } from "$components/Icon"; +import type { IconType } from '$components/Icon'; export type AlertType = 'success' | 'warning' | 'error' | 'info'; diff --git a/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte new file mode 100644 index 00000000000..75d61abbaa3 --- /dev/null +++ b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte @@ -0,0 +1,34 @@ + + + diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte similarity index 53% rename from packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte rename to packages/bridge-ui-v2/src/components/Bridge/Amount.svelte index 1349ed0cc1c..5f53de1b232 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount/Amount.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte @@ -1,91 +1,119 @@
    - +
    + {$t('amount_input.balance')}: + + {#if $computingBalance} + + + {:else} + {renderBalance($tokenBalance)} + {/if} + + +
    @@ -148,7 +185,7 @@ placeholder="0.01" min="0" loading={computingMaxAmount} - error={insufficientBalance} + error={$insufficientBalance} on:input={inputAmount} bind:this={inputBox} class="w-full input-box outline-none py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content" /> @@ -161,11 +198,11 @@
    - {#if insufficientBalance} + {#if $insufficientBalance} {/if} - {#if insufficientAllowance} + {#if $insufficientAllowance} - import type { FetchBalanceResult } from '@wagmi/core'; - import { t } from 'svelte-i18n'; - - import LoadingText from '$components/LoadingText/LoadingText.svelte'; - import { getBalance as getTokenBalance, type Token } from '$libs/token'; - import { truncateString } from '$libs/util/truncateString'; - import { type Account, account } from '$stores/account'; - import { network } from '$stores/network'; - - import { destNetwork, selectedToken } from '../state'; - - export let value: Maybe; - - let computingTokenBalance = false; - let errorComputingTokenBalance = false; - - async function updateTokenBalance(token: Maybe, account?: Account, srcChainId?: number, destChainId?: number) { - if (!token || !srcChainId || !account?.address) return; - - computingTokenBalance = true; - errorComputingTokenBalance = false; - - try { - value = await getTokenBalance({ - token, - srcChainId, - destChainId, - userAddress: account.address, - }); - } catch (err) { - console.error(err); - errorComputingTokenBalance = true; - } finally { - computingTokenBalance = false; - } - } - - export function renderTokenBalance(balance: Maybe) { - if (!balance) return '0.00'; - return `${truncateString(balance.formatted, 6)} ${balance.symbol}`; - } - - $: updateTokenBalance($selectedToken, $account, $network?.id, $destNetwork?.id); - - -
    - {$t('amount_input.balance')}: - - {#if computingTokenBalance} - - - {:else} - {renderTokenBalance(value)} - {/if} - -
    diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount/index.ts b/packages/bridge-ui-v2/src/components/Bridge/Amount/index.ts deleted file mode 100644 index e8c536613eb..00000000000 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as Amount } from './Amount.svelte'; diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 6c2fff4a576..fd7214052ce 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -1,7 +1,6 @@ @@ -57,9 +65,7 @@
    - +
    diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte b/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte index d3f479fb475..9f0afa1f0e4 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte @@ -1,15 +1,16 @@ - +
    + {#if showSteps} + + + {/if} + + +
    diff --git a/packages/bridge-ui-v2/src/components/Icon/Icon.svelte b/packages/bridge-ui-v2/src/components/Icon/Icon.svelte index f9684ac9efc..c6b02fcd432 100644 --- a/packages/bridge-ui-v2/src/components/Icon/Icon.svelte +++ b/packages/bridge-ui-v2/src/components/Icon/Icon.svelte @@ -17,7 +17,8 @@ | 'info-circle' | 'circle' | 'arrow-right' - | 'up-down'; + | 'up-down' + | 'check';
    - {#if showSteps} + {#if isSelectedERC20}
    + + diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index a7b5bb9183d..423c4a6d8c9 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -15,13 +15,17 @@ import { getConnectedWallet } from '$libs/util/getConnectedWallet'; import type { Account } from '$stores/account'; import { type Network, network } from '$stores/network'; + import { pendingTransactions } from '$stores/pendingTransactions'; import Actions from './Actions.svelte'; import Amount from './Amount.svelte'; import { ProcessingFee } from './ProcessingFee'; import Recipient from './Recipient.svelte'; - import { destNetwork, enteredAmount, insufficientAllowance, selectedToken } from './state'; + import { destNetwork, enteredAmount, processingFee, selectedToken } from './state'; import SwitchChainsButton from './SwitchChainsButton.svelte'; + import Validator from './Validator.svelte'; + + let validator: Validator; function onNetworkChange(network: Network) { if (network && chains.length === 2) { @@ -77,6 +81,11 @@ }), true, ); + + await pendingTransactions.add(txHash, $network.id); + + // Let's run the validation again, which will update UI state + validator.validate(); } catch (err) { console.error(err); } @@ -114,3 +123,5 @@ + + diff --git a/packages/bridge-ui-v2/src/components/Bridge/Validator.svelte b/packages/bridge-ui-v2/src/components/Bridge/Validator.svelte new file mode 100644 index 00000000000..0790f419743 --- /dev/null +++ b/packages/bridge-ui-v2/src/components/Bridge/Validator.svelte @@ -0,0 +1,58 @@ + diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 4aaba5a0eef..072b1c252a2 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -14,8 +14,7 @@ import { InsufficientBalanceError, TokenMintedError } from '$libs/error'; import { testERC20Tokens, type Token } from '$libs/token'; import { checkMintable, mint } from '$libs/token'; - import { account } from '$stores/account'; - import { network } from '$stores/network'; + import { account, network, pendingTransactions } from '$stores'; let minting = false; let checkingMintable = false; @@ -66,6 +65,8 @@ true, ); + await pendingTransactions.add(txHash, $network.id); + // TODO: pending transaction logic } catch (err) { console.error(err); diff --git a/packages/bridge-ui-v2/src/libs/error/errors.ts b/packages/bridge-ui-v2/src/libs/error/errors.ts index c19407be87d..aa32b49b29e 100644 --- a/packages/bridge-ui-v2/src/libs/error/errors.ts +++ b/packages/bridge-ui-v2/src/libs/error/errors.ts @@ -4,3 +4,4 @@ export class InsufficientBalanceError extends Error {} export class InsufficientAllowanceError extends Error {} export class NoAllowanceRequiredError extends Error {} export class NoTokenAddressError extends Error {} +export class FailedTransactionError extends Error {} diff --git a/packages/bridge-ui-v2/src/stores/index.ts b/packages/bridge-ui-v2/src/stores/index.ts index 4b6b85801e8..33cb4308011 100644 --- a/packages/bridge-ui-v2/src/stores/index.ts +++ b/packages/bridge-ui-v2/src/stores/index.ts @@ -1,2 +1,3 @@ export { account } from './account'; export { network } from './network'; +export { pendingTransactions } from './pendingTransactions'; diff --git a/packages/bridge-ui-v2/src/stores/pendingTransactions.ts b/packages/bridge-ui-v2/src/stores/pendingTransactions.ts index 8e298252e37..10989979c7b 100644 --- a/packages/bridge-ui-v2/src/stores/pendingTransactions.ts +++ b/packages/bridge-ui-v2/src/stores/pendingTransactions.ts @@ -3,6 +3,7 @@ import { writable } from 'svelte/store'; import type { Hex, TransactionReceipt } from 'viem'; import { pendingTransaction } from '$config'; +import { FailedTransactionError } from '$libs/error'; import { Deferred } from '$libs/util/Deferred'; import { getLogger } from '$libs/util/logger'; @@ -59,7 +60,7 @@ export const pendingTransactions = { log('Transaction successful'); deferred.resolve(receipt); } else { - deferred.reject(new Error('transaction failed', { cause: receipt })); + deferred.reject(new FailedTransactionError(`transaction with hash "${hash}" failed`, { cause: receipt })); } }) .catch((err) => { From fa38d1f0bb1220b0ebe2bf22e4b62475aa51ebbb Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 22 Jul 2023 18:56:12 +0200 Subject: [PATCH 56/67] wip --- .../bridge-ui-v2/src/components/Bridge/Amount.svelte | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte index 723902152de..8a1bae25af3 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte @@ -36,7 +36,7 @@ // We want to debounce this function for input events. // Could happen as the user enters an amount - const debouncedValidate = debounce(() => validator?.validate(), 300); + const debouncedValidate = debounce(() => validator.validate(), 300); async function updateBalance(token: Maybe, userAddress?: Address, srcChainId?: number, destChainId?: number) { if (!token || !srcChainId || !userAddress) return; @@ -71,12 +71,9 @@ if (!$selectedToken) return; const { value } = event.target as HTMLInputElement; + $enteredAmount = parseUnits(value, $selectedToken.decimals); - try { - $enteredAmount = parseUnits(value, $selectedToken.decimals); - } catch (err) { - $enteredAmount = BigInt(0); - } + debouncedValidate(); } // "MAX" button handler @@ -117,7 +114,7 @@ $: updateBalance($selectedToken, $account?.address, $network?.id, $destNetwork?.id); - $: $selectedToken && $enteredAmount && $processingFee && debouncedValidate(); + $: $selectedToken && $processingFee && validator.validate();
    From 743e46d273ea84efd556b8755bb9d778e9dfbc31 Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 22 Jul 2023 23:42:08 +0200 Subject: [PATCH 57/67] bridging --- .../src/components/Bridge/Amount.svelte | 79 +++++++++++--- .../src/components/Bridge/Bridge.svelte | 103 ++++++++++++++++-- .../Bridge/ProcessingFee/ProcessingFee.svelte | 6 + .../src/components/Bridge/Recipient.svelte | 13 ++- packages/bridge-ui-v2/src/i18n/en.json | 1 + .../src/libs/bridge/ERC20Bridge.ts | 29 +++-- .../bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 14 ++- .../bridge-ui-v2/src/libs/bridge/types.ts | 2 +- .../bridge-ui-v2/src/libs/error/errors.ts | 3 + .../src/libs/token/isDeployedCrossChain.ts | 2 +- 10 files changed, 206 insertions(+), 46 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte index 8a1bae25af3..dae7b6b042e 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte @@ -1,5 +1,5 @@
    @@ -167,5 +218,3 @@ {/if}
    - - diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 423c4a6d8c9..6e8d2ddee18 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -8,12 +8,13 @@ import { OnNetwork } from '$components/OnNetwork'; import { TokenDropdown } from '$components/TokenDropdown'; import { PUBLIC_L1_EXPLORER_URL } from '$env/static/public'; - import { bridges } from '$libs/bridge'; + import { type Bridge, type BridgeArgs, bridges, type ERC20BridgeArgs, type ETHBridgeArgs } from '$libs/bridge'; import type { ERC20Bridge } from '$libs/bridge/ERC20Bridge'; + import type { ETHBridge } from '$libs/bridge/ETHBridge'; import { chainContractsMap, chains } from '$libs/chain'; - import { ETHToken, getAddress, tokens } from '$libs/token'; + import { ETHToken, getAddress, isDeployedCrossChain, isETH, tokens } from '$libs/token'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; - import type { Account } from '$stores/account'; + import { type Account, account } from '$stores/account'; import { type Network, network } from '$stores/network'; import { pendingTransactions } from '$stores/pendingTransactions'; @@ -21,11 +22,12 @@ import Amount from './Amount.svelte'; import { ProcessingFee } from './ProcessingFee'; import Recipient from './Recipient.svelte'; - import { destNetwork, enteredAmount, processingFee, selectedToken } from './state'; + import { destNetwork, enteredAmount, processingFee, recipientAddress, selectedToken } from './state'; import SwitchChainsButton from './SwitchChainsButton.svelte'; - import Validator from './Validator.svelte'; - let validator: Validator; + let amountComponent: Amount; + let recipientComponent: Recipient; + let processingFeeComponent: ProcessingFee; function onNetworkChange(network: Network) { if (network && chains.length === 2) { @@ -84,15 +86,95 @@ await pendingTransactions.add(txHash, $network.id); - // Let's run the validation again, which will update UI state - validator.validate(); + // Let's run the validation again, which will update UI + amountComponent.validate(); } catch (err) { console.error(err); } } async function bridge() { - // TODO + if (!$selectedToken || !$network || !$destNetwork || !$account?.address) return; + + try { + const walletClient = await getConnectedWallet($network.id); + + let bridge: Bridge; + + // Common arguments for both ETH and ERC20 bridges + let bridgeArgs = { + to: $recipientAddress || $account.address, + wallet: walletClient, + srcChainId: $network.id, + destChainId: $destNetwork.id, + amount: $enteredAmount, + processingFee: $processingFee, + } as BridgeArgs; + + if (isETH($selectedToken)) { + bridge = bridges.ETH as ETHBridge; + + // Specific arguments for ETH bridge: + // - bridgeAddress + const bridgeAddress = chainContractsMap[$network.id].bridgeAddress; + bridgeArgs = { ...bridgeArgs, bridgeAddress } as ETHBridgeArgs; + } else { + bridge = bridges.ERC20 as ERC20Bridge; + + // Specific arguments for ERC20 bridge + // - tokenAddress + // - tokenVaultAddress + // - isTokenAlreadyDeployed + const tokenAddress = await getAddress({ + token: $selectedToken, + srcChainId: $network.id, + destChainId: $destNetwork.id, + }); + + if (!tokenAddress) { + throw new Error('token address not found'); + } + + const tokenVaultAddress = chainContractsMap[$network.id].tokenVaultAddress; + + const isTokenAlreadyDeployed = await isDeployedCrossChain({ + token: $selectedToken, + srcChainId: $network.id, + destChainId: $destNetwork.id, + }); + + bridgeArgs = { + ...bridgeArgs, + tokenAddress, + tokenVaultAddress, + isTokenAlreadyDeployed, + } as ERC20BridgeArgs; + } + + const txHash = await bridge.bridge(bridgeArgs); + + successToast( + $t('bridge.bridge_tx', { + values: { + token: $selectedToken.symbol, + url: `${PUBLIC_L1_EXPLORER_URL}/tx/${txHash}`, + }, + }), + true, + ); + + await pendingTransactions.add(txHash, $network.id); + + // Reset the form + amountComponent.clearAmount(); + recipientComponent.clearRecipient(); + processingFeeComponent.resetProcessingFee(); + + // Update balance + amountComponent.updateBalance(); + } catch (err) { + console.error(err); + } } @@ -103,6 +185,7 @@ +
    @@ -123,5 +206,3 @@ - - diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte index c86d94657f5..1bb3f044c2f 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/ProcessingFee.svelte @@ -33,6 +33,12 @@ let modalOpen = false; let inputBox: InputBox; + // Public API + export function resetProcessingFee() { + inputBox.clear(); + selectedFeeMethod = ProcessingFeeMethod.RECOMMENDED; + } + function closeModal() { // Let's check if we are closing with CUSTOM method selected and zero amount entered if (selectedFeeMethod === ProcessingFeeMethod.CUSTOM && $processingFee === BigInt(0)) { diff --git a/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte b/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte index 9f0afa1f0e4..867f0397d7b 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Recipient.svelte @@ -20,6 +20,12 @@ let inputBox: InputBox; + // Public API + export function clearRecipient() { + inputBox.clear(); // update UI + $recipientAddress = null; // update state + } + function closeModal() { modalOpen = false; } @@ -48,11 +54,6 @@ } } - function deleteRecipient() { - inputBox.clear(); // update UI - $recipientAddress = null; // update state - } - function modalOpenChange(open: boolean) { if (open) { // Save it in case we want to cancel @@ -101,7 +102,7 @@ class="w-full input-box outline-none p-6 pr-16 title-subsection-bold placeholder:text-tertiary-content" on:input={inputRecipientAddress} bind:this={inputBox} /> -
    diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index 54f48539bdd..42a59fc8373 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -11,6 +11,7 @@ "title": "Bridge", "description": "Send your assets across chains.", "approve_tx": "Transaction sent to approve {token} tokens. Click here to see it in the explorer.", + "bridge_tx": "Transaction sent to bridge {token} tokens. Click here to see it in the explorer.", "button": { "approve": "Approve", "approving": "Approving", diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index f65b959df5a..9bec23b63fc 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -2,7 +2,7 @@ import { getContract } from '@wagmi/core'; import { erc20ABI, tokenVaultABI } from '$abi'; import { bridge } from '$config'; -import { InsufficientAllowanceError, NoAllowanceRequiredError } from '$libs/error'; +import { ApproveError, InsufficientAllowanceError, NoAllowanceRequiredError, SendERC20Error } from '$libs/error'; import { getLogger } from '$libs/util/logger'; import type { ApproveArgs, Bridge, ERC20BridgeArgs, RequireAllowanceArgs, SendERC20Args } from './types'; @@ -105,13 +105,18 @@ export class ERC20Bridge implements Bridge { address: tokenAddress, }); - log(`Calling approve for spender "${spenderAddress}" with amount`, amount); + try { + log(`Calling approve for spender "${spenderAddress}" with amount`, amount); - const txHash = await tokenContract.write.approve([spenderAddress, amount]); + const txHash = await tokenContract.write.approve([spenderAddress, amount]); - log('Transaction hash for approve call', txHash); + log('Transaction hash for approve call', txHash); - return txHash; + return txHash; + } catch (err) { + console.error(err); + throw new ApproveError('failed to approve ERC20 token', { cause: err }); + } } async bridge(args: ERC20BridgeArgs) { @@ -133,10 +138,18 @@ export class ERC20Bridge implements Bridge { const value = processingFee; - log('Calling sendERC20 with value', value); + try { + log('Calling sendERC20 with value', value); + + const txHash = tokenVaultContract.write.sendERC20([...sendERC20Args], { value }); - const txHash = tokenVaultContract.write.sendERC20([...sendERC20Args], { value }); + log('Transaction hash for sendERC20 call', txHash); - log('Transaction hash for sendERC20 call', txHash); + return txHash; + } catch (err) { + console.error(err); + + throw new SendERC20Error('failed to bridge ERC20 token', { cause: err }); + } } } diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index 3294a4f6673..8c65ac4aa6a 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -2,6 +2,7 @@ import { getContract } from '@wagmi/core'; import { bridgeABI } from '$abi'; import { bridge } from '$config'; +import { SendMessageError } from '$libs/error'; import { getLogger } from '$libs/util/logger'; import type { Bridge, ETHBridgeArgs, Message } from './types'; @@ -74,12 +75,17 @@ export class ETHBridge implements Bridge { const value = depositValue + callValue + processingFee; - log('Calling sendMessage with value', value); + try { + log('Calling sendMessage with value', value); - const txHash = await bridgeContract.write.sendMessage([message], { value }); + const txHash = await bridgeContract.write.sendMessage([message], { value }); - log('Transaction hash for sendMessage call', txHash); + log('Transaction hash for sendMessage call', txHash); - return txHash; + return txHash; + } catch (err) { + console.error(err); + throw new SendMessageError('failed to bridge ETH', { cause: err }); + } } } diff --git a/packages/bridge-ui-v2/src/libs/bridge/types.ts b/packages/bridge-ui-v2/src/libs/bridge/types.ts index a3ed33ba093..cbb3d35c39b 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/types.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/types.ts @@ -104,5 +104,5 @@ export type RequireAllowanceArgs = { export interface Bridge { estimateGas(args: BridgeArgs): Promise; - bridge(args: BridgeArgs): Promise; + bridge(args: BridgeArgs): Promise; } diff --git a/packages/bridge-ui-v2/src/libs/error/errors.ts b/packages/bridge-ui-v2/src/libs/error/errors.ts index aa32b49b29e..9996d14d4a9 100644 --- a/packages/bridge-ui-v2/src/libs/error/errors.ts +++ b/packages/bridge-ui-v2/src/libs/error/errors.ts @@ -5,3 +5,6 @@ export class InsufficientAllowanceError extends Error {} export class NoAllowanceRequiredError extends Error {} export class NoTokenAddressError extends Error {} export class FailedTransactionError extends Error {} +export class SendMessageError extends Error {} +export class SendERC20Error extends Error {} +export class ApproveError extends Error {} diff --git a/packages/bridge-ui-v2/src/libs/token/isDeployedCrossChain.ts b/packages/bridge-ui-v2/src/libs/token/isDeployedCrossChain.ts index 8edf6a6d963..ee166c0aa23 100644 --- a/packages/bridge-ui-v2/src/libs/token/isDeployedCrossChain.ts +++ b/packages/bridge-ui-v2/src/libs/token/isDeployedCrossChain.ts @@ -17,7 +17,7 @@ export async function isDeployedCrossChain({ token, srcChainId, destChainId }: I // Check if token is already deployed as BridgedERC20 on destination chain const bridgedTokenAddress = await getCrossChainAddress({ token, srcChainId, destChainId }); - return bridgedTokenAddress && bridgedTokenAddress !== zeroAddress; + return bridgedTokenAddress ? bridgedTokenAddress !== zeroAddress : false; } return true; From a7b0cfda8b1d89e911c311aa234fcecd069bd7cb Mon Sep 17 00:00:00 2001 From: Francisco Date: Sun, 23 Jul 2023 00:04:16 +0200 Subject: [PATCH 58/67] handle errors --- .../src/components/Bridge/Actions.svelte | 2 +- .../src/components/Bridge/Amount.svelte | 2 +- .../src/components/Bridge/Bridge.svelte | 11 ++++- .../src/libs/bridge/ERC1155Bridge.ts | 6 +++ .../src/libs/bridge/ERC20Bridge.ts | 10 ++++ .../src/libs/bridge/ERC721Bridge.ts | 6 +++ .../bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 6 +++ .../bridge-ui-v2/src/libs/error/errors.ts | 49 +++++++++++++++---- 8 files changed, 79 insertions(+), 13 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte index ea436948641..9af1ab6894e 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte @@ -88,7 +88,7 @@ loading={bridging} on:click={onBridgeClick}> {#if bridging} - {$t('bridge.button.briding')} + {$t('bridge.button.bridging')} {:else} {$t('bridge.button.bridge')} {/if} diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte index dae7b6b042e..2e8d69b267b 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte @@ -82,7 +82,7 @@ export async function updateBalance( token = $selectedToken, - userAddress = $account.address, + userAddress = $account?.address, srcChainId = $network?.id, destChainId = $destNetwork?.id, ) { diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 6e8d2ddee18..4b70b9e12bc 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -1,9 +1,10 @@ diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts index ddad81ecab1..6d3e4faaf0c 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts @@ -1,7 +1,13 @@ +import type { Hex } from 'viem'; + import type { Bridge } from './types'; export class ERC1155Bridge implements Bridge { async estimateGas(): Promise { return Promise.resolve(BigInt(0)); } + + async bridge(): Promise { + return Promise.resolve('0x'); + } } diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index 9bec23b63fc..5de324659d2 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -1,4 +1,5 @@ import { getContract } from '@wagmi/core'; +import { UserRejectedRequestError } from 'viem'; import { erc20ABI, tokenVaultABI } from '$abi'; import { bridge } from '$config'; @@ -115,6 +116,11 @@ export class ERC20Bridge implements Bridge { return txHash; } catch (err) { console.error(err); + + if (`${err}`.includes('denied transaction signature')) { + throw new UserRejectedRequestError(err as Error); + } + throw new ApproveError('failed to approve ERC20 token', { cause: err }); } } @@ -149,6 +155,10 @@ export class ERC20Bridge implements Bridge { } catch (err) { console.error(err); + if (`${err}`.includes('denied transaction signature')) { + throw new UserRejectedRequestError(err as Error); + } + throw new SendERC20Error('failed to bridge ERC20 token', { cause: err }); } } diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts index a9d03418e55..12010042511 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts @@ -1,7 +1,13 @@ +import type { Hex } from 'viem'; + import type { Bridge } from './types'; export class ERC721Bridge implements Bridge { async estimateGas(): Promise { return Promise.resolve(BigInt(0)); } + + async bridge(): Promise { + return Promise.resolve('0x'); + } } diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index 8c65ac4aa6a..45f7353130d 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -1,4 +1,5 @@ import { getContract } from '@wagmi/core'; +import { UserRejectedRequestError } from 'viem'; import { bridgeABI } from '$abi'; import { bridge } from '$config'; @@ -85,6 +86,11 @@ export class ETHBridge implements Bridge { return txHash; } catch (err) { console.error(err); + + if (`${err}`.includes('denied transaction signature')) { + throw new UserRejectedRequestError(err as Error); + } + throw new SendMessageError('failed to bridge ETH', { cause: err }); } } diff --git a/packages/bridge-ui-v2/src/libs/error/errors.ts b/packages/bridge-ui-v2/src/libs/error/errors.ts index 9996d14d4a9..f0bc79d1f73 100644 --- a/packages/bridge-ui-v2/src/libs/error/errors.ts +++ b/packages/bridge-ui-v2/src/libs/error/errors.ts @@ -1,10 +1,39 @@ -export class NotConnectedError extends Error {} -export class TokenMintedError extends Error {} -export class InsufficientBalanceError extends Error {} -export class InsufficientAllowanceError extends Error {} -export class NoAllowanceRequiredError extends Error {} -export class NoTokenAddressError extends Error {} -export class FailedTransactionError extends Error {} -export class SendMessageError extends Error {} -export class SendERC20Error extends Error {} -export class ApproveError extends Error {} +export class NotConnectedError extends Error { + name = 'NotConnectedError'; +} + +export class TokenMintedError extends Error { + name = 'TokenMintedError'; +} + +export class InsufficientBalanceError extends Error { + name = 'InsufficientBalanceError'; +} + +export class InsufficientAllowanceError extends Error { + name = 'InsufficientAllowanceError'; +} + +export class NoAllowanceRequiredError extends Error { + name = 'NoAllowanceRequiredError'; +} + +export class NoTokenAddressError extends Error { + name = 'NoTokenAddressError'; +} + +export class FailedTransactionError extends Error { + name = 'FailedTransactionError'; +} + +export class SendMessageError extends Error { + name = 'SendMessageError'; +} + +export class SendERC20Error extends Error { + name = 'SendERC20Error'; +} + +export class ApproveError extends Error { + name = 'ApproveError'; +} From 8119d5087f649d5ffa0f4cf72c8f42905b43311c Mon Sep 17 00:00:00 2001 From: Francisco Date: Sun, 23 Jul 2023 00:35:51 +0200 Subject: [PATCH 59/67] wip --- .../src/components/Bridge/Amount.svelte | 5 ++- .../src/components/Bridge/Bridge.svelte | 32 +++++++++++++------ .../src/components/Faucet/Faucet.svelte | 3 +- packages/bridge-ui-v2/src/i18n/en.json | 18 ++++++++--- .../src/libs/bridge/checkBalanceToBridge.ts | 8 +++-- .../bridge-ui-v2/src/libs/error/errors.ts | 4 +++ 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte index 2e8d69b267b..30f8bb4e9dc 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Amount.svelte @@ -8,7 +8,7 @@ import { LoadingText } from '$components/LoadingText'; import { warningToast } from '$components/NotificationToast'; import { checkBalanceToBridge, getMaxAmountToBridge } from '$libs/bridge'; - import { InsufficientAllowanceError, InsufficientBalanceError } from '$libs/error'; + import { InsufficientAllowanceError, InsufficientBalanceError, RevertedWithFailedError } from '$libs/error'; import { getBalance as getTokenBalance } from '$libs/token'; import { debounce } from '$libs/util/debounce'; import { truncateString } from '$libs/util/truncateString'; @@ -76,6 +76,9 @@ case err instanceof InsufficientAllowanceError: $insufficientAllowance = true; break; + case err instanceof RevertedWithFailedError: + warningToast($t('messages.network.rejected')); + break; } } } diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 4b70b9e12bc..f8221ede9f0 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -76,24 +76,31 @@ }); successToast( - $t('bridge.approve_tx', { + $t('bridge.approve.tx', { values: { token: $selectedToken.symbol, url: `${PUBLIC_L1_EXPLORER_URL}/tx/${txHash}`, }, }), - true, ); await pendingTransactions.add(txHash, $network.id); + successToast( + $t('bridge.approve.success', { + values: { + token: $selectedToken.symbol, + }, + }), + ); + // Let's run the validation again, which will update UI amountComponent.validate(); } catch (err) { console.error(err); if (err instanceof UserRejectedRequestError) { - warningToast($t('messages.network.rejected')); + warningToast($t('bridge.approve.rejected')); } } } @@ -159,17 +166,24 @@ const txHash = await bridge.bridge(bridgeArgs); successToast( - $t('bridge.bridge_tx', { + $t('bridge.bridge.tx', { values: { token: $selectedToken.symbol, url: `${PUBLIC_L1_EXPLORER_URL}/tx/${txHash}`, }, }), - true, ); await pendingTransactions.add(txHash, $network.id); + successToast( + $t('bridge.bridge.success', { + values: { + network: $destNetwork.name, + }, + }), + ); + // Reset the form amountComponent.clearAmount(); recipientComponent.clearRecipient(); @@ -181,7 +195,7 @@ console.error(err); if (err instanceof UserRejectedRequestError) { - warningToast($t('messages.network.rejected')); + warningToast($t('bridge.bridge.rejected')); } } } @@ -200,11 +214,11 @@ - + - + - +
    diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index 072b1c252a2..e82e546acef 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -62,7 +62,6 @@ url: `${PUBLIC_L1_EXPLORER_URL}/tx/${txHash}`, }, }), - true, ); await pendingTransactions.add(txHash, $network.id); @@ -73,7 +72,7 @@ const { cause } = err as Error; if (cause instanceof UserRejectedRequestError) { - warningToast($t('messages.mint.rejected')); + warningToast($t('faucet.mint.rejected')); } } finally { minting = false; diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json index 42a59fc8373..188178b510e 100644 --- a/packages/bridge-ui-v2/src/i18n/en.json +++ b/packages/bridge-ui-v2/src/i18n/en.json @@ -10,8 +10,16 @@ "bridge": { "title": "Bridge", "description": "Send your assets across chains.", - "approve_tx": "Transaction sent to approve {token} tokens. Click here to see it in the explorer.", - "bridge_tx": "Transaction sent to bridge {token} tokens. Click here to see it in the explorer.", + "approve": { + "tx": "Transaction sent to approve {token} tokens. Click here to see it in the explorer.", + "success": "Approved {token} tokens!. You can now proceed to bridge.", + "rejected": "Request to approve rejected." + }, + "bridge": { + "tx": "Transaction sent to bridge {token} tokens. Click here to see it in the explorer.", + "success": "Transaction completed!. Your funds are getting ready to be claimed on {network}", + "rejected": "Request to bridge rejected." + }, "button": { "approve": "Approve", "approving": "Approving", @@ -91,6 +99,9 @@ "no_connected": "Please connect your wallet to mint tokens.", "insufficient_balance": "You don't have enough ETH to complete the transaction. Please add some ETH to your wallet.", "token_minted": "You have already minted this token." + }, + "mint": { + "rejected": "Request to mint rejected." } }, @@ -139,9 +150,6 @@ "network": { "switching": "Switching network", "rejected": "Request to switch chain rejected." - }, - "mint": { - "rejected": "Request to mint rejected." } }, diff --git a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts index 4abe8fe4453..1ed7f30a507 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts @@ -1,7 +1,7 @@ import { type Address, zeroAddress } from 'viem'; import { chainContractsMap } from '$libs/chain'; -import { InsufficientAllowanceError, InsufficientBalanceError } from '$libs/error'; +import { InsufficientAllowanceError, InsufficientBalanceError, RevertedWithFailedError } from '$libs/error'; import { getAddress, isETH, type Token } from '$libs/token'; import { isDeployedCrossChain } from '$libs/token/isDeployedCrossChain'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; @@ -53,9 +53,13 @@ export async function checkBalanceToBridge({ console.error(err); // TODO: rely on error code, or instance, instead of string matching - if (`${err}`.includes('transaction exceeds the balance of the account')) { + if (`${err}`.includes('transaction exceeds the balance')) { throw new InsufficientBalanceError('you do not have enough balance to bridge ETH', { cause: err }); } + + if (`${err}`.includes('reverted with the following reason: Failed')) { + throw new RevertedWithFailedError('BLL token doing its thing', { cause: err }); + } } } else { const { tokenVaultAddress } = chainContractsMap[srcChainId]; diff --git a/packages/bridge-ui-v2/src/libs/error/errors.ts b/packages/bridge-ui-v2/src/libs/error/errors.ts index f0bc79d1f73..28b5c33a49c 100644 --- a/packages/bridge-ui-v2/src/libs/error/errors.ts +++ b/packages/bridge-ui-v2/src/libs/error/errors.ts @@ -37,3 +37,7 @@ export class SendERC20Error extends Error { export class ApproveError extends Error { name = 'ApproveError'; } + +export class RevertedWithFailedError extends Error { + name = 'RevertedWithFailedError'; +} From e074ef7ec1dd36d6a9fef21998decc96b28d1bde Mon Sep 17 00:00:00 2001 From: Francisco Date: Sun, 23 Jul 2023 00:58:31 +0200 Subject: [PATCH 60/67] bridging in place --- .../src/components/Bridge/Bridge.svelte | 39 +++++++++++++++---- .../src/components/Faucet/Faucet.svelte | 3 +- .../NotificationToast/ItemToast.svelte | 5 +++ .../NotificationToast.svelte | 4 ++ .../src/components/NotificationToast/types.ts | 2 +- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index f8221ede9f0..5685b3d2a3c 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -5,6 +5,7 @@ import { Card } from '$components/Card'; import { ChainSelector } from '$components/ChainSelector'; import { successToast, warningToast } from '$components/NotificationToast'; + import { errorToast, infoToast } from '$components/NotificationToast/NotificationToast.svelte'; import { OnAccount } from '$components/OnAccount'; import { OnNetwork } from '$components/OnNetwork'; import { TokenDropdown } from '$components/TokenDropdown'; @@ -13,6 +14,7 @@ import type { ERC20Bridge } from '$libs/bridge/ERC20Bridge'; import type { ETHBridge } from '$libs/bridge/ETHBridge'; import { chainContractsMap, chains } from '$libs/chain'; + import { ApproveError, NoAllowanceRequiredError, SendERC20Error, SendMessageError } from '$libs/error'; import { ETHToken, getAddress, isDeployedCrossChain, isETH, tokens } from '$libs/token'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; import { type Account, account } from '$stores/account'; @@ -75,7 +77,7 @@ wallet: walletClient, }); - successToast( + infoToast( $t('bridge.approve.tx', { values: { token: $selectedToken.symbol, @@ -95,12 +97,23 @@ ); // Let's run the validation again, which will update UI - amountComponent.validate(); + amountComponent.validateAmount(); } catch (err) { console.error(err); - if (err instanceof UserRejectedRequestError) { - warningToast($t('bridge.approve.rejected')); + switch (true) { + case err instanceof UserRejectedRequestError: + warningToast($t('bridge.approve.rejected')); + break; + case err instanceof NoAllowanceRequiredError: + errorToast($t('bridge.approve.no_allowance_required')); + break; + case err instanceof ApproveError: + // TODO: see contract for all possible errors + errorToast($t('bridge.approve.error')); + break; + default: + errorToast($t('bridge.approve.unknown_error')); } } } @@ -165,7 +178,7 @@ const txHash = await bridge.bridge(bridgeArgs); - successToast( + infoToast( $t('bridge.bridge.tx', { values: { token: $selectedToken.symbol, @@ -194,8 +207,20 @@ } catch (err) { console.error(err); - if (err instanceof UserRejectedRequestError) { - warningToast($t('bridge.bridge.rejected')); + switch (true) { + case err instanceof UserRejectedRequestError: + warningToast($t('bridge.bridge.rejected')); + break; + case err instanceof SendMessageError: + // TODO: see contract for all possible errors + errorToast($t('bridge.bridge.send_message_error')); + break; + case err instanceof SendERC20Error: + // TODO: see contract for all possible errors + errorToast($t('bridge.bridge.send_erc20_error')); + break; + default: + errorToast($t('bridge.approve.unknown_error')); } } } diff --git a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte index e82e546acef..cd587fbd1b4 100644 --- a/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte +++ b/packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte @@ -9,6 +9,7 @@ import { ChainSelector } from '$components/ChainSelector'; import { Icon } from '$components/Icon'; import { successToast, warningToast } from '$components/NotificationToast'; + import { infoToast } from '$components/NotificationToast/NotificationToast.svelte'; import { TokenDropdown } from '$components/TokenDropdown'; import { PUBLIC_L1_CHAIN_ID, PUBLIC_L1_CHAIN_NAME, PUBLIC_L1_EXPLORER_URL } from '$env/static/public'; import { InsufficientBalanceError, TokenMintedError } from '$libs/error'; @@ -55,7 +56,7 @@ try { const txHash = await mint(selectedToken, $network.id); - successToast( + infoToast( $t('faucet.mint_tx', { values: { token: selectedToken.symbol, diff --git a/packages/bridge-ui-v2/src/components/NotificationToast/ItemToast.svelte b/packages/bridge-ui-v2/src/components/NotificationToast/ItemToast.svelte index 582f88f9559..63d9472fefe 100644 --- a/packages/bridge-ui-v2/src/components/NotificationToast/ItemToast.svelte +++ b/packages/bridge-ui-v2/src/components/NotificationToast/ItemToast.svelte @@ -14,6 +14,7 @@ success: 'check-circle', error: 'x-close-circle', warning: 'info-circle', + info: 'info-circle', unknown: 'question-circle', }; @@ -21,6 +22,7 @@ success: 'bg-positive-background', error: 'bg-negative-background', warning: 'bg-warning-background', + info: 'bg-primary-interactive', unknown: 'bg-neutral-background', }; @@ -28,6 +30,7 @@ success: 'fill-positive-sentiment', error: 'fill-negative-sentiment', warning: 'fill-warning-sentiment', + info: 'fill-pink-50', unknown: 'fill-primary-content', }; @@ -35,6 +38,7 @@ success: 'text-positive-sentiment', error: 'text-negative-sentiment', warning: 'text-warning-sentiment', + info: 'text-white', unknown: 'text-primary-content', }; @@ -42,6 +46,7 @@ success: 'fill-green-600', error: 'fill-red-500', warning: 'fill-yellow-500', + info: 'fill-pink-700', unknown: 'fill-grey-5', }; diff --git a/packages/bridge-ui-v2/src/components/NotificationToast/NotificationToast.svelte b/packages/bridge-ui-v2/src/components/NotificationToast/NotificationToast.svelte index 78c47e36de7..73d1d77f4f1 100644 --- a/packages/bridge-ui-v2/src/components/NotificationToast/NotificationToast.svelte +++ b/packages/bridge-ui-v2/src/components/NotificationToast/NotificationToast.svelte @@ -33,6 +33,10 @@ export function warningToast(message: string, closeManually = false) { notify(message, 'warning', closeManually); } + + export function infoToast(message: string, closeManually = false) { + notify(message, 'info', closeManually); + } From 637b94c3bbbf2451fe1b888762d191bfaa856002 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 24 Jul 2023 09:54:32 +0200 Subject: [PATCH 65/67] token contains the type --- .../src/components/Bridge/Bridge.svelte | 86 ++++++++++--------- .../src/components/Bridge/state.ts | 6 +- .../bridge-ui-v2/src/libs/bridge/bridges.ts | 6 +- .../src/libs/bridge/checkBalanceToBridge.ts | 4 +- .../src/libs/bridge/getMaxAmountToBridge.ts | 4 +- .../bridge-ui-v2/src/libs/bridge/types.ts | 13 --- .../bridge-ui-v2/src/libs/token/getAddress.ts | 5 +- .../bridge-ui-v2/src/libs/token/getBalance.ts | 5 +- .../src/libs/token/getCrossChainAddress.ts | 5 +- .../src/libs/token/tokens.test.ts | 28 ------ .../bridge-ui-v2/src/libs/token/tokens.ts | 19 +--- packages/bridge-ui-v2/src/libs/token/types.ts | 14 +++ 12 files changed, 81 insertions(+), 114 deletions(-) delete mode 100644 packages/bridge-ui-v2/src/libs/token/tokens.test.ts diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 47540db0a3c..56bf4a46863 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -12,10 +12,9 @@ import { PUBLIC_L1_EXPLORER_URL } from '$env/static/public'; import { type Bridge, type BridgeArgs, bridges, type ERC20BridgeArgs, type ETHBridgeArgs } from '$libs/bridge'; import type { ERC20Bridge } from '$libs/bridge/ERC20Bridge'; - import type { ETHBridge } from '$libs/bridge/ETHBridge'; import { chainContractsMap, chains } from '$libs/chain'; import { ApproveError, NoAllowanceRequiredError, SendERC20Error, SendMessageError } from '$libs/error'; - import { ETHToken, getAddress, isDeployedCrossChain, isETH, tokens } from '$libs/token'; + import { ETHToken, getAddress, isDeployedCrossChain, tokens, TokenType } from '$libs/token'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; import { type Account, account } from '$stores/account'; import { type Network, network } from '$stores/network'; @@ -25,7 +24,7 @@ import Amount from './Amount.svelte'; import { ProcessingFee } from './ProcessingFee'; import Recipient from './Recipient.svelte'; - import { destNetwork, enteredAmount, processingFee, recipientAddress, selectedToken } from './state'; + import { bridgeService, destNetwork, enteredAmount, processingFee, recipientAddress, selectedToken } from './state'; import SwitchChainsButton from './SwitchChainsButton.svelte'; let amountComponent: Amount; @@ -119,13 +118,11 @@ } async function bridge() { - if (!$selectedToken || !$network || !$destNetwork || !$account?.address) return; + if (!$bridgeService || !$selectedToken || !$network || !$destNetwork || !$account?.address) return; try { const walletClient = await getConnectedWallet($network.id); - let bridge: Bridge; - // Common arguments for both ETH and ERC20 bridges let bridgeArgs = { to: $recipientAddress || $account.address, @@ -136,47 +133,52 @@ processingFee: $processingFee, } as BridgeArgs; - if (isETH($selectedToken)) { - bridge = bridges.ETH as ETHBridge; - - // Specific arguments for ETH bridge: - // - bridgeAddress - const bridgeAddress = chainContractsMap[$network.id].bridgeAddress; - bridgeArgs = { ...bridgeArgs, bridgeAddress } as ETHBridgeArgs; - } else { - bridge = bridges.ERC20 as ERC20Bridge; - - // Specific arguments for ERC20 bridge - // - tokenAddress - // - tokenVaultAddress - // - isTokenAlreadyDeployed - const tokenAddress = await getAddress({ - token: $selectedToken, - srcChainId: $network.id, - destChainId: $destNetwork.id, - }); - - if (!tokenAddress) { - throw new Error('token address not found'); + switch ($selectedToken.type) { + case TokenType.ETH: { + // Specific arguments for ETH bridge: + // - bridgeAddress + const bridgeAddress = chainContractsMap[$network.id].bridgeAddress; + bridgeArgs = { ...bridgeArgs, bridgeAddress } as ETHBridgeArgs; + break; } - const tokenVaultAddress = chainContractsMap[$network.id].tokenVaultAddress; - - const isTokenAlreadyDeployed = await isDeployedCrossChain({ - token: $selectedToken, - srcChainId: $network.id, - destChainId: $destNetwork.id, - }); + case TokenType.ERC20: { + // Specific arguments for ERC20 bridge + // - tokenAddress + // - tokenVaultAddress + // - isTokenAlreadyDeployed + const tokenAddress = await getAddress({ + token: $selectedToken, + srcChainId: $network.id, + destChainId: $destNetwork.id, + }); + + if (!tokenAddress) { + throw new Error('token address not found'); + } + + const tokenVaultAddress = chainContractsMap[$network.id].tokenVaultAddress; + + const isTokenAlreadyDeployed = await isDeployedCrossChain({ + token: $selectedToken, + srcChainId: $network.id, + destChainId: $destNetwork.id, + }); + + bridgeArgs = { + ...bridgeArgs, + tokenAddress, + tokenVaultAddress, + isTokenAlreadyDeployed, + } as ERC20BridgeArgs; + break; + } - bridgeArgs = { - ...bridgeArgs, - tokenAddress, - tokenVaultAddress, - isTokenAlreadyDeployed, - } as ERC20BridgeArgs; + default: + throw new Error('invalid token type'); } - const txHash = await bridge.bridge(bridgeArgs); + const txHash = await $bridgeService.bridge(bridgeArgs); infoToast( $t('bridge.bridge.tx', { diff --git a/packages/bridge-ui-v2/src/components/Bridge/state.ts b/packages/bridge-ui-v2/src/components/Bridge/state.ts index 52eda1b3cfc..8dc806c3051 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/state.ts +++ b/packages/bridge-ui-v2/src/components/Bridge/state.ts @@ -1,6 +1,7 @@ import type { Address, Chain, FetchBalanceResult } from '@wagmi/core'; -import { writable } from 'svelte/store'; +import { derived, writable } from 'svelte/store'; +import { bridges } from '$libs/bridge'; import type { Token } from '$libs/token'; // Note: we could combine this with Context API, but since we'll only @@ -35,3 +36,6 @@ export const errorComputingBalance = writable(false); // is a warning but the user must approve allowance before bridging export const insufficientBalance = writable(false); export const insufficientAllowance = writable(false); + +// Derived state +export const bridgeService = derived(selectedToken, (token) => (token ? bridges[token.type] : null)); diff --git a/packages/bridge-ui-v2/src/libs/bridge/bridges.ts b/packages/bridge-ui-v2/src/libs/bridge/bridges.ts index 8eefde0a6dd..56262c7ad4b 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/bridges.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/bridges.ts @@ -1,10 +1,12 @@ +import type { TokenType } from '$libs/token'; + import { ERC20Bridge } from './ERC20Bridge'; import { ERC721Bridge } from './ERC721Bridge'; import { ERC1155Bridge } from './ERC1155Bridge'; import { ETHBridge } from './ETHBridge'; -import type { Bridge, BridgeType } from './types'; +import type { Bridge } from './types'; -export const bridges: Record = { +export const bridges: Record = { ETH: new ETHBridge(), ERC20: new ERC20Bridge(), ERC721: new ERC721Bridge(), diff --git a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts index 1ed7f30a507..b91d5356792 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts @@ -2,7 +2,7 @@ import { type Address, zeroAddress } from 'viem'; import { chainContractsMap } from '$libs/chain'; import { InsufficientAllowanceError, InsufficientBalanceError, RevertedWithFailedError } from '$libs/error'; -import { getAddress, isETH, type Token } from '$libs/token'; +import { getAddress, type Token,TokenType } from '$libs/token'; import { isDeployedCrossChain } from '$libs/token/isDeployedCrossChain'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; @@ -41,7 +41,7 @@ export async function checkBalanceToBridge({ processingFee, } as BridgeArgs; - if (isETH(token)) { + if (token.type === TokenType.ETH) { const { bridgeAddress } = chainContractsMap[srcChainId]; try { diff --git a/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts index 7852a117dcc..38651073a36 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts @@ -1,7 +1,7 @@ import type { Address } from 'viem'; import { chainContractsMap } from '$libs/chain'; -import { isETH, type Token } from '$libs/token'; +import { type Token,TokenType } from '$libs/token'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; import { getLogger } from '$libs/util/logger'; @@ -33,7 +33,7 @@ export async function getMaxAmountToBridge({ // For ERC20 tokens, we can bridge the whole balance let maxAmount = balance; - if (isETH(token)) { + if (token.type === TokenType.ETH) { // We cannot really compute the cost of bridging ETH without if (!to || !srcChainId || !destChainId) { throw Error('missing required arguments to compute cost'); diff --git a/packages/bridge-ui-v2/src/libs/bridge/types.ts b/packages/bridge-ui-v2/src/libs/bridge/types.ts index cbb3d35c39b..274906e45cf 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/types.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/types.ts @@ -1,19 +1,6 @@ import type { WalletClient } from '@wagmi/core'; import type { Address, Hex } from 'viem'; -export enum BridgeType { - ETH = 'ETH', - - // https://ethereum.org/en/developers/docs/standards/tokens/erc-20/ - ERC20 = 'ERC20', - - // https://ethereum.org/en/developers/docs/standards/tokens/erc-721/ - ERC721 = 'ERC721', - - // https://ethereum.org/en/developers/docs/standards/tokens/erc-1155/ - ERC1155 = 'ERC1155', -} - // Bridge sendMessage(message: Message) export type Message = { // Message ID. Will be set in contract diff --git a/packages/bridge-ui-v2/src/libs/token/getAddress.ts b/packages/bridge-ui-v2/src/libs/token/getAddress.ts index c2d8e022cde..988981c67dc 100644 --- a/packages/bridge-ui-v2/src/libs/token/getAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getAddress.ts @@ -4,8 +4,7 @@ import { NoTokenAddressError } from '$libs/error'; import { getLogger } from '$libs/util/logger'; import { getCrossChainAddress } from './getCrossChainAddress'; -import { isETH } from './tokens'; -import type { Token } from './types'; +import { type Token,TokenType } from './types'; type GetAddressArgs = { token: Token; @@ -16,7 +15,7 @@ type GetAddressArgs = { const log = getLogger('token:getAddress'); export async function getAddress({ token, srcChainId, destChainId }: GetAddressArgs) { - if (isETH(token)) return; // ETH doesn't have an address + if (token.type === TokenType.ETH) return; // ETH doesn't have an address // Get the address for the token on the source chain let address: Maybe
    = token.addresses[srcChainId]; diff --git a/packages/bridge-ui-v2/src/libs/token/getBalance.ts b/packages/bridge-ui-v2/src/libs/token/getBalance.ts index 33aad51707f..d8c69f03aef 100644 --- a/packages/bridge-ui-v2/src/libs/token/getBalance.ts +++ b/packages/bridge-ui-v2/src/libs/token/getBalance.ts @@ -4,8 +4,7 @@ import { type Address, zeroAddress } from 'viem'; import { getLogger } from '$libs/util/logger'; import { getAddress } from './getAddress'; -import { isETH } from './tokens'; -import type { Token } from './types'; +import { type Token,TokenType } from './types'; type GetBalanceArgs = { userAddress: Address; @@ -19,7 +18,7 @@ const log = getLogger('token:getBalance'); export async function getBalance({ userAddress, token, srcChainId, destChainId }: GetBalanceArgs) { let tokenBalance: FetchBalanceResult; - if (!token || isETH(token)) { + if (!token || token.type === TokenType.ETH) { // If no token is passed in, we assume is ETH tokenBalance = await fetchBalance({ address: userAddress }); } else { diff --git a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts index 7b30e2c2a23..eaa5e35b040 100644 --- a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts @@ -3,8 +3,7 @@ import { getContract } from '@wagmi/core'; import { tokenVaultABI } from '$abi'; import { chainContractsMap } from '$libs/chain'; -import { isETH } from './tokens'; -import type { Token } from './types'; +import { type Token,TokenType } from './types'; type GetCrossChainAddressArgs = { token: Token; @@ -13,7 +12,7 @@ type GetCrossChainAddressArgs = { }; export function getCrossChainAddress({ token, srcChainId, destChainId }: GetCrossChainAddressArgs) { - if (isETH(token)) return; // ETH doesn't have an address + if (token.type === TokenType.ETH) return; // ETH doesn't have an address const { tokenVaultAddress } = chainContractsMap[destChainId]; diff --git a/packages/bridge-ui-v2/src/libs/token/tokens.test.ts b/packages/bridge-ui-v2/src/libs/token/tokens.test.ts deleted file mode 100644 index 1f1734e8c3d..00000000000 --- a/packages/bridge-ui-v2/src/libs/token/tokens.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ETHToken, isERC20, isETH, isTestToken, testERC20Tokens, TKOToken } from './tokens'; - -vi.mock('$env/static/public'); - -const BLL = testERC20Tokens[0]; -const HORSE = testERC20Tokens[1]; - -describe('Tokens', () => { - it('tests isTestToken', () => { - expect(isTestToken(BLL)).toBeTruthy(); - expect(isTestToken(HORSE)).toBeTruthy(); - expect(isTestToken(ETHToken)).toBeFalsy(); - }); - - it('tests isETH', () => { - expect(isETH(ETHToken)).toBeTruthy(); - expect(isETH(BLL)).toBeFalsy(); - expect(isETH(HORSE)).toBeFalsy(); - expect(isETH(TKOToken)).toBeFalsy(); - }); - - it('tests isERC20', () => { - expect(isERC20(ETHToken)).toBeFalsy(); - expect(isERC20(BLL)).toBeTruthy(); - expect(isERC20(HORSE)).toBeTruthy(); - expect(isERC20(TKOToken)).toBeTruthy(); - }); -}); diff --git a/packages/bridge-ui-v2/src/libs/token/tokens.ts b/packages/bridge-ui-v2/src/libs/token/tokens.ts index 5635c9100ae..c55ec4f7993 100644 --- a/packages/bridge-ui-v2/src/libs/token/tokens.ts +++ b/packages/bridge-ui-v2/src/libs/token/tokens.ts @@ -3,7 +3,7 @@ import { zeroAddress } from 'viem'; import { PUBLIC_L1_CHAIN_ID, PUBLIC_L2_CHAIN_ID, PUBLIC_TEST_ERC20 } from '$env/static/public'; import { jsonParseWithDefault } from '$libs/util/jsonParseWithDefault'; -import type { Token, TokenEnv } from './types'; +import { type Token, type TokenEnv, TokenType } from './types'; export const ETHToken: Token = { name: 'Ether', @@ -13,6 +13,7 @@ export const ETHToken: Token = { }, decimals: 18, symbol: 'ETH', + type: TokenType.ETH, }; export const TKOToken: Token = { @@ -23,6 +24,7 @@ export const TKOToken: Token = { }, decimals: 8, symbol: 'TKO', + type: TokenType.ERC20, }; export const testERC20Tokens: Token[] = jsonParseWithDefault(PUBLIC_TEST_ERC20, []).map( @@ -35,21 +37,8 @@ export const testERC20Tokens: Token[] = jsonParseWithDefault(PUBLIC_ [PUBLIC_L2_CHAIN_ID]: zeroAddress, }, decimals: 18, + type: TokenType.ERC20, }), ); export const tokens = [ETHToken, ...testERC20Tokens]; - -export function isETH(token: Token) { - // Should be fine just by checking the symbol - return token.symbol.toLocaleLowerCase() === ETHToken.symbol.toLocaleLowerCase(); -} - -export function isERC20(token: Token): boolean { - return !isETH(token); -} - -export function isTestToken(token: Token): boolean { - const testTokenSymbols = testERC20Tokens.map((testToken) => testToken.symbol.toLocaleLowerCase()); - return testTokenSymbols.includes(token.symbol.toLocaleLowerCase()); -} diff --git a/packages/bridge-ui-v2/src/libs/token/types.ts b/packages/bridge-ui-v2/src/libs/token/types.ts index e68098c660b..96e180efb64 100644 --- a/packages/bridge-ui-v2/src/libs/token/types.ts +++ b/packages/bridge-ui-v2/src/libs/token/types.ts @@ -1,10 +1,24 @@ import type { Address } from 'viem'; +export enum TokenType { + ETH = 'ETH', + + // https://ethereum.org/en/developers/docs/standards/tokens/erc-20/ + ERC20 = 'ERC20', + + // https://ethereum.org/en/developers/docs/standards/tokens/erc-721/ + ERC721 = 'ERC721', + + // https://ethereum.org/en/developers/docs/standards/tokens/erc-1155/ + ERC1155 = 'ERC1155', +} + export type Token = { name: string; addresses: Record; symbol: string; decimals: number; + type: TokenType; }; export type TokenEnv = { From 8bbf73de0c61fd927b7975acb377370099ccb0df Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 24 Jul 2023 11:27:28 +0200 Subject: [PATCH 66/67] fix ts --- packages/bridge-ui-v2/src/components/Bridge/Actions.svelte | 4 ++-- packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts | 2 +- packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts | 2 +- packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts | 4 ++-- packages/bridge-ui-v2/src/libs/token/getAddress.ts | 2 +- packages/bridge-ui-v2/src/libs/token/getBalance.ts | 2 +- packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte index 9af1ab6894e..f85087a3270 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte @@ -3,7 +3,6 @@ import { Button } from '$components/Button'; import { Icon } from '$components/Icon'; - import { isERC20 } from '$libs/token'; import { account, network } from '$stores'; import { @@ -17,6 +16,7 @@ selectedToken, tokenBalance, } from './state'; + import { TokenType } from '$libs/token'; export let approve: () => Promise; export let bridge: () => Promise; @@ -48,7 +48,7 @@ $: canDoNothing = !hasAddress || !hasNetworks || !hasBalance || !$selectedToken || !$enteredAmount; // Conditions for approve/bridge steps - $: isSelectedERC20 = $selectedToken && isERC20($selectedToken); + $: isSelectedERC20 = $selectedToken && $selectedToken.type === TokenType.ERC20; $: isTokenApproved = isSelectedERC20 && $enteredAmount && !$insufficientAllowance; // Conditions to disable/enable buttons diff --git a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts index b91d5356792..b21addfe4b7 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts @@ -2,7 +2,7 @@ import { type Address, zeroAddress } from 'viem'; import { chainContractsMap } from '$libs/chain'; import { InsufficientAllowanceError, InsufficientBalanceError, RevertedWithFailedError } from '$libs/error'; -import { getAddress, type Token,TokenType } from '$libs/token'; +import { getAddress, type Token, TokenType } from '$libs/token'; import { isDeployedCrossChain } from '$libs/token/isDeployedCrossChain'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; diff --git a/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts index 38651073a36..06e9bc88c06 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts @@ -1,7 +1,7 @@ import type { Address } from 'viem'; import { chainContractsMap } from '$libs/chain'; -import { type Token,TokenType } from '$libs/token'; +import { type Token, TokenType } from '$libs/token'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; import { getLogger } from '$libs/util/logger'; diff --git a/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts b/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts index af8793c8826..cd49bd7262f 100644 --- a/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts +++ b/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts @@ -2,7 +2,7 @@ import { getPublicClient } from '@wagmi/core'; import { zeroAddress } from 'viem'; import { recommentProcessingFee } from '$config'; -import { getAddress, isERC20, type Token } from '$libs/token'; +import { getAddress, type Token,TokenType } from '$libs/token'; type RecommendProcessingFeeArgs = { token: Token; @@ -20,7 +20,7 @@ export async function recommendProcessingFee({ token, destChainId, srcChainId }: // To make it enticing, we say 900k let gasLimit = ethGasLimit; - if (isERC20(token)) { + if (token.type === TokenType.ERC20) { if (!srcChainId) { throw Error('missing required source chain for ERC20 token'); } diff --git a/packages/bridge-ui-v2/src/libs/token/getAddress.ts b/packages/bridge-ui-v2/src/libs/token/getAddress.ts index 988981c67dc..42baeced17b 100644 --- a/packages/bridge-ui-v2/src/libs/token/getAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getAddress.ts @@ -4,7 +4,7 @@ import { NoTokenAddressError } from '$libs/error'; import { getLogger } from '$libs/util/logger'; import { getCrossChainAddress } from './getCrossChainAddress'; -import { type Token,TokenType } from './types'; +import { type Token, TokenType } from './types'; type GetAddressArgs = { token: Token; diff --git a/packages/bridge-ui-v2/src/libs/token/getBalance.ts b/packages/bridge-ui-v2/src/libs/token/getBalance.ts index d8c69f03aef..1c26c9f93df 100644 --- a/packages/bridge-ui-v2/src/libs/token/getBalance.ts +++ b/packages/bridge-ui-v2/src/libs/token/getBalance.ts @@ -4,7 +4,7 @@ import { type Address, zeroAddress } from 'viem'; import { getLogger } from '$libs/util/logger'; import { getAddress } from './getAddress'; -import { type Token,TokenType } from './types'; +import { type Token, TokenType } from './types'; type GetBalanceArgs = { userAddress: Address; diff --git a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts index eaa5e35b040..b282a68432c 100644 --- a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts @@ -3,7 +3,7 @@ import { getContract } from '@wagmi/core'; import { tokenVaultABI } from '$abi'; import { chainContractsMap } from '$libs/chain'; -import { type Token,TokenType } from './types'; +import { type Token, TokenType } from './types'; type GetCrossChainAddressArgs = { token: Token; From 883df6a1a087112f1af2e17483ab0bb328b74942 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 24 Jul 2023 11:32:38 +0200 Subject: [PATCH 67/67] fix lint --- packages/bridge-ui-v2/src/components/Bridge/Actions.svelte | 2 +- packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte | 2 +- packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte index f85087a3270..a815a4cb17b 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Actions.svelte @@ -3,6 +3,7 @@ import { Button } from '$components/Button'; import { Icon } from '$components/Icon'; + import { TokenType } from '$libs/token'; import { account, network } from '$stores'; import { @@ -16,7 +17,6 @@ selectedToken, tokenBalance, } from './state'; - import { TokenType } from '$libs/token'; export let approve: () => Promise; export let bridge: () => Promise; diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 56bf4a46863..8cdbc5aad02 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -10,7 +10,7 @@ import { OnNetwork } from '$components/OnNetwork'; import { TokenDropdown } from '$components/TokenDropdown'; import { PUBLIC_L1_EXPLORER_URL } from '$env/static/public'; - import { type Bridge, type BridgeArgs, bridges, type ERC20BridgeArgs, type ETHBridgeArgs } from '$libs/bridge'; + import { type BridgeArgs, bridges, type ERC20BridgeArgs, type ETHBridgeArgs } from '$libs/bridge'; import type { ERC20Bridge } from '$libs/bridge/ERC20Bridge'; import { chainContractsMap, chains } from '$libs/chain'; import { ApproveError, NoAllowanceRequiredError, SendERC20Error, SendMessageError } from '$libs/error'; diff --git a/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts b/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts index cd49bd7262f..b028386003c 100644 --- a/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts +++ b/packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts @@ -2,7 +2,7 @@ import { getPublicClient } from '@wagmi/core'; import { zeroAddress } from 'viem'; import { recommentProcessingFee } from '$config'; -import { getAddress, type Token,TokenType } from '$libs/token'; +import { getAddress, type Token, TokenType } from '$libs/token'; type RecommendProcessingFeeArgs = { token: Token;