@psf/bch-js 4.20.12 → 4.20.16

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": "4.20.12",
3
+ "version": "4.20.16",
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": [
@@ -54,7 +54,7 @@
54
54
  "bip66": "^1.1.5",
55
55
  "bitcoinjs-message": "^2.0.0",
56
56
  "bs58": "^4.0.1",
57
- "cashaddrjs": "^0.3.3",
57
+ "ecashaddrjs": "^1.0.7",
58
58
  "ini": "^1.3.8",
59
59
  "randombytes": "^2.0.6",
60
60
  "safe-buffer": "^5.1.2",
@@ -76,9 +76,9 @@
76
76
  "eslint-plugin-standard": "^4.0.0",
77
77
  "husky": "^4.3.6",
78
78
  "lodash.clonedeep": "^4.5.0",
79
- "mocha": "^6.1.4",
79
+ "mocha": "^9.1.3",
80
80
  "node-mocks-http": "^1.7.0",
81
- "nyc": "^14.1.0",
81
+ "nyc": "^15.1.0",
82
82
  "prettier": "^1.18.2",
83
83
  "semantic-release": "^17.3.9",
84
84
  "sinon": "^7.3.2",
package/src/address.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // const axios = require("axios")
2
2
  const Bitcoin = require('@psf/bitcoincashjs-lib')
3
- const cashaddr = require('cashaddrjs')
3
+ const cashaddr = require('ecashaddrjs')
4
4
  const coininfo = require('@psf/coininfo')
5
5
 
