vega-frontend-monorepo/libs/web3/src/lib/use-ethereum-transaction-manager.tsx
Art 87e1f9998e
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 10:29:32 +01:00

100 lines
3.0 KiB
TypeScript

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]);
};