From 40fa6440f402d928836e3d54ce0257536cceeff7 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 23 Mar 2021 18:49:27 -0700 Subject: [PATCH] feat(Transactions.get()): Added tx hydration method --- package.json | 2 +- src/slp/utils.js | 5 --- src/transaction.js | 42 ++++++++++++++++++--- test/integration/transaction-integration.js | 22 +++++++++-- 4 files changed, 56 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index d1a258f..71d93b5 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:integration:temp:bchn": "export RESTURL=http://157.90.174.219:3000/v4/ && mocha --timeout 30000 test/integration/", "test:temp": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 -g '#Encryption' test/integration/", "test:temp2": "mocha --timeout=30000 -g '#_hydrateUtxo' test/unit/", - "test:temp3": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#getTxData' test/integration/", + "test:temp3": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#transaction' test/integration/", "test:temp4": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 -g '#decodeOpReturn' test/integration/", "coverage": "nyc report --reporter=text-lcov | coveralls", "coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/", diff --git a/src/slp/utils.js b/src/slp/utils.js index 109e484..0a9bdbb 100644 --- a/src/slp/utils.js +++ b/src/slp/utils.js @@ -1097,11 +1097,6 @@ class Utils { * "tokenType": 1 * } */ - - // CT 1/11/20: Refactored to comply with this GitHub Issue: - // https://github.com/Bitcoin-com/slp-sdk/issues/84 - - // CT 5/31/20: Refactored to use slp-parse library. async tokenUtxoDetails (utxos, usrObj = null) { try { // Throw error if input is not an array. diff --git a/src/transaction.js b/src/transaction.js index 2bac153..023b042 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -32,13 +32,38 @@ class Transaction { outTokenData = await this.slpUtils.decodeOpReturn(txid) // console.log(`outTokenData: ${JSON.stringify(outTokenData, null, 2)}`) + // Get Genesis data for this token. + const genesisData = await this.slpUtils.decodeOpReturn( + outTokenData.tokenId + // decodeOpReturnCache + // usrObj // pass user data when making an internal call. + ) + // console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`) + // Add token information to the tx details object. txDetails.tokenTxType = outTokenData.txType txDetails.tokenId = outTokenData.tokenId + txDetails.tokenTicker = genesisData.ticker + txDetails.tokenName = genesisData.name + txDetails.tokenDecimals = genesisData.decimals + txDetails.tokenUri = genesisData.documentUri + txDetails.tokenDocHash = genesisData.documentHash // Add the token quantity to each output. for (let i = 0; i < outTokenData.amounts.length; i++) { - txDetails.vout[i + 1].tokenQty = outTokenData.amounts[i] + const rawQty = outTokenData.amounts[i] + const realQty = Number(rawQty) / Math.pow(10, txDetails.tokenDecimals) + + txDetails.vout[i + 1].tokenQty = realQty + } + + // Add tokenQty = null to any outputs that don't have a value. + for (let i = 0; i < txDetails.vout.length; i++) { + const thisVout = txDetails.vout[i] + + if (!thisVout.tokenQty && thisVout.tokenQty !== 0) { + thisVout.tokenQty = null + } } // Loop through each input and retrieve the token data. @@ -60,24 +85,29 @@ class Transaction { // console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`) if (tokenQty) { - thisVin.tokenQty = tokenQty + const realQty = + Number(tokenQty) / Math.pow(10, txDetails.tokenDecimals) + + thisVin.tokenQty = realQty // txDetails.vin[i].tokenQty = tokenQty } else { thisVin.tokenQty = null } } catch (err) { - // console.log('catch 2: ', err) // If decodeOpReturn() throws an error, then this input is not // from an SLP transaction and can be ignored. // thisVin.tokenQty = null thisVin.tokenQty = null continue } - // console.log( - // `2: txDetails.vin[i]: ${JSON.stringify(txDetails.vin[i], null, 2)}` - // ) } + + // Finally, validate the SLP TX. + // this.slpUtils.waterfallValidateTxid(txid, usrObj) + txDetails.isValidSLPTx = await this.slpUtils.waterfallValidateTxid(txid) } catch (err) { + // console.log('Error: ', err) + // If decoding the op_return fails, then it's not an SLP transaction, // and the non-hyrated TX details can be returned. return txDetails diff --git a/test/integration/transaction-integration.js b/test/integration/transaction-integration.js index 1d71738..d47289e 100644 --- a/test/integration/transaction-integration.js +++ b/test/integration/transaction-integration.js @@ -26,9 +26,9 @@ describe('#transaction', () => { assert.property(result.vout[0], 'value') assert.property(result.vout[0].scriptPubKey, 'addresses') - // Assert that added properties + // Assert that added properties exist. assert.property(result.vin[0], 'address') - // TODO: Add value to input + assert.property(result.vin[0], 'value') assert.property(result, 'isValidSLPTx') assert.equal(result.isValidSLPTx, false) }) @@ -38,7 +38,23 @@ describe('#transaction', () => { '266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1' const result = await bchjs.Transaction.get(txid) - console.log(`result: ${JSON.stringify(result, null, 2)}`) + // console.log(`result: ${JSON.stringify(result, null, 2)}`) + + // Assert that there are stanardized properties. + assert.property(result, 'txid') + assert.property(result, 'vin') + assert.property(result, 'vout') + assert.property(result.vout[0], 'value') + assert.property(result.vout[1].scriptPubKey, 'addresses') + + // Assert that added properties exist. + assert.property(result.vout[0], 'tokenQty') + assert.equal(result.vout[0].tokenQty, null) + assert.property(result.vin[0], 'address') + assert.property(result.vin[0], 'value') + assert.property(result.vin[0], 'tokenQty') + assert.property(result, 'isValidSLPTx') + assert.equal(result.isValidSLPTx, true) }) }) })