6
6
  class Address {
@@ -129,6 +129,63 @@ class Address {
129
129
  return cashAddress.split(':')[1]
130
130
  }
131
131
 
132
+ /**
133
+ * @api Address.toEcashAddress() toEcashAddress()
134
+ * @apiName toEcashAddress
135
+ * @apiGroup Address
136
+ * @apiDescription Convert legacy to cashAddress format
137
+ *
138
+ * @apiExample Example usage:
139
+ * // mainnet
140
+ * bchjs.Address.toEcashAddress('bitcoincash:qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2')
141
+ * // ecash:qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da
142
+ *
143
+ * // mainnet no prefix
144
+ * bchjs.Address.toEcashAddress('bitcoincash:qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2', false)
145
+ * // qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da
146
+ *
147
+ */
148
+ toEcashAddress (address, prefix = true) {
149
+ const decoded = this._decode(address)
150
+
151
+ const ecashAddress = cashaddr.encode(
152
+ 'ecash',
153
+ decoded.type,
154
+ decoded.hash
155
+ )
156
+
157
+ if (prefix) return ecashAddress
158
+ return ecashAddress.split(':')[1]
159
+ }
160
+
161
+ /**
162
+ * @api Address.ecashtoCashAddress() ecashtoCashAddress()
163
+ * @apiName ecashtoCashAddress
164
+ * @apiGroup Address
165
+ * @apiDescription Convert legacy to cashAddress format
166
+ *
167
+ * @apiExample Example usage:
168
+ * // mainnet
169
+ * bchjs.Address.ecashtoCashAddress('ecash:qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da')
170
+ * // bitcoincash:qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2
171
+ *
172
+ * // mainnet no prefix
173
+ * bchjs.Address.ecashtoCashAddress('ecash:qq50d800hgunr8u4trz3uuppspk3mds0dyug2v69da', false)
174
+ * // qq50d800hgunr8u4trz3uuppspk3mds0dy9978plt2
175
+ */
176
+ ecashtoCashAddress (address, prefix = true) {
177
+ const decoded = this._decodeEcashAddress(address)
178
+
179
+ const cashAddress = cashaddr.encode(
180
+ 'bitcoincash',
181
+ decoded.type,
182
+ decoded.hash
183
+ )
184
+
185
+ if (prefix) return cashAddress
186
+ return cashAddress.split(':')[1]
187
+ }
188
+
132
189
  // Converts any address format to hash160
133
190
  toHash160 (address) {
134
191
  const legacyAddress = this.toLegacyAddress(address)
@@ -271,6 +328,22 @@ class Address {
271
328
  throw new Error(`Invalid format : ${address}`)
272
329
  }
273
330
 
331
+ _decodeEcashAddress (address) {
332
+ if (address.indexOf(':') !== -1) {
333
+ const decoded = cashaddr.decode(address)
334
+ decoded.format = 'cashaddr'
335
+ return decoded
336
+ }
337
+
338
+ try {
339
+ const decoded = cashaddr.decode(`ecash:${address}`)
340
+ decoded.format = 'cashaddr'
341
+ return decoded
342
+ } catch (error) {}
343
+
344
+ throw new Error(`Invalid format : ${address}`)
345
+ }
346
+
274
347
  /**
275
348
  * @api Address.isLegacyAddress() isLegacyAddress()
276
349
  * @apiName isLegacyAddress
package/src/price.js CHANGED
@@ -128,7 +128,7 @@ class Price {
128
128
  * @apiGroup Price
129
129
  * @apiDescription Return current price of BCHA in USD.
130
130
  * This endpoint gets the USD price of XEC from the Coinex API. The price
131
- * denominated in BCHA comes from bch-api, so it has a better chance of
131
+ * denominated in BCHA comes from bch-api, so it has a better chance of
132
132
  * working in Tor.
133
133
  *
134
134
  * @apiExample Example usage:
@@ -150,7 +150,7 @@ class Price {
150
150
  this.axiosOptions
151
151
  )
152
152
  // console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
153
-
153
+
154
154
  const bchaPrice = response.data.usd * 1000000
155
155
  // Convert XEC denomination to BCHA denomination
156
156
 
@@ -161,7 +161,7 @@ class Price {
161
161
  }
162
162
  }
163
163
 
164
- /**
164
+ /**
165
165
  * @api price.getXecUsd() getXecUsd()
166
166
  * @apiName Price getXecUsd()
167
167
  * @apiGroup Price
@@ -179,9 +179,9 @@ class Price {
179
179
  * }
180
180
  *})()
181
181
  *
182
- * // 0.00021234
182
+ * // 0.00021234
183
183
  */
184
- async getXecUsd () {
184
+ async getXecUsd () {
185
185
  try {
186
186
  const response = await this.axios.get(
187
187
  `${this.restURL}price/bchausd`,
@@ -319,6 +319,9 @@ class RawTransactions {
319
319
  const inputTxid = vin.txid
320
320
  const inputVout = vin.vout
321
321
 
322
+ // TODO: Coinbase TXs have no input transaction. Figure out how to
323
+ // handle this corner case.
324
+
322
325
  // Get the TX details for the input, in order to retrieve the address of
323
326
  // the sender.
324
327
  const txDetailsParent = await this.getRawTransaction(inputTxid, true)
@@ -287,9 +287,15 @@ class TokenType1 {
287
287
  try {
288
288
  // TODO: Add input validation.
289
289
 
290
- let baseQty = new BigNumber(configObj.initialQty).times(
291
- 10 ** configObj.decimals
292
- )
290
+ let baseQty
291
+ if (configObj.decimals !== 0) {
292
+ baseQty = new BigNumber(configObj.initialQty).times(
293
+ 10 ** configObj.decimals
294
+ )
295
+ } else {
296
+ baseQty = new BigNumber(configObj.initialQty)
297
+ }
298
+
293
299
  baseQty = baseQty.absoluteValue()
294
300
  baseQty = Math.floor(baseQty)
295
301
  baseQty = baseQty.toString()
package/src/slp/utils.js CHANGED
@@ -921,7 +921,7 @@ class Utils {
921
921
  * const txid =
922
922
  * "266844d53e46bbd7dd37134688dffea6e54d944edff27a0add63dd0908839bc1"
923
923
  *
924
- * const data = await slp.Utils.decodeOpReturn2(txid)
924
+ * const data = await bchjs.SLP.Utils.decodeOpReturn(txid)
925
925
  *
926
926
  * console.log(`Decoded OP_RETURN data: ${JSON.stringify(data,null,2)}`)
927
927
  * } catch (error) {
@@ -4,6 +4,7 @@
4
4
 
5
5
  const RawTransaction = require('./raw-transactions')
6
6
  const SlpUtils = require('./slp/utils')
7
+ const BigNumber = require('bignumber.js')
7
8
 
8
9
  class Transaction {
9
10
  constructor (config) {
@@ -75,9 +76,18 @@ class Transaction {
75
76
  // Add the token quantity to each output.
76
77
  for (let i = 0; i < outTokenData.amounts.length; i++) {
77
78
  const rawQty = outTokenData.amounts[i]
78
- const realQty = Number(rawQty) / Math.pow(10, txDetails.tokenDecimals)
79
-
80
- txDetails.vout[i + 1].tokenQty = realQty
79
+ // const realQty = Number(rawQty) / Math.pow(10, txDetails.tokenDecimals)
80
+
81
+ // Calculate the real quantity using a BigNumber, then convert it to a
82
+ // floating point number.
83
+ let realQty = new BigNumber(rawQty).dividedBy(
84
+ 10 ** parseInt(txDetails.tokenDecimals)
85
+ )
86
+ realQty = realQty.toString()
87
+ // realQty = parseFloat(realQty)
88
+
89
+ txDetails.vout[i + 1].tokenQtyStr = realQty
90
+ txDetails.vout[i + 1].tokenQty = parseFloat(realQty)
81
91
  }
82
92
 
83
93
  // Add tokenQty = null to any outputs that don't have a value.
@@ -101,17 +111,49 @@ class Transaction {
101
111
  // `vin[${i}] tokenData: ${JSON.stringify(inTokenData, null, 2)}`
102
112
  // )
103
113
 
104
- // Get the appropriate vout token amount. This may throw an error,
105
- // which means this Vin is not actually a token UTXO, it was just
106
- // associated with a previous token TX.
107
- const tokenQty = inTokenData.amounts[thisVin.vout - 1]
108
- // console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
114
+ let tokenQty = 0
115
+ if (inTokenData.txType === 'SEND') {
116
+ // Get the appropriate vout token amount. This may throw an error,
117
+ // which means this Vin is not actually a token UTXO, it was just
118
+ // associated with a previous token TX.
119
+ tokenQty = inTokenData.amounts[thisVin.vout - 1]
120
+ // console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
121
+
122
+ //
123
+ } else if (inTokenData.txType === 'GENESIS') {
124
+ // Only vout[1] of a Genesis transaction represents the tokens.
125
+ // Any other outputs in that transaction are normal BCH UTXOs.
126
+ if (thisVin.vout === 1) {
127
+ tokenQty = inTokenData.qty
128
+ // console.log(`tokenQty: ${JSON.stringify(tokenQty, null, 2)}`)
129
+ }
130
+ } else if (inTokenData.txType === 'MINT') {
131
+ // vout=1 (second output) recieves the newly minted tokens.
132
+ tokenQty = inTokenData.qty
133
+
134
+ //
135
+ } else {
136
+ console.log(
137
+ 'Unexpected code path in Transaction.get(). What is the txType?'
138
+ )
139
+ console.log(inTokenData)
140
+ throw new Error('Unexpected code path')
141
+ }
109
142
 
110
143
  if (tokenQty) {
111
- const realQty =
112
- Number(tokenQty) / Math.pow(10, txDetails.tokenDecimals)
113
-
114
- thisVin.tokenQty = realQty
144
+ // const realQty =
145
+ // Number(tokenQty) / Math.pow(10, txDetails.tokenDecimals)
146
+
147
+ // Calculate the real quantity using a BigNumber, then convert it to a
148
+ // floating point number.
149
+ let realQty = new BigNumber(tokenQty).dividedBy(
150
+ 10 ** parseInt(txDetails.tokenDecimals)
151
+ )
152
+ realQty = realQty.toString()
153
+ // realQty = parseFloat(realQty)
154
+
155
+ thisVin.tokenQtyStr = realQty
156
+ thisVin.tokenQty = parseFloat(realQty)
115
157
  // txDetails.vin[i].tokenQty = tokenQty
116
158
  } else {
117
159
  thisVin.tokenQty = null
@@ -175,10 +175,261 @@ const mockOpReturnData03 = {
175
175
  amounts: ['1000000000', '99883400000000']
176
176
  }
177
177
 
178
+ const genesisTestInputTx = {
179
+ txid: '874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e',
180
+ hash: '874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e',
181
+ version: 1,
182
+ size: 480,
183
+ locktime: 543408,
184
+ vin: [
185
+ {
186
+ txid: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
187
+ vout: 1,
188
+ scriptSig: {
189
+ asm:
190
+ '30440220268dacee1117975d904dd0d45ef8de42b86030d825a9522bae196a38bbf6b271022001ae1ce2536ab300040e597bcfaa8ef9fb2beaf702d0842f3161aae8e9867f55[ALL|FORKID] 028ff9e32b0dbc82c1d5e0fc945b2537b00420513b10684726f312f1b717c0ae11',
191
+ hex:
192
+ '4730440220268dacee1117975d904dd0d45ef8de42b86030d825a9522bae196a38bbf6b271022001ae1ce2536ab300040e597bcfaa8ef9fb2beaf702d0842f3161aae8e9867f554121028ff9e32b0dbc82c1d5e0fc945b2537b00420513b10684726f312f1b717c0ae11'
193
+ },
194
+ sequence: 4294967294,
195
+ address: 'bitcoincash:qp2jesd06k8ycj4wvkpl9lcwaemtr04f5yphjsa07v',
196
+ value: 0.00000546
197
+ },
198
+ {
199
+ txid: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
200
+ vout: 3,
201
+ scriptSig: {
202
+ asm:
203
+ '3045022100fa241bb2de46f68688451bfcae3f165b724e3ccf13b219e7bf2d8d2df7712ad60220353017d6e581a06efce478adfcd2047cea2f92531e283845f3d0a345ef101519[ALL|FORKID] 02cc48ad10516f97e914b8836ff25448d07ad96ebb4704c6a828339880280831bc',
204
+ hex:
205
+ '483045022100fa241bb2de46f68688451bfcae3f165b724e3ccf13b219e7bf2d8d2df7712ad60220353017d6e581a06efce478adfcd2047cea2f92531e283845f3d0a345ef101519412102cc48ad10516f97e914b8836ff25448d07ad96ebb4704c6a828339880280831bc'
206
+ },
207
+ sequence: 4294967294,
208
+ address: 'bitcoincash:qppj3euc36x5u6twr5cxrrea2rca53vsfu3dxwr86j',
209
+ value: 0.00172192
210
+ }
211
+ ],
212
+ vout: [
213
+ {
214
+ value: 0,
215
+ n: 0,
216
+ scriptPubKey: {
217
+ asm:
218
+ 'OP_RETURN 5262419 1 1145980243 323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35 00000000004c4b40 00000000004c4b40',
219
+ hex:
220
+ '6a04534c500001010453454e4420323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d350800000000004c4b400800000000004c4b40',
221
+ type: 'nulldata'
222
+ }
223
+ },
224
+ {
225
+ value: 0.00000546,
226
+ n: 1,
227
+ scriptPubKey: {
228
+ asm:
229
+ 'OP_DUP OP_HASH160 0a74cf9c0fb3f6dd62c3f5eecd1ed6e1051428e0 OP_EQUALVERIFY OP_CHECKSIG',
230
+ hex: '76a9140a74cf9c0fb3f6dd62c3f5eecd1ed6e1051428e088ac',
231
+ reqSigs: 1,
232
+ type: 'pubkeyhash',
233
+ addresses: ['bitcoincash:qq98fnuup7eldhtzc067ang76mss29pguqh7qv9eac']
234
+ }
235
+ },
236
+ {
237
+ value: 0.00000546,
238
+ n: 2,
239
+ scriptPubKey: {
240
+ asm:
241
+ 'OP_DUP OP_HASH160 d4548261e1be0de7e50b7511597799ec4af2b173 OP_EQUALVERIFY OP_CHECKSIG',
242
+ hex: '76a914d4548261e1be0de7e50b7511597799ec4af2b17388ac',
243
+ reqSigs: 1,
244
+ type: 'pubkeyhash',
245
+ addresses: ['bitcoincash:qr29fqnpuxlqmel9pd63zkthn8ky4u43wv0v7pg5mn']
246
+ }
247
+ },
248
+ {
249
+ value: 0.00171165,
250
+ n: 3,
251
+ scriptPubKey: {
252
+ asm:
253
+ 'OP_DUP OP_HASH160 d4548261e1be0de7e50b7511597799ec4af2b173 OP_EQUALVERIFY OP_CHECKSIG',
254
+ hex: '76a914d4548261e1be0de7e50b7511597799ec4af2b17388ac',
255
+ reqSigs: 1,
256
+ type: 'pubkeyhash',
257
+ addresses: ['bitcoincash:qr29fqnpuxlqmel9pd63zkthn8ky4u43wv0v7pg5mn']
258
+ }
259
+ }
260
+ ],
261
+ hex:
262
+ '0100000002359dab0d9c8ddc788b14c0b51493d195c9fbd9f2203d091663350bae351e3a32010000006a4730440220268dacee1117975d904dd0d45ef8de42b86030d825a9522bae196a38bbf6b271022001ae1ce2536ab300040e597bcfaa8ef9fb2beaf702d0842f3161aae8e9867f554121028ff9e32b0dbc82c1d5e0fc945b2537b00420513b10684726f312f1b717c0ae11feffffff359dab0d9c8ddc788b14c0b51493d195c9fbd9f2203d091663350bae351e3a32030000006b483045022100fa241bb2de46f68688451bfcae3f165b724e3ccf13b219e7bf2d8d2df7712ad60220353017d6e581a06efce478adfcd2047cea2f92531e283845f3d0a345ef101519412102cc48ad10516f97e914b8836ff25448d07ad96ebb4704c6a828339880280831bcfeffffff040000000000000000406a04534c500001010453454e4420323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d350800000000004c4b400800000000004c4b4022020000000000001976a9140a74cf9c0fb3f6dd62c3f5eecd1ed6e1051428e088ac22020000000000001976a914d4548261e1be0de7e50b7511597799ec4af2b17388ac9d9c0200000000001976a914d4548261e1be0de7e50b7511597799ec4af2b17388acb04a0800',
263
+ blockhash: '000000000000000000292a9c6150fce48e2edd8df346948494fe6249e6e7f63b',
264
+ confirmations: 163095,
265
+ time: 1534271330,
266
+ blocktime: 1534271330
267
+ }
268
+
269
+ const mintTestInputTx = {
270
+ txid: '4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa',
271
+ hash: '4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa',
272
+ version: 1,
273
+ size: 585,
274
+ locktime: 543613,
275
+ vin: [
276
+ {
277
+ txid: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
278
+ vout: 1,
279
+ scriptSig: {
280
+ asm: '3045022100e3d5f9a48f9aa1cf7e9ed1992e0281e7300b734ba0e4bd5bb9265b2be60bd71002200ccde53ce7ea9da9df3e834f234f3bea65c2e58c96f8436f93333fd8946a1db2[ALL|FORKID] 02056220984cc2cf5261a27d4f66d31c9ef601a688ca1a5ab81e55b6f0d311be74',
281
+ hex: '483045022100e3d5f9a48f9aa1cf7e9ed1992e0281e7300b734ba0e4bd5bb9265b2be60bd71002200ccde53ce7ea9da9df3e834f234f3bea65c2e58c96f8436f93333fd8946a1db2412102056220984cc2cf5261a27d4f66d31c9ef601a688ca1a5ab81e55b6f0d311be74'
282
+ },
283
+ sequence: 4294967294,
284
+ address: 'bitcoincash:qpaf9wltgmpjlg2vxwwu7zdw5y4z7m277ckxn8cufl',
285
+ value: 0.00000546,
286
+ tokenQtyStr: '43545.34534',
287
+ tokenQty: 43545.34534
288
+ },
289
+ {
290
+ txid: 'ee9d3cf5153599c134147e3fac9844c68e216843f4452a1ce15a29452af6db34',
291
+ vout: 1,
292
+ scriptSig: {
293
+ asm: '3045022100bb90d52be9b568f643fdb1a302e9f063be27a9f914e2a6b192cbabf2cbdeaf9302203c275fc8d1b82390bc1726390d361c5266056bddd54dec23efa207c79eacea4a[ALL|FORKID] 024146cfcd0c02e99d6451dc48ad0f97114aeda18fe55c52a10bfc0490f314e6a2',
294
+ hex: '483045022100bb90d52be9b568f643fdb1a302e9f063be27a9f914e2a6b192cbabf2cbdeaf9302203c275fc8d1b82390bc1726390d361c5266056bddd54dec23efa207c79eacea4a4121024146cfcd0c02e99d6451dc48ad0f97114aeda18fe55c52a10bfc0490f314e6a2'
295
+ },
296
+ sequence: 4294967294,
297
+ address: 'bitcoincash:qqf89zzwd0fqc3npkks997r5l7dpfjf9kgx2rqu500',
298
+ value: 0.00000546,
299
+ tokenQtyStr: '2.34123',
300
+ tokenQty: 2.34123
301
+ },
302
+ {
303
+ txid: 'ee9d3cf5153599c134147e3fac9844c68e216843f4452a1ce15a29452af6db34',
304
+ vout: 3,
305
+ scriptSig: {
306
+ asm: '3044022029ab770c249f467b40bb90410429f6d657f9be299baa19a6838d04d972436b450220143660297e8e836bc16d317649fad8c310bdadb4fb61d4e9f6ba11203abe5dae[ALL|FORKID] 02eed4ac9dda3405d9b1ccbbf09f8056f3e7c615924274bd5643238b543d0a1d56',
307
+ hex: '473044022029ab770c249f467b40bb90410429f6d657f9be299baa19a6838d04d972436b450220143660297e8e836bc16d317649fad8c310bdadb4fb61d4e9f6ba11203abe5dae412102eed4ac9dda3405d9b1ccbbf09f8056f3e7c615924274bd5643238b543d0a1d56'
308
+ },
309
+ sequence: 4294967294,
310
+ address: 'bitcoincash:qqt30r33k0jx3sxe34tmupaujpaljnglmvqgrrfp2x',
311
+ value: 0.00054848,
312
+ tokenQtyStr: '2.34123',
313
+ tokenQty: 2.34123
314
+ }
315
+ ],
316
+ vout: [
317
+ {
318
+ value: 0,
319
+ n: 0,
320
+ scriptPubKey: {
321
+ asm: 'OP_RETURN 5262419 1 1145980243 938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8 0000000103907f11',
322
+ hex: '6a04534c500001010453454e4420938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8080000000103907f11',
323
+ type: 'nulldata'
324
+ },
325
+ tokenQty: null
326
+ },
327
+ {
328
+ value: 0.00000546,
329
+ n: 1,
330
+ scriptPubKey: {
331
+ asm: 'OP_DUP OP_HASH160 059775ff94f65c04e8a6847e74eb9809d8cd779b OP_EQUALVERIFY OP_CHECKSIG',
332
+ hex: '76a914059775ff94f65c04e8a6847e74eb9809d8cd779b88ac',
333
+ reqSigs: 1,
334
+ type: 'pubkeyhash',
335
+ addresses: [
336
+ 'bitcoincash:qqzewa0ljnm9cp8g56z8ua8tnqya3nthnvhv5hpu8y'
337
+ ]
338
+ },
339
+ tokenQtyStr: '43547.68657',
340
+ tokenQty: 43547.68657
341
+ },
342
+ {
343
+ value: 0.00054808,
344
+ n: 2,
345
+ scriptPubKey: {
346
+ asm: 'OP_DUP OP_HASH160 0e330dc9009e1e07831f5a22d4ade8977ab674c8 OP_EQUALVERIFY OP_CHECKSIG',
347
+ hex: '76a9140e330dc9009e1e07831f5a22d4ade8977ab674c888ac',
348
+ reqSigs: 1,
349
+ type: 'pubkeyhash',
350
+ addresses: [
351
+ 'bitcoincash:qq8rxrwfqz0pupurradz949dazth4dn5eqs3mhrucv'
352
+ ]
353
+ },
354
+ tokenQty: null
355
+ }
356
+ ],
357
+ hex: '0100000003f8cda53b43b0ea49991a9bc6c74eb901d2a8b964bc7b8987d76789618ec18c93010000006b483045022100e3d5f9a48f9aa1cf7e9ed1992e0281e7300b734ba0e4bd5bb9265b2be60bd71002200ccde53ce7ea9da9df3e834f234f3bea65c2e58c96f8436f93333fd8946a1db2412102056220984cc2cf5261a27d4f66d31c9ef601a688ca1a5ab81e55b6f0d311be74feffffff34dbf62a45295ae11c2a45f44368218ec64498ac3f7e1434c1993515f53c9dee010000006b483045022100bb90d52be9b568f643fdb1a302e9f063be27a9f914e2a6b192cbabf2cbdeaf9302203c275fc8d1b82390bc1726390d361c5266056bddd54dec23efa207c79eacea4a4121024146cfcd0c02e99d6451dc48ad0f97114aeda18fe55c52a10bfc0490f314e6a2feffffff34dbf62a45295ae11c2a45f44368218ec64498ac3f7e1434c1993515f53c9dee030000006a473044022029ab770c249f467b40bb90410429f6d657f9be299baa19a6838d04d972436b450220143660297e8e836bc16d317649fad8c310bdadb4fb61d4e9f6ba11203abe5dae412102eed4ac9dda3405d9b1ccbbf09f8056f3e7c615924274bd5643238b543d0a1d56feffffff030000000000000000376a04534c500001010453454e4420938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8080000000103907f1122020000000000001976a914059775ff94f65c04e8a6847e74eb9809d8cd779b88ac18d60000000000001976a9140e330dc9009e1e07831f5a22d4ade8977ab674c888ac7d4b0800',
358
+ blockhash: '00000000000000000140f0d813052da59c811a936494a8d8b2d60b215d19e3dc',
359
+ confirmations: 167007,
360
+ time: 1534391953,
361
+ blocktime: 1534391953,
362
+ isValidSLPTx: true,
363
+ tokenTxType: 'SEND',
364
+ tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
365
+ tokenTicker: 'Bubb2',
366
+ tokenName: 'the new bubbles!',
367
+ tokenDecimals: 5,
368
+ tokenUri: '',
369
+ tokenDocHash: ''
370
+ }
371
+
372
+ const genesisTestOpReturnData01 = {
373
+ tokenType: 1,
374
+ txType: 'SEND',
375
+ tokenId: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
376
+ amounts: ['5000000', '5000000']
377
+ }
378
+
379
+ const genesisTestOpReturnData02 = {
380
+ tokenType: 1,
381
+ txType: 'GENESIS',
382
+ ticker: '',
383
+ name: '',
384
+ tokenId: '323a1e35ae0b356316093d20f2d9fbc995d19314b5c0148b78dc8d9c0dab9d35',
385
+ documentUri: '',
386
+ documentHash: '',
387
+ decimals: 0,
388
+ mintBatonVout: 2,
389
+ qty: '10000000'
390
+ }
391
+
392
+ const mintTestOpReturnData01 = {
393
+ tokenType: 1,
394
+ txType: 'SEND',
395
+ tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
396
+ amounts: [
397
+ '4354768657'
398
+ ]
399
+ }
400
+
401
+ const mintTestOpReturnData02 = {
402
+ tokenType: 1,
403
+ txType: 'GENESIS',
404
+ ticker: 'Bubb2',
405
+ name: 'the new bubbles!',
406
+ tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
407
+ documentUri: '',
408
+ documentHash: '',
409
+ decimals: 5,
410
+ mintBatonVout: 2,
411
+ qty: '4354534534'
412
+ }
413
+
414
+ const mintTestOpReturnData03 = {
415
+ tokenType: 1,
416
+ txType: 'MINT',
417
+ tokenId: '938cc18e618967d787897bbc64b9a8d201b94ec7c69b1a9949eab0433ba5cdf8',
418
+ mintBatonVout: 2,
419
+ qty: '234123'
420
+ }
421
+
178
422
  module.exports = {
179
423
  nonSlpTxDetails,
180
424
  slpTxDetails,
181
425
  mockOpReturnData01,
182
426
  mockOpReturnData02,
183
- mockOpReturnData03
427
+ mockOpReturnData03,
428
+ genesisTestInputTx,
429
+ mintTestInputTx,
430
+ genesisTestOpReturnData01,
431
+ genesisTestOpReturnData02,
432
+ mintTestOpReturnData01,
433
+ mintTestOpReturnData02,
434
+ mintTestOpReturnData03
184
435
  }
@@ -115,5 +115,101 @@ describe('#TransactionLib', () => {
115
115
  assert.include(err.message, 'test error')
116
116
  }
117
117
  })
118
+
119
+ // This test case was created in response to a bug. When the input TX
120
+ // was a Genesis SLP transaction, the inputs of the transaction were not
121
+ // being hydrated properly.
122
+ it('should get input details when input is a genesis tx', async () => {
123
+ // Mock dependencies
124
+ sandbox
125
+ .stub(bchjs.Transaction.rawTransaction, 'getTxData')
126
+ .resolves(mockData.genesisTestInputTx)
127
+ sandbox
128
+ .stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
129
+ .onCall(0)
130
+ .resolves(mockData.genesisTestOpReturnData01)
131
+ .onCall(1)
132
+ .resolves(mockData.genesisTestOpReturnData02)
133
+ .onCall(2)
134
+ .resolves(mockData.genesisTestOpReturnData02)
135
+ .onCall(3)
136
+ .resolves(mockData.genesisTestOpReturnData02)
137
+ sandbox
138
+ .stub(bchjs.Transaction.slpUtils, 'waterfallValidateTxid')
139
+ .resolves(true)
140
+
141
+ const txid =
142
+ '874306bda204d3a5dd15e03ea5732cccdca4c33a52df35162cdd64e30ea7f04e'
143
+
144
+ const result = await bchjs.Transaction.get(txid)
145
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
146
+
147
+ // Assert that there are stanardized properties.
148
+ assert.property(result, 'txid')
149
+ assert.property(result, 'vin')
150
+ assert.property(result, 'vout')
151
+ assert.property(result.vout[0], 'value')
152
+ assert.property(result.vout[1].scriptPubKey, 'addresses')
153
+
154
+ // Assert that added properties exist.
155
+ assert.property(result.vout[0], 'tokenQty')
156
+ assert.equal(result.vout[0].tokenQty, null)
157
+ assert.property(result.vin[0], 'address')
158
+ assert.property(result.vin[0], 'value')
159
+ assert.property(result.vin[0], 'tokenQty')
160
+ assert.property(result, 'isValidSLPTx')
161
+ assert.equal(result.isValidSLPTx, true)
162
+
163
+ // Assert inputs values unique to a Genesis input have the proper values.
164
+ assert.equal(result.vin[0].tokenQty, 10000000)
165
+ assert.equal(result.vin[1].tokenQty, null)
166
+ })
167
+
168
+ it('should get input details when input is a mint tx', async () => {
169
+ // Mock dependencies
170
+ sandbox
171
+ .stub(bchjs.Transaction.rawTransaction, 'getTxData')
172
+ .resolves(mockData.mintTestInputTx)
173
+ sandbox
174
+ .stub(bchjs.Transaction.slpUtils, 'decodeOpReturn')
175
+ .onCall(0)
176
+ .resolves(mockData.mintTestOpReturnData01)
177
+ .onCall(1)
178
+ .resolves(mockData.mintTestOpReturnData02)
179
+ .onCall(2)
180
+ .resolves(mockData.mintTestOpReturnData02)
181
+ .onCall(3)
182
+ .resolves(mockData.mintTestOpReturnData03)
183
+ .onCall(4)
184
+ .resolves(mockData.mintTestOpReturnData03)
185
+ sandbox
186
+ .stub(bchjs.Transaction.slpUtils, 'waterfallValidateTxid')
187
+ .resolves(true)
188
+
189
+ const txid =
190
+ '4640a734063ea79fa587a3cac38a70a2f6f3db0011e23514024185982110d0fa'
191
+
192
+ const result = await bchjs.Transaction.get(txid)
193
+ // console.log(`result: ${JSON.stringify(result, null, 2)}`)
194
+
195
+ // Assert that there are stanardized properties.
196
+ assert.property(result, 'txid')
197
+ assert.property(result, 'vin')
198
+ assert.property(result, 'vout')
199
+ assert.property(result.vout[0], 'value')
200
+ assert.property(result.vout[1].scriptPubKey, 'addresses')
201
+
202
+ // Assert that added properties exist.
203
+ assert.property(result.vout[0], 'tokenQty')
204
+ assert.equal(result.vout[0].tokenQty, null)
205
+ assert.property(result.vin[0], 'address')
206
+ assert.property(result.vin[0], 'value')
207
+ assert.property(result.vin[0], 'tokenQty')
208
+ assert.property(result, 'isValidSLPTx')
209
+ assert.equal(result.isValidSLPTx, true)
210
+
211
+ // Assert inputs values unique to a Mint input have the proper values.
212
+ assert.equal(result.vin[2].tokenQty, 2.34123)
213
+ })
118
214
  })
119
215
  })