mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-21 16:51:59 -07:00
feat(tokenUtxoDetails()): Using fallback SLP validators
This commit is contained in:
+32
-17
@@ -1,3 +1,4 @@
|
||||
// Public npm libraries
|
||||
const axios = require("axios")
|
||||
const slpParser = require("slp-parser")
|
||||
|
||||
@@ -1111,9 +1112,9 @@ class Utils {
|
||||
let slpData = false
|
||||
try {
|
||||
slpData = await this.decodeOpReturn(utxo.txid, decodeOpReturnCache)
|
||||
console.log(`slpData: ${JSON.stringify(slpData, null, 2)}`)
|
||||
// console.log(`slpData: ${JSON.stringify(slpData, null, 2)}`)
|
||||
} catch (err) {
|
||||
console.log(`error from decodeOpReturn(${utxo.txid}): `, err)
|
||||
// console.log(`error from decodeOpReturn(${utxo.txid}): `, err)
|
||||
|
||||
// An error will be thrown if the txid is not SLP.
|
||||
// If error is for some other reason, like a 429 error, mark utxo as 'null'
|
||||
@@ -1124,10 +1125,10 @@ class Utils {
|
||||
err.message.indexOf("lokad id") === -1 &&
|
||||
err.message.indexOf("trailing data") === -1)
|
||||
) {
|
||||
console.log(
|
||||
`unknown error from decodeOpReturn(). Marking as 'null'`,
|
||||
err
|
||||
)
|
||||
// console.log(
|
||||
// `unknown error from decodeOpReturn(). Marking as 'null'`,
|
||||
// err
|
||||
// )
|
||||
|
||||
utxo.isValid = null
|
||||
outAry.push(utxo)
|
||||
@@ -1136,10 +1137,9 @@ class Utils {
|
||||
// an SLP UTXO.
|
||||
// Mark as false and continue the loop.
|
||||
} else {
|
||||
console.log("marking as invalid")
|
||||
// console.log("marking as invalid")
|
||||
utxo.isValid = false
|
||||
outAry.push(utxo)
|
||||
console.log(`outAry: ${JSON.stringify(outAry, null, 2)}`)
|
||||
}
|
||||
|
||||
// Halt the execution of the loop and increase to the next index.
|
||||
@@ -1285,7 +1285,8 @@ class Utils {
|
||||
// validate the TXID with SLPDB.
|
||||
if (outAry[i].tokenType) {
|
||||
// Only execute this block if the current UTXO has a 'tokenType'
|
||||
// property. i.e. it has been hydrated with SLP information.
|
||||
// property. i.e. it has been successfully hydrated with SLP
|
||||
// information.
|
||||
|
||||
// If the value has been cached, use the cached version first.
|
||||
let isValid = cachedTxValidation[utxo.txid]
|
||||
@@ -1302,7 +1303,13 @@ class Utils {
|
||||
|
||||
// If still null, check the whitelist SLPDB
|
||||
if (isValid === null) {
|
||||
console.log(`outAry[${i}]: ${JSON.stringify(outAry[i], null, 2)}`)
|
||||
// console.log(
|
||||
// `checking against whitelist SLPDB. outAry[${i}]: ${JSON.stringify(
|
||||
// outAry[i],
|
||||
// null,
|
||||
// 2
|
||||
// )}`
|
||||
// )
|
||||
|
||||
// Figure out if the token UTXO is in the whitelist.
|
||||
let utxoInWhitelist = false
|
||||
@@ -1318,6 +1325,15 @@ class Utils {
|
||||
// if the general SLPDB is not.
|
||||
if (utxoInWhitelist) {
|
||||
isValid = await this.validateTxid3(utxo.txid)
|
||||
|
||||
// console.log(
|
||||
// `whitelist-SLPDB for ${utxo.txid}: ${JSON.stringify(
|
||||
// isValid,
|
||||
// null,
|
||||
// 2
|
||||
// )}`
|
||||
// )
|
||||
|
||||
isValid = isValid[0].valid
|
||||
|
||||
// Save the result to the local cache.
|
||||
@@ -1328,22 +1344,21 @@ class Utils {
|
||||
// If still null, as a last resort, check it against slp-validate
|
||||
if (isValid === null) {
|
||||
isValid = await this.validateTxid2(utxo.txid)
|
||||
console.log(
|
||||
`slp-validate isValid: ${JSON.stringify(isValid, null, 2)}`
|
||||
)
|
||||
isValid = isValid.valid
|
||||
// console.log(
|
||||
// `slp-validate isValid: ${JSON.stringify(isValid, null, 2)}`
|
||||
// )
|
||||
|
||||
isValid = isValid.isValid
|
||||
|
||||
// Save the result to the local cache.
|
||||
cachedTxValidation[utxo.txid] = isValid
|
||||
}
|
||||
|
||||
console.log(`isValid: ${JSON.stringify(isValid, null, 2)}`)
|
||||
// console.log(`isValid: ${JSON.stringify(isValid, null, 2)}`)
|
||||
outAry[i].isValid = isValid
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`pt2 outAry: ${JSON.stringify(outAry, null, 2)}`)
|
||||
|
||||
return outAry
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) throw error.response.data
|
||||
|
||||
@@ -1163,6 +1163,33 @@ const mockValidateTxidArray = [
|
||||
}
|
||||
]
|
||||
|
||||
const whitelist = [
|
||||
{
|
||||
name: "USDH",
|
||||
tokenId: "c4b0d62156b3fa5c8f3436079b5394f7edc1bef5dc1cd2f9d0c4d46f82cca479"
|
||||
},
|
||||
{
|
||||
name: "SPICE",
|
||||
tokenId: "4de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf"
|
||||
},
|
||||
{
|
||||
name: "PSF",
|
||||
tokenId: "38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0"
|
||||
},
|
||||
{
|
||||
name: "TROUT",
|
||||
tokenId: "a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2"
|
||||
},
|
||||
{
|
||||
name: "PSFTEST",
|
||||
tokenId: "d0ef4de95b78222bfee2326ab11382f4439aa0855936e2fe6ac129a8d778baa0"
|
||||
},
|
||||
{
|
||||
name: "TOK-CH",
|
||||
tokenId: "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7"
|
||||
}
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
mockList,
|
||||
mockToken,
|
||||
@@ -1190,5 +1217,6 @@ module.exports = {
|
||||
mockInvalidSlpSend,
|
||||
mockWhitelist,
|
||||
mockValidateTxid3Valid,
|
||||
mockValidateTxid3Invalid
|
||||
mockValidateTxid3Invalid,
|
||||
whitelist
|
||||
}
|
||||
|
||||
+76
-15
@@ -1695,21 +1695,82 @@ describe("#SLP Utils", () => {
|
||||
assert.equal(data[0].isValid, false)
|
||||
})
|
||||
|
||||
// it("should validate against the whitelist SLPDB when regular SLPDB returns null", async () => {
|
||||
// const utxos = [
|
||||
// // Malformed SLP tx
|
||||
// {
|
||||
// note: "Malformed SLP tx",
|
||||
// tx_hash:
|
||||
// "f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a",
|
||||
// tx_pos: 1,
|
||||
// value: 546
|
||||
// }
|
||||
// ]
|
||||
//
|
||||
// const data = await uut.Utils.tokenUtxoDetails(utxos)
|
||||
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
||||
// })
|
||||
it("should use backup validators when regular SLPDB returns null", async () => {
|
||||
// Mock the call to REST API
|
||||
// Stub the calls to decodeOpReturn.
|
||||
sandbox
|
||||
.stub(uut.Utils, "decodeOpReturn")
|
||||
.onCall(0)
|
||||
.resolves({
|
||||
tokenType: 1,
|
||||
txType: "SEND",
|
||||
tokenId:
|
||||
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7",
|
||||
amounts: ["200000000", "99887500000000"]
|
||||
})
|
||||
.onCall(1)
|
||||
.resolves({
|
||||
tokenType: 1,
|
||||
txType: "GENESIS",
|
||||
ticker: "TOK-CH",
|
||||
name: "TokyoCash",
|
||||
tokenId:
|
||||
"497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7",
|
||||
documentUri: "",
|
||||
documentHash: "",
|
||||
decimals: 8,
|
||||
mintBatonVout: 0,
|
||||
qty: "2100000000000000"
|
||||
})
|
||||
|
||||
// Force default SLPDB to return 'null', which should trigger usage of the
|
||||
// backup whitelist-SLPDB.
|
||||
sandbox.stub(uut.Utils, "validateTxid").resolves([
|
||||
{
|
||||
txid:
|
||||
"fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb",
|
||||
valid: null
|
||||
}
|
||||
])
|
||||
|
||||
// Force the token UTXO to be in the whitelist.
|
||||
uut.Utils.whitelist = mockData.whitelist
|
||||
|
||||
// Mock the response from the whitelist-SLPDB.
|
||||
sandbox.stub(uut.Utils, "validateTxid3").resolves([
|
||||
{
|
||||
txid:
|
||||
"fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb",
|
||||
valid: null
|
||||
}
|
||||
])
|
||||
|
||||
// Mock the response from slp-api
|
||||
sandbox.stub(uut.Utils, "validateTxid2").resolves({
|
||||
txid:
|
||||
"fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb",
|
||||
isValid: true,
|
||||
msg: ""
|
||||
})
|
||||
|
||||
const utxos = [
|
||||
{
|
||||
txid:
|
||||
"fde117b1f176b231e2fa9a6cb022e0f7c31c288221df6bcb05f8b7d040ca87cb",
|
||||
vout: 1,
|
||||
amount: 0.00000546,
|
||||
satoshis: 546,
|
||||
height: 596089,
|
||||
confirmations: 748
|
||||
}
|
||||
]
|
||||
|
||||
const data = await uut.Utils.tokenUtxoDetails(utxos)
|
||||
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
||||
|
||||
// The UTXO should have been validated by the third validation source.
|
||||
assert.equal(data[0].isValid, true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("#txDetails", () => {
|
||||
|
||||
Reference in New Issue
Block a user