@@ -19,6 +19,7 @@ import { TxJson } from './json'
 | 
			
		||||
import { TxUI } from './ui'
 | 
			
		||||
import { default as _estimateFee } from '../../utils/estimateFee'
 | 
			
		||||
import toast from 'react-hot-toast'
 | 
			
		||||
import { combineFlags, extractFlags, transactionFlags } from '../../state/constants/flags'
 | 
			
		||||
 | 
			
		||||
export interface TransactionProps {
 | 
			
		||||
  header: string
 | 
			
		||||
@@ -39,14 +40,17 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
 | 
			
		||||
  const prepareOptions = useCallback(
 | 
			
		||||
    (state: Partial<TransactionState> = txState) => {
 | 
			
		||||
      const { selectedTransaction, selectedDestAccount, selectedAccount, txFields } = state
 | 
			
		||||
      const { selectedTransaction, selectedDestAccount, selectedAccount, txFields, selectedFlags } =
 | 
			
		||||
        state
 | 
			
		||||
 | 
			
		||||
      const TransactionType = selectedTransaction?.value || null
 | 
			
		||||
      const Destination = selectedDestAccount?.value || txFields?.Destination
 | 
			
		||||
      const Account = selectedAccount?.value || null
 | 
			
		||||
      const Flags = combineFlags(selectedFlags?.map(flag => flag.value)) || txFields?.Flags
 | 
			
		||||
 | 
			
		||||
      return prepareTransaction({
 | 
			
		||||
        ...txFields,
 | 
			
		||||
        Flags,
 | 
			
		||||
        TransactionType,
 | 
			
		||||
        Destination,
 | 
			
		||||
        Account
 | 
			
		||||
@@ -136,8 +140,13 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
      } else {
 | 
			
		||||
        fields.Destination = undefined
 | 
			
		||||
      }
 | 
			
		||||
      nwState.txFields = fields
 | 
			
		||||
 | 
			
		||||
      if (transactionType?.value && transactionFlags[transactionType?.value] && fields.Flags) {
 | 
			
		||||
        nwState.selectedFlags = extractFlags(transactionType.value, fields.Flags)
 | 
			
		||||
        fields.Flags = undefined
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      nwState.txFields = fields
 | 
			
		||||
      const state = modifyTxState(header, nwState, { replaceState: true })
 | 
			
		||||
      const editorValue = getJsonString(state)
 | 
			
		||||
      return setState({ editorValue })
 | 
			
		||||
@@ -179,7 +188,12 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
 | 
			
		||||
          estimateFee={estimateFee}
 | 
			
		||||
        />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <TxUI state={txState} setState={setState} estimateFee={estimateFee} />
 | 
			
		||||
        <TxUI
 | 
			
		||||
          state={txState}
 | 
			
		||||
          resetState={resetState}
 | 
			
		||||
          setState={setState}
 | 
			
		||||
          estimateFee={estimateFee}
 | 
			
		||||
        />
 | 
			
		||||
      )}
 | 
			
		||||
      <Flex
 | 
			
		||||
        row
 | 
			
		||||
 
 | 
			
		||||
@@ -17,16 +17,19 @@ import state from '../../state'
 | 
			
		||||
import { streamState } from '../DebugStream'
 | 
			
		||||
import { Button } from '..'
 | 
			
		||||
import Textarea from '../Textarea'
 | 
			
		||||
import { getFlags } from '../../state/constants/flags'
 | 
			
		||||
 | 
			
		||||
interface UIProps {
 | 
			
		||||
  setState: (pTx?: Partial<TransactionState> | undefined) => TransactionState | undefined
 | 
			
		||||
  resetState: (tt?: SelectOption) => TransactionState | undefined
 | 
			
		||||
  state: TransactionState
 | 
			
		||||
  estimateFee?: (...arg: any) => Promise<string | undefined>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const TxUI: FC<UIProps> = ({ state: txState, setState, estimateFee }) => {
 | 
			
		||||
export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estimateFee }) => {
 | 
			
		||||
  const { accounts } = useSnapshot(state)
 | 
			
		||||
  const { selectedAccount, selectedDestAccount, selectedTransaction, txFields } = txState
 | 
			
		||||
  const { selectedAccount, selectedDestAccount, selectedTransaction, txFields, selectedFlags } =
 | 
			
		||||
    txState
 | 
			
		||||
 | 
			
		||||
  const accountOptions: SelectOption[] = accounts.map(acc => ({
 | 
			
		||||
    label: acc.name,
 | 
			
		||||
@@ -40,23 +43,15 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, estimateFee }) =>
 | 
			
		||||
    }))
 | 
			
		||||
    .filter(acc => acc.value !== selectedAccount?.value)
 | 
			
		||||
 | 
			
		||||
  const flagsOptions: SelectOption[] = Object.entries(
 | 
			
		||||
    getFlags(selectedTransaction?.value) || {}
 | 
			
		||||
  ).map(([label, value]) => ({
 | 
			
		||||
    label,
 | 
			
		||||
    value
 | 
			
		||||
  }))
 | 
			
		||||
 | 
			
		||||
  const [feeLoading, setFeeLoading] = useState(false)
 | 
			
		||||
 | 
			
		||||
  const resetFields = useCallback(
 | 
			
		||||
    (tt: string) => {
 | 
			
		||||
      const fields = getTxFields(tt)
 | 
			
		||||
 | 
			
		||||
      if (fields.Destination !== undefined) {
 | 
			
		||||
        setState({ selectedDestAccount: null })
 | 
			
		||||
        fields.Destination = ''
 | 
			
		||||
      } else {
 | 
			
		||||
        fields.Destination = undefined
 | 
			
		||||
      }
 | 
			
		||||
      return setState({ txFields: fields })
 | 
			
		||||
    },
 | 
			
		||||
    [setState]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const handleSetAccount = (acc: SelectOption) => {
 | 
			
		||||
    setState({ selectedAccount: acc })
 | 
			
		||||
    streamState.selectedAccount = acc
 | 
			
		||||
@@ -92,11 +87,11 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, estimateFee }) =>
 | 
			
		||||
    (tt: SelectOption) => {
 | 
			
		||||
      setState({ selectedTransaction: tt })
 | 
			
		||||
 | 
			
		||||
      const newState = resetFields(tt.value)
 | 
			
		||||
      const newState = resetState(tt)
 | 
			
		||||
 | 
			
		||||
      handleEstimateFee(newState, true)
 | 
			
		||||
    },
 | 
			
		||||
    [handleEstimateFee, resetFields, setState]
 | 
			
		||||
    [handleEstimateFee, resetState, setState]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const switchToJson = () => setState({ viewType: 'json' })
 | 
			
		||||
@@ -115,14 +110,16 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, estimateFee }) =>
 | 
			
		||||
    [selectedTransaction?.value]
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const specialFields = ['TransactionType', 'Account']
 | 
			
		||||
  const richFields = ['TransactionType', 'Account']
 | 
			
		||||
  if (fields.Destination !== undefined) {
 | 
			
		||||
    specialFields.push('Destination')
 | 
			
		||||
    richFields.push('Destination')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const otherFields = Object.keys(txFields).filter(k => !specialFields.includes(k)) as [
 | 
			
		||||
    keyof TxFields
 | 
			
		||||
  ]
 | 
			
		||||
  if (flagsOptions.length) {
 | 
			
		||||
    richFields.push('Flags')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const otherFields = Object.keys(txFields).filter(k => !richFields.includes(k)) as [keyof TxFields]
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Container
 | 
			
		||||
@@ -179,7 +176,32 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, estimateFee }) =>
 | 
			
		||||
            onChange={(acc: any) => handleSetAccount(acc)} // TODO make react-select have correct types for acc
 | 
			
		||||
          />
 | 
			
		||||
        </Flex>
 | 
			
		||||
        {fields.Destination !== undefined && (
 | 
			
		||||
        {richFields.includes('Destination') && (
 | 
			
		||||
          <Flex
 | 
			
		||||
            row
 | 
			
		||||
            fluid
 | 
			
		||||
            css={{
 | 
			
		||||
              justifyContent: 'flex-end',
 | 
			
		||||
              alignItems: 'center',
 | 
			
		||||
              mb: '$3',
 | 
			
		||||
              pr: '1px'
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Text muted css={{ mr: '$3', textAlign: 'end' }}>
 | 
			
		||||
              Destination account:{' '}
 | 
			
		||||
            </Text>
 | 
			
		||||
            <Select
 | 
			
		||||
              instanceId="to-account"
 | 
			
		||||
              placeholder="Select the destination account"
 | 
			
		||||
              css={{ width: '70%' }}
 | 
			
		||||
              options={destAccountOptions}
 | 
			
		||||
              value={selectedDestAccount}
 | 
			
		||||
              isClearable
 | 
			
		||||
              onChange={(acc: any) => setState({ selectedDestAccount: acc })}
 | 
			
		||||
            />
 | 
			
		||||
          </Flex>
 | 
			
		||||
        )}
 | 
			
		||||
        {richFields.includes('Flags') && (
 | 
			
		||||
          <Flex
 | 
			
		||||
            row
 | 
			
		||||
            fluid
 | 
			
		||||
@@ -191,16 +213,21 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, estimateFee }) =>
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Text muted css={{ mr: '$3' }}>
 | 
			
		||||
              Destination account:{' '}
 | 
			
		||||
              Flags:{' '}
 | 
			
		||||
            </Text>
 | 
			
		||||
            <Select
 | 
			
		||||
              instanceId="to-account"
 | 
			
		||||
              placeholder="Select the destination account"
 | 
			
		||||
              css={{ width: '70%' }}
 | 
			
		||||
              options={destAccountOptions}
 | 
			
		||||
              value={selectedDestAccount}
 | 
			
		||||
              isClearable
 | 
			
		||||
              onChange={(acc: any) => setState({ selectedDestAccount: acc })}
 | 
			
		||||
              css={{ width: '70%' }}
 | 
			
		||||
              instanceId="flags"
 | 
			
		||||
              placeholder="Select flags to apply"
 | 
			
		||||
              menuPosition="fixed"
 | 
			
		||||
              value={selectedFlags}
 | 
			
		||||
              isMulti
 | 
			
		||||
              options={flagsOptions}
 | 
			
		||||
              onChange={flags => setState({ selectedFlags: flags as any })}
 | 
			
		||||
              closeMenuOnSelect={
 | 
			
		||||
                selectedFlags ? selectedFlags.length >= flagsOptions.length - 1 : false
 | 
			
		||||
              }
 | 
			
		||||
            />
 | 
			
		||||
          </Flex>
 | 
			
		||||
        )}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
    "DestinationTag": 13,
 | 
			
		||||
    "Fee": "2000000",
 | 
			
		||||
    "Sequence": 2470665,
 | 
			
		||||
    "Flags": 2147483648
 | 
			
		||||
    "Flags": "2147483648"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "TransactionType": "AccountSet",
 | 
			
		||||
@@ -48,7 +48,7 @@
 | 
			
		||||
    "Account": "rsUiUMpnrgxQp24dJYZDhmV4bE3aBtQyt8",
 | 
			
		||||
    "Authorize": "rEhxGqkqPPSxQ3P25J66ft5TwpzV14k2de",
 | 
			
		||||
    "Fee": "10",
 | 
			
		||||
    "Flags": 2147483648,
 | 
			
		||||
    "Flags": "2147483648",
 | 
			
		||||
    "Sequence": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
@@ -109,7 +109,9 @@
 | 
			
		||||
    "Fee": "10",
 | 
			
		||||
    "NFTokenOffers": {
 | 
			
		||||
      "$type": "json",
 | 
			
		||||
      "$value": ["4AAAEEA76E3C8148473CB3840CE637676E561FB02BD4CA22CA59729EA815B862"]
 | 
			
		||||
      "$value": [
 | 
			
		||||
        "4AAAEEA76E3C8148473CB3840CE637676E561FB02BD4CA22CA59729EA815B862"
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
@@ -120,7 +122,7 @@
 | 
			
		||||
      "$value": "100",
 | 
			
		||||
      "$type": "xrp"
 | 
			
		||||
    },
 | 
			
		||||
    "Flags": 1,
 | 
			
		||||
    "Flags": "1",
 | 
			
		||||
    "Destination": "",
 | 
			
		||||
    "Fee": "10"
 | 
			
		||||
  },
 | 
			
		||||
@@ -128,7 +130,7 @@
 | 
			
		||||
    "TransactionType": "OfferCancel",
 | 
			
		||||
    "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
 | 
			
		||||
    "Fee": "12",
 | 
			
		||||
    "Flags": 0,
 | 
			
		||||
    "Flags": "0",
 | 
			
		||||
    "LastLedgerSequence": 7108629,
 | 
			
		||||
    "OfferSequence": 6,
 | 
			
		||||
    "Sequence": 7
 | 
			
		||||
@@ -137,7 +139,7 @@
 | 
			
		||||
    "TransactionType": "OfferCreate",
 | 
			
		||||
    "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
 | 
			
		||||
    "Fee": "12",
 | 
			
		||||
    "Flags": 0,
 | 
			
		||||
    "Flags": "0",
 | 
			
		||||
    "LastLedgerSequence": 7108682,
 | 
			
		||||
    "Sequence": 8,
 | 
			
		||||
    "TakerGets": "6000000",
 | 
			
		||||
@@ -155,7 +157,7 @@
 | 
			
		||||
      "$type": "xrp"
 | 
			
		||||
    },
 | 
			
		||||
    "Fee": "12",
 | 
			
		||||
    "Flags": 2147483648,
 | 
			
		||||
    "Flags": "2147483648",
 | 
			
		||||
    "Sequence": 2
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
@@ -185,14 +187,14 @@
 | 
			
		||||
    "Fee": "10"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Flags": 0,
 | 
			
		||||
    "Flags": "0",
 | 
			
		||||
    "TransactionType": "SetRegularKey",
 | 
			
		||||
    "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
 | 
			
		||||
    "Fee": "12",
 | 
			
		||||
    "RegularKey": "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Flags": 0,
 | 
			
		||||
    "Flags": "0",
 | 
			
		||||
    "TransactionType": "SignerListSet",
 | 
			
		||||
    "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
 | 
			
		||||
    "Fee": "12",
 | 
			
		||||
@@ -232,7 +234,7 @@
 | 
			
		||||
    "TransactionType": "TrustSet",
 | 
			
		||||
    "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
 | 
			
		||||
    "Fee": "12",
 | 
			
		||||
    "Flags": 262144,
 | 
			
		||||
    "Flags": "262144",
 | 
			
		||||
    "LastLedgerSequence": 8007750,
 | 
			
		||||
    "LimitAmount": {
 | 
			
		||||
      "$type": "json",
 | 
			
		||||
@@ -244,4 +246,4 @@
 | 
			
		||||
    },
 | 
			
		||||
    "Sequence": 12
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										79
									
								
								state/constants/flags.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								state/constants/flags.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
import { SelectOption } from '../transactions';
 | 
			
		||||
 | 
			
		||||
interface Flags {
 | 
			
		||||
    [key: string]: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const transactionFlags: { [key: /* TransactionType */ string]: Flags } = {
 | 
			
		||||
    "*": {
 | 
			
		||||
        tfFullyCanonicalSig: '0x80000000'
 | 
			
		||||
    },
 | 
			
		||||
    Payment: {
 | 
			
		||||
        tfNoDirectRipple: '0x00010000',
 | 
			
		||||
        tfPartialPayment: '0x00020000',
 | 
			
		||||
        tfLimitQuality: '0x00040000',
 | 
			
		||||
    },
 | 
			
		||||
    AccountSet: {
 | 
			
		||||
        tfRequireDestTag: '0x00010000',
 | 
			
		||||
        tfOptionalDestTag: '0x00020000',
 | 
			
		||||
        tfRequireAuth: '0x00040000',
 | 
			
		||||
        tfOptionalAuth: '0x00080000',
 | 
			
		||||
        tfDisallowXRP: '0x00100000',
 | 
			
		||||
        tfAllowXRP: '0x00200000',
 | 
			
		||||
    },
 | 
			
		||||
    NFTokenCreateOffer: {
 | 
			
		||||
        tfSellNFToken: '0x00000001',
 | 
			
		||||
    },
 | 
			
		||||
    NFTokenMint: {
 | 
			
		||||
        tfBurnable: '0x00000001',
 | 
			
		||||
        tfOnlyXRP: '0x00000002',
 | 
			
		||||
        tfTrustLine: '0x00000004',
 | 
			
		||||
        tfTransferable: '0x00000008',
 | 
			
		||||
    },
 | 
			
		||||
    OfferCreate: {
 | 
			
		||||
        tfPassive: '0x00010000',
 | 
			
		||||
        tfImmediateOrCancel: '0x00020000',
 | 
			
		||||
        tfFillOrKill: '0x00040000',
 | 
			
		||||
        tfSell: '0x00080000',
 | 
			
		||||
    },
 | 
			
		||||
    PaymentChannelClaim: {
 | 
			
		||||
        tfRenew: '0x00010000',
 | 
			
		||||
        tfClose: '0x00020000',
 | 
			
		||||
    },
 | 
			
		||||
    TrustSet: {
 | 
			
		||||
        tfSetfAuth: '0x00010000',
 | 
			
		||||
        tfSetNoRipple: '0x00020000',
 | 
			
		||||
        tfClearNoRipple: '0x00040000',
 | 
			
		||||
        tfSetFreeze: '0x00100000',
 | 
			
		||||
        tfClearFreeze: '0x00200000',
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getFlags = (tt?: string) => {
 | 
			
		||||
    if (!tt) return
 | 
			
		||||
    const flags = {
 | 
			
		||||
        ...transactionFlags['*'],
 | 
			
		||||
        ...transactionFlags[tt]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return flags
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export function combineFlags(flags?: string[]): string | undefined {
 | 
			
		||||
    if (!flags) return
 | 
			
		||||
 | 
			
		||||
    const num = flags.reduce((cumm, curr) => cumm | BigInt(curr), BigInt(0))
 | 
			
		||||
    return num.toString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function extractFlags(transactionType: string, flags?: string | number,): SelectOption[] {
 | 
			
		||||
    const flagsObj = getFlags(transactionType)
 | 
			
		||||
    if (!flags || !flagsObj) return []
 | 
			
		||||
 | 
			
		||||
    const extracted = Object.entries(flagsObj).reduce((cumm, [label, value]) => {
 | 
			
		||||
        return (BigInt(flags) & BigInt(value)) ? cumm.concat({ label, value }) : cumm
 | 
			
		||||
    }, [] as SelectOption[])
 | 
			
		||||
 | 
			
		||||
    return extracted
 | 
			
		||||
}
 | 
			
		||||
@@ -4,6 +4,7 @@ import transactionsData from '../content/transactions.json'
 | 
			
		||||
import state from '.'
 | 
			
		||||
import { showAlert } from '../state/actions/showAlert'
 | 
			
		||||
import { parseJSON } from '../utils/json'
 | 
			
		||||
import { extractFlags, getFlags } from './constants/flags'
 | 
			
		||||
 | 
			
		||||
export type SelectOption = {
 | 
			
		||||
  value: string
 | 
			
		||||
@@ -14,6 +15,7 @@ export interface TransactionState {
 | 
			
		||||
  selectedTransaction: SelectOption | null
 | 
			
		||||
  selectedAccount: SelectOption | null
 | 
			
		||||
  selectedDestAccount: SelectOption | null
 | 
			
		||||
  selectedFlags: SelectOption[] | null
 | 
			
		||||
  txIsLoading: boolean
 | 
			
		||||
  txIsDisabled: boolean
 | 
			
		||||
  txFields: TxFields
 | 
			
		||||
@@ -31,6 +33,7 @@ export const defaultTransaction: TransactionState = {
 | 
			
		||||
  selectedTransaction: null,
 | 
			
		||||
  selectedAccount: null,
 | 
			
		||||
  selectedDestAccount: null,
 | 
			
		||||
  selectedFlags: null,
 | 
			
		||||
  txIsLoading: false,
 | 
			
		||||
  txIsDisabled: false,
 | 
			
		||||
  txFields: {},
 | 
			
		||||
@@ -128,9 +131,8 @@ export const prepareTransaction = (data: any) => {
 | 
			
		||||
        try {
 | 
			
		||||
          options[field] = JSON.parse(_value.$value)
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
          const message = `Input error for json field '${field}': ${
 | 
			
		||||
            error instanceof Error ? error.message : ''
 | 
			
		||||
          }`
 | 
			
		||||
          const message = `Input error for json field '${field}': ${error instanceof Error ? error.message : ''
 | 
			
		||||
            }`
 | 
			
		||||
          console.error(message)
 | 
			
		||||
          options[field] = _value.$value
 | 
			
		||||
        }
 | 
			
		||||
@@ -205,6 +207,13 @@ export const prepareState = (value: string, transactionType?: string) => {
 | 
			
		||||
    rest.Destination = Destination
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (getFlags(TransactionType) && rest.Flags) {
 | 
			
		||||
    const flags = extractFlags(TransactionType, rest.Flags)
 | 
			
		||||
 | 
			
		||||
    rest.Flags = undefined
 | 
			
		||||
    tx.selectedFlags = flags
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Object.keys(rest).forEach(field => {
 | 
			
		||||
    const value = rest[field]
 | 
			
		||||
    const schemaVal = schema[field as keyof TxFields]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user