@psf/bch-js 5.2.1 → 5.2.2

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.2.2",
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": [
@@ -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/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++) {
@@ -13,84 +13,113 @@ describe('#UTXO', () => {
13
13
 
14
14
  if (process.env.IS_USING_FREE_TIER) await sleep(3000)
15
15
  })
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
-
22
- const result = await bchjs.Utxo.get(addr)
23
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
24
16
 
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)
17
+ if (process.env.TESTSLP) {
18
+ describe('#getOld', () => {
19
+ it('should get hydrated and filtered UTXOs for an address', async () => {
20
+ // const addr = 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
21
+ const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
22
+
23
+ const result = await bchjs.Utxo.getOld(addr)
24
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
25
+
26
+ assert.isArray(result)
27
+ assert.property(result[0], 'address')
28
+ assert.property(result[0], 'bchUtxos')
29
+ assert.property(result[0], 'nullUtxos')
30
+ assert.property(result[0], 'slpUtxos')
31
+ assert.isArray(result[0].bchUtxos)
32
+ assert.isArray(result[0].nullUtxos)
33
+ })
34
+
35
+ it('should handle an array of addresses', async () => {
36
+ const addr = [
37
+ 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9',
38
+ 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
39
+ ]
40
+
41
+ const result = await bchjs.Utxo.getOld(addr)
42
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
43
+
44
+ assert.isArray(result)
45
+ assert.property(result[0], 'address')
46
+ assert.property(result[0], 'bchUtxos')
47
+ assert.property(result[0], 'nullUtxos')
48
+ assert.property(result[0], 'slpUtxos')
49
+ assert.isArray(result[0].bchUtxos)
50
+ assert.isArray(result[0].nullUtxos)
51
+ })
52
+
53
+ it('should handle NFTs and minting batons', async () => {
54
+ const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
55
+
56
+ const result = await bchjs.Utxo.getOld(addr)
57
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
58
+
59
+ assert.isArray(result)
60
+ assert.property(result[0], 'address')
61
+ assert.property(result[0], 'bchUtxos')
62
+ assert.property(result[0], 'nullUtxos')
63
+ assert.property(result[0], 'slpUtxos')
64
+ assert.isArray(result[0].bchUtxos)
65
+ assert.isArray(result[0].nullUtxos)
66
+
67
+ assert.isArray(result[0].slpUtxos.type1.mintBatons)
68
+ assert.isArray(result[0].slpUtxos.type1.tokens)
69
+ assert.isArray(result[0].slpUtxos.nft.groupMintBatons)
70
+ assert.isArray(result[0].slpUtxos.nft.groupTokens)
71
+ assert.isArray(result[0].slpUtxos.nft.tokens)
72
+ })
73
+
74
+ it('should use the whitelist when flag is set', async () => {
75
+ const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
76
+ const useWhitelist = true
77
+
78
+ const result = await bchjs.Utxo.getOld(addr, useWhitelist)
79
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
80
+
81
+ assert.isArray(result)
82
+ assert.property(result[0], 'address')
83
+ assert.property(result[0], 'bchUtxos')
84
+ assert.property(result[0], 'nullUtxos')
85
+ assert.property(result[0], 'slpUtxos')
86
+ assert.isArray(result[0].bchUtxos)
87
+ assert.isArray(result[0].nullUtxos)
88
+
89
+ // Most token UTXOs should end up in the nullUtxos array.
90
+ assert.isAbove(result[0].bchUtxos.length, 0)
91
+ assert.isAbove(result[0].nullUtxos.length, 1)
92
+ })
32
93
  })
33
94
 
34
- it('should handle an array of addresses', async () => {
35
- const addr = [
36
- 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9',
37
- 'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
38
- ]
39
-
40
- const result = await bchjs.Utxo.get(addr)
41
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
95
+ describe('#findBiggestUtxo', () => {
96
+ it('should sort UTXOs from Electrumx', async () => {
97
+ const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
42
98
 
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
- })
99
+ const electrumxUtxos = await bchjs.Electrumx.utxo(addr)
100
+ // console.log(`Electrumx utxos: ${JSON.stringify(electrumxUtxos, null, 2)}`)
51
101
 
52
- it('should handle NFTs and minting batons', async () => {
53
- const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
102
+ const result = bchjs.Utxo.findBiggestUtxo(electrumxUtxos.utxos)
103
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
54
104
 
55
- const result = await bchjs.Utxo.get(addr)
56
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
105
+ assert.property(result, 'satoshis')
106
+ assert.equal(result.satoshis, 800)
107
+ })
57
108
 
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
- })
109
+ it('should sort UTXOs from Utxos.get()', async () => {
110
+ const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
72
111
 
73
- it('should use the whitelist when flag is set', async () => {
74
- const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
75
- const useWhitelist = true
112
+ const utxos = await bchjs.Utxo.getOld(addr)
113
+ // console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
76
114
 
77
- const result = await bchjs.Utxo.get(addr, useWhitelist)
78
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
115
+ const result = bchjs.Utxo.findBiggestUtxo(utxos[0].bchUtxos)
116
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
79
117
 
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)
118
+ assert.property(result, 'satoshis')
119
+ assert.equal(result.satoshis, 800)
120
+ })
91
121
  })
92
- })
93
- */
122
+ }
94
123
 
