@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.
@@ -21,7 +21,8 @@ const tokenStats = {
21
21
  totalMinted: '1',
22
22
  txs: [
23
23
  {
24
- txid: '13cad617d523c8eb4ab11fff19c010e0e0a4ea4360b58e0c8c955a45a146a669',
24
+ txid:
25
+ '13cad617d523c8eb4ab11fff19c010e0e0a4ea4360b58e0c8c955a45a146a669',
25
26
  height: 722420,
26
27
  type: 'GENESIS',
27
28
  qty: '1'
@@ -39,11 +40,14 @@ const txData = {
39
40
  locktime: 0,
40
41
  vin: [
41
42
  {
42
- txid: '8370db30d94761ab9a11b71ecd22541151bf6125c8c613f0f6fab8ab794565a7',
43
+ txid:
44
+ '8370db30d94761ab9a11b71ecd22541151bf6125c8c613f0f6fab8ab794565a7',
43
45
  vout: 0,
44
46
  scriptSig: {
45
- asm: '304402207e9631c53dfc8a9a793d1916469628c6b7c5780c01c2f676d51ef21b0ba4926f022069feb471ec869a49f8d108d0aaba04e7cd36e60a7500109d86537f55698930d4[ALL|FORKID] 02791b19a39165dbd83403d6df268d44fd621da30581b0b6e5cb15a7101ed58851',
46
- hex: '47304402207e9631c53dfc8a9a793d1916469628c6b7c5780c01c2f676d51ef21b0ba4926f022069feb471ec869a49f8d108d0aaba04e7cd36e60a7500109d86537f55698930d4412102791b19a39165dbd83403d6df268d44fd621da30581b0b6e5cb15a7101ed58851'
47
+ asm:
48
+ '304402207e9631c53dfc8a9a793d1916469628c6b7c5780c01c2f676d51ef21b0ba4926f022069feb471ec869a49f8d108d0aaba04e7cd36e60a7500109d86537f55698930d4[ALL|FORKID] 02791b19a39165dbd83403d6df268d44fd621da30581b0b6e5cb15a7101ed58851',
49
+ hex:
50
+ '47304402207e9631c53dfc8a9a793d1916469628c6b7c5780c01c2f676d51ef21b0ba4926f022069feb471ec869a49f8d108d0aaba04e7cd36e60a7500109d86537f55698930d4412102791b19a39165dbd83403d6df268d44fd621da30581b0b6e5cb15a7101ed58851'
47
51
  },
48
52
  sequence: 4294967295,
49
53
  address: 'bitcoincash:qpvsg9vl9a5mlf37a7n3yce6pktdctn73qwgaqm3wq',
@@ -58,16 +62,20 @@ const txData = {
58
62
  value: 0,
59
63
  n: 0,
60
64
  scriptPubKey: {
61
- asm: 'OP_RETURN 5262419 1 47454e45534953 54524f5554 54726f75742773207465737420746f6b656e 74726f757473626c6f672e636f6d 0 2 2 000000174876e800',
62
- hex: '6a04534c500001010747454e455349530554524f55541254726f75742773207465737420746f6b656e0e74726f757473626c6f672e636f6d4c000102010208000000174876e800',
65
+ asm:
66
+ 'OP_RETURN 5262419 1 47454e45534953 54524f5554 54726f75742773207465737420746f6b656e 74726f757473626c6f672e636f6d 0 2 2 000000174876e800',
67
+ hex:
68
+ '6a04534c500001010747454e455349530554524f55541254726f75742773207465737420746f6b656e0e74726f757473626c6f672e636f6d4c000102010208000000174876e800',
63
69
  type: 'nulldata'
64
70
  },
65
71
  tokenQtyStr: '0',
66
72
  tokenQty: 0
67
73
  }
68
74
  ],
69
- hex: '0200000001a7654579abb8faf6f013c6c82561bf51115422cd1eb7119aab6147d930db7083000000006a47304402207e9631c53dfc8a9a793d1916469628c6b7c5780c01c2f676d51ef21b0ba4926f022069feb471ec869a49f8d108d0aaba04e7cd36e60a7500109d86537f55698930d4412102791b19a39165dbd83403d6df268d44fd621da30581b0b6e5cb15a7101ed58851ffffffff040000000000000000476a04534c500001010747454e455349530554524f55541254726f75742773207465737420746f6b656e0e74726f757473626c6f672e636f6d4c000102010208000000174876e80022020000000000001976a914db4d39ceb7794ffe5d06855f249e1d3a7f1b024088ac22020000000000001976a914db4d39ceb7794ffe5d06855f249e1d3a7f1b024088accec20000000000001976a9145904159f2f69bfa63eefa712633a0d96dc2e7e8888ac00000000',
70
- blockhash: '0000000000000000009f65225a3e12e23a7ea057c869047e0f36563a1f410267',
75
+ hex:
76
+ '0200000001a7654579abb8faf6f013c6c82561bf51115422cd1eb7119aab6147d930db7083000000006a47304402207e9631c53dfc8a9a793d1916469628c6b7c5780c01c2f676d51ef21b0ba4926f022069feb471ec869a49f8d108d0aaba04e7cd36e60a7500109d86537f55698930d4412102791b19a39165dbd83403d6df268d44fd621da30581b0b6e5cb15a7101ed58851ffffffff040000000000000000476a04534c500001010747454e455349530554524f55541254726f75742773207465737420746f6b656e0e74726f757473626c6f672e636f6d4c000102010208000000174876e80022020000000000001976a914db4d39ceb7794ffe5d06855f249e1d3a7f1b024088ac22020000000000001976a914db4d39ceb7794ffe5d06855f249e1d3a7f1b024088accec20000000000001976a9145904159f2f69bfa63eefa712633a0d96dc2e7e8888ac00000000',
77
+ blockhash:
78
+ '0000000000000000009f65225a3e12e23a7ea057c869047e0f36563a1f410267',
71
79
  confirmations: 97398,
72
80
  time: 1581773131,
73
81
  blocktime: 1581773131,
@@ -88,27 +96,32 @@ const balance = {
88
96
  balance: {
89
97
  utxos: [
90
98
  {
91
- txid: 'a24a6a4abf06fabd799ecea4f8fac6a9ff21e6a8dd6169a3c2ebc03665329db9',
99
+ txid:
100
+ 'a24a6a4abf06fabd799ecea4f8fac6a9ff21e6a8dd6169a3c2ebc03665329db9',
92
101
  vout: 1,
93
102
  type: 'token',
94
103
  qty: '1800',
95
- tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
104
+ tokenId:
105
+ 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
96
106
  address: 'bitcoincash:qrqy3kj7r822ps6628vwqq5k8hyjl6ey3y4eea2m4s'
97
107
  }
98
108
  ],
99
109
  txs: [
100
110
  {
101
- txid: '078b2c48ed1db0d5d5996f2889b8d847a49200d0a781f6aa6752f740f312688f',
111
+ txid:
112
+ '078b2c48ed1db0d5d5996f2889b8d847a49200d0a781f6aa6752f740f312688f',
102
113
  height: 717796
103
114
  },
104
115
  {
105
- txid: 'a24a6a4abf06fabd799ecea4f8fac6a9ff21e6a8dd6169a3c2ebc03665329db9',
116
+ txid:
117
+ 'a24a6a4abf06fabd799ecea4f8fac6a9ff21e6a8dd6169a3c2ebc03665329db9',
106
118
  height: 717832
107
119
  }
108
120
  ],
109
121
  balances: [
110
122
  {
111
- tokenId: 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
123
+ tokenId:
124
+ 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
112
125
  qty: '1800'
113
126
  }
114
127
  ]
@@ -122,9 +135,19 @@ const status = {
122
135
  chainBlockHeight: 722679
123
136
  }
124
137
  }
138
+
139
+ const tokenData01 = {
140
+ tokenType: 1,
141
+ txType: 'MINT',
142
+ tokenId: 'dd21be4532d93661e8ffe16db6535af0fb8ee1344d1fef81a193e2b4cfa9fbc9',
143
+ mintBatonVout: 2,
144
+ qty: {}
145
+ }
146
+
125
147
  module.exports = {
126
148
  tokenStats,
127
149
  txData,
128
150
  balance,
129
- status
151
+ status,
152
+ tokenData01
130
153
  }
@@ -280,10 +280,100 @@ const electrumxUtxos = {
280
280
  ]
281
281
  }
282
282
 
283
+ const fulcrumUtxos01 = {
284
+ success: true,
285
+ utxos: [
286
+ {
287
+ height: 674512,
288
+ tx_hash:
289
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
290
+ tx_pos: 1,
291
+ value: 546
292
+ },
293
+ {
294
+ height: 674512,
295
+ tx_hash:
296
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
297
+ tx_pos: 2,
298
+ value: 546
299
+ },
300
+ {
301
+ height: 674512,
302
+ tx_hash:
303
+ 'eeddccc4d716f04157ea132ac93a48040fea34a6b57f3d8f0cccb7d1a731ab2b',
304
+ tx_pos: 1,
305
+ value: 546
306
+ },
307
+ {
308
+ height: 674513,
309
+ tx_hash:
310
+ '705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04',
311
+ tx_pos: 1,
312
+ value: 546
313
+ },
314
+ {
315
+ height: 674513,
316
+ tx_hash:
317
+ '705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04',
318
+ tx_pos: 2,
319
+ value: 546
320
+ },
321
+ {
322
+ height: 674513,
323
+ tx_hash:
324
+ '705bcc442e5a2770e560b528f52a47b1dcc9ce9ab6a8de9dfdefa55177f00d04',
325
+ tx_pos: 3,
326
+ value: 38134
327
+ }
328
+ ]
329
+ }
330
+
331
+ const psfSlpIndexerUtxos01 = {
332
+ balance: {
333
+ utxos: [
334
+ {
335
+ txid:
336
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
337
+ vout: 1,
338
+ type: 'token',
339
+ qty: '10000000000',
340
+ tokenId:
341
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
342
+ address: 'bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv'
343
+ },
344
+ {
345
+ txid:
346
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
347
+ vout: 2,
348
+ type: 'baton',
349
+ tokenId:
350
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
351
+ address: 'bitcoincash:qrm0c67wwqh0w7wjxua2gdt2xggnm90xws00a3lezv'
352
+ }
353
+ ],
354
+ txs: [
355
+ {
356
+ txid:
357
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
358
+ height: 674512
359
+ }
360
+ ],
361
+ balances: [
362
+ {
363
+ tokenId:
364
+ 'acbb0d3ceef55aa3e5fafc19335ae4bf2f8edba3c0567547dfd402391db32230',
365
+ qty: '10000000000'
366
+ }
367
+ ]
368
+ }
369
+ }
370
+
283
371
  module.exports = {
284
372
  mockUtxoData,
285
373
  mockHydratedUtxos,
286
374
  mockTwoHydratedAddrs,
287
375
  mockEveryUtxoType,
288
- electrumxUtxos
376
+ electrumxUtxos,
377
+ fulcrumUtxos01,
378
+ psfSlpIndexerUtxos01
289
379
  }
@@ -71,6 +71,7 @@ describe('#PsfSlpIndexer', () => {
71
71
  assert.isArray(result.balance.txs)
72
72
  assert.isArray(result.balance.balances)
73
73
  })
74
+
74
75
  it('should throw an error for improper input', async () => {
75
76
  try {
76
77
  const addr = 12345
@@ -82,6 +83,7 @@ describe('#PsfSlpIndexer', () => {
82
83
  assert.include(err.message, 'Input address must be a string.')
83
84
  }
84
85
  })
86
+
85
87
  it('should handle axios error', async () => {
86
88
  try {
87
89
  // Stub the network call.
@@ -96,6 +98,7 @@ describe('#PsfSlpIndexer', () => {
96
98
  assert.include(err.message, 'test error')
97
99
  }
98
100
  })
101
+
99
102
  it('should handle request error', async () => {
100
103
  try {
101
104
  // Stub the network call.
@@ -139,6 +142,7 @@ describe('#PsfSlpIndexer', () => {
139
142
  assert.property(result.tokenData, 'totalMinted')
140
143
  assert.property(result.tokenData, 'txs')
141
144
  })
145
+
142
146
  it('should throw an error for improper input', async () => {
143
147
  try {
144
148
  const tokenId = 12345
@@ -150,6 +154,7 @@ describe('#PsfSlpIndexer', () => {
150
154
  assert.include(err.message, 'Input tokenId must be a string.')
151
155
  }
152
156
  })
157
+
153
158
  it('should handle axios error', async () => {
154
159
  try {
155
160
  // Stub the network call.
@@ -164,6 +169,7 @@ describe('#PsfSlpIndexer', () => {
164
169
  assert.include(err.message, 'test error')
165
170
  }
166
171
  })
172
+
167
173
  it('should handle request error', async () => {
168
174
  try {
169
175
  // Stub the network call.
@@ -215,6 +221,7 @@ describe('#PsfSlpIndexer', () => {
215
221
  assert.property(result.txData, 'tokenDocHash')
216
222
  assert.property(result.txData, 'isValidSlp')
217
223
  })
224
+
218
225
  it('should throw an error for improper input', async () => {
219
226
  try {
220
227
  const txid = 12345
@@ -226,6 +233,7 @@ describe('#PsfSlpIndexer', () => {
226
233
  assert.include(err.message, 'Input txid must be a string.')
227
234
  }
228
235
  })
236
+
229
237
  it('should handle axios error', async () => {
230
238
  try {
231
239
  // Stub the network call.
@@ -249,6 +257,7 @@ describe('#PsfSlpIndexer', () => {
249
257
  sandbox.stub(axios, 'post').rejects(testErr)
250
258
 
251
259
  // Stub the call to the full node
260
+ sandbox.stub(bchjs.PsfSlpIndexer, 'checkBlacklist').resolves(false)
252
261
  sandbox
253
262
  .stub(bchjs.PsfSlpIndexer.rawTransaction, 'getTxData')
254
263
  .resolves({ txid: 'fakeTxid' })
@@ -259,6 +268,72 @@ describe('#PsfSlpIndexer', () => {
259
268
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
260
269
 
261
270
  assert.equal(result.txData.txid, 'fakeTxid')
271
+ assert.equal(result.txData.isValidSlp, false)
272
+ })
273
+
274
+ it('should return isValidSlp=null for blacklisted token', async () => {
275
+ // Stub the call to the SLP indexer.
276
+ const testErr = {
277
+ response: { data: { error: 'Key not found in database' } }
278
+ }
279
+ sandbox.stub(axios, 'post').rejects(testErr)
280
+
281
+ // Stub the call to the full node
282
+ sandbox.stub(bchjs.PsfSlpIndexer, 'checkBlacklist').resolves(true)
283
+ sandbox
284
+ .stub(bchjs.PsfSlpIndexer.rawTransaction, 'getTxData')
285
+ .resolves({ txid: 'fakeTxid' })
286
+
287
+ const txid =
288
+ 'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2'
289
+ const result = await bchjs.PsfSlpIndexer.tx(txid)
290
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
291
+
292
+ assert.equal(result.txData.txid, 'fakeTxid')
293
+ assert.equal(result.txData.isValidSlp, null)
294
+ })
295
+ })
296
+
297
+ describe('#checkBlacklist', () => {
298
+ it('should return true if txid contains token in blacklist', async () => {
299
+ // Mock dependencies
300
+ sandbox
301
+ .stub(bchjs.PsfSlpIndexer.slpUtils, 'decodeOpReturn')
302
+ .resolves(mockData.tokenData01)
303
+
304
+ const txid =
305
+ '302113c11b90edc5f36c073d2f8a75e1e0eaf59b56235491a843d3819cd6a85f'
306
+
307
+ const result = await bchjs.PsfSlpIndexer.checkBlacklist(txid)
308
+ // console.log('result: ', result)
309
+
310
+ assert.equal(result, true)
311
+ })
312
+
313
+ it('should return false if there is an error', async () => {
314
+ // Force an error
315
+ sandbox
316
+ .stub(bchjs.PsfSlpIndexer.slpUtils, 'decodeOpReturn')
317
+ .rejects(new Error('test error'))
318
+
319
+ const result = await bchjs.PsfSlpIndexer.checkBlacklist()
320
+
321
+ assert.equal(result, false)
322
+ })
323
+
324
+ it('should return false if there is no tokenId match', async () => {
325
+ // Mock dependencies
326
+ mockData.tokenData01.tokenId = 'abc123'
327
+ sandbox
328
+ .stub(bchjs.PsfSlpIndexer.slpUtils, 'decodeOpReturn')
329
+ .resolves(mockData.tokenData01)
330
+
331
+ const txid =
332
+ '302113c11b90edc5f36c073d2f8a75e1e0eaf59b56235491a843d3819cd6a85f'
333
+
334
+ const result = await bchjs.PsfSlpIndexer.checkBlacklist(txid)
335
+
336
+ assert.equal(result, false)
262
337
  })
263
338
  })
264
339
  })
@@ -15,7 +15,7 @@ describe('#utxo', () => {
15
15
  beforeEach(() => (sandbox = sinon.createSandbox()))
16
16
  afterEach(() => sandbox.restore())
17
17
 
18
- describe('#get', () => {
18
+ describe('#getOld', () => {
19
19
  it('should get hydrated and filtered UTXOs for an address', async () => {
20
20
  // Mock dependencies.
21
21
  sandbox.stub(bchjs.Utxo.electrumx, 'utxo').resolves(mockData.mockUtxoData)
@@ -25,7 +25,7 @@ describe('#utxo', () => {
25
25
 
26
26
  const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
27
27
 
28
- const result = await bchjs.Utxo.get(addr)
28
+ const result = await bchjs.Utxo.getOld(addr)
29
29
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
30
30
 
31
31
  assert.isArray(result)
@@ -46,7 +46,7 @@ describe('#utxo', () => {
46
46
 
47
47
  const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
48
48
 
49
- await bchjs.Utxo.get(addr)
49
+ await bchjs.Utxo.getOld(addr)
50
50
 
51
51
  assert.fail('Unexpected code path')
52
52
  } catch (err) {
@@ -66,7 +66,7 @@ describe('#utxo', () => {
66
66
  'bitcoincash:qqh793x9au6ehvh7r2zflzguanlme760wuzehgzjh9'
67
67
  ]
68
68
 
69
- const result = await bchjs.Utxo.get(addr)
69
+ const result = await bchjs.Utxo.getOld(addr)
70
70
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
71
71
 
72
72
  assert.isArray(result)
@@ -88,7 +88,7 @@ describe('#utxo', () => {
88
88
  addrs.push(addr)
89
89
  }
90
90
 
91
- await bchjs.Utxo.get(addrs)
91
+ await bchjs.Utxo.getOld(addrs)
92
92
 
93
93
  assert.fail('Unexpected code path')
94
94
  } catch (err) {
@@ -105,7 +105,7 @@ describe('#utxo', () => {
105
105
 
106
106
  const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
107
107
 
108
- const result = await bchjs.Utxo.get(addr)
108
+ const result = await bchjs.Utxo.getOld(addr)
109
109
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
110
110
 
111
111
  assert.isArray(result)
@@ -133,7 +133,7 @@ describe('#utxo', () => {
133
133
  const addr = 'simpleledger:qzv3zz2trz0xgp6a96lu4m6vp2nkwag0kvyucjzqt9'
134
134
  const useWhitelist = true
135
135
 
136
- const result = await bchjs.Utxo.get(addr, useWhitelist)
136
+ const result = await bchjs.Utxo.getOld(addr, useWhitelist)
137
137
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
138
138
 
139
139
  assert.isArray(result)
@@ -188,4 +188,48 @@ describe('#utxo', () => {
188
188
  assert.equal(result.satoshis, 800)
189
189
  })
190
190
  })
191
+
192
+ describe('#get', () => {
193
+ it('should throw an error if input is not a string', async () => {
194
+ try {
195
+ const addr = 123
196
+
197
+ await bchjs.Utxo.get(addr)
198
+
199
+ assert.fail('Unexpected code path')
200
+ } catch (err) {
201
+ assert.include(err.message, 'address input must be a string')
202
+ }
203
+ })
204
+
205
+ it('should return UTXO information', async () => {
206
+ // mock dependencies
207
+ sandbox
208
+ .stub(bchjs.Utxo.electrumx, 'utxo')
209
+ .resolves(mockData.fulcrumUtxos01)
210
+ sandbox
211
+ .stub(bchjs.Utxo.psfSlpIndexer, 'balance')
212
+ .resolves(mockData.psfSlpIndexerUtxos01)
213
+
214
+ const addr = 'simpleledger:qrm0c67wwqh0w7wjxua2gdt2xggnm90xwsr5k22euj'
215
+
216
+ const result = await bchjs.Utxo.get(addr)
217
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
218
+
219
+ // Assert expected properties exist
220
+ assert.property(result, 'address')
221
+ assert.property(result, 'bchUtxos')
222
+ assert.property(result, 'slpUtxos')
223
+ assert.property(result.slpUtxos, 'type1')
224
+ assert.property(result.slpUtxos.type1, 'tokens')
225
+ assert.property(result.slpUtxos.type1, 'mintBatons')
226
+ assert.property(result.slpUtxos, 'nft')
227
+ assert.property(result, 'nullUtxos')
228
+
229
+ assert.equal(result.bchUtxos.length, 4)
230
+ assert.equal(result.slpUtxos.type1.tokens.length, 1)
231
+ assert.equal(result.slpUtxos.type1.mintBatons.length, 1)
232
+ assert.equal(result.nullUtxos.length, 0)
233
+ })
234
+ })
191
235
  })