vega-frontend-monorepo/libs/web3/src/lib/use-ethereum-transaction-manager.tsx

100 lines
3.0 KiB
TypeScript
Raw Normal View History

feat: transaction store and toasts (#2382) * feat: add eth and vega transaction stores feat: replace useStoredEthereumTransaction with useEthTransactionManager feat: add event bus subsciption to vega transaction store feat: handle order cancellation feat: rename Deposit, Order and Withdraw status field to be unique Revert "feat: rename Deposit, Order and Withdraw status field to be unique" This reverts commit f0b314d53fb3ada6fbebaba4fd1e5af6f38beaed. feat: split transaction update subscription feat: handle order and deposit transaction feat: handle withdrawal creation through transaction store feat: handle withdraw approval feat: handle panding withdrawls, add createdAt feat: handle transaction toast/dialog dismissal feat: add use vega transaction store tests feat: add use vega transaction store tests feat: add use vega transaction menager tests feat: add use vega transaction menager tests feat: add use vega transaction updater tests feat: improve use vega transaction updater tests feat: add use eth transaction store feat: add use eth withdraw approvals store feat: add use eth transaction updater tests fixed tests * feat: toasts feat: toasts feat: toasts * feat: add use eth withdraw approval manager tests * feat: add use eth transaction manager tests * feat: add use eth transaction manager tests * feat: add useEthWithdrawApprovalsManager tests * feat: remove Web3Container react container from CreateWithdrawalDialog * feat: remove Web3Container react container around TransactionsHandler * feat: remove unnecessary async from PendingWithdrawalsTable * feat: remove comments from WithdrawalFeedback * fixed z-index issue * cypress Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2022-12-21 09:29:32 +00:00
import type { ethers } from 'ethers';
import { useRef, useEffect } from 'react';
import type { EthereumError } from './ethereum-error';
import { isExpectedEthereumError } from './ethereum-error';
import { isEthereumError } from './ethereum-error';
import { EthTxStatus } from './use-ethereum-transaction';
import { useEthTransactionStore } from './use-ethereum-transaction-store';
export const useEthTransactionManager = () => {
const update = useEthTransactionStore((state) => state.update);
const processed = useRef<Set<number>>(new Set());
const transaction = useEthTransactionStore((state) =>
state.transactions.find(
(transaction) =>
transaction?.status === EthTxStatus.Default &&
!processed.current.has(transaction.id)
)
);
useEffect(() => {
if (!transaction) {
return;
}
processed.current.add(transaction.id);
update(transaction.id, {
status: EthTxStatus.Requested,
error: null,
confirmations: 0,
});
const {
contract,
methodName,
args,
requiredConfirmations,
requiresConfirmation,
} = transaction;
(async () => {
try {
if (
!contract ||
// @ts-ignore method vary depends on contract
typeof contract[methodName] !== 'function' ||
typeof contract.contract.callStatic[methodName] !== 'function'
) {
throw new Error('method not found on contract');
}
await contract.contract.callStatic[methodName](...args);
} catch (err) {
update(transaction.id, {
status: EthTxStatus.Error,
error: err as EthereumError,
});
return;
}
try {
// @ts-ignore args will vary depends on contract and method
const tx = await contract[methodName].call(contract, ...args);
let receipt: ethers.ContractReceipt | null = null;
update(transaction.id, {
status: EthTxStatus.Pending,
txHash: tx.hash,
});
for (let i = 1; i <= requiredConfirmations; i++) {
receipt = await tx.wait(i);
update(transaction.id, {
confirmations: receipt
? receipt.confirmations
: requiredConfirmations,
});
}
if (!receipt) {
throw new Error('no receipt after confirmations are met');
}
if (requiresConfirmation) {
update(transaction.id, { status: EthTxStatus.Complete, receipt });
} else {
update(transaction.id, { status: EthTxStatus.Confirmed, receipt });
}
} catch (err) {
if (err instanceof Error || isEthereumError(err)) {
if (!isExpectedEthereumError(err)) {
update(transaction.id, { status: EthTxStatus.Error, error: err });
}
} else {
update(transaction.id, {
status: EthTxStatus.Error,
error: new Error('Something went wrong'),
});
}
return;
}
})();
}, [transaction, update]);
};