-
Notifications
You must be signed in to change notification settings - Fork 79
/
index.tsx
109 lines (92 loc) · 3.5 KB
/
index.tsx
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
import { ChainExplorerLink } from 'components';
import {
checkForComptrollerTransactionError,
checkForTokenTransactionError,
checkForVaiControllerTransactionError,
checkForVaiVaultTransactionError,
checkForXvsVaultProxyTransactionError,
} from 'errors';
import { ContractReceipt, ContractTransaction } from 'ethers';
import { displayNotification, updateNotification } from 'packages/notifications';
import { useTranslation } from 'packages/translations';
import { useCallback } from 'react';
import { useAuth } from 'context/AuthContext';
import { useGetChainMetadata } from 'hooks/useGetChainMetadata';
export const CONFIRMATIONS = 2;
interface TrackTransactionInput {
transaction: ContractTransaction;
onConfirmed?: (input: {
transaction: ContractTransaction;
transactionReceipt: ContractReceipt;
}) => Promise<unknown> | unknown;
onReverted?: (input: { transaction: ContractTransaction }) => Promise<unknown> | unknown;
}
export const useTrackTransaction = () => {
const { provider, chainId } = useAuth();
const { blockTimeMs } = useGetChainMetadata();
const { t } = useTranslation();
const trackTransaction = useCallback(
async ({ transaction, onConfirmed, onReverted }: TrackTransactionInput) => {
// Display notification indicating transaction is being processed
const notificationId = displayNotification({
id: transaction.hash,
variant: 'loading',
autoClose: false,
title: t('transactionNotification.pending.title'),
description: <ChainExplorerLink chainId={chainId} hash={transaction.hash} urlType="tx" />,
});
let transactionReceipt: ContractReceipt | undefined;
const timeoutMs = blockTimeMs * 10; // 10 blocks
try {
transactionReceipt = await provider.waitForTransaction(
transaction.hash,
CONFIRMATIONS,
timeoutMs,
);
} catch (error) {
// Do nothing
}
if (typeof transactionReceipt?.status !== 'number') {
// Update corresponding notification to say transaction receipt could not be fetched
updateNotification({
id: notificationId,
variant: 'warning',
title: t('transactionNotification.couldNotFetchReceipt.title'),
});
return;
}
let transactionSucceeded = transactionReceipt.status === 1;
// Check for non-reverting errors
try {
checkForComptrollerTransactionError(transactionReceipt);
checkForTokenTransactionError(transactionReceipt);
checkForVaiControllerTransactionError(transactionReceipt);
checkForVaiVaultTransactionError(transactionReceipt);
checkForXvsVaultProxyTransactionError(transactionReceipt);
} catch (_error) {
transactionSucceeded = false;
}
if (!transactionSucceeded) {
// Update corresponding notification to say transaction failed
updateNotification({
id: notificationId,
variant: 'error',
title: t('transactionNotification.failed.title'),
});
// Execute callback
await onReverted?.({ transaction });
return;
}
// Update corresponding notification to say transaction succeeded
updateNotification({
id: notificationId,
variant: 'success',
title: t('transactionNotification.success.title'),
});
// Execute callback
await onConfirmed?.({ transaction, transactionReceipt });
},
[chainId, provider, t, blockTimeMs],
);
return trackTransaction;
};