From 2ff0dde91dfb9b18ed39e99adbaa85cc3a70e3bc Mon Sep 17 00:00:00 2001 From: Omar Khan Date: Wed, 18 Aug 2021 17:34:36 -0400 Subject: [PATCH] refactor: define DepositPreauth transaction model (#1545) - Defines a TypeScript type for DepositPreauth - Provides an optional function to users for verifying a DepositPreauth instance at runtime: verifyDepositPreauth() - Adds tests for verifyDepositPreauth() --- src/models/transactions/depositPreauth.ts | 46 +++++++++++++ src/models/transactions/index.ts | 1 + src/models/transactions/transaction.ts | 3 +- test/models/depositPreauth.ts | 83 +++++++++++++++++++++++ 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/models/transactions/depositPreauth.ts create mode 100644 test/models/depositPreauth.ts diff --git a/src/models/transactions/depositPreauth.ts b/src/models/transactions/depositPreauth.ts new file mode 100644 index 00000000..eaa98a1d --- /dev/null +++ b/src/models/transactions/depositPreauth.ts @@ -0,0 +1,46 @@ +import { ValidationError } from '../../common/errors' +import { BaseTransaction, verifyBaseTransaction } from './common' + +export interface DepositPreauth extends BaseTransaction { + TransactionType: 'DepositPreauth' + Authorize?: string + Unauthorize?: string +} + +/** + * + * @param {DepositPreauth} tx A DepositPreauth Transaction. + * @returns {void} + * @throws {ValidationError} When the DepositPreauth is malformed. + */ +export function verifyDepositPreauth(tx: DepositPreauth): void { + verifyBaseTransaction(tx) + + if (tx.Authorize !== undefined && tx.Unauthorize !== undefined) { + throw new ValidationError("DepositPreauth: can't provide both Authorize and Unauthorize fields") + } + + if (tx.Authorize === undefined && tx.Unauthorize === undefined) { + throw new ValidationError('DepositPreauth: must provide either Authorize or Unauthorize field') + } + + if (tx.Authorize !== undefined) { + if (typeof tx.Authorize !== 'string') { + throw new ValidationError('DepositPreauth: Authorize must be a string') + } + + if (tx.Account === tx.Authorize) { + throw new ValidationError("DepositPreauth: Account can't preauthorize its own address") + } + } + + if (tx.Unauthorize !== undefined) { + if (typeof tx.Unauthorize !== 'string') { + throw new ValidationError("DepositPreauth: Unauthorize must be a string") + } + + if (tx.Account === tx.Unauthorize) { + throw new ValidationError("DepositPreauth: Account can't unauthorize its own address") + } + } +} diff --git a/src/models/transactions/index.ts b/src/models/transactions/index.ts index 1db85eaa..e333d27c 100644 --- a/src/models/transactions/index.ts +++ b/src/models/transactions/index.ts @@ -7,4 +7,5 @@ export * from './checkCash' export * from './checkCancel' export * from './accountDelete' export * from './signerListSet' +export * from './depositPreauth' export * from './paymentTransaction' diff --git a/src/models/transactions/transaction.ts b/src/models/transactions/transaction.ts index 6d19e53a..6d65e7fb 100644 --- a/src/models/transactions/transaction.ts +++ b/src/models/transactions/transaction.ts @@ -4,6 +4,7 @@ import { AccountSet } from "./accountSet" import { CheckCancel } from "./checkCancel" import { CheckCash } from "./checkCash" import { CheckCreate } from "./checkCreate" +import { DepositPreauth } from "./depositPreauth" import { OfferCancel } from "./offerCancel" import { OfferCreate } from "./offerCreate" import { PaymentTransaction } from "./paymentTransaction" @@ -15,7 +16,7 @@ export type Transaction = | CheckCancel | CheckCash | CheckCreate -// | DepositPreauth + | DepositPreauth // | EscrowCancel // | EscrowCreate // | EscrowFinish diff --git a/test/models/depositPreauth.ts b/test/models/depositPreauth.ts new file mode 100644 index 00000000..689cb8a6 --- /dev/null +++ b/test/models/depositPreauth.ts @@ -0,0 +1,83 @@ +import { ValidationError } from 'xrpl-local/common/errors' +import { verifyDepositPreauth } from './../../src/models/transactions/depositPreauth' +import { assert } from 'chai' + +/** + * DepositPreauth Transaction Verification Testing + * + * Providing runtime verification testing for each specific transaction type + */ +describe('DepositPreauth Transaction Verification', () => { + let depositPreauth + + beforeEach(() => { + depositPreauth = { + TransactionType: 'DepositPreauth', + Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo', + } as any + }) + + it ('verifies valid DepositPreauth when only Authorize is provided', () => { + depositPreauth.Authorize = 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW' + assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth)) + }) + + it ('verifies valid DepositPreauth when only Unauthorize is provided', () => { + depositPreauth.Unauthorize = 'raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n' + assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth)) + }) + + it ('throws when both Authorize and Unauthorize are provided', () => { + depositPreauth.Authorize = 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW' + depositPreauth.Unauthorize = 'raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n' + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: can't provide both Authorize and Unauthorize fields" + ) + }) + + it ('throws when neither Authorize nor Unauthorize are provided', () => { + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + 'DepositPreauth: must provide either Authorize or Unauthorize field' + ) + }) + + it ('throws when Authorize is not a string', () => { + depositPreauth.Authorize = 1234 + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + 'DepositPreauth: Authorize must be a string' + ) + }) + + it ('throws when an Account attempts to preauthorize its own address', () => { + depositPreauth.Authorize = depositPreauth.Account + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: Account can't preauthorize its own address" + ) + }) + + it ('throws when Unauthorize is not a string', () => { + depositPreauth.Unauthorize = 1234 + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + 'DepositPreauth: Unauthorize must be a string' + ) + }) + + it ('throws when an Account attempts to unauthorize its own address', () => { + depositPreauth.Unauthorize = depositPreauth.Account + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: Account can't unauthorize its own address" + ) + }) +})