import type { ReactNode } from 'react'; import { useCallback, useMemo, useState } from 'react'; import type { TransactionSubmission } from './wallet-types'; import { useVegaWallet } from './use-vega-wallet'; import type { SendTxError } from './context'; import { VegaTransactionDialog } from './vega-transaction-dialog'; import type { Intent } from '@vegaprotocol/ui-toolkit'; export interface DialogProps { children?: JSX.Element; intent?: Intent; title?: string; icon?: ReactNode; } export enum VegaTxStatus { Default = 'Default', Requested = 'Requested', Pending = 'Pending', Error = 'Error', Complete = 'Complete', } export interface VegaTxState { status: VegaTxStatus; error: object | null; txHash: string | null; signature: string | null; dialogOpen: boolean; } export const initialState = { status: VegaTxStatus.Default, error: null, txHash: null, signature: null, dialogOpen: false, }; export const useVegaTransaction = () => { const { sendTx } = useVegaWallet(); const [transaction, _setTransaction] = useState(initialState); const setTransaction = useCallback((update: Partial) => { _setTransaction((curr) => ({ ...curr, ...update, })); }, []); const handleError = useCallback( (error: SendTxError) => { setTransaction({ error, status: VegaTxStatus.Error }); }, [setTransaction] ); const reset = useCallback(() => { setTransaction(initialState); }, [setTransaction]); const setComplete = useCallback(() => { setTransaction({ status: VegaTxStatus.Complete }); }, [setTransaction]); const send = useCallback( async (tx: TransactionSubmission) => { setTransaction({ error: null, txHash: null, signature: null, status: VegaTxStatus.Requested, dialogOpen: true, }); const res = await sendTx(tx); if (res === null) { setTransaction({ status: VegaTxStatus.Default }); return null; } if ('errors' in res) { handleError(res); } else if ('error' in res) { if (res.error === 'User rejected') { reset(); } else { handleError(res); } } else if (res.tx?.signature?.value && res.txHash) { setTransaction({ status: VegaTxStatus.Pending, txHash: res.txHash, signature: res.tx.signature.value, }); return { signature: res.tx.signature?.value, }; } return null; }, [sendTx, handleError, setTransaction, reset] ); const TransactionDialog = useMemo(() => { return (props: DialogProps) => ( { if (!isOpen) reset(); setTransaction({ dialogOpen: isOpen }); }} transaction={transaction} /> ); }, [transaction, setTransaction, reset]); return { send, transaction, reset, setComplete, TransactionDialog, }; };