diff --git a/packages/arb-token-bridge-ui/public/images/LightningIcon.svg b/packages/arb-token-bridge-ui/public/images/LightningIcon.svg new file mode 100644 index 0000000000..b3b74ca881 --- /dev/null +++ b/packages/arb-token-bridge-ui/public/images/LightningIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelSummary.tsx b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelSummary.tsx index 93ce44026f..105615b671 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelSummary.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelSummary.tsx @@ -1,6 +1,7 @@ import React, { useMemo } from 'react' import { InformationCircleIcon } from '@heroicons/react/24/outline' import { twMerge } from 'tailwind-merge' +import Image from 'next/image' import { formatAmount } from '../../util/NumberUtils' import { getNetworkName, isNetwork } from '../../util/networks' @@ -20,6 +21,7 @@ import { DISABLED_CHAIN_IDS } from './useTransferReadiness' import { useSelectedToken } from '../../hooks/useSelectedToken' import { useIsBatchTransferSupported } from '../../hooks/TransferPanel/useIsBatchTransferSupported' import { getConfirmationTime } from '../../util/WithdrawalUtils' +import LightningIcon from '@/images/LightningIcon.svg' export type TransferPanelSummaryToken = { symbol: string @@ -282,7 +284,7 @@ function ConfirmationTimeInfo({ chainId }: { chainId: number }) { return ( <> Confirmation time: - + {confirmationTimeInReadableFormat} @@ -290,13 +292,19 @@ function ConfirmationTimeInfo({ chainId }: { chainId: number }) { {confirmationTimeInReadableFormatShort} {fastWithdrawalActive && ( - - - +
+ + + +
+ Lightning Icon + FAST +
+
)}
diff --git a/packages/arb-token-bridge-ui/src/util/networks.ts b/packages/arb-token-bridge-ui/src/util/networks.ts index ab8ce17bfb..ff4ca58a60 100644 --- a/packages/arb-token-bridge-ui/src/util/networks.ts +++ b/packages/arb-token-bridge-ui/src/util/networks.ts @@ -1,4 +1,4 @@ -import { StaticJsonRpcProvider } from '@ethersproject/providers' +import { Provider, StaticJsonRpcProvider } from '@ethersproject/providers' import { ArbitrumNetwork, getChildrenForNetwork, @@ -11,6 +11,7 @@ import { loadEnvironmentVariableWithFallback } from './index' import { getBridgeUiConfigForChain } from './bridgeUiConfig' import { chainIdToInfuraUrl } from './infura' import { fetchErc20Data } from './TokenUtils' +import { orbitChains } from './orbitChainsList' export enum ChainId { // L1 @@ -581,6 +582,16 @@ export function getSupportedChainIds({ }) } +export function isAlchemyChain(chainId: number) { + const chain = orbitChains[chainId] + + if (typeof chain === 'undefined') { + return false + } + + return chain.rpcUrl.toLowerCase().includes('alchemy.com') +} + export function mapCustomChainToNetworkData(chain: ChainWithRpcUrl) { // custom chain details need to be added to various objects to make it work with the UI // diff --git a/packages/arb-token-bridge-ui/src/util/orbitChainsData.json b/packages/arb-token-bridge-ui/src/util/orbitChainsData.json index 69ca450659..2c309d41e4 100644 --- a/packages/arb-token-bridge-ui/src/util/orbitChainsData.json +++ b/packages/arb-token-bridge-ui/src/util/orbitChainsData.json @@ -435,7 +435,8 @@ "name": "SX Network", "symbol": "SX", "logoUrl": "/images/sxTokenLogo.png" - } + }, + "fastWithdrawalTime": 21600000 } }, { @@ -899,7 +900,7 @@ "childWethGateway": "0x0000000000000000000000000000000000000000" }, "bridgeUiConfig": { - "color": "#b1fb00", + "color": "#7aad00", "network": { "name": "Unite Mainnet", "logo": "/images/unite-mainnet_Logo.png" @@ -1462,7 +1463,7 @@ "childWethGateway": "0x0000000000000000000000000000000000000000" }, "bridgeUiConfig": { - "color": "#b1fb00", + "color": "#7aad00", "network": { "name": "Unite Testnet", "logo": "/images/unite-testnet_Logo.png" diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogsSequentially.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogsSequentially.ts index 5087788d3c..3e421ca077 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogsSequentially.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogsSequentially.ts @@ -1,41 +1,25 @@ import { constants } from 'ethers' import { Provider, BlockTag } from '@ethersproject/providers' -import { Erc20Bridger, getArbitrumNetwork } from '@arbitrum/sdk' +import { Erc20Bridger } from '@arbitrum/sdk' import { fetchTokenWithdrawalsFromEventLogs, FetchTokenWithdrawalsFromEventLogsParams } from './fetchTokenWithdrawalsFromEventLogs' -import { getNonce } from '../AddressUtils' -import { fetchL2Gateways } from '../fetchL2Gateways' -import { backOff, wait } from '../ExponentialBackoffUtils' -async function getGateways(provider: Provider): Promise<{ - standardGateway: string - wethGateway: string - customGateway: string - otherGateways: string[] -}> { - const network = await getArbitrumNetwork(provider) - - const standardGateway = network.tokenBridge?.childErc20Gateway - const customGateway = network.tokenBridge?.childCustomGateway - const wethGateway = network.tokenBridge?.childWethGateway - const otherGateways = await fetchL2Gateways(provider) - - return { - standardGateway: standardGateway ?? constants.AddressZero, - wethGateway: wethGateway ?? constants.AddressZero, - customGateway: customGateway ?? constants.AddressZero, - otherGateways - } -} +import { backOff, wait } from '../ExponentialBackoffUtils' -type TokenWithdrawalQuery = { +type FetchTokenWithdrawalsFromEventLogsQuery = { params: FetchTokenWithdrawalsFromEventLogsParams priority: number } +export type Query = { + sender?: string + receiver?: string + gateways?: string[] +} + export type FetchTokenWithdrawalsFromEventLogsSequentiallyParams = { sender?: string receiver?: string @@ -43,9 +27,10 @@ export type FetchTokenWithdrawalsFromEventLogsSequentiallyParams = { fromBlock?: BlockTag toBlock?: BlockTag /** - * How long to delay in-between queries of different priority. + * How long to delay in-between queries of different priority. Defaults to 0. */ delayMs?: number + queries: Query[] } export type FetchTokenWithdrawalsFromEventLogsSequentiallyResult = Awaited< @@ -53,28 +38,24 @@ export type FetchTokenWithdrawalsFromEventLogsSequentiallyResult = Awaited< > export async function fetchTokenWithdrawalsFromEventLogsSequentially({ - sender, - receiver, provider, fromBlock = 0, toBlock = 'latest', - delayMs = 2_000 + delayMs = 0, + queries: queriesProp }: FetchTokenWithdrawalsFromEventLogsSequentiallyParams): Promise { // keep track of priority; increment as queries are added let priority = 0 + // keep track of queries - const queries: TokenWithdrawalQuery[] = [] + const queries: FetchTokenWithdrawalsFromEventLogsQuery[] = [] // helper function to reuse common params function buildQueryParams({ sender, receiver, gateways = [] - }: { - sender?: string - receiver?: string - gateways?: string[] - }): TokenWithdrawalQuery['params'] { + }: Query): FetchTokenWithdrawalsFromEventLogsQuery['params'] { return { sender, receiver, @@ -86,7 +67,7 @@ export async function fetchTokenWithdrawalsFromEventLogsSequentially({ } // for sanitizing, adding queries and incrementing priority - function addQuery(params: TokenWithdrawalQuery['params']) { + function addQuery(params: FetchTokenWithdrawalsFromEventLogsQuery['params']) { const gateways = params.l2GatewayAddresses ?? [] const gatewaysSanitized = gateways.filter(g => g !== constants.AddressZero) @@ -100,22 +81,9 @@ export async function fetchTokenWithdrawalsFromEventLogsSequentially({ }) } - const gateways = await getGateways(provider) - const senderNonce = await backOff(() => getNonce(sender, { provider })) - - // sender queries; only add if nonce > 0 - if (senderNonce > 0) { - addQuery(buildQueryParams({ sender, gateways: [gateways.standardGateway] })) - addQuery(buildQueryParams({ sender, gateways: [gateways.wethGateway] })) - addQuery(buildQueryParams({ sender, gateways: [gateways.customGateway] })) - addQuery(buildQueryParams({ sender, gateways: gateways.otherGateways })) - } - - // receiver queries - addQuery(buildQueryParams({ receiver, gateways: [gateways.standardGateway] })) - addQuery(buildQueryParams({ receiver, gateways: [gateways.wethGateway] })) - addQuery(buildQueryParams({ receiver, gateways: [gateways.customGateway] })) - addQuery(buildQueryParams({ receiver, gateways: gateways.otherGateways })) + queriesProp.forEach(query => { + addQuery(buildQueryParams(query)) + }) // for iterating through all priorities in the while loop below let currentPriority = 1 diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index 9b8e1b6274..aba40e7207 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -11,8 +11,37 @@ import { fetchLatestSubgraphBlockNumber } from '../SubgraphUtils' import { Withdrawal } from '../../hooks/useTransactionHistory' import { attachTimestampToTokenWithdrawal } from './helpers' import { WithdrawalInitiated } from '../../hooks/arbTokenBridge.types' -import { fetchTokenWithdrawalsFromEventLogsSequentially } from './fetchTokenWithdrawalsFromEventLogsSequentially' +import { + Query, + fetchTokenWithdrawalsFromEventLogsSequentially +} from './fetchTokenWithdrawalsFromEventLogsSequentially' import { backOff, wait } from '../ExponentialBackoffUtils' +import { isAlchemyChain } from '../networks' +import { getArbitrumNetwork } from '@arbitrum/sdk' +import { fetchL2Gateways } from '../fetchL2Gateways' +import { constants } from 'ethers' +import { getNonce } from '../AddressUtils' + +async function getGateways(provider: Provider): Promise<{ + standardGateway: string + wethGateway: string + customGateway: string + otherGateways: string[] +}> { + const network = await getArbitrumNetwork(provider) + + const standardGateway = network.tokenBridge?.childErc20Gateway + const customGateway = network.tokenBridge?.childCustomGateway + const wethGateway = network.tokenBridge?.childWethGateway + const otherGateways = await fetchL2Gateways(provider) + + return { + standardGateway: standardGateway ?? constants.AddressZero, + wethGateway: wethGateway ?? constants.AddressZero, + customGateway: customGateway ?? constants.AddressZero, + otherGateways + } +} export type FetchWithdrawalsParams = { sender?: string @@ -84,6 +113,47 @@ export async function fetchWithdrawals({ console.log('Error fetching withdrawals from subgraph', error) } + const gateways = await getGateways(l2Provider) + const senderNonce = await getNonce(sender, { provider: l2Provider }) + + const queries: Query[] = [] + + // alchemy as a raas has a global rate limit across their chains, so we have to fetch sequentially and wait in-between requests to work around this + const isAlchemy = isAlchemyChain(l2ChainID) + const delayMs = isAlchemy ? 2_000 : 0 + + const allGateways = [ + gateways.standardGateway, + gateways.wethGateway, + gateways.customGateway, + ...gateways.otherGateways + ] + + // sender queries; only add if nonce > 0 + if (senderNonce > 0) { + if (isAlchemy) { + // for alchemy, fetch sequentially + queries.push({ sender, gateways: [gateways.standardGateway] }) + queries.push({ sender, gateways: [gateways.wethGateway] }) + queries.push({ sender, gateways: [gateways.customGateway] }) + queries.push({ sender, gateways: gateways.otherGateways }) + } else { + // for other chains, fetch in parallel + queries.push({ sender, gateways: allGateways }) + } + } + + if (isAlchemy) { + // for alchemy, fetch sequentially + queries.push({ receiver, gateways: [gateways.standardGateway] }) + queries.push({ receiver, gateways: [gateways.wethGateway] }) + queries.push({ receiver, gateways: [gateways.customGateway] }) + queries.push({ receiver, gateways: gateways.otherGateways }) + } else { + // for other chains, fetch in parallel + queries.push({ receiver, gateways: allGateways }) + } + const ethWithdrawalsFromEventLogs = await backOff(() => fetchETHWithdrawalsFromEventLogs({ receiver, @@ -95,7 +165,7 @@ export async function fetchWithdrawals({ }) ) - await wait(2_000) + await wait(delayMs) const tokenWithdrawalsFromEventLogs = await fetchTokenWithdrawalsFromEventLogsSequentially({ @@ -103,7 +173,8 @@ export async function fetchWithdrawals({ receiver, fromBlock: toBlock + 1, toBlock: 'latest', - provider: l2Provider + provider: l2Provider, + queries }) const mappedEthWithdrawalsFromEventLogs: Withdrawal[] = diff --git a/packages/arb-token-bridge-ui/synpress.config.ts b/packages/arb-token-bridge-ui/synpress.config.ts index 84a332c1b0..31ae417ba1 100644 --- a/packages/arb-token-bridge-ui/synpress.config.ts +++ b/packages/arb-token-bridge-ui/synpress.config.ts @@ -226,7 +226,8 @@ export default defineConfig({ }, baseUrl: 'http://localhost:3000', specPattern: tests, - supportFile: 'tests/support/index.ts' + supportFile: 'tests/support/index.ts', + defaultCommandTimeout: 20_000 } }) diff --git a/packages/arb-token-bridge-ui/tests/e2e/cypress.d.ts b/packages/arb-token-bridge-ui/tests/e2e/cypress.d.ts index b10ab68d97..af0f75e815 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/cypress.d.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/cypress.d.ts @@ -16,7 +16,7 @@ import { findGasFeeSummary, findGasFeeForChain, findMoveFundsButton, - startTransfer, + clickMoveFundsButton, findSelectTokenButton, openTransactionDetails, closeTransactionDetails, @@ -66,7 +66,7 @@ declare global { findGasFeeForChain: typeof findGasFeeForChain findGasFeeSummary: typeof findGasFeeSummary findMoveFundsButton: typeof findMoveFundsButton - startTransfer: typeof startTransfer + clickMoveFundsButton: typeof clickMoveFundsButton findSelectTokenButton: typeof findSelectTokenButton openTransactionDetails: typeof openTransactionDetails closeTransactionDetails: typeof closeTransactionDetails diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/approveToken.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/approveToken.cy.ts index c96ceb903c..d3d90a3861 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/approveToken.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/approveToken.cy.ts @@ -39,7 +39,7 @@ describe('Approve token for deposit', () => { timeout: 50000, interval: 500 }) - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton({ shouldConfirmInMetamask: false }) cy.findByText(/pay a one-time approval fee/).click() cy.findByRole('button', { name: /Pay approval fee of/ @@ -50,7 +50,7 @@ describe('Approve token for deposit', () => { * If confirm spending fails, test is still considered to be passing by Cypress * We add another check to make sure the test fails if needed */ - cy.wait(10_000) + cy.wait(25_000) cy.rejectMetamaskTransaction() }) }) diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/batchDeposit.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/batchDeposit.cy.ts index 6319838063..0850de87f2 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/batchDeposit.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/batchDeposit.cy.ts @@ -131,7 +131,7 @@ describe('Batch Deposit', () => { } context('should deposit successfully', () => { - cy.startTransfer() + cy.clickMoveFundsButton() cy.findTransactionInTransactionHistory({ ...txData, duration: depositTime @@ -141,11 +141,7 @@ describe('Batch Deposit', () => { context('deposit should complete successfully', () => { cy.selectTransactionsPanelTab('settled') - cy.waitUntil(() => cy.findTransactionInTransactionHistory(txData), { - errorMsg: 'Could not find settled ERC20 Batch Deposit transaction', - timeout: 60_000, - interval: 500 - }) + cy.findTransactionInTransactionHistory(txData) cy.findTransactionInTransactionHistory({ duration: 'a few seconds ago', @@ -156,23 +152,29 @@ describe('Batch Deposit', () => { context('funds should reach destination account successfully', () => { // should have more funds on destination chain - cy.findByLabelText(`${ERC20TokenSymbol} balance amount on childChain`) - .invoke('text') - .then(parseFloat) - .should('be.gt', Number(parentErc20Balance)) - cy.findByLabelText(`${nativeTokenSymbol} balance amount on childChain`) - .invoke('text') - .then(parseFloat) - .should( - 'be.gt', + cy.findByLabelText( + `${ERC20TokenSymbol} balance amount on childChain` + ).should($el => { + const currentBalance = parseFloat($el.text()) + expect(currentBalance).to.be.gt(Number(parentErc20Balance)) + }) + + cy.findByLabelText( + `${nativeTokenSymbol} balance amount on childChain` + ).should($el => { + const currentBalance = parseFloat($el.text()) + expect(currentBalance).to.be.gt( Number(parentNativeTokenBalance) + nativeCurrencyAmountToSend ) + }) // the balance on the source chain should not be the same as before - cy.findByLabelText(`${ERC20TokenSymbol} balance amount on parentChain`) - .invoke('text') - .then(parseFloat) - .should('be.lt', Number(parentErc20Balance)) + cy.findByLabelText( + `${ERC20TokenSymbol} balance amount on parentChain` + ).should($el => { + const currentBalance = parseFloat($el.text()) + expect(currentBalance).to.be.lt(Number(parentErc20Balance)) + }) }) context('transfer panel amount should be reset', () => { @@ -236,7 +238,7 @@ describe('Batch Deposit', () => { } context('should deposit successfully', () => { - cy.startTransfer() + cy.clickMoveFundsButton() cy.findTransactionInTransactionHistory({ ...txData, duration: depositTime @@ -251,11 +253,7 @@ describe('Batch Deposit', () => { context('deposit should complete successfully', () => { cy.selectTransactionsPanelTab('settled') - cy.waitUntil(() => cy.findTransactionInTransactionHistory(txData), { - errorMsg: 'Could not find settled ERC20 Batch Deposit transaction', - timeout: 60_000, - interval: 500 - }) + cy.findTransactionInTransactionHistory(txData) cy.findTransactionInTransactionHistory({ duration: 'a few seconds ago', diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/depositCctp.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/depositCctp.cy.ts index 40b26f6fd6..ff663af7a0 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/depositCctp.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/depositCctp.cy.ts @@ -86,7 +86,7 @@ describe('Deposit USDC through CCTP', () => { }) it('should initiate depositing USDC to the same address through CCTP successfully', () => { - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton().click() confirmAndApproveCctpDeposit() cy.confirmSpending(USDCAmountToSend.toString()) @@ -122,7 +122,7 @@ describe('Deposit USDC through CCTP', () => { */ it.skip('should initiate depositing USDC to custom destination address through CCTP successfully', () => { cy.fillCustomDestinationAddress() - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton().click() confirmAndApproveCctpDeposit() cy.confirmSpending(USDCAmountToSend.toString()) diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/depositERC20.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/depositERC20.cy.ts index 8e1a2c6e43..7deaf23462 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/depositERC20.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/depositERC20.cy.ts @@ -89,7 +89,7 @@ describe('Deposit Token', () => { }) context('should deposit successfully', () => { - cy.startTransfer() + cy.clickMoveFundsButton() cy.findTransactionInTransactionHistory({ duration: depositTime, amount: ERC20AmountToSend, @@ -130,7 +130,7 @@ describe('Deposit Token', () => { }) context('should deposit successfully', () => { - cy.startTransfer() + cy.clickMoveFundsButton() const txData = { amount: ERC20AmountToSend, symbol: testCase.symbol @@ -150,20 +150,11 @@ describe('Deposit Token', () => { // switch to settled transactions cy.selectTransactionsPanelTab('settled') - //wait for some time for tx to go through and find the new amount in settled transactions - cy.waitUntil( - () => - cy.findTransactionInTransactionHistory({ - duration: 'a few seconds ago', - amount: ERC20AmountToSend, - symbol: testCase.symbol - }), - { - errorMsg: 'Could not find settled ERC20 Deposit transaction', - timeout: 60_000, - interval: 500 - } - ) + cy.findTransactionInTransactionHistory({ + duration: 'a few seconds ago', + amount: ERC20AmountToSend, + symbol: testCase.symbol + }) // open the tx details popup const txData = { amount: ERC20AmountToSend, diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/depositNativeToken.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/depositNativeToken.cy.ts index 65c81e0cd1..65afe0f894 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/depositNativeToken.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/depositNativeToken.cy.ts @@ -31,7 +31,7 @@ describe('Deposit native token', () => { cy.findGasFeeSummary(zeroToLessThanOneEth) cy.findGasFeeForChain(getL1NetworkName(), zeroToLessThanOneEth) cy.findGasFeeForChain(getL2NetworkName(), zeroToLessThanOneNativeToken) - cy.startTransfer() + cy.clickMoveFundsButton() cy.findTransactionInTransactionHistory({ duration: depositTime, amount: ETHAmountToDeposit, @@ -53,7 +53,7 @@ describe('Deposit native token', () => { cy.findGasFeeSummary(zeroToLessThanOneEth) cy.findGasFeeForChain(getL1NetworkName(), zeroToLessThanOneEth) cy.findGasFeeForChain(getL2NetworkName(), zeroToLessThanOneNativeToken) - cy.startTransfer() + cy.clickMoveFundsButton() const txData = { amount: ETHAmountToDeposit, diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawCctp.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawCctp.cy.ts index 7c38d25a8b..15591ee460 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawCctp.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawCctp.cy.ts @@ -72,7 +72,7 @@ describe('Withdraw USDC through CCTP', () => { 'be.visible' ) cy.findGasFeeForChain(/You'll have to pay Sepolia gas fee upon claiming./i) - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton().click() confirmAndApproveCctpWithdrawal() cy.confirmSpending(USDCAmountToSend.toString()) @@ -109,7 +109,7 @@ describe('Withdraw USDC through CCTP', () => { ) cy.findGasFeeForChain(/You'll have to pay Sepolia gas fee upon claiming./i) cy.fillCustomDestinationAddress() - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton().click() confirmAndApproveCctpWithdrawal() cy.confirmSpending(USDCAmountToSend.toString()) diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawERC20.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawERC20.cy.ts index a1ac1fb75e..5355a5fa71 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawERC20.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawERC20.cy.ts @@ -103,7 +103,7 @@ describe('Withdraw ERC20 Token', () => { }) context('should show clickable withdraw button', () => { - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton({ shouldConfirmInMetamask: false }) }) context('should withdraw successfully', () => { @@ -218,7 +218,7 @@ describe('Withdraw ERC20 Token', () => { }) context('should show clickable withdraw button', () => { - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton({ shouldConfirmInMetamask: false }) }) context('should initiate withdrawal successfully', () => { diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawNativeToken.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawNativeToken.cy.ts index 5de34a32de..21259a3d93 100644 --- a/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawNativeToken.cy.ts +++ b/packages/arb-token-bridge-ui/tests/e2e/specs/withdrawNativeToken.cy.ts @@ -61,7 +61,7 @@ describe('Withdraw native token', () => { ETHToWithdraw = Number((Math.random() * 0.001).toFixed(5)) // generate a new withdrawal amount for each test-run attempt so that findAllByText doesn't stall coz of prev transactions cy.login({ networkType: 'childChain' }) cy.typeAmount(ETHToWithdraw) - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton({ shouldConfirmInMetamask: false }) cy.findByText(/Arbitrum’s bridge/i).should('be.visible') // the Continue withdrawal button should be disabled at first @@ -146,7 +146,7 @@ describe('Withdraw native token', () => { cy.typeAmount(ETHToWithdraw) cy.fillCustomDestinationAddress() - cy.findMoveFundsButton().click() + cy.clickMoveFundsButton({ shouldConfirmInMetamask: false }) cy.findByText(/Arbitrum’s bridge/i).should('be.visible') // the Continue withdrawal button should be disabled at first diff --git a/packages/arb-token-bridge-ui/tests/support/commands.ts b/packages/arb-token-bridge-ui/tests/support/commands.ts index f6fe7efa28..64f4367fbe 100644 --- a/packages/arb-token-bridge-ui/tests/support/commands.ts +++ b/packages/arb-token-bridge-ui/tests/support/commands.ts @@ -222,11 +222,17 @@ export function findMoveFundsButton(): Cypress.Chainable> { .should('be.visible') } -export function startTransfer() { +export function clickMoveFundsButton({ + shouldConfirmInMetamask = true +}: { + shouldConfirmInMetamask?: boolean +} = {}) { cy.wait(5_000) cy.findMoveFundsButton().click() cy.wait(15_000) - cy.confirmMetamaskTransaction() + if (shouldConfirmInMetamask) { + cy.confirmMetamaskTransaction() + } } export function findSelectTokenButton( @@ -304,6 +310,8 @@ export function findTransactionInTransactionHistory({ amount2?: number duration?: string }) { + const timeout = 120_000 + // Replace . with \. const parsedAmount = amount.toString().replace(/\./g, '\\.') @@ -313,15 +321,18 @@ export function findTransactionInTransactionHistory({ }` ) - cy.findByTestId(rowId).as('row') + cy.findByTestId(rowId, { timeout }).as('row') if (duration) { - cy.get('@row').findAllByText(duration).first().should('be.visible') + cy.get('@row', { timeout }) + .findAllByText(duration, { timeout }) + .first() + .should('be.visible', { timeout }) } - cy.get('@row') - .findByLabelText('Transaction details button') - .should('be.visible') - return cy.get('@row') + cy.get('@row', { timeout }) + .findByLabelText('Transaction details button', { timeout }) + .should('be.visible', { timeout }) + return cy.get('@row', { timeout }) } export function findClaimButton( @@ -390,7 +401,7 @@ Cypress.Commands.addAll({ findGasFeeForChain, findGasFeeSummary, findMoveFundsButton, - startTransfer, + clickMoveFundsButton, findSelectTokenButton, switchToTransferPanelTab, switchToTransactionHistoryTab,