import { Play } from "phosphor-react"; import { FC, useCallback, useEffect } from "react"; import { useSnapshot } from "valtio"; import state from "../../state"; import { defaultTransactionType, getTxFields, modifyTransaction, prepareState, prepareTransaction, SelectOption, TransactionState, } from "../../state/transactions"; import { sendTransaction } from "../../state/actions"; import Box from "../Box"; import Button from "../Button"; import Flex from "../Flex"; import { TxJson } from "./json"; import { TxUI } from "./ui"; import { default as _estimateFee } from "../../utils/estimateFee"; import toast from "react-hot-toast"; export interface TransactionProps { header: string; state: TransactionState; } const Transaction: FC = ({ header, state: txState, ...props }) => { const { accounts, editorSettings } = useSnapshot(state); const { selectedAccount, selectedTransaction, txIsDisabled, txIsLoading, viewType, editorValue, } = txState; const setState = useCallback( (pTx?: Partial) => { return modifyTransaction(header, pTx); }, [header] ); const prepareOptions = useCallback( (state: Partial = txState) => { const { selectedTransaction, selectedDestAccount, selectedAccount, txFields, } = state; const TransactionType = selectedTransaction?.value || null; const Destination = selectedDestAccount?.value || txFields?.Destination; const Account = selectedAccount?.value || null; return prepareTransaction({ ...txFields, TransactionType, Destination, Account, }); }, [txState] ); useEffect(() => { const transactionType = selectedTransaction?.value; const account = selectedAccount?.value; if (!account || !transactionType || txIsLoading) { setState({ txIsDisabled: true }); } else { setState({ txIsDisabled: false }); } }, [ selectedAccount?.value, selectedTransaction?.value, setState, txIsLoading, ]); const submitTest = useCallback(async () => { let st: TransactionState | undefined; const tt = txState.selectedTransaction?.value; if (viewType === "json") { // save the editor state first const pst = prepareState(editorValue || "", tt); if (!pst) return; st = setState(pst); } const account = accounts.find( acc => acc.address === selectedAccount?.value ); if (txIsDisabled) return; setState({ txIsLoading: true }); const logPrefix = header ? `${header.split(".")[0]}: ` : undefined; try { if (!account) { throw Error("Account must be selected from imported accounts!"); } const options = prepareOptions(st); const fields = getTxFields(options.TransactionType); if (fields.Destination && !options.Destination) { throw Error("Destination account is required!"); } await sendTransaction(account, options, { logPrefix }); } catch (error) { console.error(error); if (error instanceof Error) { state.transactionLogs.push({ type: "error", message: `${logPrefix}${error.message}`, }); } } setState({ txIsLoading: false }); }, [ viewType, accounts, txIsDisabled, setState, header, editorValue, txState, selectedAccount?.value, prepareOptions, ]); const getJsonString = useCallback( (state?: Partial) => JSON.stringify( prepareOptions?.(state) || {}, null, editorSettings.tabSize ), [editorSettings.tabSize, prepareOptions] ); const resetState = useCallback( (transactionType: SelectOption | undefined = defaultTransactionType) => { const fields = getTxFields(transactionType?.value); const nwState: Partial = { viewType, selectedTransaction: transactionType, }; if (fields.Destination !== undefined) { nwState.selectedDestAccount = null; fields.Destination = ""; } else { fields.Destination = undefined; } nwState.txFields = fields; const state = modifyTransaction(header, nwState, { replaceState: true }); const editorValue = getJsonString(state); return setState({ editorValue }); }, [getJsonString, header, setState, viewType] ); const estimateFee = useCallback( async (st?: TransactionState, opts?: { silent?: boolean }) => { const state = st || txState; const ptx = prepareOptions(state); const account = accounts.find( acc => acc.address === state.selectedAccount?.value ); if (!account) { if (!opts?.silent) { toast.error("Please select account from the list."); } return; } ptx.Account = account.address; ptx.Sequence = account.sequence; const res = await _estimateFee(ptx, account, opts); const fee = res?.base_fee; setState({ estimatedFee: fee }); return fee; }, [accounts, prepareOptions, setState, txState] ); return ( {viewType === "json" ? ( ) : ( )} ); }; export default Transaction;