Skip to content

Commit

Permalink
Merge pull request #237 from G7DAO/feat/network-toggle
Browse files Browse the repository at this point in the history
Feat/network toggle
  • Loading branch information
elclandestin0 authored Dec 7, 2024
2 parents 46c3516 + c48adef commit d77ac63
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,15 @@ const Deposit: React.FC<DepositProps> = ({ deposit }) => {
</div>
</div>
<div className={styles.gridItem}>{timeAgo(deposit.lowNetworkTimestamp)}</div>
<div
className={styles.gridItem}
>{`${transactionInputs?.tokenSymbol === 'USDC' ? ethers.utils.formatUnits(transactionInputs?.amount, 6) : deposit.amount} ${transactionInputs?.tokenSymbol}`}</div>
{!transactionInputs?.tokenSymbol ? (
<div className={styles.gridItem}>
<div className={styles.loading}>Loading</div>
</div>
) : (
<div className={styles.gridItem}>
{`${transactionInputs.tokenSymbol === 'USDC' ? ethers.utils.formatUnits(transactionInputs.amount, 6) : deposit.amount} ${transactionInputs.tokenSymbol}`}
</div>
)}
<div className={styles.gridItem}>{depositInfo.from}</div>
<div className={styles.gridItem}>{depositInfo.to}</div>
<>
Expand All @@ -74,8 +80,8 @@ const Deposit: React.FC<DepositProps> = ({ deposit }) => {
>
<div className={styles.gridItem}>
{transferStatus?.status === BridgeTransferStatus.DEPOSIT_ERC20_REDEEMED ||
transferStatus?.status === BridgeTransferStatus.DEPOSIT_GAS_DEPOSITED ||
transferStatus?.status === BridgeTransferStatus.DEPOSIT_ERC20_FUNDS_DEPOSITED_ON_CHILD ? (
transferStatus?.status === BridgeTransferStatus.DEPOSIT_GAS_DEPOSITED ||
transferStatus?.status === BridgeTransferStatus.DEPOSIT_ERC20_FUNDS_DEPOSITED_ON_CHILD ? (
<div className={styles.settled}>
Completed
<IconLinkExternal02 stroke='#fff' />
Expand All @@ -98,8 +104,8 @@ const Deposit: React.FC<DepositProps> = ({ deposit }) => {
) : (
<div className={styles.gridItemImportant}>
{transferStatus?.status === BridgeTransferStatus.DEPOSIT_ERC20_REDEEMED ||
transferStatus?.status === BridgeTransferStatus.DEPOSIT_GAS_DEPOSITED ||
transferStatus?.status === BridgeTransferStatus.DEPOSIT_ERC20_FUNDS_DEPOSITED_ON_CHILD ? (
transferStatus?.status === BridgeTransferStatus.DEPOSIT_GAS_DEPOSITED ||
transferStatus?.status === BridgeTransferStatus.DEPOSIT_ERC20_FUNDS_DEPOSITED_ON_CHILD ? (
<>{timeAgo(highNetworkTimestamp)}</>
) : (
<>{ETA(deposit.lowNetworkTimestamp, deposit.retryableCreationTimeout ?? 15 * 60)}</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const Withdrawal: React.FC<WithdrawalProps> = ({ withdrawal }) => {
const status = getStatus(withdrawal, lowNetworks, highNetworks)
const { data: transferStatus, isLoading } = returnTransferData({ txRecord: withdrawal })
const { data: transactionInputs } = getTransactionInputs({ txRecord: withdrawal })

return (
<>
{status?.isLoading && smallView ? (
Expand Down Expand Up @@ -92,9 +92,15 @@ const Withdrawal: React.FC<WithdrawalProps> = ({ withdrawal }) => {
</div>
</div>
<div className={styles.gridItem}>{timeAgo(withdrawal.highNetworkTimestamp)}</div>
<div
className={styles.gridItem}
>{`${transactionInputs?.tokenSymbol === 'USDC' ? ethers.utils.formatUnits(transactionInputs?.amount, 6) : withdrawal.amount} ${transactionInputs?.tokenSymbol}`}</div>
{!transactionInputs?.tokenSymbol ? (
<div className={styles.gridItem}>
<div className={styles.loading}>Loading</div>
</div>
) : (
<div className={styles.gridItem}>
{`${transactionInputs.tokenSymbol === 'USDC' ? ethers.utils.formatUnits(transactionInputs.amount, 6) : withdrawal.amount} ${transactionInputs.tokenSymbol}`}
</div>
)}
<div className={styles.gridItem}>{status?.data?.from ?? ''}</div>
<div className={styles.gridItem}>{status?.data?.to ?? ''}</div>
<div className={styles.gridItem}>
Expand Down
76 changes: 51 additions & 25 deletions webapps/world-builder-dashboard/src/hooks/useBridgeTransfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,29 @@ interface UseTransferDataProps {
export const useBridgeTransfer = () => {
const { connectedAccount, selectedNetworkType, switchChain } = useBlockchainContext()
// Retry function with exponential backoff for handling 429 errors
const retryWithExponentialBackoff = async (fn: () => Promise<any>, retries = 5, delay = 1000, jitterFactor = 0.5) => {
const retryWithExponentialBackoff = async (fn: () => Promise<any>, retries = 20, delay = 1000, jitterFactor = 0.5) => {
let attempt = 0

while (attempt < retries) {
try {
return await fn()
} catch (error: any) {
if (error?.response?.status === 429 && attempt < retries - 1) {
const baseDelay = delay *2**attempt
const jitter = baseDelay * (Math.random() * jitterFactor * 2 - jitterFactor)
// Add network failure errors to retryable conditions
const isNetworkError = error.message?.includes('net::ERR_FAILED') ||
error.message?.includes('Network Error') ||
error.code === 'ECONNABORTED' ||
!error.response;
const retryableStatusCodes = [429, 503, 502, 500];

if ((isNetworkError || retryableStatusCodes.includes(error?.response?.status)) && attempt < retries - 1) {
const baseDelay = delay * 2 ** attempt
const jitter = baseDelay * (Math.random() * jitterFactor * 2 - jitterFactor)
const retryDelay = Math.max(baseDelay + jitter, 0)
console.warn(`Retry attempt ${attempt + 1}/${retries} after ${retryDelay}ms due to:`, error.message)
await new Promise((resolve) => setTimeout(resolve, retryDelay))
attempt++
} else {
throw error // Rethrow error if not 429 or max retries reached
throw error
}
}
}
Expand All @@ -51,11 +59,19 @@ export const useBridgeTransfer = () => {
return isPending && timeSinceLastUpdate > 1 * 60 * 1000
}

let status: any
let transferStatus: any

return useQuery(
['transferData', txHash],
async () => {
const transactions = getCachedTransactions(connectedAccount ?? '', selectedNetworkType)
const cachedTransaction = transactions.find((t: any) =>
isDeposit ? t.lowNetworkHash === txRecord.lowNetworkHash : t.highNetworkHash === txRecord.highNetworkHash
)

if (cachedTransaction?.status && !shouldFetchStatus(cachedTransaction)) {
return { status: cachedTransaction.status }
}
const _bridgeTransfer = new BridgeTransfer({
txHash: txHash ?? '',
destinationNetworkChainId: destinationChainId ?? 0,
Expand All @@ -66,25 +82,25 @@ export const useBridgeTransfer = () => {

try {
// Fetch status with retry logic
status = await retryWithExponentialBackoff(async () => await _bridgeTransfer.getStatus())
const statusResponse = await retryWithExponentialBackoff(async () => await _bridgeTransfer.getStatus())
transferStatus = statusResponse

const transactions = getCachedTransactions(connectedAccount ?? '', selectedNetworkType)

// Update the cache with the latest status
const newTransactions = transactions.map((t: any) => {
const isSameHash = isDeposit
? t.lowNetworkHash === txRecord.lowNetworkHash
: t.highNetworkHash === txRecord.highNetworkHash

return isSameHash ? { ...t, status: status?.status, lastUpdated: Date.now() } : t
return isSameHash ? { ...t, status: statusResponse?.status, lastUpdated: Date.now() } : t
})

localStorage.setItem(
`bridge-${connectedAccount}-transactions-${selectedNetworkType}`,
JSON.stringify(newTransactions)
)

return status
return statusResponse
} catch (error) {
console.error('Error fetching status:', error)

Expand All @@ -95,8 +111,8 @@ export const useBridgeTransfer = () => {
)

if (cachedTransaction && cachedTransaction.status !== undefined) {
status = cachedTransaction.status
return { status } // Return cached status
transferStatus = cachedTransaction.status
return { status: transferStatus, ...cachedTransaction } // Return cached status
}

throw error // Re-throw error if no cache
Expand All @@ -111,8 +127,8 @@ export const useBridgeTransfer = () => {
)

if (cachedTransaction && cachedTransaction.status !== undefined) {
status = cachedTransaction.status
return { status }
transferStatus = cachedTransaction.status
return { status: transferStatus }
}
},
staleTime: 0.5 * 60 * 1000,
Expand Down Expand Up @@ -221,9 +237,21 @@ export const useBridgeTransfer = () => {
const destinationRpc = getNetworks(selectedNetworkType)?.find((n) => n.chainId === destinationChainId)?.rpcs[0]
const originRpc = getNetworks(selectedNetworkType)?.find((n) => n.chainId === originChainId)?.rpcs[0]


return useQuery(
['transactionInputs', txHash],
async () => {
// Get fresh cache data
const transactions = getCachedTransactions(connectedAccount ?? '', selectedNetworkType)
const cachedTransaction = transactions.find((t: any) =>
isDeposit ? t.lowNetworkHash === txRecord.lowNetworkHash : t.highNetworkHash === txRecord.highNetworkHash
)

// Check if we have cached inputs
if (cachedTransaction?.transactionInputs !== undefined) {
return cachedTransaction.transactionInputs
}

const _bridgeTransfer = new BridgeTransfer({
txHash: txHash ?? '',
destinationNetworkChainId: destinationChainId ?? 0,
Expand All @@ -232,17 +260,17 @@ export const useBridgeTransfer = () => {
originSignerOrProviderOrRpc: originRpc
})

const transactionInputs = await _bridgeTransfer.getInfo()

const transactions = getCachedTransactions(connectedAccount ?? '', selectedNetworkType)
const transactionInputs = await retryWithExponentialBackoff(
async () => _bridgeTransfer.getInfo()
)

// Update the cache with the latest status
// Update cache with new data
const newTransactions = transactions.map((t: any) => {
const isSameHash = isDeposit
? t.lowNetworkHash === txRecord.lowNetworkHash
: t.highNetworkHash === txRecord.highNetworkHash

return isSameHash ? { ...t, transactionInputs: transactionInputs } : t
return isSameHash ? { ...t, transactionInputs: transactionInputs, lastUpdated: Date.now() } : t
})

localStorage.setItem(
Expand All @@ -253,21 +281,19 @@ export const useBridgeTransfer = () => {
},
{
placeholderData: () => {
// Get fresh cache data for placeholder
const transactions = getCachedTransactions(connectedAccount ?? '', selectedNetworkType)
const cachedTransaction = transactions.find((t: any) =>
isDeposit ? t.lowNetworkHash === txRecord.lowNetworkHash : t.highNetworkHash === txRecord.highNetworkHash
)
if (cachedTransaction && cachedTransaction.transactionInputs !== undefined) {
return cachedTransaction?.transactionInputs
}
return cachedTransaction?.transactionInputs
},
staleTime: 2 * 60 * 1000,
staleTime: 30 * 60 * 1000,
refetchOnWindowFocus: false,
enabled: !!txRecord
}
)
}

const getHighNetworkTimestamp = ({
txRecord,
transferStatus,
Expand Down Expand Up @@ -320,7 +346,7 @@ export const useBridgeTransfer = () => {
return cachedTransaction?.highNetworkTimestamp
},

staleTime: 1 * 60 * 1000,
staleTime: Infinity,
refetchInterval: false,
refetchOnWindowFocus: false,
enabled: !!txRecord && !!transferStatus?.completionTxHash // Run query only if data is valid
Expand Down

0 comments on commit d77ac63

Please sign in to comment.