import { FC, useCallback, useEffect, useState } from "react"; import Container from "../Container"; import Flex from "../Flex"; import Input from "../Input"; import Select from "../Select"; import Text from "../Text"; import { SelectOption, TransactionState, transactionsData, TxFields, getTxFields, } from "../../state/transactions"; import { useSnapshot } from "valtio"; import state from "../../state"; import { streamState } from "../DebugStream"; import { Button } from ".."; import Textarea from "../Textarea"; interface UIProps { setState: ( pTx?: Partial | undefined ) => TransactionState | undefined; state: TransactionState; estimateFee?: (...arg: any) => Promise; } export const TxUI: FC = ({ state: txState, setState, estimateFee, }) => { const { accounts } = useSnapshot(state); const { selectedAccount, selectedDestAccount, selectedTransaction, txFields, } = txState; const transactionsOptions = transactionsData.map(tx => ({ value: tx.TransactionType, label: tx.TransactionType, })); const accountOptions: SelectOption[] = accounts.map(acc => ({ label: acc.name, value: acc.address, })); const destAccountOptions: SelectOption[] = accounts .map(acc => ({ label: acc.name, value: acc.address, })) .filter(acc => acc.value !== selectedAccount?.value); const [feeLoading, setFeeLoading] = useState(false); const resetOptions = useCallback( (tt: string) => { const fields = getTxFields(tt); if (!fields.Destination) setState({ selectedDestAccount: null }); return setState({ txFields: fields }); }, [setState] ); const handleSetAccount = (acc: SelectOption) => { setState({ selectedAccount: acc }); streamState.selectedAccount = acc; }; const handleSetField = useCallback( (field: keyof TxFields, value: string, opFields?: TxFields) => { const fields = opFields || txFields; const obj = fields[field]; setState({ txFields: { ...fields, [field]: typeof obj === "object" ? { ...obj, $value: value } : value, }, }); }, [setState, txFields] ); const handleEstimateFee = useCallback( async (state?: TransactionState, silent?: boolean) => { setFeeLoading(true); const fee = await estimateFee?.(state, { silent }); if (fee) handleSetField("Fee", fee, state?.txFields); setFeeLoading(false); }, [estimateFee, handleSetField] ); const handleChangeTxType = useCallback( (tt: SelectOption) => { setState({ selectedTransaction: tt }); const newState = resetOptions(tt.value); handleEstimateFee(newState, true); }, [handleEstimateFee, resetOptions, setState] ); const specialFields = ["TransactionType", "Account", "Destination"]; const otherFields = Object.keys(txFields).filter( k => !specialFields.includes(k) ) as [keyof TxFields]; const switchToJson = () => setState({ editorSavedValue: null, viewType: "json" }); // default tx useEffect(() => { if (selectedTransaction?.value) return; const defaultOption = transactionsOptions.find( tt => tt.value === "Payment" ); if (defaultOption) { handleChangeTxType(defaultOption); } }, [handleChangeTxType, selectedTransaction?.value, transactionsOptions]); return ( Transaction type:{" "} handleSetAccount(acc)} // TODO make react-select have correct types for acc /> {txFields.Destination !== undefined && ( Destination account:{" "}