allow lowercase hex values for NFTokenMint.URI (#2008)

This commit is contained in:
Omar Khan
2022-05-31 19:22:05 -04:00
committed by GitHub
parent 42ea7d83bc
commit 6c3f5a0e3a
6 changed files with 104 additions and 3 deletions

View File

@@ -9,6 +9,7 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
* Infinite error/reconnect in browser if an exception was raised during the initial websocket connection event.
* Errors during reliable submission with no error message now properly show the preliminary result instead of a type error
* Fixed serialize/deserialize verification bug in `Wallet.sign()` when signing a non-XRP Payment with an amount that contains trailing insignificant zeros
* Allow lowercase hex values for `NFTokenMint.URI`
## 2.2.3 (2022-05-04)
### Fixed

View File

@@ -26,6 +26,7 @@ import {
import ECDSA from '../ECDSA'
import { ValidationError } from '../errors'
import { Transaction } from '../models/transactions'
import { isHex } from '../models/utils'
import { ensureClassicAddress } from '../sugar/utils'
import { hashSignedTx } from '../utils/hashes/hashLedger'
@@ -392,7 +393,7 @@ class Wallet {
* @throws A ValidationError if the transaction does not have a TxnSignature/Signers property, or if
* the serialized Transaction desn't match the original transaction.
*/
// eslint-disable-next-line class-methods-use-this -- Helper for organization purposes
// eslint-disable-next-line class-methods-use-this, max-lines-per-function -- Helper for organization purposes
private checkTxSerialization(serialized: string, tx: Transaction): void {
// Decode the serialized transaction:
const decoded = decode(serialized)
@@ -440,7 +441,15 @@ class Wallet {
return memo
})
if (!_.isEqual(decoded, tx)) {
if (txCopy.TransactionType === 'NFTokenMint' && txCopy.URI) {
if (!isHex(txCopy.URI)) {
throw new ValidationError('URI must be a hex value')
}
txCopy.URI = txCopy.URI.toUpperCase()
}
if (!_.isEqual(decoded, txCopy)) {
const data = {
decoded,
tx,

View File

@@ -1,4 +1,5 @@
import { ValidationError } from '../../errors'
import { isHex } from '../utils'
import { BaseTransaction, GlobalFlags, validateBaseTransaction } from './common'
@@ -105,6 +106,10 @@ export function validateNFTokenMint(tx: Record<string, unknown>): void {
)
}
if (typeof tx.URI === 'string' && !isHex(tx.URI)) {
throw new ValidationError('NFTokenMint: URI must be in hex format')
}
if (tx.NFTokenTaxon == null) {
throw new ValidationError('NFTokenMint: missing field NFTokenTaxon')
}

View File

@@ -1,3 +1,5 @@
const HEX_REGEX = /^[0-9A-Fa-f]+$/u
/**
* Verify that all fields of an object are in fields.
*
@@ -23,3 +25,13 @@ export function isFlagEnabled(Flags: number, checkFlag: number): boolean {
// eslint-disable-next-line no-bitwise -- flags needs bitwise
return (checkFlag & Flags) === checkFlag
}
/**
* Check if string is in hex format.
*
* @param str - The string to check if it's in hex format.
* @returns True if string is in hex format
*/
export function isHex(str: string): boolean {
return HEX_REGEX.test(str)
}

View File

@@ -66,4 +66,24 @@ describe('NFTokenMint', function () {
'NFTokenMint: Issuer must not be equal to Account',
)
})
it(`throws w/ URI not in hex format`, function () {
const invalid = {
TransactionType: 'NFTokenMint',
Account: 'rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm',
Fee: '5000000',
Sequence: 2470665,
Flags: NFTokenMintFlags.tfTransferable,
NFTokenTaxon: 0,
Issuer: 'r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ',
TransferFee: 1,
URI: 'http://xrpl.org',
} as any
assert.throws(
() => validate(invalid),
ValidationError,
'NFTokenMint: URI must be in hex format',
)
})
})

View File

@@ -1,6 +1,6 @@
import { assert } from 'chai'
import { decode } from 'ripple-binary-codec/dist'
import { Transaction } from 'xrpl-local'
import { NFTokenMint, Transaction } from 'xrpl-local'
import ECDSA from 'xrpl-local/ECDSA'
import Wallet from 'xrpl-local/Wallet'
@@ -639,6 +639,60 @@ describe('Wallet', function () {
assert.deepEqual(result, expectedResult)
})
it('sign allows lowercase hex value for NFTokenMint.URI', async function () {
const tx: NFTokenMint = {
TransactionType: 'NFTokenMint',
Account: wallet.address,
TransferFee: 314,
NFTokenTaxon: 0,
Flags: 8,
Fee: '10',
URI: '697066733a2f2f62616679626569676479727a74357366703775646d37687537367568377932366e6634646675796c71616266336f636c67747179353566627a6469',
Memos: [
{
Memo: {
MemoType:
'687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963',
MemoData: '72656e74',
},
},
],
}
const result = wallet.sign(tx)
const expectedResult = {
tx_blob:
'12001914013A2200000008202A0000000068400000000000000A732102A8A44DB3D4C73EEEE11DFE54D2029103B776AA8A8D293A91D645977C9DF5F5447446304402203795B6E9D6D0086FB26E2C6B7A8C02D50B8560D45C9D5C80DF271D3349515E5302203B0898A7D8C06243D7C2116D2011ACB68DF3123BB7336D6C27269FD388C12CC07542697066733A2F2F62616679626569676479727A74357366703775646D37687537367568377932366E6634646675796C71616266336F636C67747179353566627A64698114B3263BD0A9BF9DFDBBBBD07F536355FF477BF0E9F9EA7C1F687474703A2F2F6578616D706C652E636F6D2F6D656D6F2F67656E657269637D0472656E74E1F1',
hash: '2F359B3CFD1CE6D7BFB672F8ADCE98FE964B1FD04CFC337177FB3D8FBE889788',
}
assert.deepEqual(result, expectedResult)
})
it('sign throws when NFTokenMint.URI is not a hex value', async function () {
const tx: NFTokenMint = {
TransactionType: 'NFTokenMint',
Account: wallet.address,
TransferFee: 314,
NFTokenTaxon: 0,
Flags: 8,
Fee: '10',
URI: 'ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi',
Memos: [
{
Memo: {
MemoType:
'687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963',
MemoData: '72656e74',
},
},
],
}
assert.throws(() => {
wallet.sign(tx)
}, /URI must be a hex value/u)
})
})
describe('verifyTransaction', function () {