From 2f3df42efe8882334f35ed54e4609aea3b09bf95 Mon Sep 17 00:00:00 2001 From: Korbinian Kasberger Date: Wed, 16 Aug 2023 00:34:48 +0200 Subject: [PATCH 01/64] feat(bridge-ui-v2): enable L3 chain selection --- .../src/components/Bridge/Bridge.svelte | 13 +++---- .../ChainSelector/ChainSelector.svelte | 3 +- .../src/components/Icon/L3.svelte | 9 +++++ .../bridge-ui-v2/src/components/Icon/index.ts | 1 + .../bridge-ui-v2/src/libs/chain/chains.ts | 6 +-- .../src/libs/relayer/RelayerAPIService.ts | 4 +- packages/bridge-ui-v2/static/eldfell.svg | 39 +++++++++++++++++++ 7 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 packages/bridge-ui-v2/src/components/Icon/L3.svelte create mode 100644 packages/bridge-ui-v2/static/eldfell.svg diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index 06fdc67af19..ab07ef3fdfd 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -45,11 +45,10 @@ let recipientComponent: Recipient; let processingFeeComponent: ProcessingFee; - function onNetworkChange(network: Network) { - if (network && chains.length === 2) { - // If there are only two chains, the destination chain will be the other one - const otherChain = chains.find((chain) => chain.id !== network.id); - + function onNetworkChange(newNetwork: Network, oldNetwork: Network) { + // since we just show two networks we simply swap them + if (newNetwork) { + const otherChain = oldNetwork; if (otherChain) destNetwork.set(otherChain); } } @@ -280,12 +279,12 @@
- + - +
diff --git a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte index 5a300baedd1..032958b8a11 100644 --- a/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte +++ b/packages/bridge-ui-v2/src/components/ChainSelector/ChainSelector.svelte @@ -7,7 +7,7 @@ import { EthIcon, Icon, TaikoIcon } from '$components/Icon'; import { LoadingMask } from '$components/LoadingMask'; import { warningToast } from '$components/NotificationToast'; - import { PUBLIC_L1_CHAIN_ID, PUBLIC_L2_CHAIN_ID } from '$env/static/public'; + import { PUBLIC_L1_CHAIN_ID, PUBLIC_L2_CHAIN_ID, PUBLIC_L3_CHAIN_ID } from '$env/static/public'; import { chains } from '$libs/chain'; import { classNames } from '$libs/util/classNames'; import { uid } from '$libs/util/uid'; @@ -32,6 +32,7 @@ let chainToIconMap: Record = { [PUBLIC_L1_CHAIN_ID]: EthIcon, [PUBLIC_L2_CHAIN_ID]: TaikoIcon, + [PUBLIC_L3_CHAIN_ID]: TaikoIcon, // todo: switch to TaikoL3Icon }; let switchingNetwork = false; diff --git a/packages/bridge-ui-v2/src/components/Icon/L3.svelte b/packages/bridge-ui-v2/src/components/Icon/L3.svelte new file mode 100644 index 00000000000..4ee07eceafa --- /dev/null +++ b/packages/bridge-ui-v2/src/components/Icon/L3.svelte @@ -0,0 +1,9 @@ + + + + + diff --git a/packages/bridge-ui-v2/src/components/Icon/index.ts b/packages/bridge-ui-v2/src/components/Icon/index.ts index 6a64010b1da..96baa204900 100644 --- a/packages/bridge-ui-v2/src/components/Icon/index.ts +++ b/packages/bridge-ui-v2/src/components/Icon/index.ts @@ -2,4 +2,5 @@ export { default as BllIcon } from './BLL.svelte'; export { default as EthIcon } from './ETH.svelte'; export { default as HorseIcon } from './HORSE.svelte'; export { default as Icon, type IconType } from './Icon.svelte'; +export { default as TaikoL3Icon } from './L3.svelte'; export { default as TaikoIcon } from './Taiko.svelte'; diff --git a/packages/bridge-ui-v2/src/libs/chain/chains.ts b/packages/bridge-ui-v2/src/libs/chain/chains.ts index 31a0832842b..2c639ecedb4 100644 --- a/packages/bridge-ui-v2/src/libs/chain/chains.ts +++ b/packages/bridge-ui-v2/src/libs/chain/chains.ts @@ -71,7 +71,7 @@ export const taikoChain: Chain = { }, blockExplorers: { default: { - name: 'Main', + name: 'Layer 2', url: PUBLIC_L2_EXPLORER_URL, }, }, @@ -99,7 +99,7 @@ export const taikoL3Chain: Chain = { }; //Todo: add L3 chain -export const chains = [mainnetChain, taikoChain]; +export const chains = [mainnetChain, taikoChain, taikoL3Chain]; export const getChainName = (chainId: number) => { const chain = chains.find((chain) => chain.id === chainId); @@ -135,7 +135,7 @@ export const chainUrlMap: Record< export const chainIcons = { [PUBLIC_L1_CHAIN_ID]: '/ethereum-chain.png', [PUBLIC_L2_CHAIN_ID]: '/taiko-chain.png', - [PUBLIC_L3_CHAIN_ID]: '', + [PUBLIC_L3_CHAIN_ID]: '/eldfell.svg', }; export const chainContractsMap: Record< diff --git a/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts b/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts index 76ae56170dd..a5d8bd908d0 100644 --- a/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts +++ b/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts @@ -25,7 +25,6 @@ const log = getLogger('RelayerAPIService'); export class RelayerAPIService { //Todo: duplicate code in BridgeTxService private static async _getTransactionReceipt(chainId: number, hash: Hash) { - log(`Getting transaction receipt for ${hash} on chain ${chainId}`); try { const client = publicClient({ chainId }); const receipt = await client.getTransactionReceipt({ hash }); @@ -157,7 +156,6 @@ export class RelayerAPIService { } const items = RelayerAPIService._filterDuplicateAndWrongBridge(apiTxs.items); - const txs: BridgeTransaction[] = items.map((tx: APIResponseTransaction) => { let data: string = tx.data.Message.Data; if (data === '') { @@ -234,7 +232,7 @@ export class RelayerAPIService { bridgeTxs.reverse(); // Place new transactions at the top of the list - bridgeTxs.sort((tx) => (tx.status === MessageStatus.NEW ? -1 : 1)); + // bridgeTxs.sort((tx) => (tx.status === MessageStatus.NEW ? -1 : 1)); return { txs: bridgeTxs, paginationInfo }; } diff --git a/packages/bridge-ui-v2/static/eldfell.svg b/packages/bridge-ui-v2/static/eldfell.svg new file mode 100644 index 00000000000..c634e8df405 --- /dev/null +++ b/packages/bridge-ui-v2/static/eldfell.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 57cb45ac57e580be1ddfa919b75cf46f1b01b0ca Mon Sep 17 00:00:00 2001 From: Korbinian Kasberger Date: Wed, 16 Aug 2023 16:30:33 +0200 Subject: [PATCH 02/64] add address mapping for multiple layer configs --- .../src/components/Bridge/Bridge.svelte | 13 +- .../bridge-ui-v2/src/libs/bridge/Bridge.ts | 6 +- .../src/libs/bridge/ERC20Bridge.ts | 8 +- .../bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 4 +- .../src/libs/bridge/checkBalanceToBridge.ts | 12 +- .../src/libs/bridge/getMaxAmountToBridge.ts | 4 +- .../libs/bridge/isTransactionProcessable.ts | 4 +- .../src/libs/bridge/messageStatusPoller.ts | 5 +- .../bridge-ui-v2/src/libs/chain/chains.ts | 134 +++++++++++++----- .../src/libs/proof/BridgeProver.ts | 10 +- .../bridge-ui-v2/src/libs/proof/Prover.ts | 4 +- .../src/libs/relayer/RelayerAPIService.ts | 19 +-- .../src/libs/storage/BridgeTxService.ts | 46 ++++-- .../src/libs/token/getAddress.test.ts | 4 +- .../src/libs/token/getCrossChainAddress.ts | 41 +++--- 15 files changed, 204 insertions(+), 110 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index ab07ef3fdfd..c5f4289f3a2 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -19,7 +19,7 @@ MessageStatus, } from '$libs/bridge'; import type { ERC20Bridge } from '$libs/bridge/ERC20Bridge'; - import { chainContractsMap, chains, chainUrlMap } from '$libs/chain'; + import { routingContractsMap, chains, chainUrlMap } from '$libs/chain'; import { ApproveError, InsufficientAllowanceError, @@ -80,7 +80,7 @@ throw new Error('token address not found'); } - const spenderAddress = chainContractsMap[$network.id].tokenVaultAddress; + const spenderAddress = routingContractsMap[$network.id][$destNetwork.id].erc20VaultAddress; const txHash = await erc20Bridge.approve({ tokenAddress, @@ -155,7 +155,7 @@ case TokenType.ETH: { // Specific arguments for ETH bridge: // - bridgeAddress - const bridgeAddress = chainContractsMap[$network.id].bridgeAddress; + const bridgeAddress = routingContractsMap[$network.id][$destNetwork.id].bridgeAddress; bridgeArgs = { ...bridgeArgs, bridgeAddress } as ETHBridgeArgs; break; } @@ -175,7 +175,7 @@ throw new Error('token address not found'); } - const tokenVaultAddress = chainContractsMap[$network.id].tokenVaultAddress; + const tokenVaultAddress = routingContractsMap[$network.id][$destNetwork.id].erc20VaultAddress; const isTokenAlreadyDeployed = await isDeployedCrossChain({ token: $selectedToken, @@ -191,7 +191,10 @@ } as ERC20BridgeArgs; break; } - + case TokenType.ERC721: + // todo: implement + case TokenType.ERC1155: + // todo: implement default: throw new Error('invalid token type'); } diff --git a/packages/bridge-ui-v2/src/libs/bridge/Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/Bridge.ts index 18c94cc5e9a..b2120d23cd0 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/Bridge.ts @@ -2,7 +2,7 @@ import { getContract, type GetContractResult, type WalletClient } from '@wagmi/c import { type Hash, UserRejectedRequestError } from 'viem'; import { bridgeABI } from '$abi'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { MessageStatusError, RetryError, WrongChainError, WrongOwnerError } from '$libs/error'; import type { BridgeProver } from '$libs/proof'; import { getLogger } from '$libs/util/logger'; @@ -42,7 +42,7 @@ export abstract class Bridge { throw new WrongOwnerError('user cannot process this as it is not their message'); } - const destBridgeAddress = chainContractsMap[connectedChainId].bridgeAddress; + const destBridgeAddress = routingContractsMap[connectedChainId][destChainId].bridgeAddress; const destBridgeContract = getContract({ address: destBridgeAddress, @@ -93,7 +93,7 @@ export abstract class Bridge { // Before releasing we need to make sure the message has failed const destChainId = Number(message.destChainId); - const destBridgeAddress = chainContractsMap[destChainId].bridgeAddress; + const destBridgeAddress = routingContractsMap[srcChainId][destChainId].bridgeAddress; const destBridgeContract = getContract({ address: destBridgeAddress, diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index 91ab846c862..e50a6d6356c 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -3,7 +3,7 @@ import { UserRejectedRequestError } from 'viem'; import { erc20ABI, tokenVaultABI } from '$abi'; import { bridgeService } from '$config'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { ApproveError, InsufficientAllowanceError, @@ -53,8 +53,8 @@ export class ERC20Bridge extends Bridge { const gasLimit = !isTokenAlreadyDeployed ? BigInt(bridgeService.noTokenDeployedGasLimit) : processingFee > 0 - ? bridgeService.noOwnerGasLimit - : BigInt(0); + ? bridgeService.noOwnerGasLimit + : BigInt(0); const sendERC20Args: SendERC20Args = [ BigInt(destChainId), @@ -238,7 +238,7 @@ export class ERC20Bridge extends Bridge { const proof = await this._prover.generateProofToRelease(msgHash, srcChainId, destChainId); - const srcTokenVaultAddress = chainContractsMap[connectedChainId].tokenVaultAddress; + const srcTokenVaultAddress = routingContractsMap[connectedChainId][destChainId].erc20VaultAddress; const srcTokenVaultContract = getContract({ walletClient: wallet, abi: tokenVaultABI, diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts index 471e042d8b0..08d598bb68b 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts @@ -3,7 +3,7 @@ import { UserRejectedRequestError } from 'viem'; import { bridgeABI } from '$abi'; import { bridgeService } from '$config'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { ProcessMessageError, ReleaseError, SendMessageError } from '$libs/error'; import type { BridgeProver } from '$libs/proof'; import { getLogger } from '$libs/util/logger'; @@ -149,7 +149,7 @@ export class ETHBridge extends Bridge { const proof = await this._prover.generateProofToRelease(msgHash, srcChainId, destChainId); - const srcBridgeAddress = chainContractsMap[connectedChainId].bridgeAddress; + const srcBridgeAddress = routingContractsMap[connectedChainId][destChainId].bridgeAddress; const srcBridgeContract = getContract({ walletClient: wallet, abi: bridgeABI, diff --git a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts index 393a259fa9f..c0a0f8991b7 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 { getPublicClient } from '@wagmi/core'; import { type Address, zeroAddress } from 'viem'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { InsufficientAllowanceError, InsufficientBalanceError, RevertedWithFailedError } from '$libs/error'; import { getAddress, type Token, TokenType } from '$libs/token'; import { isDeployedCrossChain } from '$libs/token/isDeployedCrossChain'; @@ -44,8 +44,8 @@ export async function checkBalanceToBridge({ } as BridgeArgs; if (token.type === TokenType.ETH) { - const { bridgeAddress } = chainContractsMap[srcChainId]; - + const { bridgeAddress } = routingContractsMap[srcChainId][destChainId]; + console.log("getting bridge address", bridgeAddress) try { estimatedCost = await estimateCostOfBridging(bridges.ETH, { ...bridgeArgs, @@ -67,7 +67,7 @@ export async function checkBalanceToBridge({ throw new InsufficientBalanceError('you do not have enough balance to bridge'); } } else { - const { tokenVaultAddress } = chainContractsMap[srcChainId]; + const { erc20VaultAddress } = routingContractsMap[srcChainId][destChainId]; const tokenAddress = await getAddress({ token, srcChainId, destChainId }); // since we are briding a token, we need the ETH balance of the wallet @@ -84,7 +84,7 @@ export async function checkBalanceToBridge({ amount, tokenAddress, ownerAddress: wallet.account.address, - spenderAddress: tokenVaultAddress, + spenderAddress: erc20VaultAddress, }); if (allowance) { @@ -105,7 +105,7 @@ export async function checkBalanceToBridge({ estimatedCost = await estimateCostOfBridging(bridges.ERC20, { ...bridgeArgs, tokenAddress, - tokenVaultAddress, + tokenVaultAddress: erc20VaultAddress, isTokenAlreadyDeployed, } as ERC20BridgeArgs); } catch (err) { diff --git a/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts index 06e9bc88c06..612e9a83cd6 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/getMaxAmountToBridge.ts @@ -1,6 +1,6 @@ import type { Address } from 'viem'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { type Token, TokenType } from '$libs/token'; import { getConnectedWallet } from '$libs/util/getConnectedWallet'; import { getLogger } from '$libs/util/logger'; @@ -40,7 +40,7 @@ export async function getMaxAmountToBridge({ } const wallet = await getConnectedWallet(); - const { bridgeAddress } = chainContractsMap[srcChainId]; + const { bridgeAddress } = routingContractsMap[srcChainId][destChainId]; const bridgeArgs = { to, diff --git a/packages/bridge-ui-v2/src/libs/bridge/isTransactionProcessable.ts b/packages/bridge-ui-v2/src/libs/bridge/isTransactionProcessable.ts index f16ed469e15..f58a8abccc9 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/isTransactionProcessable.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/isTransactionProcessable.ts @@ -1,7 +1,7 @@ import { getContract } from '@wagmi/core'; import { crossChainSyncABI } from '$abi'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { publicClient } from '$libs/wagmi'; import { type BridgeTransaction, MessageStatus } from './types'; @@ -19,7 +19,7 @@ export async function isTransactionProcessable(bridgeTx: BridgeTransaction) { // TODO: do better job here as this is to make the UI happy if (status !== MessageStatus.NEW) return true; - const destCrossChainSyncAddress = chainContractsMap[Number(destChainId)].crossChainSyncAddress; + const destCrossChainSyncAddress = routingContractsMap[Number(srcChainId)][Number(destChainId)].crossChainSyncAddress; try { const destCrossChainSyncContract = getContract({ diff --git a/packages/bridge-ui-v2/src/libs/bridge/messageStatusPoller.ts b/packages/bridge-ui-v2/src/libs/bridge/messageStatusPoller.ts index 3c0548484d4..697a4544fd3 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/messageStatusPoller.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/messageStatusPoller.ts @@ -3,11 +3,12 @@ import { EventEmitter } from 'events'; import { bridgeABI } from '$abi'; import { bridgeTransactionPoller } from '$config'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { BridgeTxPollingError } from '$libs/error'; import { getLogger } from '$libs/util/logger'; import { nextTick } from '$libs/util/nextTick'; +import { srcChain } from './../../../../pos-dashboard/src/store/chain'; import { isTransactionProcessable } from './isTransactionProcessable'; import { type BridgeTransaction, MessageStatus } from './types'; @@ -64,7 +65,7 @@ export function startPolling(bridgeTx: BridgeTransaction, runImmediately = false let interval = hashIntervalMap[hash]; // We are gonna be polling the destination bridge contract - const destBridgeAddress = chainContractsMap[Number(destChainId)].bridgeAddress; + const destBridgeAddress = routingContractsMap[Number(srcChain)][Number(destChainId)].bridgeAddress; const destBridgeContract = getContract({ address: destBridgeAddress, abi: bridgeABI, diff --git a/packages/bridge-ui-v2/src/libs/chain/chains.ts b/packages/bridge-ui-v2/src/libs/chain/chains.ts index 2c639ecedb4..0852df5dbc6 100644 --- a/packages/bridge-ui-v2/src/libs/chain/chains.ts +++ b/packages/bridge-ui-v2/src/libs/chain/chains.ts @@ -5,32 +5,38 @@ import { PUBLIC_L1_CHAIN_ID, PUBLIC_L1_CHAIN_NAME, PUBLIC_L1_CROSS_CHAIN_SYNC_ADDRESS, + PUBLIC_L1_ERC20_VAULT_ADDRESS, PUBLIC_L1_ERC721_VAULT_ADDRESS, PUBLIC_L1_ERC1155_VAULT_ADDRESS, PUBLIC_L1_EXPLORER_URL, + PUBLIC_L1_L2_BRIDGE_ADDRESS, + PUBLIC_L1_L2_CROSS_CHAIN_SYNC_ADDRESS, + PUBLIC_L1_L2_ERC20_VAULT_ADDRESS, + PUBLIC_L1_L2_ERC721_VAULT_ADDRESS, + PUBLIC_L1_L2_ERC1155_VAULT_ADDRESS, + PUBLIC_L1_L2_SIGNAL_SERVICE_ADDRESS, PUBLIC_L1_RPC_URL, PUBLIC_L1_SIGNAL_SERVICE_ADDRESS, - PUBLIC_L1_TOKEN_VAULT_ADDRESS, - PUBLIC_L2_BRIDGE_ADDRESS, PUBLIC_L2_CHAIN_ID, PUBLIC_L2_CHAIN_NAME, - PUBLIC_L2_CROSS_CHAIN_SYNC_ADDRESS, - PUBLIC_L2_ERC721_VAULT_ADDRESS, - PUBLIC_L2_ERC1155_VAULT_ADDRESS, PUBLIC_L2_EXPLORER_URL, PUBLIC_L2_RPC_URL, - PUBLIC_L2_SIGNAL_SERVICE_ADDRESS, - PUBLIC_L2_TOKEN_VAULT_ADDRESS, PUBLIC_L3_BRIDGE_ADDRESS, PUBLIC_L3_CHAIN_ID, PUBLIC_L3_CHAIN_NAME, PUBLIC_L3_CROSS_CHAIN_SYNC_ADDRESS, + PUBLIC_L3_ERC20_VAULT_ADDRESS, PUBLIC_L3_ERC721_VAULT_ADDRESS, PUBLIC_L3_ERC1155_VAULT_ADDRESS, PUBLIC_L3_EXPLORER_URL, + PUBLIC_L3_L2_BRIDGE_ADDRESS, + PUBLIC_L3_L2_CROSS_CHAIN_SYNC_ADDRESS, + PUBLIC_L3_L2_ERC20_VAULT_ADDRESS, + PUBLIC_L3_L2_ERC721_VAULT_ADDRESS, + PUBLIC_L3_L2_ERC1155_VAULT_ADDRESS, + PUBLIC_L3_L2_SIGNAL_SERVICE_ADDRESS, PUBLIC_L3_RPC_URL, PUBLIC_L3_SIGNAL_SERVICE_ADDRESS, - PUBLIC_L3_TOKEN_VAULT_ADDRESS, } from '$env/static/public'; export type ChainID = bigint; @@ -138,39 +144,93 @@ export const chainIcons = { [PUBLIC_L3_CHAIN_ID]: '/eldfell.svg', }; -export const chainContractsMap: Record< - string, - { - bridgeAddress: Address; - tokenVaultAddress: Address; - erc721VaultAddress: Address; - erc1155VaultAddress: Address; - crossChainSyncAddress: Address; - signalServiceAddress: Address; - } -> = { +type AddressConfig = { + bridgeAddress: Address; + erc20VaultAddress: Address; + erc721VaultAddress: Address; + erc1155VaultAddress: Address; + crossChainSyncAddress: Address; + signalServiceAddress: Address; +}; + +type ConfiguredChain = typeof chains[number]['id']; +type RoutingConfig = Record; + + + +export const routingContractsMap: Record = { [PUBLIC_L1_CHAIN_ID]: { - bridgeAddress: PUBLIC_L1_BRIDGE_ADDRESS as Address, - tokenVaultAddress: PUBLIC_L1_TOKEN_VAULT_ADDRESS as Address, - erc721VaultAddress: PUBLIC_L1_ERC721_VAULT_ADDRESS as Address, - erc1155VaultAddress: PUBLIC_L1_ERC1155_VAULT_ADDRESS as Address, - crossChainSyncAddress: PUBLIC_L1_CROSS_CHAIN_SYNC_ADDRESS as Address, - signalServiceAddress: PUBLIC_L1_SIGNAL_SERVICE_ADDRESS as Address, + // L1 -> L2 + [PUBLIC_L2_CHAIN_ID]: { + bridgeAddress: PUBLIC_L1_BRIDGE_ADDRESS as Address, + erc20VaultAddress: PUBLIC_L1_ERC20_VAULT_ADDRESS as Address, + erc721VaultAddress: PUBLIC_L1_ERC721_VAULT_ADDRESS as Address, + erc1155VaultAddress: PUBLIC_L1_ERC1155_VAULT_ADDRESS as Address, + crossChainSyncAddress: PUBLIC_L1_CROSS_CHAIN_SYNC_ADDRESS as Address, + signalServiceAddress: PUBLIC_L1_SIGNAL_SERVICE_ADDRESS as Address, + } as AddressConfig, }, [PUBLIC_L2_CHAIN_ID]: { - bridgeAddress: PUBLIC_L2_BRIDGE_ADDRESS as Address, - tokenVaultAddress: PUBLIC_L2_TOKEN_VAULT_ADDRESS as Address, - erc721VaultAddress: PUBLIC_L2_ERC721_VAULT_ADDRESS as Address, - erc1155VaultAddress: PUBLIC_L2_ERC1155_VAULT_ADDRESS as Address, - crossChainSyncAddress: PUBLIC_L2_CROSS_CHAIN_SYNC_ADDRESS as Address, - signalServiceAddress: PUBLIC_L2_SIGNAL_SERVICE_ADDRESS as Address, + // L2 -> L1 + [PUBLIC_L1_CHAIN_ID]: { + bridgeAddress: PUBLIC_L1_L2_BRIDGE_ADDRESS as Address, + erc20VaultAddress: PUBLIC_L1_L2_ERC20_VAULT_ADDRESS as Address, + erc721VaultAddress: PUBLIC_L1_L2_ERC721_VAULT_ADDRESS as Address, + erc1155VaultAddress: PUBLIC_L1_L2_ERC1155_VAULT_ADDRESS as Address, + crossChainSyncAddress: PUBLIC_L1_L2_CROSS_CHAIN_SYNC_ADDRESS as Address, + signalServiceAddress: PUBLIC_L1_L2_SIGNAL_SERVICE_ADDRESS as Address, + + } as AddressConfig, + // L2 -> L3 + [PUBLIC_L3_CHAIN_ID]: { + bridgeAddress: PUBLIC_L3_L2_BRIDGE_ADDRESS as Address, + erc20VaultAddress: PUBLIC_L3_L2_ERC20_VAULT_ADDRESS as Address, + erc721VaultAddress: PUBLIC_L3_L2_ERC721_VAULT_ADDRESS as Address, + erc1155VaultAddress: PUBLIC_L3_L2_ERC1155_VAULT_ADDRESS as Address, + crossChainSyncAddress: PUBLIC_L3_L2_CROSS_CHAIN_SYNC_ADDRESS as Address, + signalServiceAddress: PUBLIC_L3_L2_SIGNAL_SERVICE_ADDRESS as Address, + } as AddressConfig, }, [PUBLIC_L3_CHAIN_ID]: { - bridgeAddress: PUBLIC_L3_BRIDGE_ADDRESS as Address, - tokenVaultAddress: PUBLIC_L3_TOKEN_VAULT_ADDRESS as Address, - erc721VaultAddress: PUBLIC_L3_ERC721_VAULT_ADDRESS as Address, - erc1155VaultAddress: PUBLIC_L3_ERC1155_VAULT_ADDRESS as Address, - crossChainSyncAddress: PUBLIC_L3_CROSS_CHAIN_SYNC_ADDRESS as Address, - signalServiceAddress: PUBLIC_L3_SIGNAL_SERVICE_ADDRESS as Address, + // L3 -> L2 + [PUBLIC_L2_CHAIN_ID]: { + bridgeAddress: PUBLIC_L3_BRIDGE_ADDRESS as Address, + erc20VaultAddress: PUBLIC_L3_ERC20_VAULT_ADDRESS as Address, + erc721VaultAddress: PUBLIC_L3_ERC721_VAULT_ADDRESS as Address, + erc1155VaultAddress: PUBLIC_L3_ERC1155_VAULT_ADDRESS as Address, + crossChainSyncAddress: PUBLIC_L3_CROSS_CHAIN_SYNC_ADDRESS as Address, + signalServiceAddress: PUBLIC_L3_SIGNAL_SERVICE_ADDRESS as Address, + + } as AddressConfig, }, }; + +// export const chainContractsMap: Record< +// string, +// BrideContractsConfig +// > = { +// [PUBLIC_L1_CHAIN_ID]: { +// bridgeAddress: PUBLIC_L1_BRIDGE_ADDRESS as Address, +// tokenVaultAddress: PUBLIC_L1_TOKEN_VAULT_ADDRESS as Address, +// erc721VaultAddress: PUBLIC_L1_ERC721_VAULT_ADDRESS as Address, +// erc1155VaultAddress: PUBLIC_L1_ERC1155_VAULT_ADDRESS as Address, +// crossChainSyncAddress: PUBLIC_L1_CROSS_CHAIN_SYNC_ADDRESS as Address, +// signalServiceAddress: PUBLIC_L1_SIGNAL_SERVICE_ADDRESS as Address, +// }, +// [PUBLIC_L2_CHAIN_ID]: { +// bridgeAddress: PUBLIC_L2_BRIDGE_ADDRESS as Address, +// tokenVaultAddress: PUBLIC_L2_TOKEN_VAULT_ADDRESS as Address, +// erc721VaultAddress: PUBLIC_L2_ERC721_VAULT_ADDRESS as Address, +// erc1155VaultAddress: PUBLIC_L2_ERC1155_VAULT_ADDRESS as Address, +// crossChainSyncAddress: PUBLIC_L2_CROSS_CHAIN_SYNC_ADDRESS as Address, +// signalServiceAddress: PUBLIC_L2_SIGNAL_SERVICE_ADDRESS as Address, +// }, +// [PUBLIC_L3_CHAIN_ID]: { +// bridgeAddress: PUBLIC_L3_BRIDGE_ADDRESS as Address, +// tokenVaultAddress: PUBLIC_L3_TOKEN_VAULT_ADDRESS as Address, +// erc721VaultAddress: PUBLIC_L3_ERC721_VAULT_ADDRESS as Address, +// erc1155VaultAddress: PUBLIC_L3_ERC1155_VAULT_ADDRESS as Address, +// crossChainSyncAddress: PUBLIC_L3_CROSS_CHAIN_SYNC_ADDRESS as Address, +// signalServiceAddress: PUBLIC_L3_SIGNAL_SERVICE_ADDRESS as Address, +// }, +// }; diff --git a/packages/bridge-ui-v2/src/libs/proof/BridgeProver.ts b/packages/bridge-ui-v2/src/libs/proof/BridgeProver.ts index 465ad203bc7..fb29da1dcd6 100644 --- a/packages/bridge-ui-v2/src/libs/proof/BridgeProver.ts +++ b/packages/bridge-ui-v2/src/libs/proof/BridgeProver.ts @@ -1,7 +1,7 @@ import { encodeAbiParameters, type Hash, toHex, toRlp } from 'viem'; import { MessageStatus } from '$libs/bridge'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { InvalidProofError } from '$libs/error'; import { Prover } from './Prover'; @@ -39,8 +39,8 @@ export class BridgeProver extends Prover { } async generateProofToProcessMessage(msgHash: Hash, srcChainId: number, destChainId: number) { - const srcBridgeAddress = chainContractsMap[srcChainId].bridgeAddress; - const srcSignalServiceAddress = chainContractsMap[srcChainId].signalServiceAddress; + const srcBridgeAddress = routingContractsMap[srcChainId][destChainId].bridgeAddress; + const srcSignalServiceAddress = routingContractsMap[srcChainId][destChainId].signalServiceAddress; const { proof, block } = await this.generateProof({ msgHash, @@ -59,8 +59,8 @@ export class BridgeProver extends Prover { } async generateProofToRelease(msgHash: Hash, srcChainId: number, destChainId: number) { - const srcBridgeAddress = chainContractsMap[srcChainId].bridgeAddress; - const destBridgeAddress = chainContractsMap[destChainId].bridgeAddress; + const srcBridgeAddress = routingContractsMap[srcChainId][destChainId].bridgeAddress; + const destBridgeAddress = routingContractsMap[srcChainId][destChainId].bridgeAddress; const { proof, block } = await this.generateProof({ msgHash, diff --git a/packages/bridge-ui-v2/src/libs/proof/Prover.ts b/packages/bridge-ui-v2/src/libs/proof/Prover.ts index 7b182137144..9813c104230 100644 --- a/packages/bridge-ui-v2/src/libs/proof/Prover.ts +++ b/packages/bridge-ui-v2/src/libs/proof/Prover.ts @@ -2,7 +2,7 @@ import { getContract, type GetContractResult, type PublicClient } from '@wagmi/c import { type Address, encodePacked, type Hex, keccak256 } from 'viem'; import { crossChainSyncABI } from '$abi'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { PendingBlockError } from '$libs/error'; import { getLogger } from '$libs/util/logger'; import { publicClient } from '$libs/wagmi'; @@ -27,7 +27,7 @@ export class Prover { async generateProof(args: GenerateProofArgs) { const { msgHash, clientChainId, contractAddress, crossChainSyncChainId, proofForAccountAddress } = args; - const crossChainSyncAddress = chainContractsMap[crossChainSyncChainId].crossChainSyncAddress; + const crossChainSyncAddress = routingContractsMap[clientChainId][crossChainSyncChainId].crossChainSyncAddress; // Get the block from chain A based on the latest block hash // we get cross chain (Taiko contract on chain B) diff --git a/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts b/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts index a5d8bd908d0..c4236dbef55 100644 --- a/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts +++ b/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts @@ -9,7 +9,8 @@ import { TokenType } from '$libs/token'; import { getLogger } from '$libs/util/logger'; import { publicClient } from '$libs/wagmi'; -import { chainContractsMap, isSupportedChain } from '../chain/chains'; +import { isSupportedChain, routingContractsMap } from '../chain/chains'; +import { destChain } from './../../../../bridge-ui/src/store/chain'; import type { APIRequestParams, APIResponse, @@ -46,7 +47,7 @@ export class RelayerAPIService { continue; } - const { bridgeAddress } = chainContractsMap[item.chainID]; // TODO: also handle unsupported chain + const { bridgeAddress } = routingContractsMap[Number(item.data.Message.SrcChainId)][Number(item.data.Message.DestChainId)]; // TODO: also handle unsupported chain const { DestChainId, SrcChainId } = Message; const { transactionHash, address } = Raw; @@ -75,12 +76,12 @@ export class RelayerAPIService { return filteredItems; } - private static async _getBridgeMessageStatus(msgHash: Hash, chainId: number) { - const { bridgeAddress } = chainContractsMap[Number(chainId)]; + private static async _getBridgeMessageStatus({ msgHash, srcChainId, destChainId }: { msgHash: Hash, srcChainId: number, destChainId: number }) { + const { bridgeAddress } = routingContractsMap[Number(srcChainId)][Number(destChainId)]; const result = await readContract({ address: bridgeAddress, abi: bridgeABI, - chainId: Number(chainId), + chainId: Number(destChainId), functionName: 'getMessageStatus', args: [msgHash], }); @@ -211,7 +212,7 @@ export class RelayerAPIService { if (!msgHash) return; //todo: handle this case - const status = await RelayerAPIService._getBridgeMessageStatus(msgHash, Number(destChainId)); + const status = await RelayerAPIService._getBridgeMessageStatus({ msgHash, srcChainId: Number(srcChainId), destChainId: Number(destChainId) }); // Update the status bridgeTx.status = status; @@ -265,11 +266,11 @@ export class RelayerAPIService { function _checkType(bridgeTx: BridgeTransaction): TokenType { const to = bridgeTx.message?.to; switch (to) { - case chainContractsMap[Number(bridgeTx.srcChainId)].tokenVaultAddress: + case routingContractsMap[Number(bridgeTx.srcChainId)][Number(bridgeTx.destChainId)].erc20VaultAddress: return TokenType.ERC20; - case chainContractsMap[Number(bridgeTx.srcChainId)].erc721VaultAddress: + case routingContractsMap[Number(bridgeTx.srcChainId)][Number(bridgeTx.destChainId)].erc721VaultAddress: return TokenType.ERC721; - case chainContractsMap[Number(bridgeTx.srcChainId)].erc1155VaultAddress: + case routingContractsMap[Number(bridgeTx.srcChainId)][Number(bridgeTx.destChainId)].erc1155VaultAddress: return TokenType.ERC1155; default: return TokenType.ETH; diff --git a/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts b/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts index bc531b77141..3e0359b6093 100644 --- a/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts +++ b/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts @@ -4,13 +4,23 @@ import type { Address, Hash, TransactionReceipt } from 'viem'; import { bridgeABI } from '$abi'; import { pendingTransaction, storageService } from '$config'; import { type BridgeTransaction, MessageStatus } from '$libs/bridge'; -import { chainContractsMap, isSupportedChain } from '$libs/chain'; +import { isSupportedChain, routingContractsMap } from '$libs/chain'; import { jsonParseWithDefault } from '$libs/util/jsonParseWithDefault'; import { getLogger } from '$libs/util/logger'; import { publicClient } from '$libs/wagmi'; +import { destChain } from './../../../../bridge-ui/src/store/chain'; + const log = getLogger('storage:BridgeTxService'); + +type BridgeMessageParams = { + msgHash: Hash; + srcChainId: number; + destChainId: number; +}; + + export class BridgeTxService { private readonly storage: Storage; @@ -27,13 +37,13 @@ export class BridgeTxService { } } - private static async _getBridgeMessageSent(userAddress: Address, chainId: number, blockNumber: number) { + private static async _getBridgeMessageSent({ userAddress, srcChainId, destChainId, blockNumber }: { userAddress: Address, srcChainId: number, destChainId: number, blockNumber: number }) { // Gets the event MessageSent from the bridge contract // in the block where the transaction was mined, and find // our event MessageSent whose owner is the address passed in - const bridgeAddress = chainContractsMap[chainId].bridgeAddress; - const client = publicClient({ chainId }); + const bridgeAddress = routingContractsMap[srcChainId][destChainId].bridgeAddress; + const client = publicClient({ chainId: srcChainId }); const filter = await client.createContractEventFilter({ abi: bridgeABI, @@ -50,15 +60,17 @@ export class BridgeTxService { return messageSentEvents.find(({ args }) => args.message?.owner.toLowerCase() === userAddress.toLowerCase()); } - private static _getBridgeMessageStatus(msgHash: Hash, chainId: number) { - const bridgeAddress = chainContractsMap[chainId].bridgeAddress; + private static _getBridgeMessageStatus({ msgHash, srcChainId, destChainId }: BridgeMessageParams) { + const bridgeAddress = routingContractsMap[srcChainId][destChainId].bridgeAddress; const bridgeContract = getContract({ - chainId, + chainId: destChainId, abi: bridgeABI, address: bridgeAddress, }); + console.log("getting message status", msgHash, bridgeContract.address, srcChainId, destChainId) + return bridgeContract.read.getMessageStatus([msgHash]) as Promise; } @@ -105,11 +117,12 @@ export class BridgeTxService { // We have receipt bridgeTx.receipt = receipt; - const messageSentEvent = await BridgeTxService._getBridgeMessageSent( - address, - Number(srcChainId), - Number(receipt.blockNumber), - ); + const messageSentEvent = await BridgeTxService._getBridgeMessageSent({ + userAddress: address, + srcChainId: Number(srcChainId), + destChainId: Number(destChainId), + blockNumber: Number(receipt.blockNumber) + }); if (!messageSentEvent?.args?.msgHash || !messageSentEvent?.args?.message) { // No message yet, so we can't get more info from this transaction @@ -123,7 +136,14 @@ export class BridgeTxService { bridgeTx.msgHash = msgHash; bridgeTx.message = message; - const status = await BridgeTxService._getBridgeMessageStatus(msgHash, Number(destChainId)); + console.log("message", message, msgHash); + + const status = await BridgeTxService._getBridgeMessageStatus( + { + msgHash: msgHash, + srcChainId: Number(srcChainId), + destChainId: Number(destChainId) + }); bridgeTx.status = status; return bridgeTx; diff --git a/packages/bridge-ui-v2/src/libs/token/getAddress.test.ts b/packages/bridge-ui-v2/src/libs/token/getAddress.test.ts index 6818da3c2f6..ba9b82886e9 100644 --- a/packages/bridge-ui-v2/src/libs/token/getAddress.test.ts +++ b/packages/bridge-ui-v2/src/libs/token/getAddress.test.ts @@ -2,7 +2,7 @@ import { getContract, type GetContractResult } from '@wagmi/core'; import { tokenVaultABI } from '$abi'; import { PUBLIC_L1_CHAIN_ID, PUBLIC_L2_CHAIN_ID } from '$env/static/public'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { getAddress } from './getAddress'; import { ETHToken, testERC20Tokens } from './tokens'; @@ -54,7 +54,7 @@ describe('getAddress', () => { ]); expect(getContract).toHaveBeenCalledWith({ abi: tokenVaultABI, - address: chainContractsMap[PUBLIC_L2_CHAIN_ID].tokenVaultAddress, + address: routingContractsMap[Number(PUBLIC_L2_CHAIN_ID)][Number(PUBLIC_L1_CHAIN_ID)].erc20VaultAddress, chainId: Number(PUBLIC_L2_CHAIN_ID), }); }); diff --git a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts index b282a68432c..9d9a9e639d1 100644 --- a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts @@ -1,7 +1,7 @@ import { getContract } from '@wagmi/core'; import { tokenVaultABI } from '$abi'; -import { chainContractsMap } from '$libs/chain'; +import { routingContractsMap } from '$libs/chain'; import { type Token, TokenType } from './types'; @@ -14,19 +14,28 @@ type GetCrossChainAddressArgs = { export function getCrossChainAddress({ token, srcChainId, destChainId }: GetCrossChainAddressArgs) { if (token.type === TokenType.ETH) return; // ETH doesn't have an address - const { tokenVaultAddress } = chainContractsMap[destChainId]; - - const srcChainTokenAddress = token.addresses[srcChainId]; - - // We cannot find the address if we don't have - // the token address on the source chain - if (!srcChainTokenAddress) return; - - const destTokenVaultContract = getContract({ - abi: tokenVaultABI, - chainId: destChainId, - address: tokenVaultAddress, - }); - - return destTokenVaultContract.read.canonicalToBridged([BigInt(srcChainId), srcChainTokenAddress]); + if (token.type === TokenType.ERC20) { + const { erc20VaultAddress } = routingContractsMap[srcChainId][destChainId]; + + const srcChainTokenAddress = token.addresses[srcChainId]; + + // We cannot find the address if we don't have + // the token address on the source chain + if (!srcChainTokenAddress) return; + + const destTokenVaultContract = getContract({ + abi: tokenVaultABI, + chainId: destChainId, + address: erc20VaultAddress, + }); + return destTokenVaultContract.read.canonicalToBridged([BigInt(srcChainId), srcChainTokenAddress]); + } + if (token.type === TokenType.ERC721) { + // todo: implement + const { erc721VaultAddress } = routingContractsMap[srcChainId][destChainId]; + } + if (token.type === TokenType.ERC1155) { + const { erc1155VaultAddress } = routingContractsMap[srcChainId][destChainId]; + //todo: implement + } } From 5756d28e3396822c47efec9fa1820aa3ded849c2 Mon Sep 17 00:00:00 2001 From: Korbinian Kasberger Date: Thu, 17 Aug 2023 00:28:04 +0200 Subject: [PATCH 03/64] additional logic of finding the crosschain address --- .../bridge-ui-v2/src/libs/token/getAddress.ts | 8 +- .../src/libs/token/getCrossChainAddress.ts | 112 +++++++++++++----- 2 files changed, 83 insertions(+), 37 deletions(-) diff --git a/packages/bridge-ui-v2/src/libs/token/getAddress.ts b/packages/bridge-ui-v2/src/libs/token/getAddress.ts index 42baeced17b..1e0ccedc0d1 100644 --- a/packages/bridge-ui-v2/src/libs/token/getAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getAddress.ts @@ -25,13 +25,11 @@ export async function getAddress({ token, srcChainId, destChainId }: GetAddressA // there is nothing we can do here. if (!destChainId) return; - // Find the address on the destination chain instead. We are - // most likely on Taiko chain. We need to then query the - // canonicalToBridged mapping on the other chain + address = await getCrossChainAddress({ token, - srcChainId: destChainId, - destChainId: srcChainId, + srcChainId: srcChainId, + destChainId: destChainId, }); if (!address || address === zeroAddress) { diff --git a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts index 4c352b366cb..0882f737a00 100644 --- a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts @@ -2,7 +2,7 @@ import { type Address, getContract } from '@wagmi/core'; import { zeroAddress } from 'viem'; import { tokenVaultABI } from '$abi'; -import { routingContractsMap } from '$libs/chain'; +import { chains, routingContractsMap } from '$libs/chain'; import { getLogger } from '$libs/util/logger'; import { type GetCrossChainAddressArgs, TokenType } from './types'; @@ -27,39 +27,87 @@ export async function getCrossChainAddress({ return token.addresses[destChainId]; } + // if (!srcChainTokenAddress) return null; + + // it could be that we don't have the token address on the current chain, but we have it on another chain if (!srcChainTokenAddress || srcChainTokenAddress === zeroAddress) { - throw new Error( - `Token ${token.symbol} (${token.name}) does not have any valid configured address on chain ${srcChainId} or ${destChainId}`, - ); + // find one chain with a configured address + const configuredChainId = Object.keys(token.addresses).find((chainId) => token.addresses[chainId] !== zeroAddress); + + // if we have no configuration at all, we cannot find the address + if (!configuredChainId) return null; + + // get the configured token address on that chain + const configuredTokenAddress = token.addresses[Number(configuredChainId)]; + + // we need find a vault that is configured with that chainId as the destination + const erc20VaultInfo = chains + .filter(chain => { + const routesForChain = routingContractsMap[chain.id]; + return routesForChain && routesForChain[Number(configuredChainId)] && routesForChain[Number(configuredChainId)].erc20VaultAddress; + }) + .map(chain => { + const erc20VaultAddress = routingContractsMap[chain.id][Number(configuredChainId)].erc20VaultAddress; + return { + chainId: chain.id, + vaultAddress: erc20VaultAddress + }; + }); + + // if we don't have any vault, we cannot find the address + if (erc20VaultInfo.length === 0) return null; + + // use the first one we find + const { chainId: foundChainId, vaultAddress: erc20VaultAddress } = erc20VaultInfo[0]; + + const configuredTokenVaultContract = getContract({ + abi: tokenVaultABI, + chainId: foundChainId, + address: erc20VaultAddress, + }); + + const bridgedAddress = await configuredTokenVaultContract.read.canonicalToBridged([BigInt(configuredChainId), configuredTokenAddress]); + + // now that we have the bridgedAddress address, we can check if it is bridged + const { erc20VaultAddress: destChainTokenVaultAddress } = routingContractsMap[destChainId][Number(configuredChainId)]; + const destTokenVaultContract = getContract({ + abi: tokenVaultABI, + chainId: srcChainId, + address: destChainTokenVaultAddress, + }); + return await destTokenVaultContract.read.canonicalToBridged([BigInt(destChainId), bridgedAddress]); } + else { + const { erc20VaultAddress: srcChainTokenVaultAddress } = routingContractsMap[srcChainId][destChainId]; + const { erc20VaultAddress: destChainTokenVaultAddress } = routingContractsMap[destChainId][srcChainId]; + + const srcTokenVaultContract = getContract({ + abi: tokenVaultABI, + chainId: srcChainId, + address: srcChainTokenVaultAddress, + }); + + const destTokenVaultContract = getContract({ + abi: tokenVaultABI, + chainId: destChainId, + address: destChainTokenVaultAddress, + }); - const { erc20VaultAddress: srcChainTokenVaultAddress } = routingContractsMap[srcChainId][destChainId]; - const { erc20VaultAddress: destChainTokenVaultAddress } = routingContractsMap[destChainId][srcChainId]; - - const srcTokenVaultContract = getContract({ - abi: tokenVaultABI, - chainId: srcChainId, - address: srcChainTokenVaultAddress, - }); - - const destTokenVaultContract = getContract({ - abi: tokenVaultABI, - chainId: destChainId, - address: destChainTokenVaultAddress, - }); - - // first we need to figure out the canonical address of the token - const canonicalTokenInfo = await srcTokenVaultContract.read.bridgedToCanonical([srcChainTokenAddress]); - const canonicalTokenAddress = canonicalTokenInfo[1]; // this will break if the contracts ever change the order of the return values - - // if the canonical address is 0x0, then the token is canonical - if (canonicalTokenAddress === zeroAddress) { - // let's check if it is bridged on the destination chain by querying the destination vault - // e.g. bridged L1 -> L2 with native L1 token - return await destTokenVaultContract.read.canonicalToBridged([BigInt(srcChainId), srcChainTokenAddress]); - } else { - // if we have found a canonical, we can check for the bridged address on the source token vault - // e.g. bridging L2 -> L1 with native L1 token - return await srcTokenVaultContract.read.canonicalToBridged([BigInt(destChainId), canonicalTokenAddress]); + // first we need to figure out the canonical address of the token + const canonicalTokenInfo = await srcTokenVaultContract.read.bridgedToCanonical([srcChainTokenAddress]); + const canonicalTokenAddress = canonicalTokenInfo[1]; // this will break if the contracts ever change the order of the return values + + // if the canonical address is 0x0, then the token is canonical + if (canonicalTokenAddress === zeroAddress) { + // let's check if it is bridged on the destination chain by querying the destination vault + // e.g. bridged L1 -> L2 with native L1 token + return await destTokenVaultContract.read.canonicalToBridged([BigInt(srcChainId), srcChainTokenAddress]); + } else { + // if we have found a canonical, we can check for the bridged address on the source token vault + // e.g. bridging L2 -> L1 with native L1 token + return await srcTokenVaultContract.read.canonicalToBridged([BigInt(destChainId), canonicalTokenAddress]); + } } + + } From 810c37dd45c5dd164ddcf2ebc0e114b64ee128fa Mon Sep 17 00:00:00 2001 From: Korbinian Kasberger Date: Thu, 17 Aug 2023 00:33:33 +0200 Subject: [PATCH 04/64] linting --- .../src/components/Bridge/Bridge.svelte | 8 +++-- .../src/libs/bridge/ERC20Bridge.ts | 4 +-- .../src/libs/bridge/checkBalanceToBridge.ts | 1 - .../bridge-ui-v2/src/libs/chain/chains.ts | 36 +------------------ .../src/libs/relayer/RelayerAPIService.ts | 22 +++++++++--- .../src/libs/storage/BridgeTxService.ts | 27 ++++++++------ .../bridge-ui-v2/src/libs/token/getAddress.ts | 1 - .../src/libs/token/getCrossChainAddress.ts | 27 ++++++++------ 8 files changed, 58 insertions(+), 68 deletions(-) diff --git a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte index c5f4289f3a2..90513034fb9 100644 --- a/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte +++ b/packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte @@ -19,7 +19,7 @@ MessageStatus, } from '$libs/bridge'; import type { ERC20Bridge } from '$libs/bridge/ERC20Bridge'; - import { routingContractsMap, chains, chainUrlMap } from '$libs/chain'; + import { chains, chainUrlMap, routingContractsMap } from '$libs/chain'; import { ApproveError, InsufficientAllowanceError, @@ -192,9 +192,11 @@ break; } case TokenType.ERC721: - // todo: implement + // todo: implement + break; case TokenType.ERC1155: - // todo: implement + // todo: implement + break; default: throw new Error('invalid token type'); } diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts index e50a6d6356c..9828693499b 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts @@ -53,8 +53,8 @@ export class ERC20Bridge extends Bridge { const gasLimit = !isTokenAlreadyDeployed ? BigInt(bridgeService.noTokenDeployedGasLimit) : processingFee > 0 - ? bridgeService.noOwnerGasLimit - : BigInt(0); + ? bridgeService.noOwnerGasLimit + : BigInt(0); const sendERC20Args: SendERC20Args = [ BigInt(destChainId), diff --git a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts index f90365aa397..adae0290f21 100644 --- a/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts +++ b/packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts @@ -45,7 +45,6 @@ export async function checkBalanceToBridge({ if (token.type === TokenType.ETH) { const { bridgeAddress } = routingContractsMap[srcChainId][destChainId]; - console.log("getting bridge address", bridgeAddress) try { estimatedCost = await estimateCostOfBridging(bridges.ETH, { ...bridgeArgs, diff --git a/packages/bridge-ui-v2/src/libs/chain/chains.ts b/packages/bridge-ui-v2/src/libs/chain/chains.ts index 0852df5dbc6..52f6cb9f0d1 100644 --- a/packages/bridge-ui-v2/src/libs/chain/chains.ts +++ b/packages/bridge-ui-v2/src/libs/chain/chains.ts @@ -153,11 +153,9 @@ type AddressConfig = { signalServiceAddress: Address; }; -type ConfiguredChain = typeof chains[number]['id']; +type ConfiguredChain = (typeof chains)[number]['id']; type RoutingConfig = Record; - - export const routingContractsMap: Record = { [PUBLIC_L1_CHAIN_ID]: { // L1 -> L2 @@ -179,7 +177,6 @@ export const routingContractsMap: Record = { erc1155VaultAddress: PUBLIC_L1_L2_ERC1155_VAULT_ADDRESS as Address, crossChainSyncAddress: PUBLIC_L1_L2_CROSS_CHAIN_SYNC_ADDRESS as Address, signalServiceAddress: PUBLIC_L1_L2_SIGNAL_SERVICE_ADDRESS as Address, - } as AddressConfig, // L2 -> L3 [PUBLIC_L3_CHAIN_ID]: { @@ -200,37 +197,6 @@ export const routingContractsMap: Record = { erc1155VaultAddress: PUBLIC_L3_ERC1155_VAULT_ADDRESS as Address, crossChainSyncAddress: PUBLIC_L3_CROSS_CHAIN_SYNC_ADDRESS as Address, signalServiceAddress: PUBLIC_L3_SIGNAL_SERVICE_ADDRESS as Address, - } as AddressConfig, }, }; - -// export const chainContractsMap: Record< -// string, -// BrideContractsConfig -// > = { -// [PUBLIC_L1_CHAIN_ID]: { -// bridgeAddress: PUBLIC_L1_BRIDGE_ADDRESS as Address, -// tokenVaultAddress: PUBLIC_L1_TOKEN_VAULT_ADDRESS as Address, -// erc721VaultAddress: PUBLIC_L1_ERC721_VAULT_ADDRESS as Address, -// erc1155VaultAddress: PUBLIC_L1_ERC1155_VAULT_ADDRESS as Address, -// crossChainSyncAddress: PUBLIC_L1_CROSS_CHAIN_SYNC_ADDRESS as Address, -// signalServiceAddress: PUBLIC_L1_SIGNAL_SERVICE_ADDRESS as Address, -// }, -// [PUBLIC_L2_CHAIN_ID]: { -// bridgeAddress: PUBLIC_L2_BRIDGE_ADDRESS as Address, -// tokenVaultAddress: PUBLIC_L2_TOKEN_VAULT_ADDRESS as Address, -// erc721VaultAddress: PUBLIC_L2_ERC721_VAULT_ADDRESS as Address, -// erc1155VaultAddress: PUBLIC_L2_ERC1155_VAULT_ADDRESS as Address, -// crossChainSyncAddress: PUBLIC_L2_CROSS_CHAIN_SYNC_ADDRESS as Address, -// signalServiceAddress: PUBLIC_L2_SIGNAL_SERVICE_ADDRESS as Address, -// }, -// [PUBLIC_L3_CHAIN_ID]: { -// bridgeAddress: PUBLIC_L3_BRIDGE_ADDRESS as Address, -// tokenVaultAddress: PUBLIC_L3_TOKEN_VAULT_ADDRESS as Address, -// erc721VaultAddress: PUBLIC_L3_ERC721_VAULT_ADDRESS as Address, -// erc1155VaultAddress: PUBLIC_L3_ERC1155_VAULT_ADDRESS as Address, -// crossChainSyncAddress: PUBLIC_L3_CROSS_CHAIN_SYNC_ADDRESS as Address, -// signalServiceAddress: PUBLIC_L3_SIGNAL_SERVICE_ADDRESS as Address, -// }, -// }; diff --git a/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts b/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts index c4236dbef55..5c3d5eef32f 100644 --- a/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts +++ b/packages/bridge-ui-v2/src/libs/relayer/RelayerAPIService.ts @@ -4,13 +4,12 @@ import axios from 'axios'; import { Buffer } from 'buffer'; import { bridgeABI } from '$abi'; -import { type BridgeTransaction, MessageStatus } from '$libs/bridge'; +import type { BridgeTransaction, MessageStatus } from '$libs/bridge'; import { TokenType } from '$libs/token'; import { getLogger } from '$libs/util/logger'; import { publicClient } from '$libs/wagmi'; import { isSupportedChain, routingContractsMap } from '../chain/chains'; -import { destChain } from './../../../../bridge-ui/src/store/chain'; import type { APIRequestParams, APIResponse, @@ -47,7 +46,8 @@ export class RelayerAPIService { continue; } - const { bridgeAddress } = routingContractsMap[Number(item.data.Message.SrcChainId)][Number(item.data.Message.DestChainId)]; // TODO: also handle unsupported chain + const { bridgeAddress } = + routingContractsMap[Number(item.data.Message.SrcChainId)][Number(item.data.Message.DestChainId)]; // TODO: also handle unsupported chain const { DestChainId, SrcChainId } = Message; const { transactionHash, address } = Raw; @@ -76,7 +76,15 @@ export class RelayerAPIService { return filteredItems; } - private static async _getBridgeMessageStatus({ msgHash, srcChainId, destChainId }: { msgHash: Hash, srcChainId: number, destChainId: number }) { + private static async _getBridgeMessageStatus({ + msgHash, + srcChainId, + destChainId, + }: { + msgHash: Hash; + srcChainId: number; + destChainId: number; + }) { const { bridgeAddress } = routingContractsMap[Number(srcChainId)][Number(destChainId)]; const result = await readContract({ address: bridgeAddress, @@ -212,7 +220,11 @@ export class RelayerAPIService { if (!msgHash) return; //todo: handle this case - const status = await RelayerAPIService._getBridgeMessageStatus({ msgHash, srcChainId: Number(srcChainId), destChainId: Number(destChainId) }); + const status = await RelayerAPIService._getBridgeMessageStatus({ + msgHash, + srcChainId: Number(srcChainId), + destChainId: Number(destChainId), + }); // Update the status bridgeTx.status = status; diff --git a/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts b/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts index eb1d1534509..a28f7a53da2 100644 --- a/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts +++ b/packages/bridge-ui-v2/src/libs/storage/BridgeTxService.ts @@ -11,14 +11,12 @@ import { publicClient } from '$libs/wagmi'; const log = getLogger('storage:BridgeTxService'); - type BridgeMessageParams = { msgHash: Hash; srcChainId: number; destChainId: number; }; - export class BridgeTxService { private readonly storage: Storage; @@ -35,7 +33,17 @@ export class BridgeTxService { } } - private static async _getBridgeMessageSent({ userAddress, srcChainId, destChainId, blockNumber }: { userAddress: Address, srcChainId: number, destChainId: number, blockNumber: number }) { + private static async _getBridgeMessageSent({ + userAddress, + srcChainId, + destChainId, + blockNumber, + }: { + userAddress: Address; + srcChainId: number; + destChainId: number; + blockNumber: number; + }) { // Gets the event MessageSent from the bridge contract // in the block where the transaction was mined, and find // our event MessageSent whose owner is the address passed in @@ -117,7 +125,7 @@ export class BridgeTxService { userAddress: address, srcChainId: Number(srcChainId), destChainId: Number(destChainId), - blockNumber: Number(receipt.blockNumber) + blockNumber: Number(receipt.blockNumber), }); if (!messageSentEvent?.args?.msgHash || !messageSentEvent?.args?.message) { @@ -132,12 +140,11 @@ export class BridgeTxService { bridgeTx.msgHash = msgHash; bridgeTx.message = message; - const status = await BridgeTxService._getBridgeMessageStatus( - { - msgHash: msgHash, - srcChainId: Number(srcChainId), - destChainId: Number(destChainId) - }); + const status = await BridgeTxService._getBridgeMessageStatus({ + msgHash: msgHash, + srcChainId: Number(srcChainId), + destChainId: Number(destChainId), + }); bridgeTx.status = status; return bridgeTx; diff --git a/packages/bridge-ui-v2/src/libs/token/getAddress.ts b/packages/bridge-ui-v2/src/libs/token/getAddress.ts index 1e0ccedc0d1..8bf22da9c48 100644 --- a/packages/bridge-ui-v2/src/libs/token/getAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getAddress.ts @@ -25,7 +25,6 @@ export async function getAddress({ token, srcChainId, destChainId }: GetAddressA // there is nothing we can do here. if (!destChainId) return; - address = await getCrossChainAddress({ token, srcChainId: srcChainId, diff --git a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts index 0882f737a00..6929d3cd338 100644 --- a/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts +++ b/packages/bridge-ui-v2/src/libs/token/getCrossChainAddress.ts @@ -42,15 +42,19 @@ export async function getCrossChainAddress({ // we need find a vault that is configured with that chainId as the destination const erc20VaultInfo = chains - .filter(chain => { + .filter((chain) => { const routesForChain = routingContractsMap[chain.id]; - return routesForChain && routesForChain[Number(configuredChainId)] && routesForChain[Number(configuredChainId)].erc20VaultAddress; + return ( + routesForChain && + routesForChain[Number(configuredChainId)] && + routesForChain[Number(configuredChainId)].erc20VaultAddress + ); }) - .map(chain => { + .map((chain) => { const erc20VaultAddress = routingContractsMap[chain.id][Number(configuredChainId)].erc20VaultAddress; return { chainId: chain.id, - vaultAddress: erc20VaultAddress + vaultAddress: erc20VaultAddress, }; }); @@ -66,18 +70,21 @@ export async function getCrossChainAddress({ address: erc20VaultAddress, }); - const bridgedAddress = await configuredTokenVaultContract.read.canonicalToBridged([BigInt(configuredChainId), configuredTokenAddress]); + const bridgedAddress = await configuredTokenVaultContract.read.canonicalToBridged([ + BigInt(configuredChainId), + configuredTokenAddress, + ]); - // now that we have the bridgedAddress address, we can check if it is bridged - const { erc20VaultAddress: destChainTokenVaultAddress } = routingContractsMap[destChainId][Number(configuredChainId)]; + // now that we have the bridgedAddress address, we can check if it is bridged + const { erc20VaultAddress: destChainTokenVaultAddress } = + routingContractsMap[destChainId][Number(configuredChainId)]; const destTokenVaultContract = getContract({ abi: tokenVaultABI, chainId: srcChainId, address: destChainTokenVaultAddress, }); return await destTokenVaultContract.read.canonicalToBridged([BigInt(destChainId), bridgedAddress]); - } - else { + } else { const { erc20VaultAddress: srcChainTokenVaultAddress } = routingContractsMap[srcChainId][destChainId]; const { erc20VaultAddress: destChainTokenVaultAddress } = routingContractsMap[destChainId][srcChainId]; @@ -108,6 +115,4 @@ export async function getCrossChainAddress({ return await srcTokenVaultContract.read.canonicalToBridged([BigInt(destChainId), canonicalTokenAddress]); } } - - } From ecef0bebb7917ee1e04c101cc47906a05901eaf5 Mon Sep 17 00:00:00 2001 From: Korbinian Kasberger Date: Mon, 21 Aug 2023 17:08:54 +0200 Subject: [PATCH 05/64] feat(bridge-ui-v2): added custom vite plugin to generate config --- .gitignore | 6 + .../config/sample/configuredBridges.json | 52 ++++ .../config/sample/configuredChains.json | 34 ++ packages/bridge-ui-v2/package.json | 1 + .../Activities/MobileDetailsDialog.svelte | 4 +- .../src/components/Activities/Status.svelte | 10 +- .../components/Activities/Transaction.svelte | 4 +- .../src/components/Bridge/Bridge.svelte | 6 +- .../ChainSelector/ChainSelector.svelte | 13 +- packages/bridge-ui-v2/src/generated/config.ts | 95 ++++++ .../bridge-ui-v2/src/libs/bridge/Bridge.ts | 2 +- .../src/libs/bridge/ERC20Bridge.ts | 6 +- .../bridge-ui-v2/src/libs/bridge/ETHBridge.ts | 2 +- .../src/libs/bridge/checkBalanceToBridge.ts | 2 +- .../src/libs/bridge/getMaxAmountToBridge.ts | 2 +- .../libs/bridge/isTransactionProcessable.ts | 2 +- .../src/libs/bridge/messageStatusPoller.ts | 2 +- .../bridge-ui-v2/src/libs/chain/chains.ts | 216 ++----------- .../src/libs/proof/BridgeProver.ts | 2 +- .../bridge-ui-v2/src/libs/proof/Prover.ts | 2 +- .../src/libs/relayer/RelayerAPIService.ts | 5 +- .../src/libs/storage/BridgeTxService.ts | 3 +- .../src/libs/token/getCrossChainAddress.ts | 3 +- .../bridge-ui-v2/src/libs/wagmi/watcher.ts | 2 +- packages/bridge-ui-v2/svelte.config.js | 2 + packages/bridge-ui-v2/tsconfig.json | 3 +- .../vite-plugins/generateChainConfigs.ts | 291 ++++++++++++++++++ .../bridge-ui-v2/vite-plugins/utils/Logger.ts | 40 +++ packages/bridge-ui-v2/vite.config.ts | 5 + pnpm-lock.yaml | 29 ++ 30 files changed, 625 insertions(+), 221 deletions(-) create mode 100644 packages/bridge-ui-v2/config/sample/configuredBridges.json create mode 100644 packages/bridge-ui-v2/config/sample/configuredChains.json create mode 100644 packages/bridge-ui-v2/src/generated/config.ts create mode 100644 packages/bridge-ui-v2/vite-plugins/generateChainConfigs.ts create mode 100644 packages/bridge-ui-v2/vite-plugins/utils/Logger.ts diff --git a/.gitignore b/.gitignore index d2cefd2067c..79f7ca4c57e 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,9 @@ __pycache__/ # VSCode .vscode/launch.json + +# Bridge config files +packages/bridge-ui-v2/config/* +!packages/bridge-ui-v2/config/sample/ + + diff --git a/packages/bridge-ui-v2/config/sample/configuredBridges.json b/packages/bridge-ui-v2/config/sample/configuredBridges.json new file mode 100644 index 00000000000..0fae45ec692 --- /dev/null +++ b/packages/bridge-ui-v2/config/sample/configuredBridges.json @@ -0,0 +1,52 @@ +{ + "configuredBridges": [ + { + "source": "", + "destination": "", + "addresses": { + "bridgeAddress": "", + "erc20VaultAddress": "", + "erc721VaultAddress": "", + "erc1155VaultAddress": "", + "crossChainSyncAddress": "", + "signalServiceAddress": "" + } + }, + { + "source": "", + "destination": "", + "addresses": { + "bridgeAddress": "", + "erc20VaultAddress": "", + "erc721VaultAddress": "", + "erc1155VaultAddress": "", + "crossChainSyncAddress": "", + "signalServiceAddress": "" + } + }, + { + "source": "", + "destination": "", + "addresses": { + "bridgeAddress": "", + "erc20VaultAddress": "", + "erc721VaultAddress": "", + "erc1155VaultAddress": "", + "crossChainSyncAddress": "", + "signalServiceAddress": "" + } + }, + { + "source": "", + "destination": "", + "addresses": { + "bridgeAddress": "", + "erc20VaultAddress": "", + "erc721VaultAddress": "", + "erc1155VaultAddress": "", + "crossChainSyncAddress": "", + "signalServiceAddress": "" + } + } + ] +} diff --git a/packages/bridge-ui-v2/config/sample/configuredChains.json b/packages/bridge-ui-v2/config/sample/configuredChains.json new file mode 100644 index 00000000000..c86f6369a59 --- /dev/null +++ b/packages/bridge-ui-v2/config/sample/configuredChains.json @@ -0,0 +1,34 @@ +{ + "configuredChains": [ + { + "123456": { + "name": "", + "type": "L1", + "urls": { + "rpc": "", + "explorer": "" + } + } + }, + { + "78910": { + "name": "", + "type": "L2", + "urls": { + "rpc": "", + "explorer": "" + } + } + }, + { + "98765": { + "name": "", + "type": "L3", + "urls": { + "rpc": "", + "explorer": "" + } + } + } + ] +} diff --git a/packages/bridge-ui-v2/package.json b/packages/bridge-ui-v2/package.json index 98c99d0d3bd..5f8bdb909f2 100644 --- a/packages/bridge-ui-v2/package.json +++ b/packages/bridge-ui-v2/package.json @@ -45,6 +45,7 @@ "svelte": "^4.1.0", "svelte-check": "^3.4.6", "tailwindcss": "^3.3.2", + "ts-morph": "^19.0.0", "tslib": "^2.4.1", "typescript": "^5.1.6", "vite": "^4.3.0", diff --git a/packages/bridge-ui-v2/src/components/Activities/MobileDetailsDialog.svelte b/packages/bridge-ui-v2/src/components/Activities/MobileDetailsDialog.svelte index 4b3ad0a5e1a..744b88a29f2 100644 --- a/packages/bridge-ui-v2/src/components/Activities/MobileDetailsDialog.svelte +++ b/packages/bridge-ui-v2/src/components/Activities/MobileDetailsDialog.svelte @@ -5,11 +5,11 @@ import { Icon } from '$components/Icon'; import { Tooltip } from '$components/Tooltip'; import type { BridgeTransaction } from '$libs/bridge'; - import { chainUrlMap } from '$libs/chain'; import { noop } from '$libs/util/noop'; import { uid } from '$libs/util/uid'; import ChainSymbolName from './ChainSymbolName.svelte'; + import { chainConfig } from '$chainConfig'; export let closeDetails = noop; export let detailsOpen = false; @@ -59,7 +59,7 @@
  • {$t('activities.header.explorer')}

    {$t('activities.link.explorer')} diff --git a/packages/bridge-ui-v2/src/components/Activities/Status.svelte b/packages/bridge-ui-v2/src/components/Activities/Status.svelte index b958e59dba1..00f65236914 100644 --- a/packages/bridge-ui-v2/src/components/Activities/Status.svelte +++ b/packages/bridge-ui-v2/src/components/Activities/Status.svelte @@ -16,7 +16,6 @@ import { bridges, type BridgeTransaction, MessageStatus } from '$libs/bridge'; import { isTransactionProcessable } from '$libs/bridge/isTransactionProcessable'; import { PollingEvent, startPolling } from '$libs/bridge/messageStatusPoller'; - import { chainUrlMap } from '$libs/chain'; import { InsufficientBalanceError, InvalidProofError, @@ -30,6 +29,7 @@ import { account } from '$stores/account'; import { network } from '$stores/network'; import { pendingTransactions } from '$stores/pendingTransactions'; + import { chainConfig } from '$chainConfig'; const log = getLogger('components:Status'); @@ -101,13 +101,13 @@ // Step 5: Call claim() method on the bridge const txHash = await bridge.claim({ msgHash, message, wallet }); - const { explorerUrl } = chainUrlMap[Number(bridgeTx.destChainId)]; + const { explorer } = chainConfig[Number(bridgeTx.destChainId)].urls; infoToast( $t('activities.actions.claim.tx', { values: { token: bridgeTx.symbol, - url: `${explorerUrl}/tx/${txHash}`, + url: `${explorer}/tx/${txHash}`, }, }), ); @@ -182,13 +182,13 @@ // Step 4: Call release() method on the bridge const txHash = await bridge.claim({ msgHash, message, wallet }); - const { explorerUrl } = chainUrlMap[Number(bridgeTx.srcChainId)]; + const { explorer } = chainConfig[Number(bridgeTx.srcChainId)].urls; infoToast( $t('activities.actions.release.tx', { values: { token: bridgeTx.symbol, - url: `${explorerUrl}/tx/${txHash}`, + url: `${explorer}/tx/${txHash}`, }, }), ); diff --git a/packages/bridge-ui-v2/src/components/Activities/Transaction.svelte b/packages/bridge-ui-v2/src/components/Activities/Transaction.svelte index 271b4163539..066d62a4516 100644 --- a/packages/bridge-ui-v2/src/components/Activities/Transaction.svelte +++ b/packages/bridge-ui-v2/src/components/Activities/Transaction.svelte @@ -3,7 +3,6 @@ import { formatEther } from 'viem'; import type { BridgeTransaction } from '$libs/bridge'; - import { chainUrlMap } from '$libs/chain'; export let item: BridgeTransaction; @@ -14,6 +13,7 @@ import ChainSymbolName from './ChainSymbolName.svelte'; import Status from './Status.svelte'; + import { chainConfig } from '$chainConfig'; const dispatch = createEventDispatcher(); @@ -70,7 +70,7 @@
  • diff --git a/packages/bridge-ui-v2/src/components/LoadingMask/LoadingMask.svelte b/packages/bridge-ui-v2/src/components/LoadingMask/LoadingMask.svelte index cfec438c309..a702a48a4fc 100644 --- a/packages/bridge-ui-v2/src/components/LoadingMask/LoadingMask.svelte +++ b/packages/bridge-ui-v2/src/components/LoadingMask/LoadingMask.svelte @@ -13,6 +13,8 @@ 'top-0 bottom-0', 'left-0 right-0', 'overflow-hidden', + 'overlay-dialog', + 'text-white', $$props.class, ); let textClasses = classNames('body-regular', textClass); diff --git a/packages/bridge-ui-v2/src/components/SwitchChainModal/SwitchChainModal.svelte b/packages/bridge-ui-v2/src/components/SwitchChainModal/SwitchChainModal.svelte index d4eb40e311d..774e3567554 100644 --- a/packages/bridge-ui-v2/src/components/SwitchChainModal/SwitchChainModal.svelte +++ b/packages/bridge-ui-v2/src/components/SwitchChainModal/SwitchChainModal.svelte @@ -1,7 +1,7 @@