Compare commits

..
4 Commits
Author SHA1 Message Date
Chris Troutner 96f96f837e Merge pull request #102 from Permissionless-Software-Foundation/ct-unstable
fix(abc): Fixing testing scripts for ABC chain
2021-02-09 15:12:47 -08:00
Chris Troutner 03be1d5838 fix(abc): Fixing testing scripts for ABC chain 2021-02-09 15:08:14 -08:00
Chris Troutner 6b6bfa2ae2 Merge pull request #101 from Permissionless-Software-Foundation/ct-unstable
feat(hydrateUtxosWL): hydrateUtxo but uses SLPDB with whitelist filter
2021-02-09 12:37:15 -08:00
Chris Troutner da3af3656a feat(hydrateUtxosWL): hydrateUtxo but uses SLPDB with whitelist filter 2021-02-09 12:34:25 -08:00
6 changed files with 161 additions and 7 deletions
+4 -3
View File
@@ -13,11 +13,12 @@
"test:integration:abc": "export RESTURL=https://abc.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/abc/",
"test:integration:bchn": "export RESTURL=https://bchn.fullstack.cash/v4/ && export IS_USING_FREE_TIER=true && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:testnet": "IS_USING_FREE_TIER=true mocha --timeout 30000 test/integration/chains/testnet/",
"test:integration:local": "RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 test/integration",
"test:integration:local:bchn": "RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:local:abc": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
"test:integration:local:bchn": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v4/ mocha --timeout 30000 test/integration/testnet",
"test:temp": "export RESTURL=https://bchn.fullstack.cash/v4/ && mocha --timeout 30000 -g '#tokenUtxoDetailsWL' test/integration/",
"test:temp": "export RESTURL=http://localhost:3000/v4/ && mocha --timeout 30000 -g '#hydrateUtxos' test/integration/",
"test:temp2": "mocha --timeout=30000 -g '#tokenUtxoDetailsWL' test/unit/",
"test:temp3": "RESTURL=http://localhost:3000/v4/ mocha --timeout 30000 test/integration/chains/abc/",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
"docs": "./node_modules/.bin/apidoc -i src/ -o docs",
+42 -2
View File
@@ -602,7 +602,8 @@ class Utils {
* @api SLP.Utils.validateTxid3() validateTxid3()
* @apiName validateTxid3
* @apiGroup SLP Utils
* @apiDescription Validate that txid is an SLP transaction using the SLPDB whitelist server.
* @apiDescription
* Validate that txid is an SLP transaction using the SLPDB whitelist server.
* Same exact functionality as the validateTxid() function, but this function
* calls the whitelist SLPDB. It will only validate SLP tokens that are in the
* whitelist. You can retrieve the whitelist with the SLP.Utils.whitelist()
@@ -652,6 +653,7 @@ class Utils {
const path = `${this.restURL}slp/validateTxid3`
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
// console.log(`path: ${JSON.stringify(path, null, 2)}`)
// Handle a single TXID or an array of TXIDs.
let txids
@@ -1109,7 +1111,7 @@ class Utils {
// Validate using a 'waterfall' of validators.
utxo.isValid = await this.waterfallValidateTxid(utxo.txid)
// console.log(`isValid: ${JSON.stringify(isValid, null, 2)}`)
// console.log(`isValid: ${JSON.stringify(utxo.isValid, null, 2)}`)
}
}
@@ -1448,6 +1450,8 @@ class Utils {
async waterfallValidateTxid (txid) {
try {
// console.log('txid: ', txid)
const cachedTxValidation = {}
// If the value has been cached, use the cached version first.
@@ -1728,6 +1732,42 @@ class Utils {
}
}
/**
* @api SLP.Utils.hydrateUtxosWL() hydrateUtxosWL()
* @apiName hydrateUtxosWL
* @apiGroup SLP Utils
* @apiDescription
* This call is exactly the same as `hydrateUtxos()`. This version hydrate a
* UTXO with SLP token metadata, but only uses the whitelist SLPDB for
* validation.
*
* Whitelist SLPDBs will return `isValid: null` for any token not in the
* 'whitelist' filter. Filtered SLPDBs are much smaller and more reliable
* to operate.
*
*/
// Same as tokenUtxoDetailsWL(), but reduces API calls by having bch-api server
// do the heavy lifting.
async hydrateUtxosWL (utxos) {
try {
// Throw error if input is not an array.
if (!Array.isArray(utxos)) throw new Error('Input must be an array.')
const response = await _this.axios.post(
`${this.restURL}slp/hydrateUtxosWL`,
{
utxos: utxos
},
_this.axiosOptions
)
return response.data
} catch (error) {
if (error.response && error.response.data) throw error.response.data
else throw error
}
}
/**
* @api SLP.Utils.getStatus() getStatus()
* @apiName getStatus
@@ -8,7 +8,7 @@
const chai = require('chai')
const assert = chai.assert
const BCHJS = require('../../../../src/bch-js')
const bchjs = new BCHJS()
const bchjs = new BCHJS({ restURL: process.env.RESTURL })
// Inspect utility used for debugging.
const util = require('util')
@@ -44,6 +44,7 @@ describe('#rawtransaction', () => {
assert.hasAllKeys(err, ['error'])
assert.include(err.error, 'bad-txns-inputs-missingorspent')
// assert.include(err.error, 'Missing inputs')
}
})
@@ -61,6 +62,7 @@ describe('#rawtransaction', () => {
assert.hasAllKeys(err, ['error'])
assert.include(err.error, 'bad-txns-inputs-missingorspent')
// assert.include(err.error, 'Missing inputs')
}
})
})
+4 -1
View File
@@ -27,7 +27,7 @@ describe('#SLP', () => {
// Introduce a delay so that the BVT doesn't trip the rate limits.
if (process.env.IS_USING_FREE_TIER) await sleep(1000)
bchjs = new BCHJS()
bchjs = new BCHJS({ restURL: process.env.RESTURL })
})
describe('#util', () => {
@@ -113,6 +113,7 @@ describe('#SLP', () => {
// Token send on BCHN network
assert.equal(data[4].tx_hash, utxos[4].tx_hash)
// assert.equal(data[4].isValid, true)
assert.equal(data[4].isValid, null)
// Token send on ABC network
@@ -180,6 +181,7 @@ describe('#SLP', () => {
assert.equal(result[0].valid, null)
assert.equal(result[1].valid, null)
assert.equal(result[2].valid, true)
// assert.equal(result[2].valid, null)
assert.equal(result[3].valid, true)
assert.equal(result[4].valid, null)
})
@@ -209,6 +211,7 @@ describe('#SLP', () => {
assert.equal(result[0].valid, null)
assert.equal(result[1].valid, null)
assert.equal(result[2].valid, true)
// assert.equal(result[2].valid, null)
assert.equal(result[3].valid, true)
assert.equal(result[4].valid, null)
assert.equal(result[5].valid, true)
+93
View File
@@ -766,6 +766,99 @@ describe('#SLP', () => {
})
})
describe('#hydrateUtxosWL', () => {
it('should hydrate UTXOs', async () => {
const utxos = [
{
utxos: [
{
txid:
'89b3f0c84efe8b01b24e2d7ac08636de5781f31dbb84478e3de868ca0a7ed93a',
vout: 1,
value: 546
}
]
}
]
const result = await bchjs.SLP.Utils.hydrateUtxosWL(utxos)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Test the general structure of the output.
assert.isArray(result.slpUtxos)
assert.equal(result.slpUtxos.length, 1)
assert.equal(result.slpUtxos[0].utxos.length, 1)
// Test the non-slp UTXO.
assert.property(result.slpUtxos[0].utxos[0], 'txid')
assert.property(result.slpUtxos[0].utxos[0], 'vout')
assert.property(result.slpUtxos[0].utxos[0], 'value')
assert.property(result.slpUtxos[0].utxos[0], 'isValid')
assert.equal(result.slpUtxos[0].utxos[0].isValid, true)
})
it('should process data directly from Electrumx', async () => {
const addrs = [
'bitcoincash:qqnt53cfw990u6y38xgezm0lfa8hknw0wueezcpagp',
'bitcoincash:qrh3qgtax6adegzc7zxm6m4sgrv9wq28yqnfn33ce5',
'bitcoincash:qqcaee5w4ws77n8s2gzy6fwtma6uxd7ctq8553e495'
]
const utxos = await bchjs.Electrumx.utxo(addrs)
// console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
const result = await bchjs.SLP.Utils.hydrateUtxosWL(utxos.utxos)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
// Test the general structure of the output.
assert.isArray(result.slpUtxos)
assert.equal(result.slpUtxos.length, 3)
assert.equal(result.slpUtxos[0].utxos.length, 1)
assert.equal(result.slpUtxos[1].utxos.length, 1)
assert.equal(result.slpUtxos[2].utxos.length, 2)
try {
// Test the expected values.
assert.equal(result.slpUtxos[0].utxos[0].isValid, false)
assert.equal(result.slpUtxos[1].utxos[0].isValid, true)
assert.equal(result.slpUtxos[1].utxos[0].tokenTicker, 'TROUT')
assert.equal(result.slpUtxos[2].utxos[0].isValid, false)
// assert.equal(result.slpUtxos[2].utxos[1].isValid, null)
assert.equal(result.slpUtxos[2].utxos[1].tokenTicker, 'VALENTINE')
} catch (err) {
console.error(
'The hydrateUtxos call may hitting rate limits, or SLPDB may be having issues if "isValid" results are "null"'
)
console.log('Error: ', err)
}
})
it('should handle null SLPDB validations', async () => {
const utxos = [
{
height: 665577,
tx_hash:
'4b89405c54d1c0bde8aa476a47561a42a6e7a5e927daa2ec69d428810eae3419',
tx_pos: 1,
value: 546
},
{
height: 665577,
tx_hash:
'f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a',
tx_pos: 1,
value: 546
}
]
const data = await bchjs.SLP.Utils.hydrateUtxosWL([{ utxos: utxos }])
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
assert.isArray(data.slpUtxos)
assert.equal(data.slpUtxos[0].isValid, null)
})
})
describe('#validateTxid', () => {
// This test is not necessary.
it('should handle a null response from SLPDB', async () => {
+15
View File
@@ -1716,6 +1716,21 @@ describe('#SLP Utils', () => {
})
})
describe('#hydrateUtxosWL', () => {
it('should throw an error if input is not an array', async () => {
try {
const utxos = 1234
await uut.Utils.hydrateUtxosWL(utxos)
assert.equal(true, false, 'Uh oh. Code path should not end here.')
} catch (err) {
// console.log(`Error: `, err)
assert.include(err.message, 'Input must be an array.')
}
})
})
describe('#validateTxid2', () => {
it('should throw an error if the input is an array', async () => {
try {