From 676fb85abfc36bda1f6237957839174797a4f7b1 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Sat, 27 Feb 2021 12:58:40 -0800 Subject: [PATCH] fix(decodeOpReturn): Added NFT child test case --- src/slp/utils.js | 7 ++- test/integration/slp.js | 23 +++++++++ test/unit/fixtures/slp/mock-utils.js | 71 ++++++++++++++++++++++++++++ test/unit/slp-utils.js | 54 ++++++++++----------- 4 files changed, 126 insertions(+), 29 deletions(-) diff --git a/src/slp/utils.js b/src/slp/utils.js index 0d621ce..917d158 100644 --- a/src/slp/utils.js +++ b/src/slp/utils.js @@ -968,7 +968,6 @@ class Utils { _this.axiosOptions ) const txDetails = response.data[0] - // console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`) // SLP spec expects OP_RETURN to be the first output of the transaction. @@ -1247,7 +1246,11 @@ class Utils { // This is a private function that is called by tokenUtxoDetails(). // It loops through an array of UTXOs and tries to hydrate them with SLP // token information from the OP_RETURN data. - // If this function hits a rate limit... TODO: describe specific behavior. + // + // This function makes several calls to decodeOpReturn() to retrieve SLP + // token data. If that call throws an error due to hitting rate limits, this + // function will not throw an error. Instead, it will mark the `isValid` + // property as `null` async _hydrateUtxo (utxos, usrObj = null) { try { const decodeOpReturnCache = {} diff --git a/test/integration/slp.js b/test/integration/slp.js index 1d4570b..1d8e8d3 100644 --- a/test/integration/slp.js +++ b/test/integration/slp.js @@ -228,6 +228,29 @@ describe('#SLP', () => { assert.include(err.message, 'amount string size not 8 bytes') } }) + + it('should decode a NFT Child transaction', async () => { + const txid = + 'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b' + + const data = await bchjs.SLP.Utils.decodeOpReturn(txid) + // console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.property(data, 'tokenType') + assert.property(data, 'txType') + assert.property(data, 'ticker') + assert.property(data, 'name') + assert.property(data, 'tokenId') + assert.property(data, 'documentUri') + assert.property(data, 'documentHash') + assert.property(data, 'decimals') + assert.property(data, 'mintBatonVout') + assert.property(data, 'qty') + + assert.equal(data.tokenType, 65) + assert.equal(data.mintBatonVout, 0) + assert.equal(data.qty, '1') + }) }) describe('#tokenUtxoDetails', () => { diff --git a/test/unit/fixtures/slp/mock-utils.js b/test/unit/fixtures/slp/mock-utils.js index a6245af..56e2e90 100644 --- a/test/unit/fixtures/slp/mock-utils.js +++ b/test/unit/fixtures/slp/mock-utils.js @@ -1290,6 +1290,76 @@ const slpdbStatus = { } } +const txDetailsSLPNftChild = { + txid: 'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b', + hash: 'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b', + version: 2, + size: 453, + locktime: 0, + vin: [ + { + txid: 'a9a2458a0f9f0761d5b8725c256f2e7fa35b9de4dec6f47b46e9f20d92d0e395', + vout: 1, + scriptSig: { + asm: '3045022100890ff2f80f3c184419ba03a575b9d159c0a5edfa817e4548cfdb6c74d16ce8d202205a8237d2139196716c273fe80506896d369a0022bb54401e2eadb364286a9f07[ALL|FORKID] 03136d9ec06adef1c9154105950e82d470d290aa019ed34a5e3bbd0b679805623b', + hex: '483045022100890ff2f80f3c184419ba03a575b9d159c0a5edfa817e4548cfdb6c74d16ce8d202205a8237d2139196716c273fe80506896d369a0022bb54401e2eadb364286a9f07412103136d9ec06adef1c9154105950e82d470d290aa019ed34a5e3bbd0b679805623b' + }, + sequence: 4294967295 + }, + { + txid: 'a9a2458a0f9f0761d5b8725c256f2e7fa35b9de4dec6f47b46e9f20d92d0e395', + vout: 3, + scriptSig: { + asm: '304402203905a61ec4e3567f7cad7eb514132e5b32d8a1d77c8838baac1b34b735282a5f022044da6130b5cc41b65615b17df6610087fe1baedd1a3a9f37552b56ea8d36d026[ALL|FORKID] 03136d9ec06adef1c9154105950e82d470d290aa019ed34a5e3bbd0b679805623b', + hex: '47304402203905a61ec4e3567f7cad7eb514132e5b32d8a1d77c8838baac1b34b735282a5f022044da6130b5cc41b65615b17df6610087fe1baedd1a3a9f37552b56ea8d36d026412103136d9ec06adef1c9154105950e82d470d290aa019ed34a5e3bbd0b679805623b' + }, + sequence: 4294967295 + } + ], + vout: [ + { + value: 0, + n: 0, + scriptPubKey: { + asm: 'OP_RETURN 5262419 65 47454e45534953 4e4654303034 4e4654204368696c64 68747470733a2f2f46756c6c537461636b2e63617368 0 0 0 0000000000000001', + hex: '6a04534c500001410747454e45534953064e4654303034094e4654204368696c641668747470733a2f2f46756c6c537461636b2e636173684c0001004c00080000000000000001', + type: 'nulldata' + } + }, + { + value: 0.00000546, + n: 1, + scriptPubKey: { + asm: 'OP_DUP OP_HASH160 f6fc6bce702ef779d2373aa4356a32113d95e674 OP_EQUALVERIFY OP_CHECKSIG', + hex: '76a914f6fc6bce702ef779d2373aa4356a32113d95e67488ac', + reqSigs: 1, + type: 'pubkeyhash', + addresses: [ + 'bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv' + ] + } + }, + { + value: 0.0003923, + n: 2, + scriptPubKey: { + asm: 'OP_DUP OP_HASH160 f6fc6bce702ef779d2373aa4356a32113d95e674 OP_EQUALVERIFY OP_CHECKSIG', + hex: '76a914f6fc6bce702ef779d2373aa4356a32113d95e67488ac', + reqSigs: 1, + type: 'pubkeyhash', + addresses: [ + 'bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv' + ] + } + } + ], + hex: '020000000295e3d0920df2e9467bf4c6dee49d5ba37f2e6f255c72b8d561079f0f8a45a2a9010000006b483045022100890ff2f80f3c184419ba03a575b9d159c0a5edfa817e4548cfdb6c74d16ce8d202205a8237d2139196716c273fe80506896d369a0022bb54401e2eadb364286a9f07412103136d9ec06adef1c9154105950e82d470d290aa019ed34a5e3bbd0b679805623bffffffff95e3d0920df2e9467bf4c6dee49d5ba37f2e6f255c72b8d561079f0f8a45a2a9030000006a47304402203905a61ec4e3567f7cad7eb514132e5b32d8a1d77c8838baac1b34b735282a5f022044da6130b5cc41b65615b17df6610087fe1baedd1a3a9f37552b56ea8d36d026412103136d9ec06adef1c9154105950e82d470d290aa019ed34a5e3bbd0b679805623bffffffff030000000000000000476a04534c500001410747454e45534953064e4654303034094e4654204368696c641668747470733a2f2f46756c6c537461636b2e636173684c0001004c0008000000000000000122020000000000001976a914f6fc6bce702ef779d2373aa4356a32113d95e67488ac3e990000000000001976a914f6fc6bce702ef779d2373aa4356a32113d95e67488ac00000000', + blockhash: '000000000000000001360fe42629f4136e9adec53546b278de0e7ef788eed328', + confirmations: 2113, + time: 1613181364, + blocktime: 1613181364 +} + module.exports = { mockList, mockToken, @@ -1311,6 +1381,7 @@ module.exports = { txDetailsSLPGenesisNoBaton, txDetailsSLPSendAlt, txDetailsSLPNftGenesis, + txDetailsSLPNftChild, mockTxDetails, mockDualValidation, mockDualOpData, diff --git a/test/unit/slp-utils.js b/test/unit/slp-utils.js index fad8e88..dda7d54 100644 --- a/test/unit/slp-utils.js +++ b/test/unit/slp-utils.js @@ -453,33 +453,33 @@ describe('#SLP Utils', () => { assert.equal(data.qty, 1) }) - // it("should decode a NFT Child transaction", async () => { - // // Mock the call to the REST API. - // // sandbox - // // .stub(uut.Utils.axios, "get") - // // .resolves({ data: mockData.txDetailsSLPNftGenesis }) - // - // const txid = - // "3de3766b10506c9156533f1639979e49d1884521543c13e4af73647df1ed3f76" - // - // const data = await uut.Utils.decodeOpReturn(txid) - // console.log(`data: ${JSON.stringify(data, null, 2)}`) - // - // // assert.property(data, "tokenType") - // // assert.property(data, "txType") - // // assert.property(data, "ticker") - // // assert.property(data, "name") - // // assert.property(data, "tokenId") - // // assert.property(data, "documentUri") - // // assert.property(data, "documentHash") - // // assert.property(data, "decimals") - // // assert.property(data, "mintBatonVout") - // // assert.property(data, "qty") - // // - // // assert.equal(data.tokenType, 129) - // // assert.equal(data.mintBatonVout, 2) - // // assert.equal(data.qty, 1) - // }) + it('should decode a NFT Child transaction', async () => { + // Mock the call to the REST API. + sandbox + .stub(uut.Utils.axios, 'get') + .resolves({ data: mockData.txDetailsSLPNftChild }) + + const txid = + 'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b' + + const data = await uut.Utils.decodeOpReturn(txid) + console.log(`data: ${JSON.stringify(data, null, 2)}`) + + assert.property(data, 'tokenType') + assert.property(data, 'txType') + assert.property(data, 'ticker') + assert.property(data, 'name') + assert.property(data, 'tokenId') + assert.property(data, 'documentUri') + assert.property(data, 'documentHash') + assert.property(data, 'decimals') + assert.property(data, 'mintBatonVout') + assert.property(data, 'qty') + + assert.equal(data.tokenType, 65) + assert.equal(data.mintBatonVout, 0) + assert.equal(data.qty, '1') + }) }) describe('#tokenUtxoDetails', () => {