UNPKG

@nextrope/xrpl

Version:

A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser

169 lines (147 loc) 4.64 kB
import { ValidationError } from '../../errors' import { Signer } from '../common' import { hasFlag } from '../utils' import { BaseTransaction, GlobalFlags, GlobalFlagsInterface, isArray, isNull, isRecord, isString, isValue, validateBaseTransaction, validateOptionalField, validateRequiredField, } from './common' import type { SubmittableTransaction } from './transaction' /** * Enum representing values of {@link Batch} transaction flags. * * @category Transaction Flags */ export enum BatchFlags { tfAllOrNothing = 0x00010000, tfOnlyOne = 0x00020000, tfUntilFailure = 0x00040000, tfIndependent = 0x00080000, } /** * Map of flags to boolean values representing {@link Batch} transaction * flags. * * @category Transaction Flags */ export interface BatchFlagsInterface extends GlobalFlagsInterface { tfAllOrNothing?: boolean tfOnlyOne?: boolean tfUntilFailure?: boolean tfIndependent?: boolean } export interface BatchSigner { BatchSigner: { Account: string SigningPubKey?: string TxnSignature?: string Signers?: Signer[] } } /** * @category Transaction Models */ export interface Batch extends BaseTransaction { TransactionType: 'Batch' BatchSigners?: BatchSigner[] RawTransactions: Array<{ RawTransaction: SubmittableTransaction }> } function validateBatchInnerTransaction( tx: Record<string, unknown>, index: number, ): void { if (tx.TransactionType === 'Batch') { throw new ValidationError( `Batch: RawTransactions[${index}] is a Batch transaction. Cannot nest Batch transactions.`, ) } // Check for the `tfInnerBatchTxn` flag in the inner transactions if (!hasFlag(tx, GlobalFlags.tfInnerBatchTxn, 'tfInnerBatchTxn')) { throw new ValidationError( `Batch: RawTransactions[${index}] must contain the \`tfInnerBatchTxn\` flag.`, ) } validateOptionalField(tx, 'Fee', isValue('0'), { paramName: `RawTransactions[${index}].RawTransaction.Fee`, txType: 'Batch', }) validateOptionalField(tx, 'SigningPubKey', isValue(''), { paramName: `RawTransactions[${index}].RawTransaction.SigningPubKey`, txType: 'Batch', }) validateOptionalField(tx, 'TxnSignature', isNull, { paramName: `RawTransactions[${index}].RawTransaction.TxnSignature`, txType: 'Batch', }) validateOptionalField(tx, 'Signers', isNull, { paramName: `RawTransactions[${index}].RawTransaction.Signers`, txType: 'Batch', }) validateOptionalField(tx, 'LastLedgerSequence', isNull, { paramName: `RawTransactions[${index}].RawTransaction.LastLedgerSequence`, txType: 'Batch', }) } /** * Verify the form and type of a Batch at runtime. * * @param tx - A Batch Transaction. * @throws When the Batch is malformed. */ // eslint-disable-next-line max-lines-per-function -- needed here due to the complexity export function validateBatch(tx: Record<string, unknown>): void { validateBaseTransaction(tx) validateRequiredField(tx, 'RawTransactions', isArray) tx.RawTransactions.forEach((rawTxObj, index) => { if (!isRecord(rawTxObj)) { throw new ValidationError( `Batch: RawTransactions[${index}] is not object.`, ) } validateRequiredField(rawTxObj, 'RawTransaction', isRecord, { paramName: `RawTransactions[${index}].RawTransaction`, txType: 'Batch', }) const rawTx = rawTxObj.RawTransaction validateBatchInnerTransaction(rawTx, index) // Full validation of each `RawTransaction` object is done in `validate` to avoid dependency cycles }) validateOptionalField(tx, 'BatchSigners', isArray) tx.BatchSigners?.forEach((signerObj, index) => { if (!isRecord(signerObj)) { throw new ValidationError(`Batch: BatchSigners[${index}] is not object.`) } const signerRecord = signerObj validateRequiredField(signerRecord, 'BatchSigner', isRecord, { paramName: `BatchSigners[${index}].BatchSigner`, txType: 'Batch', }) const signer = signerRecord.BatchSigner validateRequiredField(signer, 'Account', isString, { paramName: `BatchSigners[${index}].BatchSigner.Account`, txType: 'Batch', }) validateOptionalField(signer, 'SigningPubKey', isString, { paramName: `BatchSigners[${index}].BatchSigner.SigningPubKey`, txType: 'Batch', }) validateOptionalField(signer, 'TxnSignature', isString, { paramName: `BatchSigners[${index}].BatchSigner.TxnSignature`, txType: 'Batch', }) validateOptionalField(signer, 'Signers', isArray, { paramName: `BatchSigners[${index}].BatchSigner.Signers`, txType: 'Batch', }) }) }