@psf/bch-js 6.3.3 → 6.4.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": "6.3.3",
3
+ "version": "6.4.1",
4
4
  "description": "A JavaScript library for working with Bitcoin Cash, eCash, and SLP Tokens",
5
5
  "author": "Chris Troutner <chris.troutner@gmail.com>",
6
6
  "contributors": [
package/src/utxo.js CHANGED
@@ -10,6 +10,7 @@ const Electrumx = require('./electrumx')
10
10
  const Slp = require('./slp/slp')
11
11
  const PsfSlpIndexer = require('./psf-slp-indexer')
12
12
  const BigNumber = require('bignumber.js')
13
+ const Blockchain = require('./blockchain')
13
14
 
14
15
  class UTXO {
15
16
  constructor (config = {}) {
@@ -18,6 +19,7 @@ class UTXO {
18
19
  this.slp = new Slp(config)
19
20
  this.psfSlpIndexer = new PsfSlpIndexer(config)
20
21
  this.BigNumber = BigNumber
22
+ this.blockchain = new Blockchain(config)
21
23
  }
22
24
 
23
25
  /**
@@ -207,7 +209,7 @@ class UTXO {
207
209
 
208
210
  return outObj
209
211
  } catch (err) {
210
- console.error('Error in bchjs.Utxo.get(): ', err)
212
+ console.error('Error in bchjs.Utxo.get()')
211
213
 
212
214
  if (err.error) throw new Error(err.error)
213
215
  throw err
@@ -336,6 +338,57 @@ class UTXO {
336
338
 
337
339
  return utxos[largestIndex]
338
340
  }
341
+
342
+ /**
343
+ * @api Utxo.isValid() isValid()
344
+ * @apiName isValid
345
+ * @apiGroup UTXO
346
+ * @apiDescription Validate that UTXO exists and is still spendable.
347
+ *
348
+ * Given a UTXO, this method will return true if the UTXO is still in the
349
+ * mempool and still valid for spending. It will return false if the UTXO
350
+ * has been spent.
351
+ *
352
+ * @apiExample Example usage:
353
+ * (async () => {
354
+ * try {
355
+ * const utxos = await bchjs.Utxo.get('bitcoincash:qq54fgjn3hz0357n8a6guy4demw9xfkjk5jcj0xr0z');
356
+ * const isValid = bchjs.Utxo.isValid(utxos.bchUtxos[0])
357
+ * console.log(isValid);
358
+ * } catch(error) {
359
+ * console.error(error)
360
+ * }
361
+ * })()
362
+ *
363
+ * // returns
364
+ * true
365
+ */
366
+ async isValid (utxo) {
367
+ try {
368
+ // console.log('utxo: ', utxo)
369
+
370
+ // Convert different properties from different indexers
371
+ const txid = utxo.txid || utxo.tx_hash
372
+ const vout = utxo.vout | utxo.tx_pos
373
+
374
+ // Query the full node
375
+ const txOut = await this.blockchain.getTxOut(txid, vout, true)
376
+ // console.log('txOut: ', txOut)
377
+
378
+ // Simplify results to either true or false.
379
+ let isValid = null
380
+ if (txOut === null) {
381
+ isValid = false
382
+ } else {
383
+ isValid = true
384
+ }
385
+
386
+ return isValid
387
+ } catch (err) {
388
+ console.log('Error in Utxo.isValid()')
389
+ throw err
390
+ }
391
+ }
339
392
  }
340
393
 
341
394
  module.exports = UTXO
@@ -128,7 +128,7 @@ describe('#psf-slp-indexer', () => {
128
128
  describe('#getTokenData', () => {
129
129
  it('should get token data', async () => {
130
130
  const tokenId =
131
- 'f055256b938f1ecfa270459d6f12c7c8c82b66d3263c03d5074445a2b1a498a3'
131
+ 'd9aafa7acb514c597caf440ae268b5e4e955f2687e05f044cdf8fd9550d9a27b'
132
132
 
133
133
  // bchjs.PsfSlpIndexer.restURL = 'http://localhost:3000/v5/'
134
134
  const result = await bchjs.PsfSlpIndexer.getTokenData(tokenId)
@@ -84,7 +84,7 @@ describe('#UTXO', () => {
84
84
  })
85
85
 
86
86
  it('should handle Type1 minting batons', async () => {
87
- const addr = 'simpleledger:qz5l5yzz9r09hw9aadcz53elp2knx6gyg5qk3s8md7'
87
+ const addr = 'simpleledger:qrp4mlmsrtwlvjn4seuchvtmus06tuqmpv4awvv7m7'
88
88
 
89
89
  const result = await bchjs.Utxo.get(addr)
90
90
  // console.log(`result: ${JSON.stringify(result, null, 2)}`)
@@ -122,6 +122,65 @@ describe('#UTXO', () => {
122
122
  assert.isAbove(result.slpUtxos.nft.tokens.length, 0)
123
123
  })
124
124
  })
125
+
126
+ describe('#isValid', () => {
127
+ it('should return true for valid UTXO with fullnode properties', async () => {
128
+ const utxo = {
129
+ txid: 'b94e1ff82eb5781f98296f0af2488ff06202f12ee92b0175963b8dba688d1b40',
130
+ vout: 0
131
+ }
132
+
133
+ const result = await bchjs.Utxo.isValid(utxo)
134
+ // console.log('result: ', result)
135
+
136
+ assert.equal(result, true)
137
+ })
138
+
139
+ it('should return true for valid UTXO with fulcrum properties', async () => {
140
+ const utxo = {
141
+ tx_hash: 'b94e1ff82eb5781f98296f0af2488ff06202f12ee92b0175963b8dba688d1b40',
142
+ tx_pos: 0
143
+ }
144
+
145
+ const result = await bchjs.Utxo.isValid(utxo)
146
+ // console.log('result: ', result)
147
+
148
+ assert.equal(result, true)
149
+ })
150
+
151
+ it('should return true for valid UTXO with fullnode properties', async () => {
152
+ const utxo = {
153
+ txid: '17754221b29f189532d4fc2ae89fb467ad2dede30fdec4854eb2129b3ba90d7a',
154
+ vout: 0
155
+ }
156
+
157
+ const result = await bchjs.Utxo.isValid(utxo)
158
+ // console.log('result: ', result)
159
+
160
+ assert.equal(result, false)
161
+ })
162
+
163
+ it('should return true for valid UTXO with fulcrum properties', async () => {
164
+ const utxo = {
165
+ tx_hash: '17754221b29f189532d4fc2ae89fb467ad2dede30fdec4854eb2129b3ba90d7a',
166
+ tx_pos: 0
167
+ }
168
+
169
+ const result = await bchjs.Utxo.isValid(utxo)
170
+ // console.log('result: ', result
171
+
172
+ assert.equal(result, false)
173
+ })
174
+
175
+ it('should process output of Utxo.get()', async () => {
176
+ const utxo = await bchjs.Utxo.get('bitcoincash:qr4yscpw9jgq8ltajfeknpj32kamkf9knujffcdhyq')
177
+ // console.log(`utxo: ${JSON.stringify(utxo, null, 2)}`)
178
+
179
+ const result = await bchjs.Utxo.isValid(utxo.bchUtxos[0])
180
+
181
+ assert.equal(result, true)
182
+ })
183
+ })
125
184
  })
126
185
 
127
186
  function sleep (ms) {
@@ -174,4 +174,36 @@ describe('#utxo', () => {
174
174
  assert.equal(result.nullUtxos.length, 0)
175
175
  })
176
176
  })
177
+
178
+ describe('#isValid', () => {
179
+ it('should return false if getTxOut() returns null', async () => {
180
+ // Mock dependencies
181
+ sandbox.stub(bchjs.Utxo.blockchain, 'getTxOut').resolves(null)
182
+
183
+ const utxo = {
184
+ tx_hash: '17754221b29f189532d4fc2ae89fb467ad2dede30fdec4854eb2129b3ba90d7a',
185
+ tx_pos: 0
186
+ }
187
+
188
+ const result = await bchjs.Utxo.isValid(utxo)
189
+ // console.log('result: ', result
190
+
191
+ assert.equal(result, false)
192
+ })
193
+
194
+ it('should return true if getTxOut() returns non-null output', async () => {
195
+ // Mock dependencies
196
+ sandbox.stub(bchjs.Utxo.blockchain, 'getTxOut').resolves({ a: 'b' })
197
+
198
+ const utxo = {
199
+ tx_hash: 'b94e1ff82eb5781f98296f0af2488ff06202f12ee92b0175963b8dba688d1b40',
200
+ tx_pos: 0
201
+ }
202
+
203
+ const result = await bchjs.Utxo.isValid(utxo)
204
+ // console.log('result: ', result
205
+
206
+ assert.equal(result, true)
207
+ })
208
+ })
177
209
  })