From 72f34d9388d24bf278745c85d3e25d79974c686b Mon Sep 17 00:00:00 2001 From: Mukul Jangid <49061120+mukulljangid@users.noreply.github.com> Date: Wed, 18 Aug 2021 11:06:48 -0400 Subject: [PATCH] refactor: define typescript type for AccountSet transaction (#1515) * define typescript type for AccountSet transaction --- src/models/transactions/accountSet.ts | 69 ++++++++++++++++ src/models/transactions/index.ts | 4 +- src/models/transactions/offerCancel.ts | 24 ------ src/models/transactions/transaction.ts | 22 ++--- test/models/accountSet.ts | 110 +++++++++++++++++++++++++ test/models/checkCancel.ts | 2 +- test/models/offerCancel.ts | 53 ------------ test/models/signerListSet.ts | 63 ++++---------- 8 files changed, 206 insertions(+), 141 deletions(-) create mode 100644 src/models/transactions/accountSet.ts delete mode 100644 src/models/transactions/offerCancel.ts create mode 100644 test/models/accountSet.ts delete mode 100644 test/models/offerCancel.ts diff --git a/src/models/transactions/accountSet.ts b/src/models/transactions/accountSet.ts new file mode 100644 index 00000000..cfe6dce8 --- /dev/null +++ b/src/models/transactions/accountSet.ts @@ -0,0 +1,69 @@ +import { ValidationError } from "../../common/errors" +import { BaseTransaction, verifyBaseTransaction } from "./common" + +enum AccountSetFlagEnum { + asfRequireDest = 1, + asfRequireAuth = 2, + asfDisallowXRP = 3, + asfDisableMaster = 4, + asfAccountTxnID = 5, + asfNoFreeze = 6, + asfGlobalFreeze = 7, + asfDefaultRipple = 8, + asfDepositAuth = 9, +} + +export interface AccountSet extends BaseTransaction { + TransactionType: "AccountSet" + ClearFlag?: number + Domain?: string + EmailHash?: string + MessageKey?: string + SetFlag?: AccountSetFlagEnum + TransferRate?: number + TickSize?: number +} + +/** + * Verify the form and type of an AccountSet at runtime. + * + * @param tx - An AccountSet Transaction + * @returns - Void. + * @throws - When the AccountSet is Malformed. + */ + export function verifyAccountSet(tx: AccountSet): void { + verifyBaseTransaction(tx) + + if (tx.ClearFlag !== undefined){ + if (typeof tx.ClearFlag !== 'number') + throw new ValidationError("AccountSet: invalid ClearFlag") + if (!Object.values(AccountSetFlagEnum).includes(tx.ClearFlag)) + throw new ValidationError("AccountSet: invalid ClearFlag") + } + + if (tx.Domain !== undefined && typeof tx.Domain !== 'string') + throw new ValidationError("AccountSet: invalid Domain") + + if (tx.EmailHash !== undefined && typeof tx.EmailHash !== 'string') + throw new ValidationError("AccountSet: invalid EmailHash") + + if (tx.MessageKey !== undefined && typeof tx.MessageKey !== 'string') + throw new ValidationError("AccountSet: invalid MessageKey") + + if (tx.SetFlag !== undefined){ + if (typeof tx.SetFlag !== 'number') + throw new ValidationError("AccountSet: invalid SetFlag") + if (!Object.values(AccountSetFlagEnum).includes(tx.SetFlag)) + throw new ValidationError("AccountSet: invalid SetFlag") + } + + if (tx.TransferRate !== undefined && typeof tx.TransferRate !== 'number') + throw new ValidationError("AccountSet: invalid TransferRate") + + if (tx.TickSize !== undefined){ + if (typeof tx.TickSize !== 'number') + throw new ValidationError("AccountSet: invalid TickSize") + if (tx.TickSize !== 0 && (3 > tx.TickSize || tx.TickSize > 15)) + throw new ValidationError("AccountSet: invalid TickSize") + } +} diff --git a/src/models/transactions/index.ts b/src/models/transactions/index.ts index 9ff7baee..2b68e41f 100644 --- a/src/models/transactions/index.ts +++ b/src/models/transactions/index.ts @@ -1,7 +1,7 @@ export * from './transaction' export * from './offerCreate' -export * from './offerCancel' +export * from './accountSet' export * from './checkCreate' export * from './checkCash' export * from './checkCancel' -export * from './signerListSet' \ No newline at end of file +export * from './signerListSet' diff --git a/src/models/transactions/offerCancel.ts b/src/models/transactions/offerCancel.ts deleted file mode 100644 index 61173962..00000000 --- a/src/models/transactions/offerCancel.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" - -export interface OfferCancel extends BaseTransaction { - TransactionType: "OfferCancel" - OfferSequence: number -} - -/** - * Verify the form and type of an OfferCancel at runtime. - * - * @param tx - An OfferCancel Transaction - * @returns - Void. - * @throws - When the OfferCancel is Malformed. - */ - export function verifyOfferCancel(tx: OfferCancel): void { - verifyBaseTransaction(tx) - - if (tx.OfferSequence === undefined) - throw new ValidationError("OfferCancel: missing field OfferSequence") - - if (typeof tx.OfferSequence !== 'number') - throw new ValidationError("OfferCancel: invalid OfferSequence") -} \ No newline at end of file diff --git a/src/models/transactions/transaction.ts b/src/models/transactions/transaction.ts index df07f035..dc74ca51 100644 --- a/src/models/transactions/transaction.ts +++ b/src/models/transactions/transaction.ts @@ -1,25 +1,21 @@ -import Metadata from "../common/metadata" -import { OfferCreate } from "./offerCreate" -import { OfferCancel } from "./offerCancel" -import { CheckCash } from "./checkCash" -import { CheckCancel } from "./checkCancel" -import { CheckCreate } from "./checkCreate" -import { SignerListSet } from "./signerListSet" +import Metadata from "../common/metadata"; +import { OfferCreate } from "./offerCreate"; +import { CheckCash } from "./checkCash"; +import { CheckCancel } from "./checkCancel"; +import { CheckCreate } from "./checkCreate"; +import { SignerListSet } from "./signerListSet"; +import { AccountSet } from "./accountSet"; export type Transaction = -// AccountSet + AccountSet // | AccountDelete -// | CheckCancel -// | CheckCash -// | CheckCreate - CheckCancel + | CheckCancel | CheckCash | CheckCreate // | DepositPreauth // | EscrowCancel // | EscrowCreate // | EscrowFinish - | OfferCancel // | OfferCancel | OfferCreate // | PaymentTransaction diff --git a/test/models/accountSet.ts b/test/models/accountSet.ts new file mode 100644 index 00000000..c3829092 --- /dev/null +++ b/test/models/accountSet.ts @@ -0,0 +1,110 @@ +import { ValidationError } from 'xrpl-local/common/errors' +import { verifyAccountSet } from './../../src/models/transactions/accountSet' +import { assert } from 'chai' + +/** + * AccountSet Transaction Verification Testing + * + * Providing runtime verification testing for each specific transaction type + */ +describe('AccountSet Transaction Verification', function () { + + let account + + beforeEach(() => { + account = { + TransactionType : "AccountSet", + Account : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + Fee : "12", + Sequence : 5, + Domain : "6578616D706C652E636F6D", + SetFlag : 5, + MessageKey : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB" + } as any + }) + + it (`verifies valid AccountSet`, () => { + assert.doesNotThrow(() => verifyAccountSet(account)) + }) + + it (`throws w/ invalid SetFlag (out of range)`, () => { + account.SetFlag = 12 + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid SetFlag" + ) + }) + + it (`throws w/ invalid SetFlag (incorrect type)`, () => { + account.SetFlag = 'abc' + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid SetFlag" + ) + }) + + it (`throws w/ invalid ClearFlag`, () => { + account.ClearFlag = 12 + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid ClearFlag" + ) + }) + + it (`throws w/ invalid Domain`, () => { + account.Domain = 6578616 + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid Domain" + ) + }) + + it (`throws w/ invalid EmailHash`, () => { + account.EmailHash = 657861645678909876543456789876543 + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid EmailHash" + ) + }) + + it (`throws w/ invalid MessageKey`, () => { + account.MessageKey = 65786165678908765456789567890678 + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid MessageKey" + ) + }) + + it (`throws w/ invalid TransferRate`, () => { + account.TransferRate = "1000000001" + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid TransferRate" + ) + }) + + it (`throws w/ invalid TickSize`, () => { + account.TickSize = 20 + + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid TickSize" + ) + }) + +}) \ No newline at end of file diff --git a/test/models/checkCancel.ts b/test/models/checkCancel.ts index 2fc0dee9..7e3768a1 100644 --- a/test/models/checkCancel.ts +++ b/test/models/checkCancel.ts @@ -7,7 +7,7 @@ import { assert } from 'chai' * * Providing runtime verification testing for each specific transaction type */ -describe('CheckCancel Transaction Verification', function () { +describe('Transaction Verification', function () { it (`verifies valid CheckCancel`, () => { const validCheckCancel = { diff --git a/test/models/offerCancel.ts b/test/models/offerCancel.ts deleted file mode 100644 index 98bbd533..00000000 --- a/test/models/offerCancel.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyOfferCancel } from './../../src/models/transactions/offerCancel' -import { assert } from 'chai' - -/** - * OfferCancel Transaction Verification Testing - * - * Providing runtime verification testing for each specific transaction type - */ -describe('OfferCancel Transaction Verification', function () { - let offer - - beforeEach(() => { - offer = { - Account: "rnKiczmiQkZFiDES8THYyLA2pQohC5C6EF", - Fee: "10", - LastLedgerSequence: 65477334, - OfferSequence: 60797528, - Sequence: 60797535, - SigningPubKey: "0361BFD43D1EEA54B77CC152887312949EBF052997FBFFCDAF6F2653164B55B21...", - TransactionType: "OfferCancel", - TxnSignature: "30450221008C43BDCFC68B4793857CA47DF454C07E5B45D3F80E8E6785CAB9292...", - date: "2021-08-06T21:04:11Z" - } as any - }) - - it (`verifies valid OfferCancel`, () => { - assert.doesNotThrow(() => verifyOfferCancel(offer)) - }) - - it (`verifies valid OfferCancel with flags`, () => { - offer.Flags = 2147483648 - assert.doesNotThrow(() => verifyOfferCancel(offer)) - }) - - it (`throws w/ invalid OfferSequence`, () => { - offer.OfferSequence = '99' - assert.throws( - () => verifyOfferCancel(offer), - ValidationError, - "OfferCancel: invalid OfferSequence" - ) - }) - - it (`throws w/ missing OfferSequence`, () => { - delete offer.OfferSequence - assert.throws( - () => verifyOfferCancel(offer), - ValidationError, - "OfferCancel: missing field OfferSequence" - ) - }) -}) \ No newline at end of file diff --git a/test/models/signerListSet.ts b/test/models/signerListSet.ts index 8293d489..a810c6ec 100644 --- a/test/models/signerListSet.ts +++ b/test/models/signerListSet.ts @@ -8,9 +8,10 @@ import { assert } from 'chai' * Providing runtime verification testing for each specific transaction type */ describe('SignerListSet Transaction Verification', function () { - - it (`verifies valid SignerListSet`, () => { - const validSignerListSet = { + let SignerListSetTx + + beforeEach(() => { + SignerListSetTx = { Flags: 0, TransactionType: "SignerListSet", Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", @@ -37,72 +38,38 @@ describe('SignerListSet Transaction Verification', function () { } ] } as any - - assert.doesNotThrow(() => verifySignerListSet(validSignerListSet)) + }) + + it (`verifies valid SignerListSet`, () => { + assert.doesNotThrow(() => verifySignerListSet(SignerListSetTx)) }) it (`throws w/ missing SignerQuorum`, () => { - const invalidSignerQuorum = { - Flags: 0, - TransactionType: "SignerListSet", - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - SignerEntries: [ - { - SignerEntry: { - Account: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", - SignerWeight: 2 - } - }, - { - SignerEntry: { - Account: "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v", - SignerWeight: 1 - } - }, - { - SignerEntry: { - Account: "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n", - SignerWeight: 1 - } - } - ] - } as any + SignerListSetTx.SignerQuorum = undefined assert.throws( - () => verifySignerListSet(invalidSignerQuorum), + () => verifySignerListSet(SignerListSetTx), ValidationError, "SignerListSet: missing field SignerQuorum" ) }) it (`throws w/ empty SignerEntries`, () => { - const emptySignerEntries = { - Flags: 0, - TransactionType: "SignerListSet", - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - SignerQuorum: 3, - SignerEntries: [] - } as any + SignerListSetTx.SignerEntries = [] assert.throws( - () => verifySignerListSet(emptySignerEntries), + () => verifySignerListSet(SignerListSetTx), ValidationError, "SignerListSet: need atleast 1 member in SignerEntries" ) }) it (`throws w/ invalid SignerEntries`, () => { - const invalidSignerEntries = { - Flags: 0, - TransactionType: "SignerListSet", - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - SignerQuorum: 3, - SignerEntries: "khgfgyhujk" - } as any - + SignerListSetTx.SignerEntries = "khgfgyhujk" + assert.throws( - () => verifySignerListSet(invalidSignerEntries), + () => verifySignerListSet(SignerListSetTx), ValidationError, "SignerListSet: invalid SignerEntries" )