mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-21 16:51:59 -07:00
fix(waterfallValidateTxid): Skipping validateTxid3() if it throws an error
This commit is contained in:
+44
-36
@@ -11,7 +11,7 @@ const Util = require('../util')
|
|||||||
let _this
|
let _this
|
||||||
|
|
||||||
class Utils {
|
class Utils {
|
||||||
constructor (config) {
|
constructor(config) {
|
||||||
this.restURL = config.restURL
|
this.restURL = config.restURL
|
||||||
this.apiToken = config.apiToken
|
this.apiToken = config.apiToken
|
||||||
this.slpParser = slpParser
|
this.slpParser = slpParser
|
||||||
@@ -197,7 +197,7 @@ class Utils {
|
|||||||
* circulatingSupply: 19882.03820723,
|
* circulatingSupply: 19882.03820723,
|
||||||
* mintingBatonStatus: 'ALIVE' } ]
|
* mintingBatonStatus: 'ALIVE' } ]
|
||||||
*/
|
*/
|
||||||
async list (id) {
|
async list(id) {
|
||||||
let path
|
let path
|
||||||
let method
|
let method
|
||||||
|
|
||||||
@@ -309,7 +309,7 @@ class Utils {
|
|||||||
* array of addresses.
|
* array of addresses.
|
||||||
*/
|
*/
|
||||||
// Retrieve token balances for a given address.
|
// Retrieve token balances for a given address.
|
||||||
async balancesForAddress (address) {
|
async balancesForAddress(address) {
|
||||||
try {
|
try {
|
||||||
// Single address.
|
// Single address.
|
||||||
if (typeof address === 'string') {
|
if (typeof address === 'string') {
|
||||||
@@ -376,7 +376,7 @@ class Utils {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// Retrieve token balances for a given tokenId.
|
// Retrieve token balances for a given tokenId.
|
||||||
async balancesForToken (tokenId) {
|
async balancesForToken(tokenId) {
|
||||||
try {
|
try {
|
||||||
const path = `${this.restURL}slp/balancesForToken/${tokenId}`
|
const path = `${this.restURL}slp/balancesForToken/${tokenId}`
|
||||||
|
|
||||||
@@ -438,7 +438,7 @@ class Utils {
|
|||||||
// will be like the examples above. If SLPDB has fallen behind real-time
|
// will be like the examples above. If SLPDB has fallen behind real-time
|
||||||
// processing, it will return this output:
|
// processing, it will return this output:
|
||||||
// [ null ]
|
// [ null ]
|
||||||
async validateTxid (txid, usrObj = null) {
|
async validateTxid(txid, usrObj = null) {
|
||||||
const path = `${this.restURL}slp/validateTxid`
|
const path = `${this.restURL}slp/validateTxid`
|
||||||
|
|
||||||
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
|
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
|
||||||
@@ -506,7 +506,7 @@ class Utils {
|
|||||||
* 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
|
* 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb',
|
||||||
* valid: true } ]
|
* valid: true } ]
|
||||||
*/
|
*/
|
||||||
async validateTxid2 (txid) {
|
async validateTxid2(txid) {
|
||||||
try {
|
try {
|
||||||
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
|
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
|
||||||
|
|
||||||
@@ -585,7 +585,7 @@ class Utils {
|
|||||||
* }
|
* }
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
async getWhitelist () {
|
async getWhitelist() {
|
||||||
try {
|
try {
|
||||||
const path = `${this.restURL}slp/whitelist`
|
const path = `${this.restURL}slp/whitelist`
|
||||||
|
|
||||||
@@ -655,7 +655,7 @@ class Utils {
|
|||||||
* '00ea27261196a411776f81029c0ebe34362936b4a9847deb1f7a40a02b3a1476',
|
* '00ea27261196a411776f81029c0ebe34362936b4a9847deb1f7a40a02b3a1476',
|
||||||
* valid: true } ]
|
* valid: true } ]
|
||||||
*/
|
*/
|
||||||
async validateTxid3 (txid, usrObj = null) {
|
async validateTxid3(txid, usrObj = null) {
|
||||||
const path = `${this.restURL}slp/validateTxid3`
|
const path = `${this.restURL}slp/validateTxid3`
|
||||||
|
|
||||||
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
|
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
|
||||||
@@ -731,7 +731,7 @@ class Utils {
|
|||||||
* satoshisLockedUp: 135408
|
* satoshisLockedUp: 135408
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async tokenStats (tokenId) {
|
async tokenStats(tokenId) {
|
||||||
try {
|
try {
|
||||||
const path = `${this.restURL}slp/tokenStats/${tokenId}`
|
const path = `${this.restURL}slp/tokenStats/${tokenId}`
|
||||||
|
|
||||||
@@ -802,7 +802,7 @@ class Utils {
|
|||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
// Retrieve token transactions for a given tokenId and address.
|
// Retrieve token transactions for a given tokenId and address.
|
||||||
async transactions (tokenId, address) {
|
async transactions(tokenId, address) {
|
||||||
try {
|
try {
|
||||||
const path = `${this.restURL}slp/transactions/${tokenId}/${address}`
|
const path = `${this.restURL}slp/transactions/${tokenId}/${address}`
|
||||||
|
|
||||||
@@ -842,7 +842,7 @@ class Utils {
|
|||||||
* burnTotal: 100
|
* burnTotal: 100
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async burnTotal (transactionId) {
|
async burnTotal(transactionId) {
|
||||||
try {
|
try {
|
||||||
const path = `${this.restURL}slp/burnTotal/${transactionId}`
|
const path = `${this.restURL}slp/burnTotal/${transactionId}`
|
||||||
|
|
||||||
@@ -876,7 +876,7 @@ class Utils {
|
|||||||
* })()
|
* })()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async txDetails (txid) {
|
async txDetails(txid) {
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
!txid ||
|
!txid ||
|
||||||
@@ -942,7 +942,7 @@ class Utils {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// Reimplementation of decodeOpReturn() using slp-parser.
|
// Reimplementation of decodeOpReturn() using slp-parser.
|
||||||
async decodeOpReturn (txid, cache = null, usrObj = null) {
|
async decodeOpReturn(txid, cache = null, usrObj = 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
|
||||||
@@ -1109,7 +1109,7 @@ class Utils {
|
|||||||
* "tokenType": 1
|
* "tokenType": 1
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async tokenUtxoDetails (utxos, usrObj = null) {
|
async tokenUtxoDetails(utxos, usrObj = null) {
|
||||||
try {
|
try {
|
||||||
// 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.')
|
||||||
@@ -1200,7 +1200,7 @@ class Utils {
|
|||||||
* could burn tokens. It's safest to ignore UTXOs with a value of `null`.
|
* could burn tokens. It's safest to ignore UTXOs with a value of `null`.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async tokenUtxoDetailsWL (utxos, usrObj = null) {
|
async tokenUtxoDetailsWL(utxos, usrObj = null) {
|
||||||
try {
|
try {
|
||||||
// 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.')
|
||||||
@@ -1294,7 +1294,7 @@ class Utils {
|
|||||||
//
|
//
|
||||||
// If the usrObj has a utxoDelay property, then it will delay the loop for
|
// If the usrObj has a utxoDelay property, then it will delay the loop for
|
||||||
// each UTXO by that many milliseconds.
|
// each UTXO by that many milliseconds.
|
||||||
async _hydrateUtxo (utxos, usrObj = null) {
|
async _hydrateUtxo(utxos, usrObj = null) {
|
||||||
try {
|
try {
|
||||||
const decodeOpReturnCache = {}
|
const decodeOpReturnCache = {}
|
||||||
|
|
||||||
@@ -1557,7 +1557,7 @@ class Utils {
|
|||||||
* // returns
|
* // returns
|
||||||
* true
|
* true
|
||||||
*/
|
*/
|
||||||
async waterfallValidateTxid (txid, usrObj = null) {
|
async waterfallValidateTxid(txid, usrObj = null) {
|
||||||
try {
|
try {
|
||||||
// console.log('txid: ', txid)
|
// console.log('txid: ', txid)
|
||||||
|
|
||||||
@@ -1588,25 +1588,31 @@ class Utils {
|
|||||||
// Note: validateTxid3() has the same output as validateTxid().
|
// Note: validateTxid3() has the same output as validateTxid().
|
||||||
// validateTxid2() uses slp-validate, which has a different output format.
|
// validateTxid2() uses slp-validate, which has a different output format.
|
||||||
|
|
||||||
// Validate against the whitelist SLPDB first.
|
// If the whitelist SLPDB is having issues, the try/catch will skip it
|
||||||
const whitelistResult = await this.validateTxid3(txid, usrObj)
|
// and continue execution.
|
||||||
// console.log(
|
try {
|
||||||
// `whitelist-SLPDB for ${txid}: ${JSON.stringify(
|
// Validate against the whitelist SLPDB first.
|
||||||
// whitelistResult,
|
const whitelistResult = await this.validateTxid3(txid, usrObj)
|
||||||
// null,
|
// console.log(
|
||||||
// 2
|
// `whitelist-SLPDB for ${txid}: ${JSON.stringify(
|
||||||
// )}`
|
// whitelistResult,
|
||||||
// )
|
// null,
|
||||||
|
// 2
|
||||||
|
// )}`
|
||||||
|
// )
|
||||||
|
|
||||||
// Safely retrieve the returned value.
|
// Safely retrieve the returned value.
|
||||||
if (whitelistResult[0] !== null) isValid = whitelistResult[0].valid
|
if (whitelistResult[0] !== null) isValid = whitelistResult[0].valid
|
||||||
|
|
||||||
// Exit if isValid is not null.
|
// Exit if isValid is not null.
|
||||||
if (isValid !== null) {
|
if (isValid !== null) {
|
||||||
// Save to the cache.
|
// Save to the cache.
|
||||||
cachedTxValidation[txid] = isValid
|
cachedTxValidation[txid] = isValid
|
||||||
|
|
||||||
return isValid
|
return isValid
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* exit quietly */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try the general SLPDB, if the whitelist returned null.
|
// Try the general SLPDB, if the whitelist returned null.
|
||||||
@@ -1842,7 +1848,7 @@ class Utils {
|
|||||||
*/
|
*/
|
||||||
// Same as tokenUtxoDetails(), but reduces API calls by having bch-api server
|
// Same as tokenUtxoDetails(), but reduces API calls by having bch-api server
|
||||||
// do the heavy lifting.
|
// do the heavy lifting.
|
||||||
async hydrateUtxos (utxos, usrObj) {
|
async hydrateUtxos(utxos, usrObj) {
|
||||||
try {
|
try {
|
||||||
// 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.')
|
||||||
@@ -1858,6 +1864,8 @@ class Utils {
|
|||||||
|
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log('Error in hydrateUtxos(): ', error)
|
||||||
|
|
||||||
if (error.response && error.response.data) {
|
if (error.response && error.response.data) {
|
||||||
throw new Error(JSON.stringify(error.response.data, null, 2))
|
throw new Error(JSON.stringify(error.response.data, null, 2))
|
||||||
}
|
}
|
||||||
@@ -1881,7 +1889,7 @@ class Utils {
|
|||||||
*/
|
*/
|
||||||
// Same as tokenUtxoDetailsWL(), but reduces API calls by having bch-api server
|
// Same as tokenUtxoDetailsWL(), but reduces API calls by having bch-api server
|
||||||
// do the heavy lifting.
|
// do the heavy lifting.
|
||||||
async hydrateUtxosWL (utxos) {
|
async hydrateUtxosWL(utxos) {
|
||||||
try {
|
try {
|
||||||
// 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.')
|
||||||
@@ -1927,7 +1935,7 @@ class Utils {
|
|||||||
* valid: true } ]
|
* valid: true } ]
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async getStatus (txid) {
|
async getStatus(txid) {
|
||||||
const path = `${this.restURL}slp/status`
|
const path = `${this.restURL}slp/status`
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
+19
-17
@@ -2281,23 +2281,25 @@ describe('#SLP Utils', () => {
|
|||||||
assert.equal(result, true)
|
assert.equal(result, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('catches and throws an error', async () => {
|
// CT 08-09-21 Changed behavior. validateTxid3() is now wrapped in a
|
||||||
try {
|
// try/catch statement that exits quietly if there is an error.
|
||||||
const txid = 'fakeTxid'
|
// it('catches and throws an error', async () => {
|
||||||
|
// try {
|
||||||
// Force an error
|
// const txid = 'fakeTxid'
|
||||||
sandbox
|
//
|
||||||
.stub(uut.Utils, 'validateTxid3')
|
// // Force an error
|
||||||
.rejects(new Error('fake error'))
|
// sandbox
|
||||||
|
// .stub(uut.Utils, 'validateTxid3')
|
||||||
await await uut.Utils.waterfallValidateTxid(txid)
|
// .rejects(new Error('fake error'))
|
||||||
|
//
|
||||||
assert.fail('Unexpected result')
|
// await await uut.Utils.waterfallValidateTxid(txid)
|
||||||
} catch (err) {
|
//
|
||||||
// console.log(`err.message: ${err.message}`)
|
// assert.fail('Unexpected result')
|
||||||
assert.include(err.message, 'fake error')
|
// } catch (err) {
|
||||||
}
|
// // console.log(`err.message: ${err.message}`)
|
||||||
})
|
// assert.include(err.message, 'fake error')
|
||||||
|
// }
|
||||||
|
// })
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#getWhitelist', () => {
|
describe('#getWhitelist', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user