95
124
  describe('#hydrateTokenData', () => {
96
125
  it('should hydrate token UTXOs', async () => {
@@ -138,7 +167,13 @@ describe('#UTXO', () => {
138
167
  ]
139
168
 
140
169
  const result = await bchjs.Utxo.hydrateTokenData(utxos)
141
- console.log('result: ', result)
170
+ // console.log('result: ', result)
171
+
172
+ assert.property(result[0], 'ticker')
173
+ assert.property(result[0], 'name')
174
+ assert.property(result[0], 'qtyStr')
175
+ assert.property(result[0], 'documentUri')
176
+ assert.property(result[0], 'documentHash')
142
177
  })
143
178
  })
144
179
 
@@ -168,42 +203,22 @@ describe('#UTXO', () => {
168
203
  const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
169
204
 
170
205
  const result = await bchjs.Utxo.get(addr)
171
- console.log(`result: ${JSON.stringify(result, null, 2)}`)
206
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
172
207
 
173
208
  // Assert that minting batons are correctly identified.
174
209
  assert.isAbove(result.slpUtxos.type1.mintBatons.length, 0)
175
210
  })
176
- })
177
-
178
- /*
179
- describe('#findBiggestUtxo', () => {
180
- it('should sort UTXOs from Electrumx', async () => {
181
- const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
182
-
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)
187
- // console.log(`result: ${JSON.stringify(result, null, 2)}`)
188
-
189
- assert.property(result, 'satoshis')
190
- assert.equal(result.satoshis, 800)
191
- })
192
211
 
193
- it('should sort UTXOs from Utxos.get()', async () => {
194
- const addr = 'bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z'
212
+ it('should return UTXOs for address with no SLP tokens', async () => {
213
+ const addr = 'bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7'
195
214
 
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)
215
+ const result = await bchjs.Utxo.get(addr)
200
216
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
201
217
 
202
- assert.property(result, 'satoshis')
203
- assert.equal(result.satoshis, 800)
218
+ assert.isAbove(result.bchUtxos.length, 0)
219
+ assert.equal(result.slpUtxos.type1.tokens.length, 0)
204
220
  })
205
221
  })
206
- */
207
222
  })
208
223
 
209
224
  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
  }
@@ -272,5 +272,30 @@ describe('#utxo', () => {
272
272
  assert.equal(result.slpUtxos.type1.mintBatons.length, 1)
273
273
  assert.equal(result.nullUtxos.length, 0)
274
274
  })
275
+
276
+ it('should handle an address with no SLP UTXOs', async () => {
277
+ // mock dependencies
278
+ sandbox
279
+ .stub(bchjs.Utxo.electrumx, 'utxo')
280
+ .resolves(mockData.fulcrumUtxos02)
281
+
282
+ // Force psf-slp-indexer to return no UTXOs
283
+ sandbox
284
+ .stub(bchjs.Utxo.psfSlpIndexer, 'balance')
285
+ .rejects(mockData.noUtxoErr)
286
+
287
+ // Mock function to return the same input. Good enough for this test.
288
+ sandbox.stub(bchjs.Utxo, 'hydrateTokenData').resolves(() => [])
289
+
290
+ const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
291
+
292
+ const result = await bchjs.Utxo.get(addr)
293
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
294
+
295
+ assert.equal(result.bchUtxos.length, 1)
296
+ assert.equal(result.slpUtxos.type1.tokens.length, 0)
297
+ assert.equal(result.slpUtxos.type1.mintBatons.length, 0)
298
+ assert.equal(result.nullUtxos.length, 0)
299
+ })
275
300
  })
276
301
  })