@psf/bch-js 5.1.0 → 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/bch-js.js +0 -4
- package/src/psf-slp-indexer.js +46 -7
- package/src/slp/utils.js +1 -1
- package/src/utxo.js +219 -6
- package/test/integration/chains/abc/utxo-integration.js +5 -3
- package/test/integration/chains/bchn/psf-slp-indexer.integration.js +20 -4
- package/test/integration/chains/bchn/transaction-integration.js +28 -0
- package/test/integration/chains/bchn/utxo-integration.js +179 -78
- package/test/integration/transaction-integration.js +58 -56
- package/test/unit/fixtures/psf-slp-indexer-mock.js +37 -14
- package/test/unit/fixtures/utxo-mocks.js +205 -1
- package/test/unit/psf-slp-indexer.js +75 -0
- package/test/unit/utxo-unit.js +117 -7
- package/src/ninsight.js +0 -319
- package/test/unit/fixtures/ninsight-mock.js +0 -170
- package/test/unit/ninsight.js +0 -255
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@psf/bch-js",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.3",
|
|
4
4
|
"description": "The FullStack.cash JavaScript library for Bitcoin Cash and SLP Tokens",
|
|
5
5
|
"author": "Chris Troutner <chris.troutner@gmail.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"test:integration:local:abc": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration && mocha --timeout 30000 test/integration/chains/abc/",
|
|
19
19
|
"test:integration:local:bchn": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
|
|
20
20
|
"test:integration:local:testnet": "RESTURL=http://localhost:4000/v5/ mocha --timeout 30000 test/integration/chains/testnet",
|
|
21
|
-
"test:integration:decatur:bchn": "export RESTURL=http://192.168.2.
|
|
21
|
+
"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/",
|
|
22
22
|
"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/",
|
|
23
23
|
"test:integration:temp:bchn": "export RESTURL=http://157.90.174.219:3000/v5/ && mocha --timeout 30000 test/integration/",
|
|
24
24
|
"test:temp": "export RESTURL=http://localhost:3000/v5/ && mocha --timeout 30000 -g '#Encryption' test/integration/",
|
package/src/bch-js.js
CHANGED
|
@@ -36,7 +36,6 @@ const DSProof = require('./dsproof')
|
|
|
36
36
|
const Ecash = require('./ecash')
|
|
37
37
|
|
|
38
38
|
// Indexers
|
|
39
|
-
const Ninsight = require('./ninsight')
|
|
40
39
|
const Electrumx = require('./electrumx')
|
|
41
40
|
const PsfSlpIndexer = require('./psf-slp-indexer')
|
|
42
41
|
|
|
@@ -83,9 +82,6 @@ class BCHJS {
|
|
|
83
82
|
|
|
84
83
|
// console.log(`apiToken: ${this.apiToken}`)
|
|
85
84
|
|
|
86
|
-
// Bitcoin.com Ninsight indexer
|
|
87
|
-
this.Ninsight = new Ninsight(config)
|
|
88
|
-
|
|
89
85
|
// ElectrumX indexer
|
|
90
86
|
this.Electrumx = new Electrumx(libConfig)
|
|
91
87
|
|
package/src/psf-slp-indexer.js
CHANGED
|
@@ -11,11 +11,12 @@ const axios = require('axios')
|
|
|
11
11
|
|
|
12
12
|
// Local libraries
|
|
13
13
|
const RawTransaction = require('./raw-transactions')
|
|
14
|
+
const SlpUtils = require('./slp/utils')
|
|
14
15
|
|
|
15
16
|
// let _this
|
|
16
17
|
|
|
17
18
|
class PsfSlpIndexer {
|
|
18
|
-
constructor (config) {
|
|
19
|
+
constructor (config = {}) {
|
|
19
20
|
this.restURL = config.restURL
|
|
20
21
|
this.apiToken = config.apiToken
|
|
21
22
|
this.authToken = config.authToken
|
|
@@ -38,6 +39,7 @@ class PsfSlpIndexer {
|
|
|
38
39
|
|
|
39
40
|
// Encapsulate dependencies
|
|
40
41
|
this.rawTransaction = new RawTransaction(config)
|
|
42
|
+
this.slpUtils = new SlpUtils(config)
|
|
41
43
|
|
|
42
44
|
// _this = this
|
|
43
45
|
}
|
|
@@ -130,6 +132,8 @@ class PsfSlpIndexer {
|
|
|
130
132
|
*/
|
|
131
133
|
async balance (address) {
|
|
132
134
|
try {
|
|
135
|
+
// console.log('balance() address: ', address)
|
|
136
|
+
|
|
133
137
|
// Handle single address.
|
|
134
138
|
if (typeof address === 'string') {
|
|
135
139
|
const response = await axios.post(
|
|
@@ -308,16 +312,18 @@ class PsfSlpIndexer {
|
|
|
308
312
|
// 'TX not found in psf-slp-indexer. Retrieving from full node.'
|
|
309
313
|
// )
|
|
310
314
|
|
|
315
|
+
// Check if this txid belongs to a blacklisted token.
|
|
316
|
+
const isInBlacklist = await this.checkBlacklist(txid)
|
|
317
|
+
|
|
311
318
|
// Get the TX Details from the full node.
|
|
312
319
|
const txDetails = await this.rawTransaction.getTxData(txid)
|
|
313
320
|
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
|
|
314
321
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
txDetails.isValidSlp = false
|
|
322
|
+
if (isInBlacklist) {
|
|
323
|
+
txDetails.isValidSlp = null
|
|
324
|
+
} else {
|
|
325
|
+
txDetails.isValidSlp = false
|
|
326
|
+
}
|
|
321
327
|
|
|
322
328
|
const outObj = {
|
|
323
329
|
txData: txDetails
|
|
@@ -327,6 +333,39 @@ class PsfSlpIndexer {
|
|
|
327
333
|
} else throw error
|
|
328
334
|
}
|
|
329
335
|
}
|
|
336
|
+
|
|
337
|
+
// Check if the txid has an OP_RETURN containing a tokenID that is in the
|
|
338
|
+
// blacklist. In that case, the isValidSlp property should be marked as
|
|
339
|
+
// null, and not false.
|
|
340
|
+
async checkBlacklist (txid) {
|
|
341
|
+
try {
|
|
342
|
+
// TODO: Add endpoint to psf-slp-indexer to retrieve current blacklist.
|
|
343
|
+
// This should be done once at startup, and not each time this function
|
|
344
|
+
// is called.
|
|
345
|
+
const blacklist = [
|
|
346
|
+
'dd21be4532d93661e8ffe16db6535af0fb8ee1344d1fef81a193e2b4cfa9fbc9'
|
|
347
|
+
]
|
|
348
|
+
|
|
349
|
+
const outTokenData = await this.slpUtils.decodeOpReturn(txid)
|
|
350
|
+
// console.log('outTokenData: ', outTokenData)
|
|
351
|
+
|
|
352
|
+
// Loop through each token in the blacklist.
|
|
353
|
+
for (let i = 0; i < blacklist.length; i++) {
|
|
354
|
+
// If a match is found, return true.
|
|
355
|
+
if (outTokenData.tokenId === blacklist[i]) {
|
|
356
|
+
return true
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// By default, return false.
|
|
361
|
+
return false
|
|
362
|
+
} catch (err) {
|
|
363
|
+
// console.log(err)
|
|
364
|
+
|
|
365
|
+
// Exit quietly.
|
|
366
|
+
return false
|
|
367
|
+
}
|
|
368
|
+
}
|
|
330
369
|
}
|
|
331
370
|
|
|
332
371
|
module.exports = PsfSlpIndexer
|
package/src/slp/utils.js
CHANGED
package/src/utxo.js
CHANGED
|
@@ -8,19 +8,23 @@
|
|
|
8
8
|
// Local libraries
|
|
9
9
|
const Electrumx = require('./electrumx')
|
|
10
10
|
const Slp = require('./slp/slp')
|
|
11
|
+
const PsfSlpIndexer = require('./psf-slp-indexer')
|
|
12
|
+
const BigNumber = require('bignumber.js')
|
|
11
13
|
|
|
12
14
|
class UTXO {
|
|
13
|
-
constructor (config) {
|
|
15
|
+
constructor (config = {}) {
|
|
14
16
|
// Encapsulate dependencies for easier mocking.
|
|
15
17
|
this.electrumx = new Electrumx(config)
|
|
16
18
|
this.slp = new Slp(config)
|
|
19
|
+
this.psfSlpIndexer = new PsfSlpIndexer(config)
|
|
20
|
+
this.BigNumber = BigNumber
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
/**
|
|
20
|
-
* @api Utxo.
|
|
21
|
-
* @apiName
|
|
24
|
+
* @api Utxo.getOld() getOld()
|
|
25
|
+
* @apiName getOld
|
|
22
26
|
* @apiGroup UTXO
|
|
23
|
-
* @apiDescription Get UTXOs for an address
|
|
27
|
+
* @apiDescription Get UTXOs for an address (from SLPDB)
|
|
24
28
|
*
|
|
25
29
|
* Given an address, this function will return an object with thre following
|
|
26
30
|
* properties:
|
|
@@ -45,7 +49,7 @@ class UTXO {
|
|
|
45
49
|
* @apiExample Example usage:
|
|
46
50
|
* (async () => {
|
|
47
51
|
* try {
|
|
48
|
-
* let utxos = await bchjs.Utxo.
|
|
52
|
+
* let utxos = await bchjs.Utxo.getOld('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
|
|
49
53
|
* console.log(utxos);
|
|
50
54
|
* } catch(error) {
|
|
51
55
|
* console.error(error)
|
|
@@ -181,7 +185,7 @@ class UTXO {
|
|
|
181
185
|
*
|
|
182
186
|
*
|
|
183
187
|
*/
|
|
184
|
-
async
|
|
188
|
+
async getOld (address, useWhitelist = false) {
|
|
185
189
|
try {
|
|
186
190
|
if (!address) {
|
|
187
191
|
throw new Error('Address must be an array or a string')
|
|
@@ -286,6 +290,215 @@ class UTXO {
|
|
|
286
290
|
}
|
|
287
291
|
}
|
|
288
292
|
|
|
293
|
+
/**
|
|
294
|
+
* @api Utxo.get() get()
|
|
295
|
+
* @apiName get
|
|
296
|
+
* @apiGroup UTXO
|
|
297
|
+
* @apiDescription Get UTXOs for an address (from psf-slp-indexer)
|
|
298
|
+
*
|
|
299
|
+
* Given an address, this function will return an object with thre following
|
|
300
|
+
* properties:
|
|
301
|
+
* - address: "" - the address these UTXOs are associated with
|
|
302
|
+
* - bchUtxos: [] - UTXOs confirmed to be spendable as normal BCH
|
|
303
|
+
* - nullUtxo: [] - UTXOs that did not pass SLP validation. Should be ignored and
|
|
304
|
+
* not spent, to be safe.
|
|
305
|
+
* - slpUtxos: {} - UTXOs confirmed to be colored as valid SLP tokens
|
|
306
|
+
* - type1: {}
|
|
307
|
+
* - tokens: [] - SLP token Type 1 tokens.
|
|
308
|
+
* - mintBatons: [] - SLP token Type 1 mint batons.
|
|
309
|
+
* - nft: {}
|
|
310
|
+
* - tokens: [] - NFT tokens
|
|
311
|
+
* - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
|
|
312
|
+
* - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
|
|
313
|
+
*
|
|
314
|
+
*
|
|
315
|
+
* @apiExample Example usage:
|
|
316
|
+
* (async () => {
|
|
317
|
+
* try {
|
|
318
|
+
* let utxos = await bchjs.Utxo.get('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
|
|
319
|
+
* console.log(utxos);
|
|
320
|
+
* } catch(error) {
|
|
321
|
+
* console.error(error)
|
|
322
|
+
* }
|
|
323
|
+
* })()
|
|
324
|
+
*
|
|
325
|
+
* // returns
|
|
326
|
+
* [
|
|
327
|
+
* {
|
|
328
|
+
* "address": "bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv",
|
|
329
|
+
* "bchUtxos": [
|
|
330
|
+
* {
|
|
331
|
+
* "height": 674513,
|
|
332
|
+
* "tx_hash": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
|
|
333
|
+
* "tx_pos": 3,
|
|
334
|
+
* "value": 38134,
|
|
335
|
+
* "txid": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
|
|
336
|
+
* "vout": 3,
|
|
337
|
+
* "isValid": false
|
|
338
|
+
* }
|
|
339
|
+
* ],
|
|
340
|
+
*/
|
|
341
|
+
// This version of get() uses the psf-slp-indexer. It will replace the older
|
|
342
|
+
// get() function that uses SLPDB.
|
|
343
|
+
// TODO: NFT UTXOs are identified as non-token UTXOs, which will cause a wallet
|
|
344
|
+
// to burn them. The psf-slp-indexer needs to be updated to mark these UTXOs.
|
|
345
|
+
async get (address) {
|
|
346
|
+
try {
|
|
347
|
+
// Convert address to an array if it is a string.
|
|
348
|
+
if (typeof address !== 'string') {
|
|
349
|
+
throw new Error('address input must be a string')
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Ensure the address is a BCH address.
|
|
353
|
+
const addr = this.slp.Address.toCashAddress(address)
|
|
354
|
+
|
|
355
|
+
// Get the UTXOs associated with the address.
|
|
356
|
+
const utxoData = await this.electrumx.utxo(addr)
|
|
357
|
+
// console.log(`utxoData: ${JSON.stringify(utxoData, null, 2)}`)
|
|
358
|
+
const utxos = utxoData.utxos
|
|
359
|
+
|
|
360
|
+
let slpUtxos = []
|
|
361
|
+
|
|
362
|
+
// Get SLP UTXOs from the psf-slp-indexer
|
|
363
|
+
try {
|
|
364
|
+
const slpUtxoData = await this.psfSlpIndexer.balance(addr)
|
|
365
|
+
// console.log(`slpUtxoData: ${JSON.stringify(slpUtxoData, null, 2)}`)
|
|
366
|
+
|
|
367
|
+
slpUtxos = slpUtxoData.balance.utxos
|
|
368
|
+
} catch (err) {
|
|
369
|
+
// console.log('err: ', err)
|
|
370
|
+
|
|
371
|
+
// Exit quietly if address has no SLP UTXOs. Otherwise, throw the error.
|
|
372
|
+
if (err.error && !err.error.includes('Key not found in database')) {
|
|
373
|
+
throw err
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Loop through the Fulcrum UTXOs.
|
|
378
|
+
for (let i = 0; i < utxos.length; i++) {
|
|
379
|
+
const thisUtxo = utxos[i]
|
|
380
|
+
|
|
381
|
+
// Loop through the UTXOs from psf-slp-indexer.
|
|
382
|
+
for (let j = 0; j < slpUtxos.length; j++) {
|
|
383
|
+
const thisSlpUtxo = slpUtxos[j]
|
|
384
|
+
|
|
385
|
+
// If the non-hydrated UTXO matches the SLP UTXO, then combine the data
|
|
386
|
+
// and mark the UTXO as an SLP token.
|
|
387
|
+
if (
|
|
388
|
+
thisUtxo.tx_hash === thisSlpUtxo.txid &&
|
|
389
|
+
thisUtxo.tx_pos === thisSlpUtxo.vout
|
|
390
|
+
) {
|
|
391
|
+
thisUtxo.txid = thisUtxo.tx_hash
|
|
392
|
+
thisUtxo.vout = thisUtxo.tx_pos
|
|
393
|
+
thisUtxo.isSlp = true
|
|
394
|
+
thisUtxo.type = thisSlpUtxo.type
|
|
395
|
+
thisUtxo.qty = thisSlpUtxo.qty
|
|
396
|
+
thisUtxo.tokenId = thisSlpUtxo.tokenId
|
|
397
|
+
thisUtxo.address = thisSlpUtxo.address
|
|
398
|
+
|
|
399
|
+
break
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// If there was no match, then this is a normal BCH UTXO. Mark it as such.
|
|
404
|
+
if (!thisUtxo.isSlp) {
|
|
405
|
+
thisUtxo.txid = thisUtxo.tx_hash
|
|
406
|
+
thisUtxo.vout = thisUtxo.tx_pos
|
|
407
|
+
thisUtxo.isSlp = false
|
|
408
|
+
thisUtxo.address = addr
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Get token UTXOs
|
|
413
|
+
let type1TokenUtxos = utxos.filter(
|
|
414
|
+
x => x.isSlp === true && x.type === 'token'
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
// Hydrate the UTXOs with additional token data.
|
|
418
|
+
type1TokenUtxos = await this.hydrateTokenData(type1TokenUtxos)
|
|
419
|
+
|
|
420
|
+
const bchUtxos = utxos.filter(x => x.isSlp === false)
|
|
421
|
+
const type1BatonUtxos = utxos.filter(
|
|
422
|
+
x => x.isSlp === true && x.type === 'baton'
|
|
423
|
+
)
|
|
424
|
+
const nullUtxos = utxos.filter(x => x.isSlp === null)
|
|
425
|
+
|
|
426
|
+
const outObj = {
|
|
427
|
+
address: addr,
|
|
428
|
+
bchUtxos,
|
|
429
|
+
slpUtxos: {
|
|
430
|
+
type1: {
|
|
431
|
+
tokens: type1TokenUtxos,
|
|
432
|
+
mintBatons: type1BatonUtxos
|
|
433
|
+
},
|
|
434
|
+
nft: {} // Allocated for future support of NFT spec.
|
|
435
|
+
},
|
|
436
|
+
nullUtxos
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return outObj
|
|
440
|
+
} catch (err) {
|
|
441
|
+
// console.error('Error in bchjs.utxo.get2(): ', err)
|
|
442
|
+
|
|
443
|
+
if (err.error) throw new Error(err.error)
|
|
444
|
+
throw err
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Hydrate an array of token UTXOs with token information.
|
|
449
|
+
// Returns an array of token UTXOs with additional data.
|
|
450
|
+
async hydrateTokenData (utxoAry) {
|
|
451
|
+
try {
|
|
452
|
+
// console.log('utxoAry: ', utxoAry)
|
|
453
|
+
|
|
454
|
+
// Create a list of token IDs without duplicates.
|
|
455
|
+
let tokenIds = utxoAry.map(x => x.tokenId)
|
|
456
|
+
|
|
457
|
+
// Remove duplicates. https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array
|
|
458
|
+
tokenIds = [...new Set(tokenIds)]
|
|
459
|
+
// console.log('tokenIds: ', tokenIds)
|
|
460
|
+
|
|
461
|
+
// Get Genesis data for each tokenId
|
|
462
|
+
const genesisData = []
|
|
463
|
+
for (let i = 0; i < tokenIds.length; i++) {
|
|
464
|
+
const thisTokenId = tokenIds[i]
|
|
465
|
+
const thisTokenData = await this.psfSlpIndexer.tokenStats(thisTokenId)
|
|
466
|
+
// console.log('thisTokenData: ', thisTokenData)
|
|
467
|
+
|
|
468
|
+
genesisData.push(thisTokenData)
|
|
469
|
+
}
|
|
470
|
+
// console.log('genesisData: ', genesisData)
|
|
471
|
+
|
|
472
|
+
// Hydrate each token UTXO with data from the genesis transaction.
|
|
473
|
+
for (let i = 0; i < utxoAry.length; i++) {
|
|
474
|
+
const thisUtxo = utxoAry[i]
|
|
475
|
+
|
|
476
|
+
// Get the genesis data for this token.
|
|
477
|
+
const genData = genesisData.filter(
|
|
478
|
+
x => x.tokenData.tokenId === thisUtxo.tokenId
|
|
479
|
+
)
|
|
480
|
+
// console.log('genData: ', genData)
|
|
481
|
+
|
|
482
|
+
thisUtxo.ticker = genData[0].tokenData.ticker
|
|
483
|
+
thisUtxo.name = genData[0].tokenData.name
|
|
484
|
+
thisUtxo.documentUri = genData[0].tokenData.documentUri
|
|
485
|
+
thisUtxo.documentHash = genData[0].tokenData.documentHash
|
|
486
|
+
thisUtxo.decimals = genData[0].tokenData.decimals
|
|
487
|
+
|
|
488
|
+
// Calculate the real token quantity
|
|
489
|
+
const qty = new BigNumber(thisUtxo.qty).dividedBy(
|
|
490
|
+
10 ** parseInt(thisUtxo.decimals)
|
|
491
|
+
)
|
|
492
|
+
thisUtxo.qtyStr = qty.toString()
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return utxoAry
|
|
496
|
+
} catch (err) {
|
|
497
|
+
console.log('Error in hydrateTokenData()')
|
|
498
|
+
throw err
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
289
502
|
/**
|
|
290
503
|
* @api Utxo.findBiggestUtxo() findBiggestUtxo()
|
|
291
504
|
* @apiName findBiggestUtxo
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Integration tests for the utxo.js library.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const assert = require('chai').assert
|
|
5
|
+
// const assert = require('chai').assert
|
|
6
6
|
|
|
7
|
-
const BCHJS = require('../../../../src/bch-js')
|
|
8
|
-
const bchjs = new BCHJS()
|
|
7
|
+
// const BCHJS = require('../../../../src/bch-js')
|
|
8
|
+
// const bchjs = new BCHJS()
|
|
9
9
|
|
|
10
10
|
describe('#UTXO', () => {
|
|
11
11
|
beforeEach(async () => {
|
|
@@ -14,6 +14,7 @@ describe('#UTXO', () => {
|
|
|
14
14
|
if (process.env.IS_USING_FREE_TIER) await sleep(1500)
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
+
/*
|
|
17
18
|
describe('#get', () => {
|
|
18
19
|
it('should get hydrated and filtered UTXOs for an address', async () => {
|
|
19
20
|
// const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
|
@@ -31,6 +32,7 @@ describe('#UTXO', () => {
|
|
|
31
32
|
assert.isArray(result[0].nullUtxos)
|
|
32
33
|
})
|
|
33
34
|
})
|
|
35
|
+
*/
|
|
34
36
|
})
|
|
35
37
|
|
|
36
38
|
function sleep (ms) {
|
|
@@ -56,7 +56,7 @@ describe('#psf-slp-indexer', () => {
|
|
|
56
56
|
describe('#tx', () => {
|
|
57
57
|
it('should get hydrated tx data for an SLP transaction', async () => {
|
|
58
58
|
const txid =
|
|
59
|
-
'
|
|
59
|
+
'947ccb2a0d62ca287bc4b0993874ab0f9f6afd454193e631e2bf84dca66731fc'
|
|
60
60
|
|
|
61
61
|
const result = await bchjs.PsfSlpIndexer.tx(txid)
|
|
62
62
|
// console.log('result: ', result)
|
|
@@ -67,7 +67,7 @@ describe('#psf-slp-indexer', () => {
|
|
|
67
67
|
assert.equal(result.txData.isValidSlp, true)
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
-
it('should
|
|
70
|
+
it('should mark non-SLP transaction as false', async () => {
|
|
71
71
|
const txid =
|
|
72
72
|
'03d6e6b63647ce7b02ecc73dc6d41b485be14a3e20eed4474b8a840358ddf14e'
|
|
73
73
|
|
|
@@ -84,7 +84,7 @@ describe('#psf-slp-indexer', () => {
|
|
|
84
84
|
// Currently FlexUSD UTXOs are reported as invalid SLP UTXOs, which means
|
|
85
85
|
// the wallet will burn them. There is a TODO in the code. This test will
|
|
86
86
|
// need to be changed when it is done.
|
|
87
|
-
it('should
|
|
87
|
+
it('should mark blacklisted token as null', async () => {
|
|
88
88
|
const txid =
|
|
89
89
|
'302113c11b90edc5f36c073d2f8a75e1e0eaf59b56235491a843d3819cd6a85f'
|
|
90
90
|
|
|
@@ -94,7 +94,23 @@ describe('#psf-slp-indexer', () => {
|
|
|
94
94
|
assert.property(result.txData, 'vin')
|
|
95
95
|
assert.property(result.txData, 'vout')
|
|
96
96
|
assert.property(result.txData, 'isValidSlp')
|
|
97
|
-
assert.equal(result.txData.isValidSlp,
|
|
97
|
+
assert.equal(result.txData.isValidSlp, null)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('should throw error for non-existent txid', async () => {
|
|
101
|
+
try {
|
|
102
|
+
const txid =
|
|
103
|
+
'302113c11b90edc5f36c073d2f8a75e1e0eaf59b56235491a843d3819cd6a85e'
|
|
104
|
+
|
|
105
|
+
await bchjs.PsfSlpIndexer.tx(txid)
|
|
106
|
+
// console.log('result: ', result)
|
|
107
|
+
|
|
108
|
+
assert.fail('Unexpected code path')
|
|
109
|
+
} catch (err) {
|
|
110
|
+
// console.log(err)
|
|
111
|
+
|
|
112
|
+
assert.include(err.message, 'No such mempool or blockchain transaction')
|
|
113
|
+
}
|
|
98
114
|
})
|
|
99
115
|
})
|
|
100
116
|
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Integration tests for the transaction.js library.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const assert = require('chai').assert
|
|
6
|
+
const BCHJS = require('../../../../src/bch-js')
|
|
7
|
+
const bchjs = new BCHJS()
|
|
8
|
+
|
|
9
|
+
describe('#Transaction', () => {
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
if (process.env.IS_USING_FREE_TIER) await bchjs.Util.sleep(1000)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('#get', () => {
|
|
15
|
+
it('should get a tx details for a non-SLP TX with an OP_RETURN', async () => {
|
|
16
|
+
const txid =
|
|
17
|
+
'01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b'
|
|
18
|
+
|
|
19
|
+
const result = await bchjs.Transaction.get(txid)
|
|
20
|
+
// console.log('result: ', result)
|
|
21
|
+
|
|
22
|
+
assert.property(result.txData, 'txid')
|
|
23
|
+
assert.property(result.txData, 'vin')
|
|
24
|
+
assert.property(result.txData, 'vout')
|
|
25
|
+
assert.equal(result.txData.isValidSlp, false)
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
})
|