-
Notifications
You must be signed in to change notification settings - Fork 29
/
useTransactionListForPendingTxs.ts
123 lines (113 loc) 路 3.89 KB
/
useTransactionListForPendingTxs.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { useEffect } from 'react';
import { Address } from 'viem';
import { useConsolidatedTransactions } from '~/core/resources/transactions/consolidatedTransactions';
import {
nonceStore,
pendingTransactionsStore,
useCurrentAddressStore,
useCurrentCurrencyStore,
} from '~/core/state';
import { useTestnetModeStore } from '~/core/state/currentSettings/testnetMode';
import { ChainId } from '~/core/types/chains';
import { RainbowTransaction } from '~/core/types/transactions';
import {
getSupportedChainIds,
useBackendSupportedChains,
} from '~/core/utils/chains';
import { isLowerCaseMatch } from '~/core/utils/strings';
export const useTransactionListForPendingTxs = () => {
const { currentAddress: address } = useCurrentAddressStore();
const { currentCurrency: currency } = useCurrentCurrencyStore();
const { testnetMode } = useTestnetModeStore();
const supportedChainIds = useBackendSupportedChains({ testnetMode }).map(
({ id }) => id,
);
const { data } = useConsolidatedTransactions({
address,
currency,
userChainIds: supportedChainIds,
});
useEffect(() => {
if (!data?.pages) return;
const latestTransactions = data.pages
.map((p) => p.transactions)
.flat()
.filter((t) => isLowerCaseMatch(t.from, address))
.reduce(
(latestTxMap, currentTx) => {
const currentChain = currentTx?.chainId;
if (currentChain) {
const latestTx = latestTxMap.get(currentChain);
if (!latestTx) {
latestTxMap.set(currentChain, currentTx);
}
}
return latestTxMap;
},
new Map(
getSupportedChainIds().map((chain) => [
chain,
null as RainbowTransaction | null,
]),
),
);
watchForPendingTransactionsReportedByRainbowBackend({
currentAddress: address,
latestTransactions,
});
}, [address, data?.pages]);
};
function watchForPendingTransactionsReportedByRainbowBackend({
currentAddress,
latestTransactions,
}: {
currentAddress: Address;
latestTransactions: Map<ChainId, RainbowTransaction | null>;
}) {
const { setNonce } = nonceStore.getState();
const {
setPendingTransactions,
pendingTransactions: storePendingTransactions,
} = pendingTransactionsStore.getState();
const pendingTransactions = storePendingTransactions[currentAddress] || [];
const supportedChainIds = getSupportedChainIds();
for (const supportedChainId of supportedChainIds) {
const latestTxConfirmedByBackend = latestTransactions.get(supportedChainId);
if (latestTxConfirmedByBackend) {
const latestNonceConfirmedByBackend =
latestTxConfirmedByBackend.nonce || 0;
const [latestPendingTx] = pendingTransactions.filter(
(tx) => tx?.chainId === supportedChainId,
);
let currentNonce;
if (latestPendingTx) {
const latestPendingNonce = latestPendingTx?.nonce || 0;
const latestTransactionIsPending =
latestPendingNonce > latestNonceConfirmedByBackend;
currentNonce = latestTransactionIsPending
? latestPendingNonce
: latestNonceConfirmedByBackend;
} else {
currentNonce = latestNonceConfirmedByBackend;
}
setNonce({
address: currentAddress,
chainId: supportedChainId,
currentNonce,
latestConfirmedNonce: latestNonceConfirmedByBackend,
});
}
}
const updatedPendingTransactions = pendingTransactions?.filter((tx) => {
const txNonce = tx.nonce || 0;
const latestTx = latestTransactions.get(tx.chainId);
const latestTxNonce = latestTx?.nonce || 0;
// still pending or backend is not returning confirmation yet
// if !latestTx means that is the first tx of the wallet
return !latestTx || txNonce > latestTxNonce;
});
setPendingTransactions({
address: currentAddress,
pendingTransactions: updatedPendingTransactions,
});
}