Merge pull request #112 from Permissionless-Software-Foundation/ct-unstable

fix(decodeOpReturn): Switching to POST from GET to getRawTx call
This commit is contained in:
Chris Troutner
2021-02-24 15:14:51 -08:00
committed by GitHub
3 changed files with 55 additions and 28 deletions
+1
View File
@@ -19,6 +19,7 @@
"test:temp": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 -g '#hydrateUtxos' test/integration/", "test:temp": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 -g '#hydrateUtxos' test/integration/",
"test:temp2": "mocha --timeout=30000 -g '#Util' test/unit/", "test:temp2": "mocha --timeout=30000 -g '#Util' test/unit/",
"test:temp3": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#hydrateUtxos' test/integration/", "test:temp3": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#hydrateUtxos' 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": "nyc report --reporter=text-lcov | coveralls",
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/", "coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
"docs": "./node_modules/.bin/apidoc -i src/ -o docs", "docs": "./node_modules/.bin/apidoc -i src/ -o docs",
+36 -10
View File
@@ -655,7 +655,7 @@ class Utils {
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`) // console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
// console.log(`path: ${JSON.stringify(path, null, 2)}`) // console.log(`path: ${JSON.stringify(path, null, 2)}`)
console.log('ip: ', ip) console.log('validateTxid3 ip: ', ip)
// Handle a single TXID or an array of TXIDs. // Handle a single TXID or an array of TXIDs.
let txids let txids
@@ -925,7 +925,7 @@ class Utils {
* *
*/ */
// Reimplementation of decodeOpReturn() using slp-parser. // Reimplementation of decodeOpReturn() using slp-parser.
async decodeOpReturn (txid, cache = null) { async decodeOpReturn (txid, cache = null, ip = null) {
// The cache object is an in-memory cache (JS Object) that can be passed // The cache object is an in-memory cache (JS Object) that can be passed
// into this function. It helps if multiple vouts from the same TXID are // into this function. It helps if multiple vouts from the same TXID are
// being evaluated. In that case, it can significantly reduce the number // being evaluated. In that case, it can significantly reduce the number
@@ -942,16 +942,32 @@ class Utils {
if (cachedVal) return cachedVal if (cachedVal) return cachedVal
} }
console.log(`decodeOpReturn ip: ${ip}`)
try { try {
// Validate the txid input. // Validate the txid input.
if (!txid || txid === '' || typeof txid !== 'string') { if (!txid || txid === '' || typeof txid !== 'string') {
throw new Error('txid string must be included.') throw new Error('txid string must be included.')
} }
// CT: 2/24/21 Deprected GET in favor of POST, to pass IP address.
// Retrieve the transaction object from the full node. // Retrieve the transaction object from the full node.
const path = `${this.restURL}rawtransactions/getRawTransaction/${txid}?verbose=true` // const path = `${this.restURL}rawtransactions/getRawTransaction/${txid}?verbose=true`
const response = await _this.axios.get(path, _this.axiosOptions) // const response = await _this.axios.get(path, _this.axiosOptions)
const txDetails = response.data // const txDetails = response.data
const path = `${this.restURL}rawtransactions/getRawTransaction`
const response = await _this.axios.post(
path,
{
verbose: true,
txids: [txid],
ip
},
_this.axiosOptions
)
const txDetails = response.data[0]
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`) // console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
// SLP spec expects OP_RETURN to be the first output of the transaction. // SLP spec expects OP_RETURN to be the first output of the transaction.
@@ -1069,6 +1085,8 @@ class Utils {
// Throw error if input is not an array. // Throw error if input is not an array.
if (!Array.isArray(utxos)) throw new Error('Input must be an array.') if (!Array.isArray(utxos)) throw new Error('Input must be an array.')
console.log(`tokenUtxoDetails ip: ${ip}`)
// Loop through each element in the array and validate the input before // Loop through each element in the array and validate the input before
// further processing. // further processing.
for (let i = 0; i < utxos.length; i++) { for (let i = 0; i < utxos.length; i++) {
@@ -1100,7 +1118,7 @@ class Utils {
} }
// Hydrate each UTXO with data from SLP OP_REUTRNs. // Hydrate each UTXO with data from SLP OP_REUTRNs.
const outAry = await this._hydrateUtxo(utxos) const outAry = await this._hydrateUtxo(utxos, ip)
// console.log(`outAry: ${JSON.stringify(outAry, null, 2)}`) // console.log(`outAry: ${JSON.stringify(outAry, null, 2)}`)
// *After* each UTXO has been hydrated with SLP data, // *After* each UTXO has been hydrated with SLP data,
@@ -1220,10 +1238,12 @@ class Utils {
// This is a private function that is called by tokenUtxoDetails(). // This is a private function that is called by tokenUtxoDetails().
// It loops through an array of UTXOs and tries to hydrate them with SLP // It loops through an array of UTXOs and tries to hydrate them with SLP
// token information from the OP_RETURN data. // token information from the OP_RETURN data.
async _hydrateUtxo (utxos) { async _hydrateUtxo (utxos, ip = null) {
try { try {
const decodeOpReturnCache = {} const decodeOpReturnCache = {}
console.log(`_hydrateUtxo ip: ${ip}`)
// Output Array // Output Array
const outAry = [] const outAry = []
@@ -1236,7 +1256,11 @@ class Utils {
// If there is no OP_RETURN, mark the UTXO as false. // If there is no OP_RETURN, mark the UTXO as false.
let slpData = false let slpData = false
try { try {
slpData = await this.decodeOpReturn(utxo.txid, decodeOpReturnCache) slpData = await this.decodeOpReturn(
utxo.txid,
decodeOpReturnCache,
ip
)
// console.log(`slpData: ${JSON.stringify(slpData, null, 2)}`) // console.log(`slpData: ${JSON.stringify(slpData, null, 2)}`)
} catch (err) { } catch (err) {
// console.log(`error from decodeOpReturn(${utxo.txid}): `, err) // console.log(`error from decodeOpReturn(${utxo.txid}): `, err)
@@ -1326,7 +1350,8 @@ class Utils {
const genesisData = await this.decodeOpReturn( const genesisData = await this.decodeOpReturn(
slpData.tokenId, slpData.tokenId,
decodeOpReturnCache decodeOpReturnCache,
ip
) )
// console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`) // console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`)
@@ -1378,7 +1403,8 @@ class Utils {
const genesisData = await this.decodeOpReturn( const genesisData = await this.decodeOpReturn(
slpData.tokenId, slpData.tokenId,
decodeOpReturnCache decodeOpReturnCache,
ip
) )
// console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`) // console.log(`genesisData: ${JSON.stringify(genesisData, null, 2)}`)
+18 -18
View File
@@ -273,8 +273,8 @@ describe('#SLP Utils', () => {
try { try {
// Mock the call to the REST API // Mock the call to the REST API
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.nonSLPTxDetailsWithoutOpReturn }) .resolves({ data: [mockData.nonSLPTxDetailsWithoutOpReturn] })
const txid = const txid =
'3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec' '3793d4906654f648e659f384c0f40b19c8f10c1e9fb72232a9b8edd61abaa1ec'
@@ -292,8 +292,8 @@ describe('#SLP Utils', () => {
try { try {
// Mock the call to the REST API // Mock the call to the REST API
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.nonSLPTxDetailsWithOpReturn }) .resolves({ data: [mockData.nonSLPTxDetailsWithOpReturn] })
const txid = const txid =
'2ff74c48a5d657cf45f699601990bffbbe7a2a516d5480674cbf6c6a4497908f' '2ff74c48a5d657cf45f699601990bffbbe7a2a516d5480674cbf6c6a4497908f'
@@ -310,8 +310,8 @@ describe('#SLP Utils', () => {
it('should decode a genesis transaction', async () => { it('should decode a genesis transaction', async () => {
// Mock the call to the REST API // Mock the call to the REST API
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.txDetailsSLPGenesis }) .resolves({ data: [mockData.txDetailsSLPGenesis] })
const txid = const txid =
'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90' 'bd158c564dd4ef54305b14f44f8e94c44b649f246dab14bcb42fb0d0078b8a90'
@@ -336,8 +336,8 @@ describe('#SLP Utils', () => {
it('should decode a mint transaction', async () => { it('should decode a mint transaction', async () => {
// Mock the call to the REST API // Mock the call to the REST API
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.txDetailsSLPMint }) .resolves({ data: [mockData.txDetailsSLPMint] })
const txid = const txid =
'65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4' '65f21bbfcd545e5eb515e38e861a9dfe2378aaa2c4e458eb9e59e4d40e38f3a4'
@@ -357,8 +357,8 @@ describe('#SLP Utils', () => {
it('should decode a send transaction', async () => { it('should decode a send transaction', async () => {
// Mock the call to the REST API // Mock the call to the REST API
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.txDetailsSLPSend }) .resolves({ data: [mockData.txDetailsSLPSend] })
const txid = const txid =
'4f922565af664b6fdf0a1ba3924487344be721b3d8815c62cafc8a51e04a8afa' '4f922565af664b6fdf0a1ba3924487344be721b3d8815c62cafc8a51e04a8afa'
@@ -372,8 +372,8 @@ describe('#SLP Utils', () => {
it('should properly decode a Genesis transaction with no minting baton', async () => { it('should properly decode a Genesis transaction with no minting baton', async () => {
// Mock the call to the REST API. // Mock the call to the REST API.
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.txDetailsSLPGenesisNoBaton }) .resolves({ data: [mockData.txDetailsSLPGenesisNoBaton] })
const txid = const txid =
'497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7'
@@ -387,8 +387,8 @@ describe('#SLP Utils', () => {
it('should decode a send transaction with alternate encoding', async () => { it('should decode a send transaction with alternate encoding', async () => {
// Mock the call to the REST API // Mock the call to the REST API
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.txDetailsSLPSendAlt }) .resolves({ data: [mockData.txDetailsSLPSendAlt] })
const txid = const txid =
'd94357179775425ebc59c93173bd6dc9854095f090a2eb9dcfe9797398bc8eae' 'd94357179775425ebc59c93173bd6dc9854095f090a2eb9dcfe9797398bc8eae'
@@ -411,8 +411,8 @@ describe('#SLP Utils', () => {
try { try {
// Mock the call to the REST API // Mock the call to the REST API
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.mockInvalidSlpSend }) .resolves({ data: [mockData.mockInvalidSlpSend] })
const txid = const txid =
'a60a522cc11ad7011b74e57fbabbd99296e4b9346bcb175dcf84efb737030415' 'a60a522cc11ad7011b74e57fbabbd99296e4b9346bcb175dcf84efb737030415'
@@ -428,8 +428,8 @@ describe('#SLP Utils', () => {
it('should decode a NFT Parent transaction', async () => { it('should decode a NFT Parent transaction', async () => {
// Mock the call to the REST API. // Mock the call to the REST API.
sandbox sandbox
.stub(uut.Utils.axios, 'get') .stub(uut.Utils.axios, 'post')
.resolves({ data: mockData.txDetailsSLPNftGenesis }) .resolves({ data: [mockData.txDetailsSLPNftGenesis] })
const txid = const txid =
'4ef6eb92950a13a69e97c2c02c7967d806aa874c0e2a6b5546a8880f2cd14bc4' '4ef6eb92950a13a69e97c2c02c7967d806aa874c0e2a6b5546a8880f2cd14bc4'