@exodus/bitcoin-api 2.9.2 → 2.9.3-hotfix

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.
Files changed (35) hide show
  1. package/package.json +2 -3
  2. package/src/bitcoinjs-lib/ecc/common.js +1 -1
  3. package/src/bitcoinjs-lib/ecc/mobile.js +3 -3
  4. package/src/bitcoinjs-lib/script-classify/index.js +1 -1
  5. package/src/btc-like-address.js +3 -4
  6. package/src/btc-like-keys.js +4 -0
  7. package/src/constants/bip44.js +2 -2
  8. package/src/fee/can-bump-tx.js +3 -1
  9. package/src/fee/fee-estimator.js +5 -1
  10. package/src/fee/fee-utils.js +6 -5
  11. package/src/fee/get-fee-resolver.js +2 -1
  12. package/src/fee/script-classifier.js +5 -10
  13. package/src/fee/utxo-selector.js +10 -3
  14. package/src/hash-utils.js +4 -9
  15. package/src/insight-api-client/index.js +14 -12
  16. package/src/insight-api-client/util.js +16 -15
  17. package/src/insight-api-client/ws.js +1 -1
  18. package/src/move-funds.js +17 -17
  19. package/src/ordinals-utils.js +2 -2
  20. package/src/parse-unsigned-tx.js +80 -81
  21. package/src/tx-log/bitcoin-monitor-scanner.js +50 -38
  22. package/src/tx-log/bitcoin-monitor.js +14 -13
  23. package/src/tx-log/ordinals-indexer-utils.js +6 -0
  24. package/src/tx-send/dogecoin.js +2 -2
  25. package/src/tx-send/index.js +426 -418
  26. package/src/tx-sign/common.js +9 -9
  27. package/src/tx-sign/create-get-key-and-purpose.js +2 -2
  28. package/src/tx-sign/create-sign-with-wallet.js +3 -3
  29. package/src/tx-sign/default-entropy.js +1 -3
  30. package/src/tx-sign/default-prepare-for-signing.js +16 -18
  31. package/src/tx-sign/default-sign-hardware.js +2 -1
  32. package/src/tx-sign/taproot.js +4 -0
  33. package/src/tx-utils.js +5 -5
  34. package/src/unconfirmed-ancestor-data.js +1 -0
  35. package/src/utxos-utils.js +12 -6
@@ -4,95 +4,94 @@ import BN from 'bn.js'
4
4
  import lodash from 'lodash'
5
5
  import { Transaction as BitcoinTransactionClass } from '@exodus/bitcoinjs-lib'
6
6
 
