fix: fix escrow OfferSequence validation (#2474)

* Fix escrow validation

* update .nvmrc

* fix tests

* fix EscrowFinish too

* fix test

* update HISTORY

* fix validation

* fix linter issues

* forgot to save

* change test string
This commit is contained in:
Mayukha Vadari
2023-09-14 17:21:18 -04:00
committed by GitHub
parent f6f5f6b09a
commit 556addff64
23 changed files with 44 additions and 29 deletions

2
.nvmrc
View File

@@ -1 +1 @@
v14 v18

1
.prettierignore Normal file
View File

@@ -0,0 +1 @@
*.md

View File

@@ -128,6 +128,12 @@ module.exports = {
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
}, },
}, },
{
files: ['src/models/**/*.ts'],
rules: {
complexity: ['off'],
},
},
{ {
files: ['.eslintrc.js', 'jest.config.js'], files: ['.eslintrc.js', 'jest.config.js'],
rules: { rules: {

View File

@@ -1,10 +1,12 @@
# xrpl.js (ripple-lib) Release History # xrpl.js (ripple-lib) Release History
Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xrpl-announce) for release announcements. We recommend that xrpl.js (ripple-lib) users stay up-to-date with the latest stable release. Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xrpl-announce) for release announcements. We recommend that xrpl.js (ripple-lib) users stay up-to-date with the latest stable release.
## Unreleased ## Unreleased
## Fixed ## Fixed
* Fix request model fields related to AMM * Fix request model fields related to AMM
* Fixed `EscrowCancel` and `EscrowFinish` validation
## 2.11.0 (2023-08-24) ## 2.11.0 (2023-08-24)

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- required for validateAMMBid */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { AuthAccount, Currency, IssuedCurrencyAmount } from '../common' import { AuthAccount, Currency, IssuedCurrencyAmount } from '../common'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- required for validateAMMDeposit */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { Amount, Currency, IssuedCurrencyAmount } from '../common' import { Amount, Currency, IssuedCurrencyAmount } from '../common'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- required for validateAMMWithdraw */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { Amount, Currency, IssuedCurrencyAmount } from '../common' import { Amount, Currency, IssuedCurrencyAmount } from '../common'

View File

@@ -1,5 +1,3 @@
/* eslint-disable complexity -- Necessary for validateAccountSet */
import { isValidClassicAddress } from 'ripple-address-codec' import { isValidClassicAddress } from 'ripple-address-codec'
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validateCheckCash */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { Amount } from '../common' import { Amount } from '../common'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validateCheckCreate */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { Amount } from '../common' import { Amount } from '../common'

View File

@@ -1,5 +1,4 @@
/* eslint-disable max-lines-per-function -- Necessary for validateBaseTransaction */ /* eslint-disable max-lines-per-function -- Necessary for validateBaseTransaction */
/* eslint-disable complexity -- Necessary for validateBaseTransaction */
/* eslint-disable max-statements -- Necessary for validateBaseTransaction */ /* eslint-disable max-statements -- Necessary for validateBaseTransaction */
import { TRANSACTION_TYPES } from 'ripple-binary-codec' import { TRANSACTION_TYPES } from 'ripple-binary-codec'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validateDepositPreauth */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { BaseTransaction, validateBaseTransaction } from './common' import { BaseTransaction, validateBaseTransaction } from './common'

View File

@@ -15,7 +15,7 @@ export interface EscrowCancel extends BaseTransaction {
* Transaction sequence (or Ticket number) of EscrowCreate transaction that. * Transaction sequence (or Ticket number) of EscrowCreate transaction that.
* created the escrow to cancel. * created the escrow to cancel.
*/ */
OfferSequence: number OfferSequence: number | string
} }
/** /**
@@ -27,7 +27,7 @@ export interface EscrowCancel extends BaseTransaction {
export function validateEscrowCancel(tx: Record<string, unknown>): void { export function validateEscrowCancel(tx: Record<string, unknown>): void {
validateBaseTransaction(tx) validateBaseTransaction(tx)
if (tx.Owner === undefined) { if (tx.Owner == null) {
throw new ValidationError('EscrowCancel: missing Owner') throw new ValidationError('EscrowCancel: missing Owner')
} }
@@ -35,11 +35,15 @@ export function validateEscrowCancel(tx: Record<string, unknown>): void {
throw new ValidationError('EscrowCancel: Owner must be a string') throw new ValidationError('EscrowCancel: Owner must be a string')
} }
if (tx.OfferSequence === undefined) { if (tx.OfferSequence == null) {
throw new ValidationError('EscrowCancel: missing OfferSequence') throw new ValidationError('EscrowCancel: missing OfferSequence')
} }
if (typeof tx.OfferSequence !== 'number') { if (
(typeof tx.OfferSequence !== 'number' &&
typeof tx.OfferSequence !== 'string') ||
Number.isNaN(Number(tx.OfferSequence))
) {
throw new ValidationError('EscrowCancel: OfferSequence must be a number') throw new ValidationError('EscrowCancel: OfferSequence must be a number')
} }
} }

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validateEscrowCreate */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { BaseTransaction, validateBaseTransaction } from './common' import { BaseTransaction, validateBaseTransaction } from './common'

View File

@@ -15,7 +15,7 @@ export interface EscrowFinish extends BaseTransaction {
* Transaction sequence of EscrowCreate transaction that created the held. * Transaction sequence of EscrowCreate transaction that created the held.
* payment to finish. * payment to finish.
*/ */
OfferSequence: number OfferSequence: number | string
/** /**
* Hex value matching the previously-supplied PREIMAGE-SHA-256. * Hex value matching the previously-supplied PREIMAGE-SHA-256.
* crypto-condition of the held payment. * crypto-condition of the held payment.
@@ -37,7 +37,7 @@ export interface EscrowFinish extends BaseTransaction {
export function validateEscrowFinish(tx: Record<string, unknown>): void { export function validateEscrowFinish(tx: Record<string, unknown>): void {
validateBaseTransaction(tx) validateBaseTransaction(tx)
if (tx.Owner === undefined) { if (tx.Owner == null) {
throw new ValidationError('EscrowFinish: missing field Owner') throw new ValidationError('EscrowFinish: missing field Owner')
} }
@@ -45,11 +45,15 @@ export function validateEscrowFinish(tx: Record<string, unknown>): void {
throw new ValidationError('EscrowFinish: Owner must be a string') throw new ValidationError('EscrowFinish: Owner must be a string')
} }
if (tx.OfferSequence === undefined) { if (tx.OfferSequence == null) {
throw new ValidationError('EscrowFinish: missing field OfferSequence') throw new ValidationError('EscrowFinish: missing field OfferSequence')
} }
if (typeof tx.OfferSequence !== 'number') { if (
(typeof tx.OfferSequence !== 'number' &&
typeof tx.OfferSequence !== 'string') ||
Number.isNaN(Number(tx.OfferSequence))
) {
throw new ValidationError('EscrowFinish: OfferSequence must be a number') throw new ValidationError('EscrowFinish: OfferSequence must be a number')
} }

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validateOfferCreate */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { Amount } from '../common' import { Amount } from '../common'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validatePayment */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { Amount, Path } from '../common' import { Amount, Path } from '../common'
import { isFlagEnabled } from '../utils' import { isFlagEnabled } from '../utils'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validatePaymentChannelClaim */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { BaseTransaction, GlobalFlags, validateBaseTransaction } from './common' import { BaseTransaction, GlobalFlags, validateBaseTransaction } from './common'

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- Necessary for validatePaymentChannelCreate */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'
import { BaseTransaction, validateBaseTransaction } from './common' import { BaseTransaction, validateBaseTransaction } from './common'

View File

@@ -36,7 +36,6 @@ const HEX_WALLET_LOCATOR_REGEX = /^[0-9A-Fa-f]{64}$/u
* @param tx - An SignerListSet Transaction. * @param tx - An SignerListSet Transaction.
* @throws When the SignerListSet is Malformed. * @throws When the SignerListSet is Malformed.
*/ */
// eslint-disable-next-line complexity -- validation can be complex
export function validateSignerListSet(tx: Record<string, unknown>): void { export function validateSignerListSet(tx: Record<string, unknown>): void {
validateBaseTransaction(tx) validateBaseTransaction(tx)

View File

@@ -1,4 +1,3 @@
/* eslint-disable complexity -- verifies 19 tx types hence a lot of checks needed */
/* eslint-disable max-lines-per-function -- need to work with a lot of Tx verifications */ /* eslint-disable max-lines-per-function -- need to work with a lot of Tx verifications */
import { ValidationError } from '../../errors' import { ValidationError } from '../../errors'

View File

@@ -25,6 +25,13 @@ describe('EscrowCancel', function () {
assert.doesNotThrow(() => validate(cancel)) assert.doesNotThrow(() => validate(cancel))
}) })
it(`Valid EscrowCancel with string OfferSequence`, function () {
cancel.OfferSequence = '7'
assert.doesNotThrow(() => validateEscrowCancel(cancel))
assert.doesNotThrow(() => validate(cancel))
})
it(`Invalid EscrowCancel missing owner`, function () { it(`Invalid EscrowCancel missing owner`, function () {
delete cancel.Owner delete cancel.Owner
@@ -55,7 +62,7 @@ describe('EscrowCancel', function () {
) )
}) })
it(`Invalid OfferSequence`, function () { it(`Invalid Owner`, function () {
cancel.Owner = 10 cancel.Owner = 10
assert.throws( assert.throws(
@@ -70,8 +77,8 @@ describe('EscrowCancel', function () {
) )
}) })
it(`Invalid owner`, function () { it(`Invalid OfferSequence`, function () {
cancel.OfferSequence = '10' cancel.OfferSequence = 'random'
assert.throws( assert.throws(
() => validateEscrowCancel(cancel), () => validateEscrowCancel(cancel),

View File

@@ -35,6 +35,13 @@ describe('EscrowFinish', function () {
assert.doesNotThrow(() => validate(escrow)) assert.doesNotThrow(() => validate(escrow))
}) })
it(`verifies valid EscrowFinish w/string OfferSequence`, function () {
escrow.OfferSequence = '7'
assert.doesNotThrow(() => validateEscrowFinish(escrow))
assert.doesNotThrow(() => validate(escrow))
})
it(`throws w/ invalid Owner`, function () { it(`throws w/ invalid Owner`, function () {
escrow.Owner = 0x15415253 escrow.Owner = 0x15415253
@@ -51,7 +58,7 @@ describe('EscrowFinish', function () {
}) })
it(`throws w/ invalid OfferSequence`, function () { it(`throws w/ invalid OfferSequence`, function () {
escrow.OfferSequence = '10' escrow.OfferSequence = 'random'
assert.throws( assert.throws(
() => validateEscrowFinish(escrow), () => validateEscrowFinish(escrow),