-
+
diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadiness.ts b/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadiness.ts
index 34899b953b..46dc6768c7 100644
--- a/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadiness.ts
+++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadiness.ts
@@ -31,6 +31,7 @@ import { isTeleportEnabledToken } from '../../util/TokenTeleportEnabledUtils'
import { isNetwork } from '../../util/networks'
import { useBalances } from '../../hooks/useBalances'
import { useArbQueryParams } from '../../hooks/useArbQueryParams'
+import { formatAmount } from '../../util/NumberUtils'
// Add chains IDs that are currently down or disabled
// It will block transfers and display an info box in the transfer panel
@@ -413,7 +414,9 @@ export function useTransferReadiness(): UseTransferReadinessResult {
errorMessages: {
inputAmount1: getInsufficientFundsForGasFeesErrorMessage({
asset: ether.symbol,
- chain: networks.sourceChain.name
+ chain: networks.sourceChain.name,
+ balance: formatAmount(ethBalanceFloat),
+ requiredBalance: formatAmount(estimatedL1GasFees)
})
}
})
@@ -425,7 +428,9 @@ export function useTransferReadiness(): UseTransferReadinessResult {
errorMessages: {
inputAmount1: getInsufficientFundsForGasFeesErrorMessage({
asset: nativeCurrency.symbol,
- chain: networks.sourceChain.name
+ chain: networks.sourceChain.name,
+ balance: formatAmount(customFeeTokenL1BalanceFloat),
+ requiredBalance: formatAmount(estimatedL2GasFees)
})
}
})
@@ -447,7 +452,11 @@ export function useTransferReadiness(): UseTransferReadinessResult {
inputAmount1: notEnoughEthForGasFees
? getInsufficientFundsForGasFeesErrorMessage({
asset: ether.symbol,
- chain: networks.sourceChain.name
+ chain: networks.sourceChain.name,
+ balance: formatAmount(ethBalanceFloat),
+ requiredBalance: formatAmount(
+ estimatedL1GasFees + estimatedL2GasFees
+ )
})
: undefined,
inputAmount2:
@@ -472,7 +481,11 @@ export function useTransferReadiness(): UseTransferReadinessResult {
errorMessages: {
inputAmount1: getInsufficientFundsForGasFeesErrorMessage({
asset: ether.symbol,
- chain: networks.sourceChain.name
+ chain: networks.sourceChain.name,
+ balance: formatAmount(ethBalanceFloat),
+ requiredBalance: formatAmount(
+ estimatedL1GasFees + estimatedL2GasFees
+ )
})
}
})
@@ -490,7 +503,9 @@ export function useTransferReadiness(): UseTransferReadinessResult {
errorMessages: {
inputAmount1: getInsufficientFundsForGasFeesErrorMessage({
asset: nativeCurrency.symbol,
- chain: networks.sourceChain.name
+ chain: networks.sourceChain.name,
+ balance: formatAmount(ethBalanceFloat),
+ requiredBalance: formatAmount(total)
})
}
})
diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadinessUtils.ts b/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadinessUtils.ts
index 53085925ee..f274106133 100644
--- a/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadinessUtils.ts
+++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/useTransferReadinessUtils.ts
@@ -4,11 +4,17 @@ export enum TransferReadinessRichErrorMessage {
TOKEN_TRANSFER_DISABLED
}
-export type GetInsufficientFundsErrorMessageParams = {
+type GetInsufficientFundsErrorMessageParams = {
asset: string
chain: string
}
+type GetInsufficientFundsForGasFeesErrorMessageParams =
+ GetInsufficientFundsErrorMessageParams & {
+ balance: string
+ requiredBalance: string
+ }
+
export function getInsufficientFundsErrorMessage({
asset,
chain
@@ -18,9 +24,21 @@ export function getInsufficientFundsErrorMessage({
export function getInsufficientFundsForGasFeesErrorMessage({
asset,
- chain
-}: GetInsufficientFundsErrorMessageParams) {
- return `Insufficient ${asset} to pay for gas fees. Please add more funds to ${chain}.`
+ chain,
+ balance,
+ requiredBalance
+}: GetInsufficientFundsForGasFeesErrorMessageParams) {
+ const errorMessage = `Please add more ${asset} on ${chain} to pay for gas fees.`
+
+ if (balance === requiredBalance) {
+ // An edge case where formatAmount returns the same value. In this case we don't want to show balances because in the UI it's the same as requiredBalance.
+ return errorMessage
+ }
+
+ return (
+ errorMessage +
+ ` You currently have ${balance} ${asset}, but the transaction requires ${requiredBalance} ${asset}.`
+ )
}
export function getSmartContractWalletNativeCurrencyTransfersNotSupportedErrorMessage({
diff --git a/packages/arb-token-bridge-ui/src/components/common/atoms/Loader.tsx b/packages/arb-token-bridge-ui/src/components/common/atoms/Loader.tsx
index acccdb2cdc..6d82603aab 100644
--- a/packages/arb-token-bridge-ui/src/components/common/atoms/Loader.tsx
+++ b/packages/arb-token-bridge-ui/src/components/common/atoms/Loader.tsx
@@ -2,10 +2,16 @@ import { TailSpin } from 'react-loader-spinner'
import { BaseProps } from 'react-loader-spinner/dist/type'
export type LoaderProps = BaseProps & {
- size: 'small' | 'medium' | 'large'
+ size: 'small' | 'medium' | 'large' | number
}
-const getSizeByLoaderProps = (loaderSize: LoaderProps['size'] | undefined) => {
+const getSizeByLoaderProps = (
+ loaderSize: LoaderProps['size'] | number | undefined
+) => {
+ if (typeof loaderSize === 'number') {
+ return loaderSize
+ }
+
switch (loaderSize) {
case 'small':
return 16
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 1e1761833c..f9596e541e 100644
--- a/packages/arb-token-bridge-ui/tests/e2e/cypress.d.ts
+++ b/packages/arb-token-bridge-ui/tests/e2e/cypress.d.ts
@@ -11,6 +11,7 @@ import {
searchAndSelectToken,
fillCustomDestinationAddress,
typeAmount,
+ findAmountInput,
findSourceChainButton,
findDestinationChainButton,
findGasFeeSummary,
@@ -56,6 +57,7 @@ declare global {
}): typeof searchAndSelectToken
fillCustomDestinationAddress(): typeof fillCustomDestinationAddress
typeAmount: typeof typeAmount
+ findAmountInput: typeof findAmountInput
findSourceChainButton: typeof findSourceChainButton
findDestinationChainButton: typeof findDestinationChainButton
findGasFeeForChain: typeof findGasFeeForChain
diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/login.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/login.cy.ts
index 25c8552974..0b6286f7e3 100644
--- a/packages/arb-token-bridge-ui/tests/e2e/specs/login.cy.ts
+++ b/packages/arb-token-bridge-ui/tests/e2e/specs/login.cy.ts
@@ -15,7 +15,7 @@ describe('Login Account', () => {
before(() => {
getInitialETHBalance(Cypress.env('ETH_RPC_URL')).then(
- val => (l1ETHbal = formatAmount(val, { symbol: 'ETH' }))
+ val => (l1ETHbal = formatAmount(val))
)
getInitialETHBalance(Cypress.env('ARB_RPC_URL')).then(
val => (l2ETHbal = formatAmount(val, { symbol: 'ETH' }))
diff --git a/packages/arb-token-bridge-ui/tests/e2e/specs/urlQueryParam.cy.ts b/packages/arb-token-bridge-ui/tests/e2e/specs/urlQueryParam.cy.ts
index 0124434723..4b19a7d3f5 100644
--- a/packages/arb-token-bridge-ui/tests/e2e/specs/urlQueryParam.cy.ts
+++ b/packages/arb-token-bridge-ui/tests/e2e/specs/urlQueryParam.cy.ts
@@ -31,7 +31,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i)
+ cy.findAmountInput()
.should('be.visible')
.should('not.have.text', 'max')
.should('not.have.text', 'MAX')
@@ -41,7 +41,7 @@ describe('User enters site with query params on URL', () => {
cy.waitUntil(
() =>
cy
- .findByPlaceholderText(/Enter amount/i)
+ .findAmountInput()
.invoke('val')
.should($val => {
cy.wrap(Number($val)).should('be.gt', 0)
@@ -53,7 +53,7 @@ describe('User enters site with query params on URL', () => {
interval: 500
}
)
- cy.findByPlaceholderText(/Enter amount/i)
+ cy.findAmountInput()
.invoke('val')
.should($val => {
cy.wrap(Number($val)).should('be.lt', l1ETHbal)
@@ -71,7 +71,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i)
+ cy.findAmountInput()
.should('be.visible')
.should('not.have.text', 'max')
.should('not.have.text', 'MAX')
@@ -79,10 +79,7 @@ describe('User enters site with query params on URL', () => {
// so this test only asserts the amount set for the input field is less than user's balance
// but not the exact MAX AMOUNT set by the `setMaxAmount` function in `TransferPanelMain.tsx`
cy.waitUntil(
- () =>
- cy
- .findByPlaceholderText(/Enter amount/i)
- .then($el => Number($el.val()) > 0),
+ () => cy.findAmountInput().then($el => Number($el.val()) > 0),
// optional timeouts and error messages
{
errorMsg: 'was expecting a numerical input value greater than 0',
@@ -90,7 +87,7 @@ describe('User enters site with query params on URL', () => {
interval: 500
}
)
- cy.findByPlaceholderText(/Enter amount/i)
+ cy.findAmountInput()
.invoke('val')
.should($val => {
cy.wrap(Number($val)).should('be.lt', l1ETHbal)
@@ -108,7 +105,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i)
+ cy.findAmountInput()
.should('be.visible')
.should('not.have.text', 'max')
.should('not.have.text', 'MAX')
@@ -119,7 +116,7 @@ describe('User enters site with query params on URL', () => {
cy.waitUntil(
() =>
cy
- .findByPlaceholderText(/Enter amount/i)
+ .findAmountInput()
.invoke('val')
.should($val => {
cy.wrap(Number($val)).should('be.gt', 0)
@@ -131,7 +128,7 @@ describe('User enters site with query params on URL', () => {
interval: 500
}
)
- cy.findByPlaceholderText(/Enter amount/i)
+ cy.findAmountInput()
.invoke('val')
.should($val => {
cy.wrap(Number($val)).should('be.lt', l1ETHbal)
@@ -147,7 +144,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('have.value', '56')
+ cy.findAmountInput().should('have.value', '56')
})
context('?amount=1.6678 should set transfer panel amount to 1.6678', () => {
visitAfterSomeDelay('/', {
@@ -158,7 +155,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('have.value', '1.6678')
+ cy.findAmountInput().should('have.value', '1.6678')
})
context('?amount=6 should set transfer panel amount to 6', () => {
visitAfterSomeDelay('/', {
@@ -169,7 +166,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('have.value', '6')
+ cy.findAmountInput().should('have.value', '6')
})
context('?amount=0.123 should set transfer panel amount to 0.123', () => {
visitAfterSomeDelay('/', {
@@ -181,7 +178,7 @@ describe('User enters site with query params on URL', () => {
})
cy.url().should('include', 'amount=0.123')
- cy.findByPlaceholderText(/Enter amount/i).should('have.value', '0.123')
+ cy.findAmountInput().should('have.value', '0.123')
})
context('?amount=-0.123 should set transfer panel amount to 0.123', () => {
visitAfterSomeDelay('/', {
@@ -192,7 +189,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('have.value', '0.123')
+ cy.findAmountInput().should('have.value', '0.123')
})
it('?amount=asdfs should not set transfer panel amount', () => {
visitAfterSomeDelay('/', {
@@ -203,7 +200,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('be.empty')
+ cy.findAmountInput().should('be.empty')
})
context('?amount=0 should set transfer panel amount to 0', () => {
visitAfterSomeDelay('/', {
@@ -214,7 +211,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('have.value', '0')
+ cy.findAmountInput().should('have.value', '0')
})
context('?amount=0.0001 should set transfer panel amount to 0.0001', () => {
visitAfterSomeDelay('/', {
@@ -225,7 +222,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('have.value', '0.0001')
+ cy.findAmountInput().should('have.value', '0.0001')
})
context('?amount=123,3,43 should not set transfer panel amount', () => {
visitAfterSomeDelay('/', {
@@ -236,7 +233,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('be.empty')
+ cy.findAmountInput().should('be.empty')
})
context(
'?amount=0, 123.222, 0.3 should not set transfer panel amount',
@@ -249,7 +246,7 @@ describe('User enters site with query params on URL', () => {
}
})
- cy.findByPlaceholderText(/Enter amount/i).should('be.empty')
+ cy.findAmountInput().should('be.empty')
}
)
})
diff --git a/packages/arb-token-bridge-ui/tests/support/commands.ts b/packages/arb-token-bridge-ui/tests/support/commands.ts
index 425398add7..6671c79693 100644
--- a/packages/arb-token-bridge-ui/tests/support/commands.ts
+++ b/packages/arb-token-bridge-ui/tests/support/commands.ts
@@ -249,10 +249,14 @@ export const fillCustomDestinationAddress = () => {
.type(Cypress.env('CUSTOM_DESTINATION_ADDRESS'))
}
+export function findAmountInput(): Cypress.Chainable
> {
+ return cy.findByLabelText('Amount input')
+}
+
export function typeAmount(
amount: string | number
): Cypress.Chainable> {
- return cy.findByPlaceholderText(/enter amount/i).type(String(amount))
+ return cy.findAmountInput().type(String(amount))
}
export function findSourceChainButton(
@@ -386,6 +390,7 @@ Cypress.Commands.addAll({
searchAndSelectToken,
fillCustomDestinationAddress,
typeAmount,
+ findAmountInput,
findSourceChainButton,
findDestinationChainButton,
findGasFeeForChain,