7
- export const parseUnsignedTxFactory = ({ Transaction = BitcoinTransactionClass } = {}) => async ({
8
- asset,
9
- unsignedTx,
10
- getAddress,
11
- }) => {
12
- const assetName = asset.name
13
-
14
- const toNumberUnit = (value) => {
15
- const parsedValue = Buffer.isBuffer(value) ? new BN(value, 10, 'le') : value // handle Dogecoin buffer values
16
- return asset.currency.baseUnit(parsedValue).toDefault()
17
- }
7
+ export const parseUnsignedTxFactory =
8
+ ({ Transaction = BitcoinTransactionClass } = {}) =>
9
+ async ({ asset, unsignedTx, getAddress }) => {
10
+ const assetName = asset.name
11
+
12
+ const toNumberUnit = (value) => {
13
+ const parsedValue = Buffer.isBuffer(value) ? new BN(value, 10, 'le') : value // handle Dogecoin buffer values
14
+ return asset.currency.baseUnit(parsedValue).toDefault()
15
+ }
18
16
 
19
- const parseAddress = assetName === 'bcash' ? asset.address.toCashAddress : (address) => address
17
+ const parseAddress = assetName === 'bcash' ? asset.address.toCashAddress : (address) => address
20
18
 
21
- const { inputs, outputs } = unsignedTx.txData
19
+ const { inputs, outputs } = unsignedTx.txData
22
20
 
23
- const from = lodash.uniq(inputs.map(({ address }) => parseAddress(address)))
24
- const outputAddresses = lodash.uniq(outputs.map(([address]) => address))
25
- const inputTxIds = lodash.uniq(inputs.map(({ txId }) => txId))
26
- const insightClient = asset.baseAsset.insightClient
27
- const inputTxsRaw = await Promise.all(inputTxIds.map((txId) => insightClient.fetchRawTx(txId)))
28
- const inputTxsById = new Map(
29
- inputTxsRaw.map((hex) => {
30
- const tx = Transaction.fromHex(hex)
31
- return [tx.getId(), tx]
21
+ const from = lodash.uniq(inputs.map(({ address }) => parseAddress(address)))
22
+ const outputAddresses = lodash.uniq(outputs.map(([address]) => address))
23
+ const inputTxIds = lodash.uniq(inputs.map(({ txId }) => txId))
24
+ const insightClient = asset.baseAsset.insightClient
25
+ const inputTxsRaw = await Promise.all(inputTxIds.map((txId) => insightClient.fetchRawTx(txId)))
26
+ const inputTxsById = new Map(
27
+ inputTxsRaw.map((hex) => {
28
+ const tx = Transaction.fromHex(hex)
29
+ return [tx.getId(), tx]
30
+ })
31
+ )
32
+
33
+ inputs.forEach(({ txId, vout, value }) => {
34
+ const tx = inputTxsById.get(txId)
35
+ const output = tx.outs[vout]
36
+ const expected = assetName === 'dogecoin' ? output.valueBuffer : output.value
37
+ assert(
38
+ lodash.isEqual(expected, value),
39
+ `${txId} tx input has invalid value. Expected: ${expected} , Actual: ${value}`
40
+ )
32
41
  })
33
- )
34
-
35
- inputs.forEach(({ txId, vout, value }) => {
36
- const tx = inputTxsById.get(txId)
37
- const output = tx.outs[vout]
38
- const expected = assetName === 'dogecoin' ? output.valueBuffer : output.value
39
- assert(
40
- lodash.isEqual(expected, value),
41
- `${txId} tx input has invalid value. Expected: ${expected} , Actual: ${value}`
42
+
43
+ const { addressPathsMap } = unsignedTx.txMeta
44
+ const [changeOutputAddresses, toOutputAddresses] = lodash.partition(
45
+ outputAddresses,
46
+ (address) => {
47
+ const path = addressPathsMap[address]
48
+ if (!path) return false
49
+
50
+ const [chain, index] = BIPPath.fromString(path).path
51
+ const isOurs = getAddress({ chain, index }).toString() === address
52
+ return isOurs && chain === 1
53
+ }
42
54
  )
43
- })
44
-
45
- const { addressPathsMap } = unsignedTx.txMeta
46
- const [changeOutputAddresses, toOutputAddresses] = lodash.partition(
47
- outputAddresses,
48
- (address) => {
49
- const path = addressPathsMap[address]
50
- if (!path) return false
51
-
52
- const [chain, index] = BIPPath.fromString(path).path
53
- const isOurs = getAddress({ chain, index }).toString() === address
54
- return isOurs && chain === 1
55
+
56
+ // the user is explicitly sending to a change address, so take a wild guess
57
+ if (toOutputAddresses.length === 0) {
58
+ toOutputAddresses.push(changeOutputAddresses.pop())
55
59
  }
56
- )
57
60
 
58
- // the user is explicitly sending to a change address, so take a wild guess
59
- if (!toOutputAddresses.length) {
60
- toOutputAddresses.push(changeOutputAddresses.pop())
61
- }
61
+ const [changeOutputs, sendOutputs] = lodash.partition(outputs, ([address]) =>
62
+ changeOutputAddresses.includes(address)
63
+ )
62
64
 
63
- const [changeOutputs, sendOutputs] = lodash.partition(outputs, ([address]) =>
64
- changeOutputAddresses.includes(address)
65
- )
66
-
67
- const sum = (arr) => arr.reduce((a, b) => a.add(b), asset.currency.ZERO)
68
- const sumOutputs = (outputs) => sum(outputs.map(([_, value]) => toNumberUnit(value)))
69
-
70
- // sum(inputs) = intendedSendAmount + fee + change
71
- // sum(outputs) = intendedSendAmount + change
72
-
73
- const inputsNF = inputs.map(({ value }) => toNumberUnit(value))
74
- const outputsNF = outputs.map(([_, value]) => toNumberUnit(value))
75
- const changeAmount = sumOutputs(changeOutputs)
76
- const amount = sumOutputs(sendOutputs)
77
-
78
- const inputsTotal = sum(inputsNF)
79
- const outputsTotal = sum(outputsNF)
80
- const fee = inputsTotal.sub(outputsTotal)
81
-
82
- const changeAddress = changeOutputAddresses.length ? parseAddress(changeOutputAddresses[0]) : null
83
- // TODO: return entire toOutputAddresses array
84
- assert(toOutputAddresses.length === 1, 'multiple outputs not supported yet in 2fa mode')
85
-
86
- const to = parseAddress(toOutputAddresses[0])
87
- return {
88
- asset,
89
- from,
90
- to,
91
- amount,
92
- changeAddress,
93
- changeAmount,
94
- fee,
65
+ const sum = (arr) => arr.reduce((a, b) => a.add(b), asset.currency.ZERO)
66
+ const sumOutputs = (outputs) => sum(outputs.map(([_, value]) => toNumberUnit(value)))
67
+
68
+ // sum(inputs) = intendedSendAmount + fee + change
69
+ // sum(outputs) = intendedSendAmount + change
70
+
71
+ const inputsNF = inputs.map(({ value }) => toNumberUnit(value))
72
+ const outputsNF = outputs.map(([_, value]) => toNumberUnit(value))
73
+ const changeAmount = sumOutputs(changeOutputs)
74
+ const amount = sumOutputs(sendOutputs)
75
+
76
+ const inputsTotal = sum(inputsNF)
77
+ const outputsTotal = sum(outputsNF)
78
+ const fee = inputsTotal.sub(outputsTotal)
79
+
80
+ const changeAddress =
81
+ changeOutputAddresses.length > 0 ? parseAddress(changeOutputAddresses[0]) : null
82
+ // TODO: return entire toOutputAddresses array
83
+ assert(toOutputAddresses.length === 1, 'multiple outputs not supported yet in 2fa mode')
84
+
85
+ const to = parseAddress(toOutputAddresses[0])
86
+ return {
87
+ asset,
88
+ from,
89
+ to,
90
+ amount,
91
+ changeAddress,
92
+ changeAmount,
93
+ fee,
94
+ }
95
95
  }
96
- }
97
96
 
98
97
  export const parseUnsignedTx = parseUnsignedTxFactory()
@@ -71,14 +71,15 @@ export class BitcoinMonitorScanner {
71
71
 
72
72
  const currentStoredUtxos = storedUtxos.union(storedOrdinalUtxos)
73
73
 
74
- const currentTime = new Date().getTime()
75
- const unconfirmedTxsToCheck = Array.from(currentTxs).reduce((txs, tx) => {
76
- if (tx.pending) {
77
- // Don't check sent tx that is younger than 2 minutes, because server might not have indexed it yet
78
- if (!tx.sent || !tx.date || currentTime - tx.date.getTime() > SENT_TIME_TO_DROP) {
79
- txs[tx.txId] = tx
80
- }
74
+ const currentTime = Date.now()
75
+ const unconfirmedTxsToCheck = [...currentTxs].reduce((txs, tx) => {
76
+ if (
77
+ tx.pending && // Don't check sent tx that is younger than 2 minutes, because server might not have indexed it yet
78
+ (!tx.sent || !tx.date || currentTime - tx.date.getTime() > SENT_TIME_TO_DROP)
79
+ ) {
80
+ txs[tx.txId] = tx
81
81
  }
82
+
82
83
  return txs
83
84
  }, Object.create(null))
84
85
 
@@ -139,7 +140,7 @@ export class BitcoinMonitorScanner {
139
140
 
140
141
  const aggregateAddresses = async (chainObjects) => {
141
142
  const promises = []
142
- for (let chainObject of chainObjects) {
143
+ for (const chainObject of chainObjects) {
143
144
  const { purpose, chainIndex, startAddressIndex, endAddressIndex } = chainObject
144
145
  for (let addressIndex = startAddressIndex; addressIndex < endAddressIndex; addressIndex++) {
145
146
  promises.push(
@@ -165,6 +166,7 @@ export class BitcoinMonitorScanner {
165
166
  )
166
167
  }
167
168
  }
169
+
168
170
  const addresses = []
169
171
  const result = await Promise.all(promises)
170
172
  result.forEach(({ address, purpose }) => {
@@ -192,13 +194,12 @@ export class BitcoinMonitorScanner {
192
194
  promises.push(promise)
193
195
  }
194
196
 
195
- const insightTxs = (await Promise.all(promises)).reduce(
196
- (total, some) => total.concat(some),
197
- []
198
- )
197
+ const listOfTxs = await Promise.all(promises)
198
+ const insightTxs = listOfTxs.flat()
199
199
  if (!this.#ordinalsEnabled) {
200
200
  return insightTxs
201
201
  }
202
+
202
203
  return Promise.all(
203
204
  insightTxs.map((tx) => {
204
205
  try {
@@ -232,8 +233,8 @@ export class BitcoinMonitorScanner {
232
233
  let allTxs = []
233
234
 
234
235
  for (let fetchCount = 0; ; fetchCount++) {
235
- const chainObjects = gapSearchParameters
236
- .map(({ purpose, chain, startAddressIndexes, endAddressIndexes }) => {
236
+ const chainObjects = gapSearchParameters.flatMap(
237
+ ({ purpose, chain, startAddressIndexes, endAddressIndexes }) => {
237
238
  return chain.map((_, chainIndex) => {
238
239
  return {
239
240
  purpose,
@@ -242,8 +243,8 @@ export class BitcoinMonitorScanner {
242
243
  endAddressIndex: endAddressIndexes[chainIndex],
243
244
  }
244
245
  })
245
- })
246
- .flat()
246
+ }
247
+ )
247
248
 
248
249
  if (
249
250
  fetchCount === 0 &&
@@ -277,7 +278,7 @@ export class BitcoinMonitorScanner {
277
278
 
278
279
  const txs = await fetchAllTxs(addresses)
279
280
  if (txs.length === 0) break
280
- allTxs = allTxs.concat(txs)
281
+ allTxs = [...allTxs, ...txs]
281
282
 
282
283
  // Update chains to see if we need to fetch more
283
284
  txs.forEach((tx) =>
@@ -307,6 +308,7 @@ export class BitcoinMonitorScanner {
307
308
  console.warn(`${assetName}: Cannot resolve purpose from address ${addressString}`)
308
309
  return
309
310
  }
311
+
310
312
  const chainToUpgrade = newChains.find((newChain) => newChain.purpose === purposeToUpdate)
311
313
  if (!chainToUpgrade) {
312
314
  console.log(
@@ -314,12 +316,14 @@ export class BitcoinMonitorScanner {
314
316
  )
315
317
  return
316
318
  }
319
+
317
320
  if (chainToUpgrade.chain[metaChainIndex] === undefined) {
318
321
  console.log(
319
322
  `${assetName}: There is no chain info for purpose ${purposeToUpdate}, address ${addressString} and chain index ${metaChainIndex}`
320
323
  )
321
324
  return
322
325
  }
326
+
323
327
  chainToUpgrade.chain[metaChainIndex] = Math.max(
324
328
  metaAddressIndex + 1,
325
329
  chainToUpgrade.chain[metaChainIndex]
@@ -328,7 +332,9 @@ export class BitcoinMonitorScanner {
328
332
  )
329
333
 
330
334
  gapSearchParameters.forEach((indexData) => {
335
+ // eslint-disable-next-line @exodus/mutable/no-param-reassign-prop-only
331
336
  indexData.startAddressIndexes = [...indexData.endAddressIndexes]
337
+ // eslint-disable-next-line @exodus/mutable/no-param-reassign-prop-only
332
338
  indexData.endAddressIndexes = indexData.chain.map((addressIndex) => {
333
339
  const resolvedGapLimit = refresh ? this.#refreshGapLimit : this.#gapLimit
334
340
  return addressIndex + resolvedGapLimit
@@ -343,14 +349,14 @@ export class BitcoinMonitorScanner {
343
349
 
344
350
  // post process TX data
345
351
  // NOTE: this can be optimized
346
- let vinTxids = Object.create(null)
352
+ const vinTxids = Object.create(null)
347
353
  let utxos = []
348
354
  const utxosToRemove = []
349
- let newTxs = []
350
- let existingTxs = []
355
+ const newTxs = []
356
+ const existingTxs = []
351
357
 
352
358
  allTxs.forEach((txItem) => {
353
- let txLogItem = {
359
+ const txLogItem = {
354
360
  txId: txItem.txid,
355
361
  coinAmount: currency.ZERO,
356
362
  date: txItem.time ? new Date(txItem.time * 1000) : new Date(),
@@ -406,7 +412,7 @@ export class BitcoinMonitorScanner {
406
412
 
407
413
  // this is only used to exclude the utxos in the reducer which is why we don't care about the other fields
408
414
  utxosToRemove.push({
409
- address: address,
415
+ address,
410
416
  txId: vin.txid,
411
417
  vout: vin.vout,
412
418
  value: currency.defaultUnit(vin.value || 0),
@@ -459,6 +465,7 @@ export class BitcoinMonitorScanner {
459
465
  const sentDisplayAddress = asset.address.displayAddress?.(sentAddress) || sentAddress
460
466
  txLogItem.data.sent.push({ address: sentDisplayAddress, amount: val })
461
467
  }
468
+
462
469
  return
463
470
  }
464
471
 
@@ -481,7 +488,7 @@ export class BitcoinMonitorScanner {
481
488
  }
482
489
 
483
490
  // it was sent to us...
484
- let val = currency.defaultUnit(vout.value)
491
+ const val = currency.defaultUnit(vout.value)
485
492
  txLogItem.coinAmount = txLogItem.coinAmount.add(val)
486
493
 
487
494
  const output = {
@@ -502,6 +509,7 @@ export class BitcoinMonitorScanner {
502
509
  if (this.#shouldExcludeVoutUtxo({ asset, output, txItem, vout })) {
503
510
  return
504
511
  }
512
+
505
513
  if (vout.spentTxId) return
506
514
  utxos.push(output) // but save the unspent ones for state.utxos
507
515
  })
@@ -510,6 +518,7 @@ export class BitcoinMonitorScanner {
510
518
  if (txLogItem.to) {
511
519
  txLogItem.to = asset.address.displayAddress(txLogItem.to)
512
520
  }
521
+
513
522
  from = from.map(asset.address.displayAddress)
514
523
  }
515
524
 
@@ -557,17 +566,18 @@ export class BitcoinMonitorScanner {
557
566
  // Keep new utxos when they intersect with the stored utxos.
558
567
  utxoCol = utxoCol.union(currentStoredUtxos).difference(utxosToRemoveCol)
559
568
 
560
- for (let tx of Object.values(unconfirmedTxsToCheck)) {
569
+ for (const tx of Object.values(unconfirmedTxsToCheck)) {
561
570
  existingTxs.push({ ...tx, dropped: true }) // TODO: this will decrease the chain index, it shouldn't be an issue considering the gap limit
562
571
  utxoCol = utxoCol.difference(utxoCol.getTxIdUtxos(tx.txId))
563
572
  const utxosToAdd = []
564
573
  if (tx.data.inputs) {
565
574
  const prevUtxos = UtxoCollection.fromJSON(tx.data.inputs, { currency })
566
- for (let utxo of prevUtxos.toArray()) {
575
+ for (const utxo of prevUtxos.toArray()) {
567
576
  if (vinTxids[`${utxo.txId}-${utxo.vout}`]) {
568
577
  // This utxo was already spent in another tx
569
578
  continue
570
579
  }
580
+
571
581
  const tx = await insightClient.fetchTx(utxo.txId)
572
582
  if (tx) {
573
583
  // previously spent tx still exists, readd utxo
@@ -575,6 +585,7 @@ export class BitcoinMonitorScanner {
575
585
  }
576
586
  }
577
587
  }
588
+
578
589
  utxoCol = utxoCol.union(UtxoCollection.fromArray(utxosToAdd, { currency }))
579
590
  }
580
591
 
@@ -626,7 +637,7 @@ export class BitcoinMonitorScanner {
626
637
  const storedOrdinalsUtxos = getOrdinalsUtxos({ accountState, asset })
627
638
  const allStoredUtxos = storedUtxos.union(storedOrdinalsUtxos)
628
639
 
629
- const currentTxs = Array.from(await aci.getTxLog({ assetName, walletAccount }))
640
+ const currentTxs = [...(await aci.getTxLog({ assetName, walletAccount }))]
630
641
 
631
642
  const unconfirmedTxIds = uniq([
632
643
  ...storedUtxos
@@ -636,17 +647,17 @@ export class BitcoinMonitorScanner {
636
647
  ...currentTxs.filter((tx) => !tx.dropped && !tx.confirmations).map((tx) => tx.txId),
637
648
  ])
638
649
 
639
- const confirmationsList = (
640
- await Promise.all(
641
- unconfirmedTxIds.map(async (txId) => {
642
- const txStatus = await this.#insightClient.fetchTx(txId)
643
- if (!txStatus?.confirmations) {
644
- return undefined
645
- }
646
- return { txId, confirmations: txStatus.confirmations }
647
- })
648
- )
649
- ).filter(Boolean)
650
+ const maybeConfirmationList = await Promise.all(
651
+ unconfirmedTxIds.map(async (txId) => {
652
+ const txStatus = await this.#insightClient.fetchTx(txId)
653
+ if (!txStatus?.confirmations) {
654
+ return
655
+ }
656
+
657
+ return { txId, confirmations: txStatus.confirmations }
658
+ })
659
+ )
660
+ const confirmationsList = maybeConfirmationList.filter(Boolean)
650
661
 
651
662
  const updatedPropertiesTxs = currentTxs
652
663
  .map((tx) => {
@@ -655,6 +666,7 @@ export class BitcoinMonitorScanner {
655
666
  if (!tx.dropped && !tx.confirmations && confirmations > 0) {
656
667
  updatedProperties.confirmations = confirmations
657
668
  }
669
+
658
670
  return { txId: tx.txId, ...updatedProperties }
659
671
  })
660
672
  .filter((tx) => Object.keys(tx).length > 1)
@@ -672,7 +684,7 @@ export class BitcoinMonitorScanner {
672
684
  const { utxos, ordinalsUtxos } = partitionUtxos({
673
685
  allUtxos: txConfirmedUtxos,
674
686
  ordinalsEnabled: this.#ordinalsEnabled,
675
- ordinalAddress: ordinalAddress,
687
+ ordinalAddress,
676
688
  knownBalanceUtxoIds: latestAccountState.knownBalanceUtxoIds,
677
689
  mustAvoidUtxoIds: latestAccountState.mustAvoidUtxoIds,
678
690
  additionalInscriptions: latestAccountState.additionalInscriptions,
@@ -72,6 +72,7 @@ export class Monitor extends BaseMonitor {
72
72
  if (apiUrl) {
73
73
  this.#insightClient.setBaseUrl(apiUrl)
74
74
  }
75
+
75
76
  if (!this.#wsUrl || this.#wsUrl !== wsUrl) {
76
77
  this.#connectWS(wsUrl || this.#wsUrl || toWSUrl(this.#apiUrl))
77
78
  }
@@ -101,10 +102,12 @@ export class Monitor extends BaseMonitor {
101
102
  if (!this.#webSocketEnabled) {
102
103
  return
103
104
  }
105
+
104
106
  if (this.#ws) {
105
107
  this.#ws.close()
106
108
  this.#ws = null
107
109
  }
110
+
108
111
  this.#wsUrl = wsUrl
109
112
  if (!wsUrl) {
110
113
  return
@@ -114,7 +117,7 @@ export class Monitor extends BaseMonitor {
114
117
 
115
118
  const addressesArr = Object.values(this.#addressesByWalletAccount).flat()
116
119
 
117
- if (!addressesArr.length) {
120
+ if (addressesArr.length === 0) {
118
121
  this.#logWsStatus('no addressesArr to subscribe')
119
122
  return
120
123
  }
@@ -167,7 +170,7 @@ export class Monitor extends BaseMonitor {
167
170
  )
168
171
  }
169
172
 
170
- if (txsToUpdate.length) {
173
+ if (txsToUpdate.length > 0) {
171
174
  await this.updateTxLog({ assetName, walletAccount, logItems: txsToUpdate })
172
175
  if (utxos && ['bitcoin', 'bitcoinregtest', 'bitcointestnet'].includes(assetName)) {
173
176
  const unconfirmedTxAncestor = await resolveUnconfirmedAncestorData({
@@ -177,6 +180,7 @@ export class Monitor extends BaseMonitor {
177
180
  newData.mem = { unconfirmedTxAncestor }
178
181
  }
179
182
  }
183
+
180
184
  await aci.updateAccountState({
181
185
  assetName,
182
186
  walletAccount,
@@ -202,10 +206,12 @@ export class Monitor extends BaseMonitor {
202
206
  if (refresh && this.#runningByWalletAccount[walletAccount]?.refresh !== refresh) {
203
207
  await this.#waitForWalletToFinish(walletAccount)
204
208
  }
209
+
205
210
  if (this.#runningByWalletAccount[walletAccount]) {
206
211
  this.logger.debug(`Skipping ${walletAccount} tick as previous tick is still running`)
207
212
  return
208
213
  }
214
+
209
215
  const promise = this.#syncWalletAccount({ walletAccount, refresh })
210
216
  this.#runningByWalletAccount[walletAccount] = { refresh, promise }
211
217
  try {
@@ -221,16 +227,11 @@ export class Monitor extends BaseMonitor {
221
227
  // wait for all wallet accounts to load
222
228
  await aci.getWalletAccounts({ assetName })
223
229
 
224
- const {
225
- txsToAdd,
226
- txsToUpdate,
227
- utxos,
228
- ordinalsUtxos,
229
- changedUnusedAddressIndexes,
230
- } = await this.#scanner.rescanBlockchainInsight({
231
- walletAccount,
232
- refresh,
233
- })
230
+ const { txsToAdd, txsToUpdate, utxos, ordinalsUtxos, changedUnusedAddressIndexes } =
231
+ await this.#scanner.rescanBlockchainInsight({
232
+ walletAccount,
233
+ refresh,
234
+ })
234
235
 
235
236
  const newData = {}
236
237
  if (utxos || ordinalsUtxos)
@@ -256,7 +257,7 @@ export class Monitor extends BaseMonitor {
256
257
 
257
258
  const txs = [...txsToUpdate, ...txsToAdd]
258
259
 
259
- if (txs.length) {
260
+ if (txs.length > 0) {
260
261
  await this.updateTxLog({
261
262
  assetName,
262
263
  logItems: txs,
@@ -26,6 +26,8 @@ export const indexOutputs = ({ tx, currency }) => {
26
26
  .map((i) => ({ ...i, offset: i.offset.sub(outputOffset).toBaseNumber() }))
27
27
  outputOffset = outputOffset.add(value)
28
28
  }
29
+
30
+ // eslint-disable-next-line @exodus/mutable/no-param-reassign-prop-only
29
31
  tx.inscriptionsMemoryIndexed = true // avoids btc being spent even when the mempool index was done in memory
30
32
  return tx
31
33
  }
@@ -35,6 +37,7 @@ export const cachedIndexOrdinalUnconfirmedTx = memoizeLruCache(
35
37
  if (tx.inscriptionsIndexed || tx.inscriptionsMemoryIndexed) {
36
38
  return tx
37
39
  }
40
+
38
41
  const copyTx = cloneDeep(tx)
39
42
  await Promise.all(
40
43
  copyTx.vin.map(async (vin) => {
@@ -46,6 +49,8 @@ export const cachedIndexOrdinalUnconfirmedTx = memoizeLruCache(
46
49
  if (!outputTx.inscriptionsIndexed && !outputTx.inscriptionsMemoryIndexed) {
47
50
  throw new Error(`Cannot index ${tx.txid}. Input tx ${outputTx.txid} is not indexed. `)
48
51
  }
52
+
53
+ // eslint-disable-next-line @exodus/mutable/no-param-reassign-prop-only
49
54
  vin.inscriptions = outputTx.vout[vin.vout].inscriptions
50
55
  })
51
56
  )
@@ -59,6 +64,7 @@ export const indexOrdinalUnconfirmedTx = ({ insightClient, currency, tx }) => {
59
64
  if (tx.inscriptionsIndexed) {
60
65
  return tx
61
66
  }
67
+
62
68
  return cachedIndexOrdinalUnconfirmedTx({
63
69
  insightClient,
64
70
  currency,
@@ -3,10 +3,10 @@ export function createInputs(utxos) {
3
3
  txId: utxo.txId,
4
4
  vout: utxo.vout,
5
5
  address: utxo.address.toString(),
6
- value: utxo.value._number.toArrayLike(Buffer, 'le', 8),
6
+ value: utxo.value.toBaseBufferLE(8),
7
7
  }))
8
8
  }
9
9
 
10
10
  export function createOutput(address, sendAmount) {
11
- return [address, sendAmount._number.toArrayLike(Buffer, 'le', 8)]
11
+ return [address, sendAmount.toBaseBufferLE(8)]
12
12
  }