From 6d08b9e12cdf1beb87ade5f24b341c3115d2616f Mon Sep 17 00:00:00 2001 From: Mukul Jangid <49061120+mukulljangid@users.noreply.github.com> Date: Mon, 16 Aug 2021 18:41:07 -0400 Subject: [PATCH] refactor: define typescript types for CheckCash Transaction Model (#1522) * Define Typescript types for CheckCash Transaction Model --- .github/workflows/nodejs.yml | 4 +- src/models/transactions/checkCash.ts | 36 +++++++++++ src/models/transactions/common.ts | 13 +++- src/models/transactions/index.ts | 3 +- src/models/transactions/offerCreate.ts | 15 ++--- src/models/transactions/transaction.ts | 3 +- test/models/checkCash.ts | 84 ++++++++++++++++++++++++++ 7 files changed, 142 insertions(+), 16 deletions(-) create mode 100644 src/models/transactions/checkCash.ts create mode 100644 test/models/checkCash.ts diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 850c1ab1..9125b9ac 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -5,9 +5,9 @@ name: Node.js CI on: push: - branches: [ develop, master ] + branches: [ develop, master, 2.0 ] pull_request: - branches: [ develop ] + branches: [ develop, 2.0 ] jobs: unit: diff --git a/src/models/transactions/checkCash.ts b/src/models/transactions/checkCash.ts new file mode 100644 index 00000000..558e86b6 --- /dev/null +++ b/src/models/transactions/checkCash.ts @@ -0,0 +1,36 @@ +import { ValidationError } from "../../common/errors"; +import { Amount } from "../common"; +import { BaseTransaction, verifyBaseTransaction, isAmount } from "./common"; + +export interface CheckCash extends BaseTransaction { + TransactionType: "CheckCash"; + CheckID: string; + Amount?: Amount; + DeliverMin?: Amount; +} + +/** + * Verify the form and type of an CheckCash at runtime. + * + * @param tx - An CheckCash Transaction + * @returns - Void. + * @throws - When the CheckCash is Malformed. + */ + export function verifyCheckCash(tx: CheckCash): void { + verifyBaseTransaction(tx) + + if (tx.hasOwnProperty('Amount') && tx.hasOwnProperty('DeliverMin')) + throw new ValidationError("CheckCash: cannot have both Amount and DeliverMin") + + if (!tx.hasOwnProperty('Amount') && !tx.hasOwnProperty('DeliverMin')) + throw new ValidationError("CheckCash: must have either Amount or DeliverMin") + + if (tx.hasOwnProperty('Amount') && tx.Amount !== undefined && !isAmount(tx.Amount)) + throw new ValidationError("CheckCash: invalid Amount") + + if (tx.hasOwnProperty('DeliverMin') && tx.DeliverMin !== undefined && !isAmount(tx.DeliverMin)) + throw new ValidationError("CheckCash: invalid DeliverMin") + + if (tx.CheckID !== undefined && typeof tx.CheckID !== 'string') + throw new ValidationError("CheckCash: invalid CheckID") +} \ No newline at end of file diff --git a/src/models/transactions/common.ts b/src/models/transactions/common.ts index fd414615..f2c095b7 100644 --- a/src/models/transactions/common.ts +++ b/src/models/transactions/common.ts @@ -1,5 +1,5 @@ import { ValidationError } from "../../common/errors" -import { Memo, Signer } from "../common" +import { Amount, Memo, Signer, IssuedCurrencyAmount } from "../common" import { onlyHasFields } from "../utils" const transactionTypes = [ @@ -48,6 +48,17 @@ const isSigner = (signer: Signer): boolean => { && typeof signer.SigningPubKey === 'string' } +export function isIssuedCurrency (obj: IssuedCurrencyAmount): boolean { + return Object.keys(obj).length === 3 + && typeof obj.value === 'string' + && typeof obj.issuer === 'string' + && typeof obj.currency === 'string' +} + +export function isAmount(amount: Amount): boolean { + return typeof amount === 'string' || isIssuedCurrency(amount); +} + export interface GlobalFlags { tfFullyCanonicalSig: boolean, } diff --git a/src/models/transactions/index.ts b/src/models/transactions/index.ts index 9990f3cd..099840a8 100644 --- a/src/models/transactions/index.ts +++ b/src/models/transactions/index.ts @@ -1,4 +1,5 @@ export * from './transaction' export * from './offerCreate' +export * from './checkCreate' +export * from './checkCash' export * from './checkCancel' -export * from './checkCreate' \ No newline at end of file diff --git a/src/models/transactions/offerCreate.ts b/src/models/transactions/offerCreate.ts index a63caad2..a3763149 100644 --- a/src/models/transactions/offerCreate.ts +++ b/src/models/transactions/offerCreate.ts @@ -1,6 +1,6 @@ import { ValidationError } from "../../common/errors"; -import { Amount, IssuedCurrencyAmount } from "../common"; -import { BaseTransaction, GlobalFlags, verifyBaseTransaction } from "./common"; +import { Amount } from "../common"; +import { BaseTransaction, GlobalFlags, verifyBaseTransaction, isAmount } from "./common"; export interface OfferCreateFlags extends GlobalFlags { tfPassive?: boolean; @@ -34,17 +34,10 @@ export interface OfferCreate extends BaseTransaction { if (tx.TakerPays === undefined) throw new ValidationError("OfferCreate: missing field TakerPays") - const isIssuedCurrency = (obj: IssuedCurrencyAmount): boolean => { - return Object.keys(obj).length === 3 - && typeof obj.value === 'string' - && typeof obj.issuer === 'string' - && typeof obj.currency === 'string' - } - - if (typeof tx.TakerGets !== 'string' && !isIssuedCurrency(tx.TakerGets)) + if (typeof tx.TakerGets !== 'string' && !isAmount(tx.TakerGets)) throw new ValidationError("OfferCreate: invalid TakerGets") - if (typeof tx.TakerPays !== 'string' && !isIssuedCurrency(tx.TakerPays)) + if (typeof tx.TakerPays !== 'string' && !isAmount(tx.TakerPays)) throw new ValidationError("OfferCreate: invalid TakerPays") if (tx.Expiration !== undefined && typeof tx.Expiration !== 'number') diff --git a/src/models/transactions/transaction.ts b/src/models/transactions/transaction.ts index f4d81c5f..1f152481 100644 --- a/src/models/transactions/transaction.ts +++ b/src/models/transactions/transaction.ts @@ -1,5 +1,6 @@ import Metadata from "../common/metadata"; import { OfferCreate } from "./offerCreate"; +import { CheckCash } from "./checkCash"; import { CheckCancel } from "./checkCancel"; import { CheckCreate } from "./checkCreate"; @@ -7,7 +8,7 @@ export type Transaction = // AccountSet // | AccountDelete CheckCancel -// | CheckCash + | CheckCash | CheckCreate // | DepositPreauth // | EscrowCancel diff --git a/test/models/checkCash.ts b/test/models/checkCash.ts new file mode 100644 index 00000000..3eed17e6 --- /dev/null +++ b/test/models/checkCash.ts @@ -0,0 +1,84 @@ +import { ValidationError } from 'ripple-api/common/errors' +import { verifyCheckCash } from './../../src/models/transactions/checkCash' +import { assert } from 'chai' + +/** + * CheckCash Transaction Verification Testing + * + * Providing runtime verification testing for each specific transaction type + */ +describe('CheckCash Transaction Verification', function () { + + it (`verifies valid CheckCash`, () => { + const validCheckCash = { + Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType : "CheckCash", + Amount : "100000000", + CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334", + Fee : "12" + } as any + + assert.doesNotThrow(() => verifyCheckCash(validCheckCash)) + }) + + it (`throws w/ invalid CheckID`, () => { + const invalidCheckID = { + Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType : "CheckCash", + Amount : "100000000", + CheckID : 83876645678909854567890 + } as any + + assert.throws( + () => verifyCheckCash(invalidCheckID), + ValidationError, + "CheckCash: invalid CheckID" + ) + }) + + it (`throws w/ invalid Amount`, () => { + const invalidAmount = { + Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType : "CheckCash", + Amount : 100000000, + CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334" + } as any + + assert.throws( + () => verifyCheckCash(invalidAmount), + ValidationError, + "CheckCash: invalid Amount" + ) + }) + + it (`throws w/ having both Amount and DeliverMin`, () => { + const invalidDeliverMin = { + Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType : "CheckCash", + Amount : "100000000", + DeliverMin: 852156963, + CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334" + } as any + + assert.throws( + () => verifyCheckCash(invalidDeliverMin), + ValidationError, + "CheckCash: cannot have both Amount and DeliverMin" + ) + }) + + it (`throws w/ invalid DeliverMin`, () => { + const invalidDeliverMin = { + Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType : "CheckCash", + DeliverMin: 852156963, + CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334" + } as any + + assert.throws( + () => verifyCheckCash(invalidDeliverMin), + ValidationError, + "CheckCash: invalid DeliverMin" + ) + }) +}) \ No newline at end of file