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 0a5200018c..a26be83a8b 100644
--- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelSummary.tsx
+++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelSummary.tsx
@@ -1,4 +1,5 @@
import React, { useMemo } from 'react'
+import { InformationCircleIcon } from '@heroicons/react/24/outline'
import { twMerge } from 'tailwind-merge'
import { formatAmount } from '../../util/NumberUtils'
@@ -13,10 +14,12 @@ import { useNetworksRelationship } from '../../hooks/useNetworksRelationship'
import { NativeCurrencyPrice, useIsBridgingEth } from './NativeCurrencyPrice'
import { useAppState } from '../../state'
import { Loader } from '../common/atoms/Loader'
+import { Tooltip } from '../common/Tooltip'
import { isTokenNativeUSDC } from '../../util/TokenUtils'
import { NoteBox } from '../common/NoteBox'
import { DISABLED_CHAIN_IDS } from './useTransferReadiness'
import { useIsBatchTransferSupported } from '../../hooks/TransferPanel/useIsBatchTransferSupported'
+import { getConfirmationTime } from '../../util/WithdrawalUtils'
export type TransferPanelSummaryToken = {
symbol: string
@@ -259,6 +262,47 @@ export function TransferPanelSummary({ token }: TransferPanelSummaryProps) {
)}
+ {!isDepositMode &&
+ (isDestinationChainArbitrumOne ||
+ isDestinationChainArbitrumSepolia) && (
+
+
+
+ )}
)
}
+
+function ConfirmationTimeInfo({ chainId }: { chainId: number }) {
+ const {
+ confirmationTimeInReadableFormat,
+ confirmationTimeInReadableFormatShort,
+ isDefaultConfirmationTime
+ } = getConfirmationTime(chainId)
+ return (
+ <>
+ Confirmation time:
+
+
+ {confirmationTimeInReadableFormat}
+
+
+ {confirmationTimeInReadableFormatShort}
+
+ {!isDefaultConfirmationTime && (
+
+
+
+ )}
+
+ >
+ )
+}
diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/WithdrawalConfirmationDialog.tsx b/packages/arb-token-bridge-ui/src/components/TransferPanel/WithdrawalConfirmationDialog.tsx
index 5b57633497..eda5f9edda 100644
--- a/packages/arb-token-bridge-ui/src/components/TransferPanel/WithdrawalConfirmationDialog.tsx
+++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/WithdrawalConfirmationDialog.tsx
@@ -12,12 +12,16 @@ import { useAppState } from '../../state'
import { trackEvent } from '../../util/AnalyticsUtils'
import { getNetworkName, isNetwork } from '../../util/networks'
import { getFastBridges } from '../../util/fastBridges'
-import { CONFIRMATION_PERIOD_ARTICLE_LINK } from '../../constants'
+import {
+ CONFIRMATION_PERIOD_ARTICLE_LINK,
+ FAST_WITHDRAWAL_DOCS_ARTICLE_LINK
+} from '../../constants'
import { useNativeCurrency } from '../../hooks/useNativeCurrency'
import { useNetworks } from '../../hooks/useNetworks'
import { useNetworksRelationship } from '../../hooks/useNetworksRelationship'
import { SecurityGuaranteed, SecurityNotGuaranteed } from './SecurityLabels'
import { getWithdrawalConfirmationDate } from '../../hooks/useTransferDuration'
+import { getConfirmationTime } from '../../util/WithdrawalUtils'
function getCalendarUrl(
withdrawalDate: dayjs.Dayjs,
@@ -42,6 +46,8 @@ export function WithdrawalConfirmationDialog(
const { childChain, childChainProvider, parentChain } =
useNetworksRelationship(networks)
+ const { fastWithdrawalActive } = getConfirmationTime(childChain.id)
+
const [selectedIndex, setSelectedIndex] = useState(0)
const destinationNetworkName = getNetworkName(parentChain.id)
@@ -63,9 +69,14 @@ export function WithdrawalConfirmationDialog(
const [checkbox1Checked, setCheckbox1Checked] = useState(false)
const [checkbox2Checked, setCheckbox2Checked] = useState(false)
+ const [checkbox3Checked, setCheckbox3Checked] = useState(false)
const { isArbitrumOne } = isNetwork(childChain.id)
- const bothCheckboxesChecked = checkbox1Checked && checkbox2Checked
+
+ const allCheckboxesChecked =
+ checkbox1Checked &&
+ checkbox2Checked &&
+ (fastWithdrawalActive ? checkbox3Checked : true)
const estimatedConfirmationDate = getWithdrawalConfirmationDate({
createdAt: null,
@@ -81,6 +92,7 @@ export function WithdrawalConfirmationDialog(
setCheckbox1Checked(false)
setCheckbox2Checked(false)
+ setCheckbox3Checked(false)
setSelectedIndex(0)
}
@@ -91,7 +103,7 @@ export function WithdrawalConfirmationDialog(
className="max-w-[700px]"
title={`Move funds to ${destinationNetworkName}`}
actionButtonProps={{
- disabled: !bothCheckboxesChecked,
+ disabled: !allCheckboxesChecked,
hidden: isFastBridgesTab
}}
>
@@ -157,6 +169,29 @@ export function WithdrawalConfirmationDialog(
onChange={setCheckbox2Checked}
/>
+ {fastWithdrawalActive && (
+
+ I understand that ~{confirmationPeriod} is an estimate,
+ and it's possible the committee fails and it will
+ default back to the 8 days.{' '}
+ {
+ e.stopPropagation()
+ }}
+ >
+ Learn more.
+
+
+ }
+ checked={checkbox3Checked}
+ onChange={setCheckbox3Checked}
+ />
+ )}
+
diff --git a/packages/arb-token-bridge-ui/src/constants.ts b/packages/arb-token-bridge-ui/src/constants.ts
index 2e62500b05..85b03a5336 100644
--- a/packages/arb-token-bridge-ui/src/constants.ts
+++ b/packages/arb-token-bridge-ui/src/constants.ts
@@ -20,6 +20,8 @@ export const ETH_BALANCE_ARTICLE_LINK = `${SUPPORT_LINK_BASE}/hc/en-us/articles/
export const CONFIRMATION_PERIOD_ARTICLE_LINK = `${SUPPORT_LINK_BASE}/hc/en-us/articles/18213843096091`
+export const FAST_WITHDRAWAL_DOCS_ARTICLE_LINK = `${DOCS_DOMAIN}/run-arbitrum-node/arbos-releases/arbos31#additional-requirement-for-arbitrum-orbit-chains-who-wish-to-enable-fast-withdrawals`
+
export const ORBIT_QUICKSTART_LINK =
'https://docs.arbitrum.io/launch-orbit-chain/orbit-quickstart'
diff --git a/packages/arb-token-bridge-ui/src/hooks/useTransferDuration.ts b/packages/arb-token-bridge-ui/src/hooks/useTransferDuration.ts
index 771454a252..f8671e23e2 100644
--- a/packages/arb-token-bridge-ui/src/hooks/useTransferDuration.ts
+++ b/packages/arb-token-bridge-ui/src/hooks/useTransferDuration.ts
@@ -9,6 +9,7 @@ import {
getL1BlockTime,
isNetwork
} from '../util/networks'
+import { getConfirmationTime } from '../util/WithdrawalUtils'
const DEPOSIT_TIME_MINUTES = {
mainnet: 15,
@@ -121,6 +122,12 @@ export function getWithdrawalConfirmationDate({
// For new txs createdAt won't be defined yet, we default to the current time in that case
const createdAtDate = createdAt ? dayjs(createdAt) : dayjs()
+ const { confirmationTimeInSeconds, fastWithdrawalActive } =
+ getConfirmationTime(withdrawalFromChainId)
+ if (fastWithdrawalActive && confirmationTimeInSeconds) {
+ return createdAtDate.add(confirmationTimeInSeconds, 'second')
+ }
+
const blockNumberReferenceChainId = getBlockNumberReferenceChainIdByChainId({
chainId: withdrawalFromChainId
})
diff --git a/packages/arb-token-bridge-ui/src/util/WithdrawalUtils.ts b/packages/arb-token-bridge-ui/src/util/WithdrawalUtils.ts
index 2bf9334593..fe6f091928 100644
--- a/packages/arb-token-bridge-ui/src/util/WithdrawalUtils.ts
+++ b/packages/arb-token-bridge-ui/src/util/WithdrawalUtils.ts
@@ -9,6 +9,8 @@ import { BigNumber } from 'ethers'
import { GasEstimates } from '../hooks/arbTokenBridge.types'
import { Address } from './AddressUtils'
import { captureSentryErrorWithExtraData } from './SentryUtils'
+import { getBridgeUiConfigForChain } from './bridgeUiConfig'
+import { isNetwork } from './networks'
export async function withdrawInitTxEstimateGas({
amount,
@@ -105,3 +107,69 @@ export async function withdrawInitTxEstimateGas({
}
}
}
+
+const SECONDS_IN_MINUTE = 60
+const SECONDS_IN_HOUR = 3600
+const SECONDS_IN_DAY = 86400
+const DEFAULT_CONFIRMATION_TIME = 7 * SECONDS_IN_DAY
+const DEFAULT_FAST_WITHDRAWAL_TIME = SECONDS_IN_DAY
+const DEFAULT_TESTNET_CONFIRMATION_TIME = SECONDS_IN_HOUR
+
+function formatDuration(seconds: number, short = false): string {
+ if (seconds < SECONDS_IN_MINUTE) {
+ return `${seconds} ${short ? 'secs' : 'seconds'}`
+ }
+ if (seconds < SECONDS_IN_HOUR) {
+ return `${Math.round(seconds / SECONDS_IN_MINUTE)} ${
+ short ? 'mins' : 'minutes'
+ }`
+ }
+ if (seconds < SECONDS_IN_DAY) {
+ return `${Math.round(seconds / SECONDS_IN_HOUR)} hours`
+ }
+ return `${Math.round(seconds / SECONDS_IN_DAY)} days`
+}
+
+/**
+ * Calculate confirmation time for bridge transactions.
+ * @param {number} chainId - The ID of the parent chain.
+ */
+export function getConfirmationTime(chainId: number) {
+ const { fastWithdrawalTime, fastWithdrawalActive } =
+ getBridgeUiConfigForChain(chainId)
+ const isTestnet = isNetwork(chainId).isTestnet
+
+ const isDefaultConfirmationTime = !fastWithdrawalActive
+ const isDefaultFastWithdrawal = fastWithdrawalActive && !fastWithdrawalTime
+ const isCustomFastWithdrawal = fastWithdrawalActive && !!fastWithdrawalTime
+
+ let confirmationTimeInSeconds: number
+
+ if (isDefaultFastWithdrawal) {
+ confirmationTimeInSeconds = DEFAULT_FAST_WITHDRAWAL_TIME
+ } else if (isCustomFastWithdrawal) {
+ confirmationTimeInSeconds = fastWithdrawalTime / 1000
+ } else {
+ confirmationTimeInSeconds = isTestnet
+ ? DEFAULT_TESTNET_CONFIRMATION_TIME
+ : DEFAULT_CONFIRMATION_TIME
+ }
+
+ const confirmationTimeInReadableFormat = formatDuration(
+ confirmationTimeInSeconds
+ )
+ const confirmationTimeInReadableFormatShort = formatDuration(
+ confirmationTimeInSeconds,
+ true
+ )
+
+ return {
+ fastWithdrawalActive,
+ isDefaultConfirmationTime,
+ isDefaultFastWithdrawal,
+ isCustomFastWithdrawal,
+ confirmationTimeInSeconds,
+ confirmationTimeInReadableFormat,
+ confirmationTimeInReadableFormatShort
+ }
+}
diff --git a/packages/arb-token-bridge-ui/src/util/orbitChainsData.json b/packages/arb-token-bridge-ui/src/util/orbitChainsData.json
index 36738bab09..0c614f96ac 100644
--- a/packages/arb-token-bridge-ui/src/util/orbitChainsData.json
+++ b/packages/arb-token-bridge-ui/src/util/orbitChainsData.json
@@ -768,7 +768,9 @@
"symbol": "CHEESE",
"decimals": 18,
"logoUrl": "/images/CheeseChain_NativeTokenLogo.jpg"
- }
+ },
+ "fastWithdrawalTime": 900000,
+ "fastWithdrawalActive": true
}
},
{
diff --git a/packages/arb-token-bridge-ui/src/util/orbitChainsList.ts b/packages/arb-token-bridge-ui/src/util/orbitChainsList.ts
index 03602d9495..5888a68167 100644
--- a/packages/arb-token-bridge-ui/src/util/orbitChainsList.ts
+++ b/packages/arb-token-bridge-ui/src/util/orbitChainsList.ts
@@ -17,6 +17,8 @@ export type BridgeUiConfig = {
description?: string
}
nativeTokenData?: NativeCurrencyBase
+ fastWithdrawalTime?: number
+ fastWithdrawalActive?: boolean
}
export type OrbitChainConfig = ChainWithRpcUrl & {