@psf/bch-js 5.1.0 → 5.2.0
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 +1 -1
- package/src/bch-js.js +0 -4
- package/src/psf-slp-indexer.js +45 -7
- package/src/slp/utils.js +1 -1
- package/src/utxo.js +150 -6
- package/test/integration/chains/bchn/psf-slp-indexer.integration.js +20 -4
- package/test/integration/chains/bchn/utxo-integration.js +35 -1
- 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 +91 -1
- package/test/unit/psf-slp-indexer.js +75 -0
- package/test/unit/utxo-unit.js +51 -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
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,7 @@ class PsfSlpIndexer {
|
|
|
130
132
|
*/
|
|
131
133
|
async balance (address) {
|
|
132
134
|
try {
|
|
135
|
+
console.log('balance() address: ', address)
|
|
133
136
|
// Handle single address.
|
|
134
137
|
if (typeof address === 'string') {
|
|
135
138
|
const response = await axios.post(
|
|
@@ -308,16 +311,18 @@ class PsfSlpIndexer {
|
|
|
308
311
|
// 'TX not found in psf-slp-indexer. Retrieving from full node.'
|
|
309
312
|
// )
|
|
310
313
|
|
|
314
|
+
// Check if this txid belongs to a blacklisted token.
|
|
315
|
+
const isInBlacklist = await this.checkBlacklist(txid)
|
|
316
|
+
|
|
311
317
|
// Get the TX Details from the full node.
|
|
312
318
|
const txDetails = await this.rawTransaction.getTxData(txid)
|
|
313
319
|
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
|
|
314
320
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
txDetails.isValidSlp = false
|
|
321
|
+
if (isInBlacklist) {
|
|
322
|
+
txDetails.isValidSlp = null
|
|
323
|
+
} else {
|
|
324
|
+
txDetails.isValidSlp = false
|
|
325
|
+
}
|
|
321
326
|
|
|
322
327
|
const outObj = {
|
|
323
328
|
txData: txDetails
|
|
@@ -327,6 +332,39 @@ class PsfSlpIndexer {
|
|
|
327
332
|
} else throw error
|
|
328
333
|
}
|
|
329
334
|
}
|
|
335
|
+
|
|
336
|
+
// Check if the txid has an OP_RETURN containing a tokenID that is in the
|
|
337
|
+
// blacklist. In that case, the isValidSlp property should be marked as
|
|
338
|
+
// null, and not false.
|
|
339
|
+
async checkBlacklist (txid) {
|
|
340
|
+
try {
|
|
341
|
+
// TODO: Add endpoint to psf-slp-indexer to retrieve current blacklist.
|
|
342
|
+
// This should be done once at startup, and not each time this function
|
|
343
|
+
// is called.
|
|
344
|
+
const blacklist = [
|
|
345
|
+
'dd21be4532d93661e8ffe16db6535af0fb8ee1344d1fef81a193e2b4cfa9fbc9'
|
|
346
|
+
]
|
|
347
|
+
|
|
348
|
+
const outTokenData = await this.slpUtils.decodeOpReturn(txid)
|
|
349
|
+
// console.log('outTokenData: ', outTokenData)
|
|
350
|
+
|
|
351
|
+
// Loop through each token in the blacklist.
|
|
352
|
+
for (let i = 0; i < blacklist.length; i++) {
|
|
353
|
+
// If a match is found, return true.
|
|
354
|
+
if (outTokenData.tokenId === blacklist[i]) {
|
|
355
|
+
return true
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// By default, return false.
|
|
360
|
+
return false
|
|
361
|
+
} catch (err) {
|
|
362
|
+
// console.log(err)
|
|
363
|
+
|
|
364
|
+
// Exit quietly.
|
|
365
|
+
return false
|
|
366
|
+
}
|
|
367
|
+
}
|
|
330
368
|
}
|
|
331
369
|
|
|
332
370
|
module.exports = PsfSlpIndexer
|
package/src/slp/utils.js
CHANGED
package/src/utxo.js
CHANGED
|
@@ -8,19 +8,21 @@
|
|
|
8
8
|
// Local libraries
|
|
9
9
|
const Electrumx = require('./electrumx')
|
|
10
10
|
const Slp = require('./slp/slp')
|
|
11
|
+
const PsfSlpIndexer = require('./psf-slp-indexer')
|
|
11
12
|
|
|
12
13
|
class UTXO {
|
|
13
|
-
constructor (config) {
|
|
14
|
+
constructor (config = {}) {
|
|
14
15
|
// Encapsulate dependencies for easier mocking.
|
|
15
16
|
this.electrumx = new Electrumx(config)
|
|
16
17
|
this.slp = new Slp(config)
|
|
18
|
+
this.psfSlpIndexer = new PsfSlpIndexer(config)
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
|
-
* @api Utxo.
|
|
21
|
-
* @apiName
|
|
22
|
+
* @api Utxo.getOld() getOld()
|
|
23
|
+
* @apiName getOld
|
|
22
24
|
* @apiGroup UTXO
|
|
23
|
-
* @apiDescription Get UTXOs for an address
|
|
25
|
+
* @apiDescription Get UTXOs for an address (from SLPDB)
|
|
24
26
|
*
|
|
25
27
|
* Given an address, this function will return an object with thre following
|
|
26
28
|
* properties:
|
|
@@ -45,7 +47,7 @@ class UTXO {
|
|
|
45
47
|
* @apiExample Example usage:
|
|
46
48
|
* (async () => {
|
|
47
49
|
* try {
|
|
48
|
-
* let utxos = await bchjs.Utxo.
|
|
50
|
+
* let utxos = await bchjs.Utxo.getOld('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
|
|
49
51
|
* console.log(utxos);
|
|
50
52
|
* } catch(error) {
|
|
51
53
|
* console.error(error)
|
|
@@ -181,7 +183,7 @@ class UTXO {
|
|
|
181
183
|
*
|
|
182
184
|
*
|
|
183
185
|
*/
|
|
184
|
-
async
|
|
186
|
+
async getOld (address, useWhitelist = false) {
|
|
185
187
|
try {
|
|
186
188
|
if (!address) {
|
|
187
189
|
throw new Error('Address must be an array or a string')
|
|
@@ -286,6 +288,148 @@ class UTXO {
|
|
|
286
288
|
}
|
|
287
289
|
}
|
|
288
290
|
|
|
291
|
+
/**
|
|
292
|
+
* @api Utxo.get() get()
|
|
293
|
+
* @apiName get
|
|
294
|
+
* @apiGroup UTXO
|
|
295
|
+
* @apiDescription Get UTXOs for an address (from psf-slp-indexer)
|
|
296
|
+
*
|
|
297
|
+
* Given an address, this function will return an object with thre following
|
|
298
|
+
* properties:
|
|
299
|
+
* - address: "" - the address these UTXOs are associated with
|
|
300
|
+
* - bchUtxos: [] - UTXOs confirmed to be spendable as normal BCH
|
|
301
|
+
* - nullUtxo: [] - UTXOs that did not pass SLP validation. Should be ignored and
|
|
302
|
+
* not spent, to be safe.
|
|
303
|
+
* - slpUtxos: {} - UTXOs confirmed to be colored as valid SLP tokens
|
|
304
|
+
* - type1: {}
|
|
305
|
+
* - tokens: [] - SLP token Type 1 tokens.
|
|
306
|
+
* - mintBatons: [] - SLP token Type 1 mint batons.
|
|
307
|
+
* - nft: {}
|
|
308
|
+
* - tokens: [] - NFT tokens
|
|
309
|
+
* - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
|
|
310
|
+
* - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
|
|
311
|
+
*
|
|
312
|
+
* Note: You can pass in an optional second Boolean argument. The default
|
|
313
|
+
* `false` will use the normal waterfall validation method. Set to `true`,
|
|
314
|
+
* SLP UTXOs will be validated with the whitelist filtered SLPDB. This will
|
|
315
|
+
* result is many more UTXOs in the `nullUtxos` array.
|
|
316
|
+
*
|
|
317
|
+
* @apiExample Example usage:
|
|
318
|
+
* (async () => {
|
|
319
|
+
* try {
|
|
320
|
+
* let utxos = await bchjs.Utxo.get('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
|
|
321
|
+
* console.log(utxos);
|
|
322
|
+
* } catch(error) {
|
|
323
|
+
* console.error(error)
|
|
324
|
+
* }
|
|
325
|
+
* })()
|
|
326
|
+
*
|
|
327
|
+
* // returns
|
|
328
|
+
* [
|
|
329
|
+
* {
|
|
330
|
+
* "address": "bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv",
|
|
331
|
+
* "bchUtxos": [
|
|
332
|
+
* {
|
|
333
|
+
* "height": 674513,
|
|
334
|
+
* "tx_hash": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
|
|
335
|
+
* "tx_pos": 3,
|
|
336
|
+
* "value": 38134,
|
|
337
|
+
* "txid": "705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04",
|
|
338
|
+
* "vout": 3,
|
|
339
|
+
* "isValid": false
|
|
340
|
+
* }
|
|
341
|
+
* ],
|
|
342
|
+
*/
|
|
343
|
+
// This version of get() uses the psf-slp-indexer. It will replace the older
|
|
344
|
+
// get() function that uses SLPDB.
|
|
345
|
+
// TODO: NFT UTXOs are identified as non-token UTXOs, which will cause a wallet
|
|
346
|
+
// to burn them. The psf-slp-indexer needs to be updated to mark these UTXOs.
|
|
347
|
+
async get (address) {
|
|
348
|
+
try {
|
|
349
|
+
// Convert address to an array if it is a string.
|
|
350
|
+
if (typeof address !== 'string') {
|
|
351
|
+
throw new Error('address input must be a string')
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Ensure the address is a BCH address.
|
|
355
|
+
const addr = this.slp.Address.toCashAddress(address)
|
|
356
|
+
|
|
357
|
+
// Get the UTXOs associated with the address.
|
|
358
|
+
const utxoData = await this.electrumx.utxo(addr)
|
|
359
|
+
// console.log(`utxoData: ${JSON.stringify(utxoData, null, 2)}`)
|
|
360
|
+
const utxos = utxoData.utxos
|
|
361
|
+
|
|
362
|
+
// Get SLP UTXOs from the psf-slp-indexer
|
|
363
|
+
const slpUtxoData = await this.psfSlpIndexer.balance(addr)
|
|
364
|
+
// console.log(`slpUtxoData: ${JSON.stringify(slpUtxoData, null, 2)}`)
|
|
365
|
+
const slpUtxos = slpUtxoData.balance.utxos
|
|
366
|
+
|
|
367
|
+
// Loop through the Fulcrum UTXOs.
|
|
368
|
+
for (let i = 0; i < utxos.length; i++) {
|
|
369
|
+
const thisUtxo = utxos[i]
|
|
370
|
+
|
|
371
|
+
// Loop through the UTXOs from psf-slp-indexer.
|
|
372
|
+
for (let j = 0; j < slpUtxos.length; j++) {
|
|
373
|
+
const thisSlpUtxo = slpUtxos[j]
|
|
374
|
+
|
|
375
|
+
// If the non-hydrated UTXO matches the SLP UTXO, then combine the data
|
|
376
|
+
// and mark the UTXO as an SLP token.
|
|
377
|
+
if (
|
|
378
|
+
thisUtxo.tx_hash === thisSlpUtxo.txid &&
|
|
379
|
+
thisUtxo.tx_pos === thisSlpUtxo.vout
|
|
380
|
+
) {
|
|
381
|
+
thisUtxo.txid = thisUtxo.tx_hash
|
|
382
|
+
thisUtxo.vout = thisUtxo.tx_pos
|
|
383
|
+
thisUtxo.isSlp = true
|
|
384
|
+
thisUtxo.type = thisSlpUtxo.type
|
|
385
|
+
thisUtxo.qty = thisSlpUtxo.qty
|
|
386
|
+
thisUtxo.tokenId = thisSlpUtxo.tokenId
|
|
387
|
+
thisUtxo.address = thisSlpUtxo.address
|
|
388
|
+
|
|
389
|
+
break
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// If there was no match, then this is a normal BCH UTXO. Mark it as such.
|
|
394
|
+
if (!thisUtxo.isSlp) {
|
|
395
|
+
thisUtxo.txid = thisUtxo.tx_hash
|
|
396
|
+
thisUtxo.vout = thisUtxo.tx_pos
|
|
397
|
+
thisUtxo.isSlp = false
|
|
398
|
+
thisUtxo.address = addr
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const bchUtxos = utxos.filter(x => x.isSlp === false)
|
|
403
|
+
const type1TokenUtxos = utxos.filter(
|
|
404
|
+
x => x.isSlp === true && x.type === 'token'
|
|
405
|
+
)
|
|
406
|
+
const type1BatonUtxos = utxos.filter(
|
|
407
|
+
x => x.isSlp === true && x.type === 'baton'
|
|
408
|
+
)
|
|
409
|
+
const nullUtxos = utxos.filter(x => x.isSlp === null)
|
|
410
|
+
|
|
411
|
+
const outObj = {
|
|
412
|
+
address: addr,
|
|
413
|
+
bchUtxos,
|
|
414
|
+
slpUtxos: {
|
|
415
|
+
type1: {
|
|
416
|
+
tokens: type1TokenUtxos,
|
|
417
|
+
mintBatons: type1BatonUtxos
|
|
418
|
+
},
|
|
419
|
+
nft: {} // Allocated for future support of NFT spec.
|
|
420
|
+
},
|
|
421
|
+
nullUtxos
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return outObj
|
|
425
|
+
} catch (err) {
|
|
426
|
+
// console.error('Error in bchjs.utxo.get2(): ', err)
|
|
427
|
+
|
|
428
|
+
if (err.error) throw new Error(err.error)
|
|
429
|
+
throw err
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
289
433
|
/**
|
|
290
434
|
* @api Utxo.findBiggestUtxo() findBiggestUtxo()
|
|
291
435
|
* @apiName findBiggestUtxo
|
|
@@ -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
|
})
|
|
@@ -13,7 +13,7 @@ describe('#UTXO', () => {
|
|
|
13
13
|
|
|
14
14
|
if (process.env.IS_USING_FREE_TIER) await sleep(3000)
|
|
15
15
|
})
|
|
16
|
-
|
|
16
|
+
/*
|
|
17
17
|
describe('#get', () => {
|
|
18
18
|
it('should get hydrated and filtered UTXOs for an address', async () => {
|
|
19
19
|
// const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
|
|
@@ -90,7 +90,40 @@ describe('#UTXO', () => {
|
|
|
90
90
|
assert.isAbove(result[0].nullUtxos.length, 1)
|
|
91
91
|
})
|
|
92
92
|
})
|
|
93
|
+
*/
|
|
94
|
+
describe('#get', () => {
|
|
95
|
+
it('should hydrate address with BCH and SLP UTXOs', async () => {
|
|
96
|
+
const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
|
|
97
|
+
|
|
98
|
+
const result = await bchjs.Utxo.get(addr)
|
|
99
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
100
|
+
|
|
101
|
+
// Assert expected properties exist.
|
|
102
|
+
assert.property(result, 'address')
|
|
103
|
+
assert.property(result, 'bchUtxos')
|
|
104
|
+
assert.property(result, 'slpUtxos')
|
|
105
|
+
assert.property(result.slpUtxos, 'type1')
|
|
106
|
+
assert.property(result.slpUtxos, 'nft')
|
|
107
|
+
assert.property(result, 'nullUtxos')
|
|
108
|
+
|
|
109
|
+
assert.isAbove(result.bchUtxos.length, 0)
|
|
110
|
+
assert.isAbove(result.slpUtxos.type1.tokens.length, 0)
|
|
111
|
+
assert.equal(result.slpUtxos.type1.mintBatons.length, 0)
|
|
112
|
+
})
|
|
93
113
|
|
|
114
|
+
// TODO: NFTs are currently not identified as different than normal BCH UTXOs.
|
|
115
|
+
// The psf-slp-indexer needs to be updated to fix this issue.
|
|
116
|
+
it('should handle NFTs and minting batons', async () => {
|
|
117
|
+
const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
|
|
118
|
+
|
|
119
|
+
const result = await bchjs.Utxo.get(addr)
|
|
120
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
121
|
+
|
|
122
|
+
// Assert that minting batons are correctly identified.
|
|
123
|
+
assert.isAbove(result.slpUtxos.type1.mintBatons.length, 0)
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
/*
|
|
94
127
|
describe('#findBiggestUtxo', () => {
|
|
95
128
|
it('should sort UTXOs from Electrumx', async () => {
|
|
96
129
|
const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
|
|
@@ -118,6 +151,7 @@ describe('#UTXO', () => {
|
|
|
118
151
|
assert.equal(result.satoshis, 800)
|
|
119
152
|
})
|
|
120
153
|
})
|
|
154
|
+
*/
|
|
121
155
|
})
|
|
122
156
|
|
|
123
157
|
function sleep (ms) {
|
|
@@ -11,72 +11,74 @@ describe('#Transaction', () => {
|
|
|
11
11
|
if (process.env.IS_USING_FREE_TIER) await bchjs.Util.sleep(1000)
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if (process.env.TESTSLP) {
|
|
15
|
+
describe('#getOld', () => {
|
|
16
|
+
it('should get details about a non-SLP transaction', async () => {
|
|
17
|
+
const txid =
|
|
18
|
+
'2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7'
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
21
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
// Assert that there are stanardized properties.
|
|
24
|
+
assert.property(result, 'txid')
|
|
25
|
+
assert.property(result, 'vin')
|
|
26
|
+
assert.property(result, 'vout')
|
|
27
|
+
assert.property(result.vout[0], 'value')
|
|
28
|
+
assert.property(result.vout[0].scriptPubKey, 'addresses')
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
// Assert that added properties exist.
|
|
31
|
+
assert.property(result.vin[0], 'address')
|
|
32
|
+
assert.property(result.vin[0], 'value')
|
|
33
|
+
assert.property(result, 'isValidSLPTx')
|
|
34
|
+
assert.equal(result.isValidSLPTx, false)
|
|
35
|
+
})
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
it('should get details about a SLP transaction', async () => {
|
|
38
|
+
const txid =
|
|
39
|
+
'266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1'
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
42
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
// Assert that there are stanardized properties.
|
|
45
|
+
assert.property(result, 'txid')
|
|
46
|
+
assert.property(result, 'vin')
|
|
47
|
+
assert.property(result, 'vout')
|
|
48
|
+
assert.property(result.vout[0], 'value')
|
|
49
|
+
assert.property(result.vout[1].scriptPubKey, 'addresses')
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
// Assert that added properties exist.
|
|
52
|
+
assert.property(result.vout[0], 'tokenQty')
|
|
53
|
+
assert.equal(result.vout[0].tokenQty, null)
|
|
54
|
+
assert.property(result.vin[0], 'address')
|
|
55
|
+
assert.property(result.vin[0], 'value')
|
|
56
|
+
assert.property(result.vin[0], 'tokenQty')
|
|
57
|
+
assert.property(result, 'isValidSLPTx')
|
|
58
|
+
assert.equal(result.isValidSLPTx, true)
|
|
59
|
+
})
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
// it('should get problematic transaction', async () => {
|
|
62
|
+
// const txid = 'a55515de32577e296c512840bcaabed5823bb773fb4f8fd8e5197cc96cbc54d1'
|
|
63
|
+
//
|
|
64
|
+
// const result = await bchjs.Transaction.get(txid)
|
|
65
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
66
|
+
// })
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
// TX a19f2f395a8b0e15b6202944c56834367d128f1e3630486a4756de53424a46fe has
|
|
69
|
+
// an input TXID (bd84bc1dd5ecd976165892306992401272f6bedeb37d7b2cdbf74fc4a55967a6)
|
|
70
|
+
// that is also a valid SLP tx, but is unrelated. Both TXs pass DAG validation,
|
|
71
|
+
// but for separate tokens.
|
|
72
|
+
it('should get problematic transaction', async () => {
|
|
73
|
+
const txid =
|
|
74
|
+
'a19f2f395a8b0e15b6202944c56834367d128f1e3630486a4756de53424a46fe'
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
const result = await bchjs.Transaction.getOld(txid)
|
|
77
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
// The token ID should equal the txid for this Vin.
|
|
80
|
+
assert.equal(result.vin[2].txid, result.vin[2].tokenId)
|
|
81
|
+
})
|
|
80
82
|
})
|
|
81
|
-
}
|
|
83
|
+
}
|
|
82
84
|
})
|