Skip to content

Commit

Permalink
feat: transaction history for batch transfers (#1851)
Browse files Browse the repository at this point in the history
Co-authored-by: Fionna Chan <[email protected]>
  • Loading branch information
brtkx and fionnachan authored Aug 22, 2024
1 parent 8c9ff2e commit a09a468
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ import { TransactionsTableRow } from './TransactionsTableRow'
import { EmptyTransactionHistory } from './EmptyTransactionHistory'
import { Address } from '../../util/AddressUtils'

export const BatchTransferEthTooltip = ({ children }: PropsWithChildren) => {
return (
<Tooltip content="This is any additional ETH you might have deposited along with your ERC-20, plus the refunded excess gas fee.">
{children}
</Tooltip>
)
}

export const ContentWrapper = ({
children,
className = ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Image from 'next/image'
import dayjs from 'dayjs'
import CctpLogoColor from '@/images/CctpLogoColor.svg'
import ArbitrumLogo from '@/images/ArbitrumLogo.svg'
import EthereumLogoRoundLight from '@/images/EthereumLogoRoundLight.svg'

import { useTxDetailsStore } from './TransactionHistory'
import { getExplorerUrl, getNetworkName, isNetwork } from '../../util/networks'
Expand All @@ -22,6 +23,8 @@ import { shortenAddress } from '../../util/CommonUtils'
import { isTxCompleted } from './helpers'
import { Address } from '../../util/AddressUtils'
import { sanitizeTokenSymbol } from '../../util/TokenUtils'
import { isBatchTransfer } from '../../util/TokenDepositUtils'
import { BatchTransferEthTooltip } from './TransactionHistoryTable'

const DetailsBox = ({
children,
Expand Down Expand Up @@ -135,17 +138,41 @@ export const TransactionsTableDetails = ({
<span>{dayjs(tx.createdAt).format('MMMM DD, YYYY')}</span>
<span>{dayjs(tx.createdAt).format('h:mma')}</span>
</div>
<div className="flex items-center space-x-2">
<TransactionsTableTokenImage tx={tx} />
<span>
{formatAmount(Number(tx.value), {
symbol: tokenSymbol
})}
</span>
{showPriceInUsd && (
<span className="text-white/70">
{formatUSD(ethToUSD(Number(tx.value)))}
<div className="flex flex-col space-y-1">
<div className="flex items-center space-x-2">
<TransactionsTableTokenImage tx={tx} />
<span>
{formatAmount(Number(tx.value), {
symbol: tokenSymbol
})}
</span>
{showPriceInUsd && (
<span className="text-white/70">
{formatUSD(ethToUSD(Number(tx.value)))}
</span>
)}
</div>
{isBatchTransfer(tx) && (
<BatchTransferEthTooltip>
<div className="flex items-center space-x-2">
<Image
height={20}
width={20}
alt="ETH logo"
src={EthereumLogoRoundLight}
/>
<span className="ml-2">
{formatAmount(Number(tx.value2), {
symbol: ether.symbol
})}
</span>
{isNetwork(tx.sourceChainId).isEthereumMainnet && (
<span className="text-white/70">
{formatUSD(ethToUSD(Number(tx.value2)))}
</span>
)}
</div>
</BatchTransferEthTooltip>
)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
CheckCircleIcon,
XCircleIcon
} from '@heroicons/react/24/outline'
import EthereumLogoRoundLight from '@/images/EthereumLogoRoundLight.svg'
import Image from 'next/image'

import { DepositStatus, MergedTransaction } from '../../state/app/state'
import { formatAmount } from '../../util/NumberUtils'
Expand All @@ -28,6 +30,9 @@ import { TransactionsTableTokenImage } from './TransactionsTableTokenImage'
import { useTxDetailsStore } from './TransactionHistory'
import { TransactionsTableExternalLink } from './TransactionsTableExternalLink'
import { Address } from '../../util/AddressUtils'
import { ether } from '../../constants'
import { isBatchTransfer } from '../../util/TokenDepositUtils'
import { BatchTransferEthTooltip } from './TransactionHistoryTable'

const StatusLabel = ({ tx }: { tx: MergedTransaction }) => {
const { sourceChainId, destinationChainId } = tx
Expand Down Expand Up @@ -170,18 +175,37 @@ export function TransactionsTableRow({
)}
>
<div className="pr-3 align-middle">{txRelativeTime}</div>
<div className="flex items-center pr-3 align-middle">
<TransactionsTableExternalLink
href={`${getExplorerUrl(sourceChainId)}/token/${tx.tokenAddress}`}
disabled={!tx.tokenAddress}
>
<TransactionsTableTokenImage tx={tx} />
<span className="ml-2">
{formatAmount(Number(tx.value), {
symbol: tokenSymbol
})}
</span>
</TransactionsTableExternalLink>
<div className="flex flex-col space-y-1">
<div className="flex items-center pr-3 align-middle">
<TransactionsTableExternalLink
href={`${getExplorerUrl(sourceChainId)}/token/${tx.tokenAddress}`}
disabled={!tx.tokenAddress}
>
<TransactionsTableTokenImage tx={tx} />
<span className="ml-2">
{formatAmount(Number(tx.value), {
symbol: tokenSymbol
})}
</span>
</TransactionsTableExternalLink>
</div>
{isBatchTransfer(tx) && (
<BatchTransferEthTooltip>
<div className="flex items-center pr-3 align-middle">
<Image
height={20}
width={20}
alt="ETH logo"
src={EthereumLogoRoundLight}
/>
<span className="ml-2">
{formatAmount(Number(tx.value2), {
symbol: ether.symbol
})}
</span>
</div>
</BatchTransferEthTooltip>
)}
</div>
<div className="flex items-center space-x-2">
<TransactionsTableExternalLink
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import dayjs from 'dayjs'
import { useState, useMemo } from 'react'
import Tippy from '@tippyjs/react'
import { BigNumber, constants, utils } from 'ethers'
import { constants, utils } from 'ethers'
import { useLatest } from 'react-use'
import { useAccount, useChainId, useSigner } from 'wagmi'
import { TransactionResponse } from '@ethersproject/providers'
Expand Down Expand Up @@ -930,6 +930,8 @@ export function TransferPanel() {

const { sourceChainTransaction } = bridgeTransfer

const isBatchTransfer = isBatchTransferSupported && Number(amount2) > 0

const timestampCreated = Math.floor(Date.now() / 1000).toString()

const txHistoryCompatibleObject = convertBridgeSdkToMergedTransaction({
Expand All @@ -941,6 +943,7 @@ export function TransferPanel() {
destinationAddress,
nativeCurrency,
amount: amountBigNumber,
amount2: isBatchTransfer ? utils.parseEther(amount2) : undefined,
timestampCreated
})

Expand All @@ -959,6 +962,7 @@ export function TransferPanel() {
destinationAddress,
nativeCurrency,
amount: amountBigNumber,
amount2: isBatchTransfer ? utils.parseEther(amount2) : undefined,
timestampCreated
})
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type SdkToUiConversionProps = {
destinationAddress?: string
nativeCurrency: NativeCurrency
amount: BigNumber
amount2?: BigNumber
timestampCreated: string
}

Expand All @@ -34,7 +35,8 @@ export const convertBridgeSdkToMergedTransaction = ({
walletAddress,
destinationAddress,
nativeCurrency,
amount
amount,
amount2
}: SdkToUiConversionProps): MergedTransaction => {
const { transferType } = bridgeTransfer
const isDeposit =
Expand All @@ -57,6 +59,7 @@ export const convertBridgeSdkToMergedTransaction = ({
amount,
selectedToken ? selectedToken.decimals : nativeCurrency.decimals
),
value2: amount2 ? utils.formatEther(amount2) : undefined,
depositStatus: isDeposit ? DepositStatus.L1_PENDING : undefined,
uniqueId: null,
isWithdrawal: !isDeposit,
Expand All @@ -78,6 +81,7 @@ export const convertBridgeSdkToPendingDepositTransaction = ({
nativeCurrency,
destinationAddress,
amount,
amount2,
timestampCreated
}: SdkToUiConversionProps): Deposit => {
const transaction =
Expand All @@ -95,6 +99,7 @@ export const convertBridgeSdkToPendingDepositTransaction = ({
amount,
selectedToken ? selectedToken.decimals : nativeCurrency.decimals
),
value2: amount2 ? utils.formatEther(amount2) : undefined,
parentChainId,
childChainId,
direction: 'deposit',
Expand Down
1 change: 1 addition & 0 deletions packages/arb-token-bridge-ui/src/hooks/useTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type TransactionBase = {
type: TxnType
status?: TxnStatus
value: string | null
value2?: string
txID?: string
assetName: string
assetType: AssetType
Expand Down
1 change: 1 addition & 0 deletions packages/arb-token-bridge-ui/src/state/app/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface MergedTransaction {
asset: string
assetType: AssetType
value: string | null
value2?: string
uniqueId: BigNumber | null
isWithdrawal: boolean
blockNum: number | null
Expand Down
1 change: 1 addition & 0 deletions packages/arb-token-bridge-ui/src/state/app/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export const transformDeposit = (
asset: tx.assetName || '',
assetType: tx.assetType,
value: tx.value,
value2: tx.value2,
uniqueId: null, // not needed
isWithdrawal: false,
blockNum: tx.blockNumber || null,
Expand Down
15 changes: 14 additions & 1 deletion packages/arb-token-bridge-ui/src/util/TokenDepositUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import {
fetchErc20ParentChainGatewayAddress,
getL2ERC20Address
} from './TokenUtils'
import { DepositGasEstimates } from '../hooks/arbTokenBridge.types'
import { AssetType, DepositGasEstimates } from '../hooks/arbTokenBridge.types'
import { addressIsSmartContract } from './AddressUtils'
import { getChainIdFromProvider } from '../token-bridge-sdk/utils'
import { captureSentryErrorWithExtraData } from './SentryUtils'
import { MergedTransaction } from '../state/app/state'
import { isExperimentalFeatureEnabled } from '.'

async function fetchTokenFallbackGasEstimates({
inboxAddress,
Expand Down Expand Up @@ -216,3 +218,14 @@ async function addressIsCustomGatewayToken({
childChainNetwork.tokenBridge?.parentCustomGateway.toLowerCase()
)
}

export function isBatchTransfer(tx: MergedTransaction) {
return (
isExperimentalFeatureEnabled('batch') &&
!tx.isCctp &&
!tx.isWithdrawal &&
tx.assetType === AssetType.ERC20 &&
typeof tx.value2 !== 'undefined' &&
Number(tx.value2) > 0
)
}
Loading

0 comments on commit a09a468

Please sign in to comment.