From d5d996a92e5b63d6b7bfcd9ab7cb042a3e83dc2b Mon Sep 17 00:00:00 2001 From: Omar Khan Date: Thu, 19 Aug 2021 11:47:01 -0400 Subject: [PATCH] refactor: define TrustSet transaction model (#1549) - Defines a TypeScript type for TrustSet - Provides an optional function to users for verifying a TrustSet instance at runtime: verifyTrustSet() - Adds tests for verifyTrustSet() --- src/models/transactions/index.ts | 1 + src/models/transactions/transaction.ts | 3 +- src/models/transactions/trustSet.ts | 54 +++++++++++++++++++++ test/models/trustSet.ts | 66 ++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/models/transactions/trustSet.ts create mode 100644 test/models/trustSet.ts diff --git a/src/models/transactions/index.ts b/src/models/transactions/index.ts index e333d27c..8a88e365 100644 --- a/src/models/transactions/index.ts +++ b/src/models/transactions/index.ts @@ -7,5 +7,6 @@ export * from './checkCash' export * from './checkCancel' export * from './accountDelete' export * from './signerListSet' +export * from './trustSet' export * from './depositPreauth' export * from './paymentTransaction' diff --git a/src/models/transactions/transaction.ts b/src/models/transactions/transaction.ts index 6d65e7fb..66223e01 100644 --- a/src/models/transactions/transaction.ts +++ b/src/models/transactions/transaction.ts @@ -9,6 +9,7 @@ import { OfferCancel } from "./offerCancel" import { OfferCreate } from "./offerCreate" import { PaymentTransaction } from "./paymentTransaction" import { SignerListSet } from "./signerListSet" +import { TrustSet } from "./trustSet" export type Transaction = AccountDelete @@ -30,7 +31,7 @@ export type Transaction = // | SetRegularKey | SignerListSet // | TicketCreate -// | TrustSet + | TrustSet export interface TransactionAndMetadata { transaction: Transaction diff --git a/src/models/transactions/trustSet.ts b/src/models/transactions/trustSet.ts new file mode 100644 index 00000000..4bdca574 --- /dev/null +++ b/src/models/transactions/trustSet.ts @@ -0,0 +1,54 @@ +import { ValidationError } from '../../common/errors' +import { Amount } from '../common' +import { BaseTransaction, GlobalFlags, isAmount, verifyBaseTransaction } from './common' + +export enum TrustSetFlagsEnum { + tfSetfAuth = 0x00010000, + tfSetNoRipple = 0x00020000, + tfClearNoRipple = 0x00040000, + tfSetFreeze = 0x00100000, + tfClearFreeze = 0x00200000, +} + +export interface TrustSetFlags extends GlobalFlags { + tfSetfAuth?: boolean + tfSetNoRipple?: boolean + tfClearNoRipple?: boolean + tfSetFreeze?: boolean + tfClearFreeze?: boolean +} + +export interface TrustSet extends BaseTransaction { + TransactionType: 'TrustSet' + LimitAmount: Amount + QualityIn?: number + QualityOut?: number + Flags?: number | TrustSetFlags +} + +/** + * + * @param tx A TrustSet Transaction. + * @returns {void} + * @throws {ValidationError} When the TrustSet is malformed. + */ +export function verifyTrustSet(tx: TrustSet): void { + verifyBaseTransaction(tx) + const { LimitAmount, QualityIn, QualityOut } = tx + + if (LimitAmount === undefined) { + throw new ValidationError('TrustSet: missing field LimitAmount') + } + + if (!isAmount(LimitAmount)) { + throw new ValidationError('TrustSet: invalid LimitAmount') + } + + if (QualityIn !== undefined && typeof QualityIn !== 'number') { + throw new ValidationError('TrustSet: QualityIn must be a number') + } + + if (QualityOut !== undefined && typeof QualityOut !== 'number') { + throw new ValidationError('TrustSet: QualityOut must be a number') + } +} diff --git a/test/models/trustSet.ts b/test/models/trustSet.ts new file mode 100644 index 00000000..16165a8d --- /dev/null +++ b/test/models/trustSet.ts @@ -0,0 +1,66 @@ +import { ValidationError } from 'xrpl-local/common/errors' +import { verifyTrustSet } from './../../src/models/transactions/trustSet' +import { assert } from 'chai' + +/** + * TrustSet Transaction Verification Testing + * + * Providing runtime verification testing for each specific transaction type + */ +describe('TrustSet Transaction Verification', () => { + let trustSet + + beforeEach(() => { + trustSet = { + TransactionType: 'TrustSet', + Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo', + LimitAmount: { + currency: 'XRP', + issuer: 'rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX', + value: '4329.23' + }, + QualityIn: 1234, + QualityOut: 4321, + } as any + }) + + it ('verifies valid TrustSet', () => { + assert.doesNotThrow(() => verifyTrustSet(trustSet)) + }) + + it ('throws when LimitAmount is missing', () => { + delete trustSet.LimitAmount + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + 'TrustSet: missing field LimitAmount' + ) + }) + + it ('throws when LimitAmount is invalid', () => { + trustSet.LimitAmount = 1234 + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + 'TrustSet: invalid LimitAmount' + ) + }) + + it ('throws when QualityIn is not a number', () => { + trustSet.QualityIn = '1234' + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + 'TrustSet: QualityIn must be a number' + ) + }) + + it ('throws when QualityOut is not a number', () => { + trustSet.QualityOut = '4321' + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + 'TrustSet: QualityOut must be a number' + ) + }) +})