From b529355c6456aaf399e8f4dbe3af7265ec11fcf5 Mon Sep 17 00:00:00 2001 From: Ramiro Vazquez Date: Thu, 7 Oct 2021 10:07:49 -0300 Subject: [PATCH] handle cancel state for ethereum txs --- src/custom/hooks/useRecentActivity.ts | 10 +++++----- .../state/enhancedTransactions/actions.ts | 6 ++---- .../state/enhancedTransactions/reducer.ts | 17 +++++------------ .../updater/CancelReplaceTxUpdater.tsx | 13 +++++-------- 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/custom/hooks/useRecentActivity.ts b/src/custom/hooks/useRecentActivity.ts index 8627d9327..c09ed491b 100644 --- a/src/custom/hooks/useRecentActivity.ts +++ b/src/custom/hooks/useRecentActivity.ts @@ -137,12 +137,12 @@ export function useActivityDescriptors({ chainId, id }: { chainId?: ChainId; id: // setup variables accordingly... const isReceiptConfirmed = tx.receipt?.status === TxReceiptStatus.CONFIRMED || typeof tx.receipt?.status === 'undefined' + const isCancelTx = tx?.replacementType === 'cancel' isPending = !tx?.receipt isPresignaturePending = false isConfirmed = !isPending && isReceiptConfirmed - // TODO: can't tell when it's cancelled from the network yet - isCancelling = false - isCancelled = false + isCancelling = isCancelTx && isPending + isCancelled = isCancelTx && !isPending && isReceiptConfirmed activity = tx type = ActivityType.TX @@ -156,10 +156,10 @@ export function useActivityDescriptors({ chainId, id }: { chainId?: ChainId; id: status = ActivityStatus.PENDING } else if (isPresignaturePending) { status = ActivityStatus.PRESIGNATURE_PENDING - } else if (isConfirmed) { - status = ActivityStatus.CONFIRMED } else if (isCancelled) { status = ActivityStatus.CANCELLED + } else if (isConfirmed) { + status = ActivityStatus.CONFIRMED } else { status = ActivityStatus.EXPIRED } diff --git a/src/custom/state/enhancedTransactions/actions.ts b/src/custom/state/enhancedTransactions/actions.ts index 390ed219b..2484306f6 100644 --- a/src/custom/state/enhancedTransactions/actions.ts +++ b/src/custom/state/enhancedTransactions/actions.ts @@ -23,13 +23,11 @@ export const checkedTransaction = createAction<{ blockNumber: number }>('enhancedTransactions/checkedTransaction') -export const cancelTransaction = createAction<{ - chainId: number - hash: string -}>('enhancedTransactions/cancelTransaction') +export type REPLACEMENT_TYPE = 'speedup' | 'cancel' export const replaceTransaction = createAction<{ chainId: number oldHash: string newHash: string + type: REPLACEMENT_TYPE }>('enhancedTransactions/replaceTransaction') diff --git a/src/custom/state/enhancedTransactions/reducer.ts b/src/custom/state/enhancedTransactions/reducer.ts index 497f64e95..c58ac1a01 100644 --- a/src/custom/state/enhancedTransactions/reducer.ts +++ b/src/custom/state/enhancedTransactions/reducer.ts @@ -4,8 +4,8 @@ import { clearAllTransactions, checkedTransaction, finalizeTransaction, - cancelTransaction, replaceTransaction, + REPLACEMENT_TYPE, // updateSafeTransactions, } from 'state/enhancedTransactions/actions' import { SerializableTransactionReceipt } from '@src/state/transactions/actions' @@ -31,6 +31,8 @@ export interface EnhancedTransactionDetails { // Operations approval?: { tokenAddress: string; spender: string } presign?: { orderId: string } + + replacementType?: REPLACEMENT_TYPE // if the user cancelled or speedup the tx it will be reflected here } export interface EnhancedTransactionState { @@ -93,22 +95,13 @@ export default createReducer(initialState, (builder) => tx.confirmedTime = now() }) - .addCase(cancelTransaction, (transactions, { payload: { chainId, hash } }) => { - if (!transactions[chainId]?.[hash]) { - console.error('Attempted to cancel an unknown transaction.') - return - } - const allTxs = transactions[chainId] ?? {} - delete allTxs[hash] - }) - - .addCase(replaceTransaction, (transactions, { payload: { chainId, oldHash, newHash } }) => { + .addCase(replaceTransaction, (transactions, { payload: { chainId, oldHash, newHash, type } }) => { if (!transactions[chainId]?.[oldHash]) { console.error('Attempted to replace an unknown transaction.') return } const allTxs = transactions[chainId] ?? {} - allTxs[newHash] = { ...allTxs[oldHash], hash: newHash, addedTime: new Date().getTime() } + allTxs[newHash] = { ...allTxs[oldHash], hash: newHash, addedTime: new Date().getTime(), replacementType: type } delete allTxs[oldHash] }) ) diff --git a/src/custom/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx b/src/custom/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx index 9bc693aaf..4050e8c29 100644 --- a/src/custom/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx +++ b/src/custom/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx @@ -2,7 +2,7 @@ import { useEffect } from 'react' import { useAppDispatch } from 'state/hooks' import { useActiveWeb3React } from 'hooks/web3' import { sdk } from 'utils/blocknative' -import { cancelTransaction, replaceTransaction } from 'state/enhancedTransactions/actions' +import { replaceTransaction } from 'state/enhancedTransactions/actions' import { useAllPendingHashes } from 'state/enhancedTransactions/hooks' import { Dispatch } from 'redux' @@ -11,19 +11,16 @@ function watchTxChanges(pendingHashes: string[], chainId: number, dispatch: Disp try { const { emitter } = sdk[chainId].transaction(hash) const currentHash = hash - let isSpeedup = false emitter.on('txSpeedUp', (e) => { - isSpeedup = true if ('hash' in e && typeof e.hash === 'string') { - dispatch(replaceTransaction({ chainId, oldHash: currentHash, newHash: e.hash })) + dispatch(replaceTransaction({ chainId, oldHash: currentHash, newHash: e.hash, type: 'speedup' })) } }) - emitter.on('txConfirmed', (e) => { - // canceled txs are automatically watched by bnc so if the confirmed tx hash is different than the previously tracked one, it means the user sent a cancel tx - if ('hash' in e && e.hash !== currentHash && !isSpeedup) { - dispatch(cancelTransaction({ chainId, hash: currentHash })) + emitter.on('txCancel', (e) => { + if ('hash' in e && typeof e.hash === 'string') { + dispatch(replaceTransaction({ chainId, oldHash: currentHash, newHash: e.hash, type: 'cancel' })) } }) } catch (error) {