@psf/bch-js 5.2.1 → 5.3.1

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.2.1",
3
+ "version": "5.3.1",
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.139:3000/v5/ && mocha --timeout 30000 test/integration/ && mocha --timeout 30000 test/integration/chains/bchn/",
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/electrumx.js CHANGED
@@ -638,13 +638,24 @@ class ElectrumX {
638
638
  // Sort confirmed Transactions by the block height
639
639
  sortConfTxs (txs, sortingOrder = 'DESCENDING') {
640
640
  try {
641
+ // console.log(`sortConfTxs txs: ${JSON.stringify(txs, null, 2)}`)
642
+
641
643
  // Filter out unconfirmed transactions, with a height of 0 or less.
642
644
  txs = txs.filter(elem => elem.height > 0)
643
645
 
644
646
  if (sortingOrder === 'DESCENDING') {
645
- return txs.sort((a, b) => b.height - a.height)
647
+ // console.log('Sorting in descending order')
648
+ return txs.sort((a, b) => {
649
+ // console.log(`descending b.height: ${b.height}, a.height: ${a.height}`)
650
+ return b.height - a.height
651
+ })
646
652
  }
647
- return txs.sort((a, b) => a.height - b.height)
653
+
654
+ // console.log('Sorting in ascending order')
655
+ return txs.sort((a, b) => {
656
+ // console.log(`ascending b.height: ${b.height}, a.height: ${a.height}`)
657
+ return a.height - b.height
658
+ })
648
659
  } catch (err) {
649
660
  console.log('Error in util.js/sortConfTxs()')
650
661
  throw err
@@ -685,6 +696,8 @@ class ElectrumX {
685
696
  // Substitute zero-conf txs with the current block-height + 1
686
697
  async sortAllTxs (txs, sortingOrder = 'DESCENDING') {
687
698
  try {
699
+ // console.log(`sortingOrder: ${sortingOrder}`)
700
+
688
701
  // Calculate the height of the next block
689
702
  const nextBlock = (await this.blockchain.getBlockCount()) + 1
690
703
 
@@ -132,7 +132,8 @@ class PsfSlpIndexer {
132
132
  */
133
133
  async balance (address) {
134
134
  try {
135
- console.log('balance() address: ', address)
135
+ // console.log('balance() address: ', address)
136
+
136
137
  // Handle single address.
137
138
  if (typeof address === 'string') {
138
139
  const response = await axios.post(
package/src/util.js CHANGED
@@ -150,6 +150,56 @@ class Util {
150
150
  }
151
151
  }
152
152
 
153
+ /**
154
+ * @api Util.chunk100() chunk100()
155
+ * @apiName chunk100
156
+ * @apiGroup Util
157
+ * @apiDescription chunk up an array into multiple arrays of 100 elements each.
158
+ * Input: arrayToSlice - a one-dimensional array of elements.
159
+ * Returns a two-dimensional array. An array of 100-element arrays.
160
+ *
161
+ * @apiExample Example usage:
162
+ * (async () => {
163
+ * try {
164
+ * const bigArray = [0,1,2,3,4,5,6,7,8,9,10,...,148, 149, 150]
165
+ *
166
+ * const chunked = bchjs.Util.chunk20(bigArray)
167
+ * console.log(chunked)
168
+ * } catch(error) {
169
+ * console.error(error)
170
+ * }
171
+ * })()
172
+ *
173
+ * // returns
174
+ * [
175
+ * [0,1,2,3,4,5,6,7,8,9,10,11,...,98,99],
176
+ * [100,101,102,...,148,149,150]
177
+ * ]
178
+ */
179
+ chunk100 (arrayToSlice) {
180
+ try {
181
+ // Validate inputs
182
+ if (!Array.isArray(arrayToSlice)) {
183
+ throw new Error('input must be an array')
184
+ }
185
+
186
+ let offset = 0
187
+ const result = []
188
+
189
+ // Loop over the array and slice off chunks of 100 elements.
190
+ while (offset < arrayToSlice.length) {
191
+ const chunk = arrayToSlice.slice(offset, offset + 100)
192
+ result.push(chunk)
193
+ offset = offset + 100
194
+ }
195
+
196
+ return result
197
+ } catch (err) {
198
+ console.error('Error in chunk100()')
199
+ throw err
200
+ }
201
+ }
202
+
153
203
  /**
154
204
  * @api Util.sleep() sleep()
155
205
  * @apiName sleep
package/src/utxo.js CHANGED
@@ -311,10 +311,6 @@ class UTXO {
311
311
  * - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
312
312
  * - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
313
313
  *
314
- * Note: You can pass in an optional second Boolean argument. The default
315
- * `false` will use the normal waterfall validation method. Set to `true`,
316
- * SLP UTXOs will be validated with the whitelist filtered SLPDB. This will
317
- * result is many more UTXOs in the `nullUtxos` array.
318
314
  *
319
315
  * @apiExample Example usage:
320
316
  * (async () => {
@@ -361,10 +357,22 @@ class UTXO {
361
357
  // console.log(`utxoData: ${JSON.stringify(utxoData, null, 2)}`)
362
358
  const utxos = utxoData.utxos
363
359
 
360
+ let slpUtxos = []
361
+
364
362
  // Get SLP UTXOs from the psf-slp-indexer
365
- const slpUtxoData = await this.psfSlpIndexer.balance(addr)
366
- // console.log(`slpUtxoData: ${JSON.stringify(slpUtxoData, null, 2)}`)
367
- const slpUtxos = slpUtxoData.balance.utxos
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
+ }
368
376
 
369
377
  // Loop through the Fulcrum UTXOs.
370
378
  for (let i = 0; i < utxos.length; i++) {
@@ -396,8 +404,18 @@ class UTXO {
396
404
  if (!thisUtxo.isSlp) {
397
405
  thisUtxo.txid = thisUtxo.tx_hash
398
406
  thisUtxo.vout = thisUtxo.tx_pos
399
- thisUtxo.isSlp = false
400
407
  thisUtxo.address = addr
408
+
409
+ // Check the transaction to see if its a 'null' token, ignored by
410
+ // the indexer.
411
+ const txData = await this.psfSlpIndexer.tx(thisUtxo.tx_hash)
412
+ // console.log(`txData: ${JSON.stringify(txData, null, 2)}`)
413
+ if (txData.txData.isValidSlp === null) {
414
+ thisUtxo.isSlp = null
415
+ } else {
416
+ thisUtxo.isSlp = false
417
+ }
418
+ // console.log(`thisUtxo.isSlp: ${thisUtxo.isSlp}`)
401
419
  }
402
420
  }
403
421
 
@@ -430,7 +448,7 @@ class UTXO {
430
448
 
431
449
  return outObj
432
450
  } catch (err) {
433
- // console.error('Error in bchjs.utxo.get2(): ', err)
451
+ console.error('Error in bchjs.Utxo.get(): ', err)
434
452
 
435
453
  if (err.error) throw new Error(err.error)
436
454
  throw err
@@ -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) {
@@ -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
+ })
@@ -5,7 +5,8 @@
5
5
  const assert = require('chai').assert
6
6
 
7
7
  const BCHJS = require('../../../../src/bch-js')
8
- const bchjs = new BCHJS()
8
+ // const bchjs = new BCHJS()
9
+ const bchjs = new BCHJS({ restURL: 'http://192.168.2.129:3000/v5/' })
9
10
 
10
11
  describe('#UTXO', () => {
11
12
  beforeEach(async () => {
@@ -13,84 +14,113 @@ describe('#UTXO', () => {
13
14
 
14
15
  if (process.env.IS_USING_FREE_TIER) await sleep(3000)
15
16
  })
16
- /*
17
- describe('#get', () => {
18
- it('should get hydrated and filtered UTXOs for an address', async () => {
19
- // const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
20
- const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
21
17
 
22
- const result = await bchjs.Utxo.get(addr)
23
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
24
-
25
- assert.isArray(result)
26
- assert.property(result[0], 'address')
27
- assert.property(result[0], 'bchUtxos')
28
- assert.property(result[0], 'nullUtxos')
29
- assert.property(result[0], 'slpUtxos')
30
- assert.isArray(result[0].bchUtxos)
31
- assert.isArray(result[0].nullUtxos)
18
+ if (process.env.TESTSLP) {
19
+ describe('#getOld', () => {
20
+ it('should get hydrated and filtered UTXOs for an address', async () => {
21
+ // const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
22
+ const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
23
+
24
+ const result = await bchjs.Utxo.getOld(addr)
25
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
26
+
27
+ assert.isArray(result)
28
+ assert.property(result[0], 'address')
29
+ assert.property(result[0], 'bchUtxos')
30
+ assert.property(result[0], 'nullUtxos')
31
+ assert.property(result[0], 'slpUtxos')
32
+ assert.isArray(result[0].bchUtxos)
33
+ assert.isArray(result[0].nullUtxos)
34
+ })
35
+
36
+ it('should handle an array of addresses', async () => {
37
+ const addr = [
38
+ 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9',
39
+ 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
40
+ ]
41
+
42
+ const result = await bchjs.Utxo.getOld(addr)
43
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
44
+
45
+ assert.isArray(result)
46
+ assert.property(result[0], 'address')
47
+ assert.property(result[0], 'bchUtxos')
48
+ assert.property(result[0], 'nullUtxos')
49
+ assert.property(result[0], 'slpUtxos')
50
+ assert.isArray(result[0].bchUtxos)
51
+ assert.isArray(result[0].nullUtxos)
52
+ })
53
+
54
+ it('should handle NFTs and minting batons', async () => {
55
+ const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
56
+
57
+ const result = await bchjs.Utxo.getOld(addr)
58
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
59
+
60
+ assert.isArray(result)
61
+ assert.property(result[0], 'address')
62
+ assert.property(result[0], 'bchUtxos')
63
+ assert.property(result[0], 'nullUtxos')
64
+ assert.property(result[0], 'slpUtxos')
65
+ assert.isArray(result[0].bchUtxos)
66
+ assert.isArray(result[0].nullUtxos)
67
+
68
+ assert.isArray(result[0].slpUtxos.type1.mintBatons)
69
+ assert.isArray(result[0].slpUtxos.type1.tokens)
70
+ assert.isArray(result[0].slpUtxos.nft.groupMintBatons)
71
+ assert.isArray(result[0].slpUtxos.nft.groupTokens)
72
+ assert.isArray(result[0].slpUtxos.nft.tokens)
73
+ })
74
+
75
+ it('should use the whitelist when flag is set', async () => {
76
+ const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
77
+ const useWhitelist = true
78
+
79
+ const result = await bchjs.Utxo.getOld(addr, useWhitelist)
80
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
81
+
82
+ assert.isArray(result)
83
+ assert.property(result[0], 'address')
84
+ assert.property(result[0], 'bchUtxos')
85
+ assert.property(result[0], 'nullUtxos')
86
+ assert.property(result[0], 'slpUtxos')
87
+ assert.isArray(result[0].bchUtxos)
88
+ assert.isArray(result[0].nullUtxos)
89
+
90
+ // Most token UTXOs should end up in the nullUtxos array.
91
+ assert.isAbove(result[0].bchUtxos.length, 0)
92
+ assert.isAbove(result[0].nullUtxos.length, 1)
93
+ })
32
94
  })
33
95
 
34
- it('should handle an array of addresses', async () => {
35
- const addr = [
36
- 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9',
37
- 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
38
- ]
96
+ describe('#findBiggestUtxo', () => {
97
+ it('should sort UTXOs from Electrumx', async () => {
98
+ const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
39
99
 
40
- const result = await bchjs.Utxo.get(addr)
41
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
100
+ const electrumxUtxos = await bchjs.Electrumx.utxo(addr)
101
+ // console.log(`Electrumx utxos: ${JSON.stringify(electrumxUtxos, null, 2)}`)
42
102
 
43
- assert.isArray(result)
44
- assert.property(result[0], 'address')
45
- assert.property(result[0], 'bchUtxos')
46
- assert.property(result[0], 'nullUtxos')
47
- assert.property(result[0], 'slpUtxos')
48
- assert.isArray(result[0].bchUtxos)
49
- assert.isArray(result[0].nullUtxos)
50
- })
103
+ const result = bchjs.Utxo.findBiggestUtxo(electrumxUtxos.utxos)
104
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
51
105
 
52
- it('should handle NFTs and minting batons', async () => {
53
- const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
106
+ assert.property(result, 'satoshis')
107
+ assert.equal(result.satoshis, 800)
108
+ })
54
109
 
55
- const result = await bchjs.Utxo.get(addr)
56
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
110
+ it('should sort UTXOs from Utxos.get()', async () => {
111
+ const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
57
112
 
58
- assert.isArray(result)
59
- assert.property(result[0], 'address')
60
- assert.property(result[0], 'bchUtxos')
61
- assert.property(result[0], 'nullUtxos')
62
- assert.property(result[0], 'slpUtxos')
63
- assert.isArray(result[0].bchUtxos)
64
- assert.isArray(result[0].nullUtxos)
65
-
66
- assert.isArray(result[0].slpUtxos.type1.mintBatons)
67
- assert.isArray(result[0].slpUtxos.type1.tokens)
68
- assert.isArray(result[0].slpUtxos.nft.groupMintBatons)
69
- assert.isArray(result[0].slpUtxos.nft.groupTokens)
70
- assert.isArray(result[0].slpUtxos.nft.tokens)
71
- })
113
+ const utxos = await bchjs.Utxo.getOld(addr)
114
+ // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
72
115
 
73
- it('should use the whitelist when flag is set', async () => {
74
- const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
75
- const useWhitelist = true
116
+ const result = bchjs.Utxo.findBiggestUtxo(utxos[0].bchUtxos)
117
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
76
118
 
77
- const result = await bchjs.Utxo.get(addr, useWhitelist)
78
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
79
-
80
- assert.isArray(result)
81
- assert.property(result[0], 'address')
82
- assert.property(result[0], 'bchUtxos')
83
- assert.property(result[0], 'nullUtxos')
84
- assert.property(result[0], 'slpUtxos')
85
- assert.isArray(result[0].bchUtxos)
86
- assert.isArray(result[0].nullUtxos)
87
-
88
- // Most token UTXOs should end up in the nullUtxos array.
89
- assert.isAbove(result[0].bchUtxos.length, 0)
90
- assert.isAbove(result[0].nullUtxos.length, 1)
119
+ assert.property(result, 'satoshis')
120
+ assert.equal(result.satoshis, 800)
121
+ })
91
122
  })
92
- })
93
- */
123
+ }
94
124
 
95
125
  describe('#hydrateTokenData', () => {
96
126
  it('should hydrate token UTXOs', async () => {
@@ -138,7 +168,13 @@ describe('#UTXO', () => {
138
168
  ]
139
169
 
140
170
  const result = await bchjs.Utxo.hydrateTokenData(utxos)
141
- console.log('result: ', result)
171
+ // console.log('result: ', result)
172
+
173
+ assert.property(result[0], 'ticker')
174
+ assert.property(result[0], 'name')
175
+ assert.property(result[0], 'qtyStr')
176
+ assert.property(result[0], 'documentUri')
177
+ assert.property(result[0], 'documentHash')
142
178
  })
143
179
  })
144
180
 
@@ -164,46 +200,35 @@ describe('#UTXO', () => {
164
200
 
165
201
  // TODO: NFTs are currently not identified as different than normal BCH UTXOs.
166
202
  // The psf-slp-indexer needs to be updated to fix this issue.
167
- it('should handle NFTs and minting batons', async () => {
203
+ it('should handle minting batons', async () => {
168
204
  const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
169
205
 
170
206
  const result = await bchjs.Utxo.get(addr)
171
- console.log(`result: ${JSON.stringify(result, null, 2)}`)
207
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
172
208
 
173
209
  // Assert that minting batons are correctly identified.
174
210
  assert.isAbove(result.slpUtxos.type1.mintBatons.length, 0)
175
211
  })
176
- })
177
212
 
178
- /*
179
- describe('#findBiggestUtxo', () => {
180
- it('should sort UTXOs from Electrumx', async () => {
181
- const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
213
+ it('should return UTXOs for address with no SLP tokens', async () => {
214
+ const addr = 'bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7'
182
215
 
183
- const electrumxUtxos = await bchjs.Electrumx.utxo(addr)
184
- // console.log(`Electrumx utxos: ${JSON.stringify(electrumxUtxos, null, 2)}`)
185
-
186
- const result = bchjs.Utxo.findBiggestUtxo(electrumxUtxos.utxos)
216
+ const result = await bchjs.Utxo.get(addr)
187
217
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
188
218
 
189
- assert.property(result, 'satoshis')
190
- assert.equal(result.satoshis, 800)
219
+ assert.isAbove(result.bchUtxos.length, 0)
220
+ assert.equal(result.slpUtxos.type1.tokens.length, 0)
191
221
  })
192
222
 
193
- it('should sort UTXOs from Utxos.get()', async () => {
194
- const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
223
+ it('should handle Group NFTs', async () => {
224
+ const addr = 'bitcoincash:qrnghwrfgccf3s5e9wnglzxegcnhje9rkcwv2eka33'
195
225
 
196
- const utxos = await bchjs.Utxo.get(addr)
197
- // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
198
-
199
- const result = bchjs.Utxo.findBiggestUtxo(utxos[0].bchUtxos)
226
+ const result = await bchjs.Utxo.get(addr)
200
227
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
201
228
 
202
- assert.property(result, 'satoshis')
203
- assert.equal(result.satoshis, 800)
229
+ assert.isAbove(result.nullUtxos.length, 0)
204
230
  })
205
231
  })
206
- */
207
232
  })
208
233
 
209
234
  function sleep (ms) {
@@ -328,6 +328,19 @@ const fulcrumUtxos01 = {
328
328
  ]
329
329
  }
330
330
 
331
+ const fulcrumUtxos02 = {
332
+ success: true,
333
+ utxos: [
334
+ {
335
+ height: 674513,
336
+ tx_hash:
337
+ '705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04',
338
+ tx_pos: 3,
339
+ value: 38134
340
+ }
341
+ ]
342
+ }
343
+
331
344
  const psfSlpIndexerUtxos01 = {
332
345
  balance: {
333
346
  utxos: [
@@ -457,6 +470,12 @@ const genesisData03 = {
457
470
  }
458
471
  }
459
472
 
473
+ const noUtxoErr = {
474
+ success: false,
475
+ error:
476
+ 'Key not found in database [bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7]'
477
+ }
478
+
460
479
  module.exports = {
461
480
  mockUtxoData,
462
481
  mockHydratedUtxos,
@@ -464,9 +483,11 @@ module.exports = {
464
483
  mockEveryUtxoType,
465
484
  electrumxUtxos,
466
485
  fulcrumUtxos01,
486
+ fulcrumUtxos02,
467
487
  psfSlpIndexerUtxos01,
468
488
  tokenUtxos01,
469
489
  genesisData01,
470
490
  genesisData02,
471
- genesisData03
491
+ genesisData03,
492
+ noUtxoErr
472
493
  }
@@ -249,6 +249,10 @@ describe('#utxo', () => {
249
249
  sandbox
250
250
  .stub(bchjs.Utxo.psfSlpIndexer, 'balance')
251
251
  .resolves(mockData.psfSlpIndexerUtxos01)
252
+ sandbox
253
+ .stub(bchjs.Utxo.psfSlpIndexer, 'tx')
254
+ .resolves({ txData: { isValidSlp: false } })
255
+
252
256
  // Mock function to return the same input. Good enough for this test.
253
257
  sandbox.stub(bchjs.Utxo, 'hydrateTokenData').resolves(x => x)
254
258
 
@@ -272,5 +276,33 @@ describe('#utxo', () => {
272
276
  assert.equal(result.slpUtxos.type1.mintBatons.length, 1)
273
277
  assert.equal(result.nullUtxos.length, 0)
274
278
  })
279
+
280
+ it('should handle an address with no SLP UTXOs', async () => {
281
+ // mock dependencies
282
+ sandbox
283
+ .stub(bchjs.Utxo.electrumx, 'utxo')
284
+ .resolves(mockData.fulcrumUtxos02)
285
+ sandbox
286
+ .stub(bchjs.Utxo.psfSlpIndexer, 'tx')
287
+ .resolves({ txData: { isValidSlp: false } })
288
+
289
+ // Force psf-slp-indexer to return no UTXOs
290
+ sandbox
291
+ .stub(bchjs.Utxo.psfSlpIndexer, 'balance')
292
+ .rejects(mockData.noUtxoErr)
293
+
294
+ // Mock function to return the same input. Good enough for this test.
295
+ sandbox.stub(bchjs.Utxo, 'hydrateTokenData').resolves(() => [])
296
+
297
+ const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
298
+
299
+ const result = await bchjs.Utxo.get(addr)
300
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
301
+
302
+ assert.equal(result.bchUtxos.length, 1)
303
+ assert.equal(result.slpUtxos.type1.tokens.length, 0)
304
+ assert.equal(result.slpUtxos.type1.mintBatons.length, 0)
305
+ assert.equal(result.nullUtxos.length, 0)
306
+ })
275
307
  })
276
308
  })