@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
package/src/psf-slp-indexer.js
CHANGED
|
@@ -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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
'
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
|
|
53
|
-
|
|
102
|
+
const result = bchjs.Utxo.findBiggestUtxo(electrumxUtxos.utxos)
|
|
103
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
54
104
|
|
|
55
|
-
|
|
56
|
-
|
|
105
|
+
assert.property(result, 'satoshis')
|
|
106
|
+
assert.equal(result.satoshis, 800)
|
|
107
|
+
})
|
|
57
108
|
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
const useWhitelist = true
|
|
112
|
+
const utxos = await bchjs.Utxo.getOld(addr)
|
|
113
|
+
// console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
|
|
76
114
|
|
|
77
|
-
|
|
78
|
-
|
|
115
|
+
const result = bchjs.Utxo.findBiggestUtxo(utxos[0].bchUtxos)
|
|
116
|
+
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
79
117
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
194
|
-
const addr = 'bitcoincash:
|
|
212
|
+
it('should return UTXOs for address with no SLP tokens', async () => {
|
|
213
|
+
const addr = 'bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7'
|
|
195
214
|
|
|
196
|
-
const
|
|
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.
|
|
203
|
-
assert.equal(result.
|
|
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
|
}
|
package/test/unit/utxo-unit.js
CHANGED
|
@@ -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
|
})
|