Compare commits

...
13 Commits
Author SHA1 Message Date
Chris Troutner 02e3ff4dcd Merge pull request #216 from Permissionless-Software-Foundation/ct-unstable
fix(psf-slp-indexer): Adding flag for tx history of tokens
2022-02-06 13:26:05 -08:00
Chris Troutner 64f8adea25 fix(psf-slp-indexer): Adding flag for tx history of tokens 2022-02-06 13:23:25 -08:00
Chris Troutner bcf817f5c7 Merge pull request #215 from Permissionless-Software-Foundation/ct-unstable
Fixing integration test
2022-01-31 21:22:25 -08:00
Chris Troutner 541377e548 Fixing integration test 2022-01-31 21:18:08 -08:00
Chris Troutner 84b44b299a Merge pull request #214 from Permissionless-Software-Foundation/ct-unstable
fix(UTXO.get()): Added detection of null-tagged UTXOs
2022-01-31 21:13:50 -08:00
Chris Troutner b6456df1f4 Fixing unit tests 2022-01-31 21:11:11 -08:00
Chris Troutner b1826c04cb fix(UTXO.get()): Added detection of null-tagged UTXOs 2022-01-31 20:57:36 -08:00
Chris Troutner 71755964c8 Merge pull request #213 from Permissionless-Software-Foundation/ct-unstable
Adding Util.chunk100()
2022-01-27 17:39:47 -08:00
Chris Troutner bd1c3b622d feat(chunk100): Adding chunk100 which works just like chunk20 2022-01-27 17:37:20 -08:00
Chris Troutner bdced13230 fix(Electrumx): Added commented code for debugging sorting 2022-01-27 08:52:12 -08:00
Chris Troutner c925bfce46 Merge pull request #212 from Permissionless-Software-Foundation/ct-unstable
Integration Test Maintenance
2022-01-23 07:11:32 -08:00
Chris Troutner 056a47f6b2 fix(integration tests): Got BCHN and ABC integration tests passing 2022-01-23 07:08:41 -08:00
Chris Troutner 51038681d3 fix(transaction.js): Added integrationt test 2022-01-23 06:46:06 -08:00
10 changed files with 146 additions and 13 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
"test:integration:local:abc": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
"test:integration:local:bchn": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v5/ mocha --timeout 30000 test/integration/chains/testnet",
"test:integration:decatur:bchn": "export RESTURL=http://192.168.2.139:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:decatur:bchn": "export RESTURL=http://192.168.2.129:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
"test:integration:decatur:abc": "export RESTURL=http://192.168.2.141:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
"test:integration:temp:bchn": "export RESTURL=http://157.90.174.219:3000/v5/ && mocha --timeout 30000 test/integration/",
"test:temp": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 -g '#Encryption' test/integration/",
+15 -2
View File
@@ -638,13 +638,24 @@ class ElectrumX {
// Sort confirmed Transactions by the block height
sortConfTxs (txs, sortingOrder = 'DESCENDING') {
try {
// console.log(`sortConfTxs txs: ${JSON.stringify(txs, null, 2)}`)
// Filter out unconfirmed transactions, with a height of 0 or less.
txs = txs.filter(elem => elem.height > 0)
if (sortingOrder === 'DESCENDING') {
return txs.sort((a, b) => b.height - a.height)
// console.log('Sorting in descending order')
return txs.sort((a, b) => {
// console.log(`descending b.height: ${b.height}, a.height: ${a.height}`)
return b.height - a.height
})
}
return txs.sort((a, b) => a.height - b.height)
// console.log('Sorting in ascending order')
return txs.sort((a, b) => {
// console.log(`ascending b.height: ${b.height}, a.height: ${a.height}`)
return a.height - b.height
})
} catch (err) {
console.log('Error in util.js/sortConfTxs()')
throw err
@@ -685,6 +696,8 @@ class ElectrumX {
// Substitute zero-conf txs with the current block-height + 1
async sortAllTxs (txs, sortingOrder = 'DESCENDING') {
try {
// console.log(`sortingOrder: ${sortingOrder}`)
// Calculate the height of the next block
const nextBlock = (await this.blockchain.getBlockCount()) + 1
+5 -3
View File
@@ -155,11 +155,13 @@ class PsfSlpIndexer {
* @apiName Token Stats
* @apiGroup PSF SLP
* @apiDescription Return list stats for a single slp token.
* The second input is a Boolean, which determins the the transaction history
* of the token is included in the returned data. The default is false.
*
* @apiExample Example usage:
* (async () => {
* try {
* let tokenStats = await bchjs.PsfSlpIndexer.tokenStats('a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2');
* let tokenStats = await bchjs.PsfSlpIndexer.tokenStats('a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2', true);
* console.log(tokenStats);
* } catch(error) {
* console.error(error)
@@ -194,13 +196,13 @@ class PsfSlpIndexer {
*
*/
async tokenStats (tokenId) {
async tokenStats (tokenId, withTxHistory = false) {
try {
// Handle single address.
if (typeof tokenId === 'string') {
const response = await axios.post(
`${this.restURL}psf/slp/token`,
{ tokenId },
{ tokenId, withTxHistory },
this.axiosOptions
)
return response.data
+50
View File
@@ -150,6 +150,56 @@ class Util {
}
}
/**
* @api Util.chunk100() chunk100()
* @apiName chunk100
* @apiGroup Util
* @apiDescription chunk up an array into multiple arrays of 100 elements each.
* Input: arrayToSlice - a one-dimensional array of elements.
* Returns a two-dimensional array. An array of 100-element arrays.
*
* @apiExample Example usage:
* (async () => {
* try {
* const bigArray = [0,1,2,3,4,5,6,7,8,9,10,...,148, 149, 150]
*
* const chunked = bchjs.Util.chunk20(bigArray)
* console.log(chunked)
* } catch(error) {
* console.error(error)
* }
* })()
*
* // returns
* [
* [0,1,2,3,4,5,6,7,8,9,10,11,...,98,99],
* [100,101,102,...,148,149,150]
* ]
*/
chunk100 (arrayToSlice) {
try {
// Validate inputs
if (!Array.isArray(arrayToSlice)) {
throw new Error('input must be an array')
}
let offset = 0
const result = []
// Loop over the array and slice off chunks of 100 elements.
while (offset < arrayToSlice.length) {
const chunk = arrayToSlice.slice(offset, offset + 100)
result.push(chunk)
offset = offset + 100
}
return result
} catch (err) {
console.error('Error in chunk100()')
throw err
}
}
/**
* @api Util.sleep() sleep()
* @apiName sleep
+12 -2
View File
@@ -404,8 +404,18 @@ class UTXO {
if (!thisUtxo.isSlp) {
thisUtxo.txid = thisUtxo.tx_hash
thisUtxo.vout = thisUtxo.tx_pos
thisUtxo.isSlp = false
thisUtxo.address = addr
// Check the transaction to see if its a 'null' token, ignored by
// the indexer.
const txData = await this.psfSlpIndexer.tx(thisUtxo.tx_hash)
// console.log(`txData: ${JSON.stringify(txData, null, 2)}`)
if (txData.txData.isValidSlp === null) {
thisUtxo.isSlp = null
} else {
thisUtxo.isSlp = false
}
// console.log(`thisUtxo.isSlp: ${thisUtxo.isSlp}`)
}
}
@@ -438,7 +448,7 @@ class UTXO {
return outObj
} catch (err) {
// console.error('Error in bchjs.utxo.get2(): ', err)
console.error('Error in bchjs.Utxo.get(): ', err)
if (err.error) throw new Error(err.error)
throw err
@@ -2,10 +2,10 @@
Integration tests for the utxo.js library.
*/
const assert = require('chai').assert
// const assert = require('chai').assert
const BCHJS = require('../../../../src/bch-js')
const bchjs = new BCHJS()
// const BCHJS = require('../../../../src/bch-js')
// const bchjs = new BCHJS()
describe('#UTXO', () => {
beforeEach(async () => {
@@ -14,6 +14,7 @@ describe('#UTXO', () => {
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
})
/*
describe('#get', () => {
it('should get hydrated and filtered UTXOs for an address', async () => {
// const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
@@ -31,6 +32,7 @@ describe('#UTXO', () => {
assert.isArray(result[0].nullUtxos)
})
})
*/
})
function sleep (ms) {
@@ -40,13 +40,24 @@ describe('#psf-slp-indexer', () => {
})
describe('#tokenStats', () => {
it('should get stats on a token', async () => {
it('should get stats on a token, without tx history', async () => {
const tokenId =
'38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0'
const result = await bchjs.PsfSlpIndexer.tokenStats(tokenId)
// console.log('result: ', result)
assert.property(result.tokenData, 'documentUri')
assert.property(result.tokenData, 'totalBurned')
})
it('should get stats on a token, with tx history', async () => {
const tokenId =
'38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0'
const result = await bchjs.PsfSlpIndexer.tokenStats(tokenId, true)
// console.log('result: ', result)
assert.property(result.tokenData, 'documentUri')
assert.property(result.tokenData, 'txs')
assert.property(result.tokenData, 'totalBurned')
@@ -0,0 +1,28 @@
/*
Integration tests for the transaction.js library.
*/
const assert = require('chai').assert
const BCHJS = require('../../../../src/bch-js')
const bchjs = new BCHJS()
describe('#Transaction', () => {
beforeEach(async () => {
if (process.env.IS_USING_FREE_TIER) await bchjs.Util.sleep(1000)
})
describe('#get', () => {
it('should get a tx details for a non-SLP TX with an OP_RETURN', async () => {
const txid =
'01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b'
const result = await bchjs.Transaction.get(txid)
// console.log('result: ', result)
assert.property(result.txData, 'txid')
assert.property(result.txData, 'vin')
assert.property(result.txData, 'vout')
assert.equal(result.txData.isValidSlp, false)
})
})
})
@@ -6,6 +6,7 @@ const assert = require('chai').assert
const BCHJS = require('../../../../src/bch-js')
const bchjs = new BCHJS()
// const bchjs = new BCHJS({ restURL: 'http://192.168.2.129:3000/v5/' })
describe('#UTXO', () => {
beforeEach(async () => {
@@ -199,7 +200,7 @@ describe('#UTXO', () => {
// TODO: NFTs are currently not identified as different than normal BCH UTXOs.
// The psf-slp-indexer needs to be updated to fix this issue.
it('should handle NFTs and minting batons', async () => {
it('should handle minting batons', async () => {
const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
const result = await bchjs.Utxo.get(addr)
@@ -218,6 +219,15 @@ describe('#UTXO', () => {
assert.isAbove(result.bchUtxos.length, 0)
assert.equal(result.slpUtxos.type1.tokens.length, 0)
})
it('should handle Group NFTs', async () => {
const addr = 'bitcoincash:qrnghwrfgccf3s5e9wnglzxegcnhje9rkcwv2eka33'
const result = await bchjs.Utxo.get(addr)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isAbove(result.nullUtxos.length, 0)
})
})
})
+7
View File
@@ -249,6 +249,10 @@ describe('#utxo', () => {
sandbox
.stub(bchjs.Utxo.psfSlpIndexer, 'balance')
.resolves(mockData.psfSlpIndexerUtxos01)
sandbox
.stub(bchjs.Utxo.psfSlpIndexer, 'tx')
.resolves({ txData: { isValidSlp: false } })
// Mock function to return the same input. Good enough for this test.
sandbox.stub(bchjs.Utxo, 'hydrateTokenData').resolves(x => x)
@@ -278,6 +282,9 @@ describe('#utxo', () => {
sandbox
.stub(bchjs.Utxo.electrumx, 'utxo')
.resolves(mockData.fulcrumUtxos02)
sandbox
.stub(bchjs.Utxo.psfSlpIndexer, 'tx')
.resolves({ txData: { isValidSlp: false } })
// Force psf-slp-indexer to return no UTXOs
sandbox