@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@psf/bch-js",
3
- "version": "5.1.0",
3
+ "version": "5.2.0",
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": [
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
 
@@ -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
- // TODO: Run the TX through decodeOpReturn() to see if it has a tokenID
316
- // that is in the blacklist. If it is, then set isValidSlp = null to
317
- // signal that it's state can not be determined.
318
-
319
- // Assumption: transaction is not a valid SLP UTXO.
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
@@ -11,7 +11,7 @@ const Util = require('../util')
11
11
  let _this
12
12
 
13
13
  class Utils {
14
- constructor (config) {
14
+ constructor (config = {}) {
15
15
  this.restURL = config.restURL
16
16
  this.apiToken = config.apiToken
17
17
  this.slpParser = slpParser
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.get() get()
21
- * @apiName get
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.get('simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj');
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 get (address, useWhitelist = false) {
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
- '83361c34cac2ea7f9ca287fca57a96cc0763719f0cdf4850f9696c1e68eb635c'
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 handle non-SLP transaction', async () => {
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 handle a blacklisted token', async () => {
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, false)
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
- describe('#getOld', () => {
15
- it('should get details about a non-SLP transaction', async () => {
16
- const txid =
17
- '2b37bdb3b63dd0bca720437754a36671431a950e684b64c44ea910ea9d5297c7'
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
- const result = await bchjs.Transaction.getOld(txid)
20
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
20
+ const result = await bchjs.Transaction.getOld(txid)
21
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
21
22
 
22
- // Assert that there are stanardized properties.
23
- assert.property(result, 'txid')
24
- assert.property(result, 'vin')
25
- assert.property(result, 'vout')
26
- assert.property(result.vout[0], 'value')
27
- assert.property(result.vout[0].scriptPubKey, 'addresses')
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
- // Assert that added properties exist.
30
- assert.property(result.vin[0], 'address')
31
- assert.property(result.vin[0], 'value')
32
- assert.property(result, 'isValidSLPTx')
33
- assert.equal(result.isValidSLPTx, false)
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
- it('should get details about a SLP transaction', async () => {
37
- const txid =
38
- '266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1'
37
+ it('should get details about a SLP transaction', async () => {
38
+ const txid =
39
+ '266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1'
39
40
 
40
- const result = await bchjs.Transaction.getOld(txid)
41
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
41
+ const result = await bchjs.Transaction.getOld(txid)
42
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
42
43
 
43
- // Assert that there are stanardized properties.
44
- assert.property(result, 'txid')
45
- assert.property(result, 'vin')
46
- assert.property(result, 'vout')
47
- assert.property(result.vout[0], 'value')
48
- assert.property(result.vout[1].scriptPubKey, 'addresses')
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
- // Assert that added properties exist.
51
- assert.property(result.vout[0], 'tokenQty')
52
- assert.equal(result.vout[0].tokenQty, null)
53
- assert.property(result.vin[0], 'address')
54
- assert.property(result.vin[0], 'value')
55
- assert.property(result.vin[0], 'tokenQty')
56
- assert.property(result, 'isValidSLPTx')
57
- assert.equal(result.isValidSLPTx, true)
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
- // it('should get problematic transaction', async () => {
61
- // const txid = 'a55515de32577e296c512840bcaabed5823bb773fb4f8fd8e5197cc96cbc54d1'
62
- //
63
- // const result = await bchjs.Transaction.get(txid)
64
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
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
- // TX a19f2f395a8b0e15b6202944c56834367d128f1e3630486a4756de53424a46fe has
68
- // an input TXID (bd84bc1dd5ecd976165892306992401272f6bedeb37d7b2cdbf74fc4a55967a6)
69
- // that is also a valid SLP tx, but is unrelated. Both TXs pass DAG validation,
70
- // but for separate tokens.
71
- it('should get problematic transaction', async () => {
72
- const txid =
73
- 'a19f2f395a8b0e15b6202944c56834367d128f1e3630486a4756de53424a46fe'
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
- const result = await bchjs.Transaction.getOld(txid)
76
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
76
+ const result = await bchjs.Transaction.getOld(txid)
77
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
77
78
 
78
- // The token ID should equal the txid for this Vin.
79
- assert.equal(result.vin[2].txid, result.vin[2].tokenId)
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
  })