@exodus/bitcoin-api 4.9.4 → 4.9.5

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/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [4.9.5](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.9.4...@exodus/bitcoin-api@4.9.5) (2026-02-14)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix: Remove ordinals paths from bitcoin monitor scanner (#7430)
13
+
14
+
15
+
6
16
  ## [4.9.4](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.9.3...@exodus/bitcoin-api@4.9.4) (2026-02-10)
7
17
 
8
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bitcoin-api",
3
- "version": "4.9.4",
3
+ "version": "4.9.5",
4
4
  "description": "Bitcoin transaction and fee monitors, RPC with the blockchain node, other networking code.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -61,5 +61,5 @@
61
61
  "type": "git",
62
62
  "url": "git+https://github.com/ExodusMovement/assets.git"
63
63
  },
64
- "gitHead": "b4d4b4bf36591dca5c82bfacfbac80db41805e02"
64
+ "gitHead": "8c4fcde522beb978df6a5099e0fa9e34bb4a7e04"
65
65
  }
@@ -5,9 +5,7 @@ import ms from 'ms'
5
5
 
6
6
  import { isChangeAddress, isReceiveAddress } from '../address-utils.js'
7
7
  import { orderTxs } from '../insight-api-client/util.js'
8
- import { getOrdinalAddress } from '../ordinals-utils.js'
9
- import { getOrdinalsUtxos, getUtxos, partitionUtxos } from '../utxos-utils.js'
10
- import { indexOrdinalUnconfirmedTx } from './ordinals-indexer-utils.js'
8
+ import { getUtxos } from '../utxos-utils.js'
11
9
 
12
10
  const { compact, isEqual, uniq } = lodash
13
11
 
@@ -23,8 +21,6 @@ export class BitcoinMonitorScanner {
23
21
  #txFetchLimitResolver
24
22
  #shouldExcludeVoutUtxo
25
23
  #yieldToUI
26
- #ordinalsEnabled
27
- #ordinalChainIndex
28
24
  #extraChainIndexEnabled
29
25
  #extraChainIndex
30
26
  #gapLimit
@@ -36,8 +32,6 @@ export class BitcoinMonitorScanner {
36
32
  yieldToUI = () => {},
37
33
  shouldExcludeVoutUtxo = () => false,
38
34
  txFetchLimitResolver = ({ refresh }) => (refresh ? 50 : 10),
39
- ordinalsEnabled,
40
- ordinalChainIndex,
41
35
  extraChainIndexEnabled,
42
36
  extraChainIndex,
43
37
  gapLimit = 10,
@@ -57,8 +51,6 @@ export class BitcoinMonitorScanner {
57
51
  this.#assetClientInterface = assetClientInterface
58
52
  this.#txFetchLimitResolver = txFetchLimitResolver
59
53
  this.#shouldExcludeVoutUtxo = shouldExcludeVoutUtxo
60
- this.#ordinalsEnabled = ordinalsEnabled
61
- this.#ordinalChainIndex = ordinalChainIndex
62
54
  this.#extraChainIndexEnabled = extraChainIndexEnabled
63
55
  this.#extraChainIndex = extraChainIndex
64
56
  this.#gapLimit = gapLimit
@@ -92,9 +84,6 @@ export class BitcoinMonitorScanner {
92
84
  const multiAddressMode = assetConfig.multiAddressMode ?? true
93
85
 
94
86
  const storedUtxos = getUtxos({ asset, accountState })
95
- const storedOrdinalUtxos = getOrdinalsUtxos({ asset, accountState })
96
-
97
- const currentStoredUtxos = storedUtxos.union(storedOrdinalUtxos)
98
87
 
99
88
  const currentTime = Date.now()
100
89
  const unconfirmedTxsToCheck = [...currentTxs].reduce((txs, tx) => {
@@ -116,9 +105,7 @@ export class BitcoinMonitorScanner {
116
105
  : (txs) =>
117
106
  txs.filter((tx) => {
118
107
  const txItem = currentTxs.get(tx.txid)
119
- const confirmed = txItem && txItem.confirmed
120
- const inscriptionsIndexed = txItem?.data?.inscriptionsIndexed
121
- return confirmed && (!this.#ordinalsEnabled || inscriptionsIndexed)
108
+ return txItem && txItem.confirmed
122
109
  }).length >= txs.length
123
110
 
124
111
  const unusedAddressIndexes = await assetClientInterface.getUnusedAddressIndexes({
@@ -254,28 +241,7 @@ export class BitcoinMonitorScanner {
254
241
  }
255
242
 
256
243
  const listOfTxs = await Promise.all(promises)
257
- const insightTxs = listOfTxs.flat()
258
- if (!this.#ordinalsEnabled) {
259
- return insightTxs
260
- }
261
-
262
- return Promise.all(
263
- insightTxs.map((tx) => {
264
- try {
265
- return indexOrdinalUnconfirmedTx({
266
- tx,
267
- currency: this.#asset.currency,
268
- insightClient,
269
- })
270
- } catch (e) {
271
- console.warn(
272
- `Could not index ${asset.name} ordinal tx ${tx.txid} for wallet account ${walletAccount}. message: ${e.message}`,
273
- e
274
- )
275
- return tx
276
- }
277
- })
278
- )
244
+ return listOfTxs.flat()
279
245
  }
280
246
 
281
247
  const gapSearchParameters = newChains.map(({ purpose, chain }) => {
@@ -305,21 +271,6 @@ export class BitcoinMonitorScanner {
305
271
  }
306
272
  )
307
273
 
308
- if (
309
- fetchCount === 0 &&
310
- this.#ordinalsEnabled &&
311
- this.#ordinalChainIndex > 1 &&
312
- purposes.includes(86)
313
- ) {
314
- // this is the ordinal address
315
- chainObjects.push({
316
- purpose: 86,
317
- chainIndex: this.#ordinalChainIndex,
318
- startAddressIndex: 0,
319
- endAddressIndex: 1,
320
- })
321
- }
322
-
323
274
  if (
324
275
  fetchCount === 0 &&
325
276
  this.#extraChainIndexEnabled &&
@@ -373,10 +324,7 @@ export class BitcoinMonitorScanner {
373
324
  const addressString = String(address)
374
325
  const purposeToUpdate = purposeMap[addressString]
375
326
 
376
- if (
377
- metaAddressIndex === undefined ||
378
- (metaChainIndex === this.#ordinalChainIndex && this.#ordinalChainIndex > 1)
379
- ) {
327
+ if (metaAddressIndex === undefined) {
380
328
  return
381
329
  }
382
330
 
@@ -461,15 +409,6 @@ export class BitcoinMonitorScanner {
461
409
  currencies: { [assetName]: currency },
462
410
  }
463
411
 
464
- if (this.#ordinalsEnabled) {
465
- txLogItem.data = {
466
- ...txLogItem.data,
467
- inscriptionsIndexed: txItem.inscriptionsIndexed,
468
- sentInscriptions: [],
469
- receivedInscriptions: [],
470
- }
471
- }
472
-
473
412
  let from = []
474
413
 
475
414
  // if txItem.vin has an address that matches ours, means we've spent this tx
@@ -495,14 +434,6 @@ export class BitcoinMonitorScanner {
495
434
  txLogItem.coinAmount = txLogItem.coinAmount.sub(currency.defaultUnit(vin.value))
496
435
  isSent = true
497
436
  txLogItem.data.sent = []
498
- if (this.#ordinalsEnabled && vin.inscriptions) {
499
- txLogItem.data.sentInscriptions.push(
500
- ...vin.inscriptions.map((i) => ({
501
- ...i,
502
- value: currency.defaultUnit(vin.value).toBaseNumber(),
503
- }))
504
- )
505
- }
506
437
 
507
438
  // this is only used to exclude the utxos in the reducer which is why we don't care about the other fields
508
439
  utxosToRemove.push({
@@ -584,15 +515,6 @@ export class BitcoinMonitorScanner {
584
515
  amount: currency.defaultUnit(vout.value).toBaseString(),
585
516
  })
586
517
 
587
- if (this.#ordinalsEnabled && vout.inscriptions) {
588
- txLogItem.data.receivedInscriptions.push(
589
- ...vout.inscriptions.map((i) => ({
590
- ...i,
591
- value: currency.defaultUnit(vout.value).toBaseNumber(),
592
- }))
593
- )
594
- }
595
-
596
518
  // it was sent to us...
597
519
  const val = currency.defaultUnit(vout.value)
598
520
  txLogItem.coinAmount = txLogItem.coinAmount.add(val)
@@ -609,11 +531,6 @@ export class BitcoinMonitorScanner {
609
531
  ...(isCoinbase ? { isCoinbase: true } : undefined),
610
532
  }
611
533
 
612
- if (this.#ordinalsEnabled) {
613
- output.inscriptionsIndexed = txItem.inscriptionsIndexed
614
- output.inscriptions = vout.inscriptions || []
615
- }
616
-
617
534
  if (this.#shouldExcludeVoutUtxo({ asset, output, txItem, vout })) {
618
535
  utxosToRemove.push({
619
536
  address,
@@ -682,7 +599,7 @@ export class BitcoinMonitorScanner {
682
599
 
683
600
  const utxosToRemoveCol = UtxoCollection.fromArray(utxosToRemove, { currency })
684
601
  // Keep new utxos when they intersect with the stored utxos.
685
- utxoCol = utxoCol.union(currentStoredUtxos).difference(utxosToRemoveCol)
602
+ utxoCol = utxoCol.union(storedUtxos).difference(utxosToRemoveCol)
686
603
 
687
604
  const pendingDropCandidates = Object.values(unconfirmedTxsToCheck)
688
605
  const verificationResults = await Promise.all(
@@ -727,7 +644,7 @@ export class BitcoinMonitorScanner {
727
644
  }
728
645
 
729
646
  // no changes, ignore
730
- if (utxoCol.equals(currentStoredUtxos)) {
647
+ if (utxoCol.equals(storedUtxos)) {
731
648
  utxoCol = null
732
649
  }
733
650
 
@@ -737,28 +654,10 @@ export class BitcoinMonitorScanner {
737
654
  return !isEqual(chain, originalChain.chain)
738
655
  })
739
656
 
740
- const ordinalAddress = await this.getOrdinalAddress({ walletAccount })
741
-
742
- // latest account state, in case knownBalanceUtxoIds or mustAvoidUtxoIds gets updated in on another promise
743
- const latestAccountState = await assetClientInterface.getAccountState({
744
- assetName,
745
- walletAccount,
746
- })
747
- const utxosData = utxoCol
748
- ? partitionUtxos({
749
- allUtxos: utxoCol,
750
- ordinalsEnabled: this.#ordinalsEnabled,
751
- ordinalAddress,
752
- knownBalanceUtxoIds: latestAccountState.knownBalanceUtxoIds,
753
- mustAvoidUtxoIds: latestAccountState.mustAvoidUtxoIds,
754
- additionalInscriptions: latestAccountState.additionalInscriptions,
755
- })
756
- : {}
757
-
758
657
  return {
759
658
  txsToUpdate: existingTxs,
760
659
  txsToAdd: newTxs,
761
- ...utxosData,
660
+ ...(utxoCol ? { utxos: utxoCol } : {}),
762
661
  changedUnusedAddressIndexes,
763
662
  }
764
663
  }
@@ -771,8 +670,6 @@ export class BitcoinMonitorScanner {
771
670
  const accountState = await aci.getAccountState({ assetName, walletAccount })
772
671
 
773
672
  const storedUtxos = getUtxos({ accountState, asset })
774
- const storedOrdinalsUtxos = getOrdinalsUtxos({ accountState, asset })
775
- const allStoredUtxos = storedUtxos.union(storedOrdinalsUtxos)
776
673
 
777
674
  const currentTxs = [...(await aci.getTxLog({ assetName, walletAccount }))]
778
675
 
@@ -819,38 +716,18 @@ export class BitcoinMonitorScanner {
819
716
  })
820
717
  .filter((tx) => Object.keys(tx).length > 1)
821
718
 
822
- const txConfirmedUtxos = allStoredUtxos.updateConfirmations(confirmationsList)
823
-
824
- const ordinalAddress = await this.getOrdinalAddress({ walletAccount })
825
-
826
- // latest account state, in case knownBalanceUtxoIds or mustAvoidUtxoIds gets updated in on another promise
827
- const latestAccountState = await aci.getAccountState({
828
- assetName,
829
- walletAccount,
719
+ // Check before updateConfirmations since it mutates the shared utxo object references,
720
+ // which would cause storedUtxos.toJSON() to also reflect the updated confirmations.
721
+ const utxosChanged = storedUtxos.toArray().some((utxo) => {
722
+ const update = confirmationsList.find(({ txId }) => utxo.txId === txId)
723
+ return update && utxo.confirmations !== update.confirmations
830
724
  })
831
725
 
832
- const { utxos, ordinalsUtxos } = partitionUtxos({
833
- allUtxos: txConfirmedUtxos,
834
- ordinalsEnabled: this.#ordinalsEnabled,
835
- ordinalAddress,
836
- knownBalanceUtxoIds: latestAccountState.knownBalanceUtxoIds,
837
- mustAvoidUtxoIds: latestAccountState.mustAvoidUtxoIds,
838
- additionalInscriptions: latestAccountState.additionalInscriptions,
839
- })
726
+ const txConfirmedUtxos = storedUtxos.updateConfirmations(confirmationsList)
840
727
 
841
728
  return {
842
- utxos: utxos.equals(storedUtxos) ? null : utxos,
843
- ordinalsUtxos: ordinalsUtxos.equals(storedOrdinalsUtxos) ? null : ordinalsUtxos,
729
+ utxos: utxosChanged ? txConfirmedUtxos : null,
844
730
  txsToUpdate: updatedPropertiesTxs,
845
731
  }
846
732
  }
847
-
848
- getOrdinalAddress({ walletAccount }) {
849
- return getOrdinalAddress({
850
- asset: this.#asset,
851
- assetClientInterface: this.#assetClientInterface,
852
- walletAccount,
853
- ordinalChainIndex: this.#ordinalChainIndex,
854
- })
855
- }
856
733
  }
@@ -166,13 +166,12 @@ export class Monitor extends BaseMonitor {
166
166
  const assetName = asset.name
167
167
  const walletAccounts = await aci.getWalletAccounts({ assetName })
168
168
  for (const walletAccount of walletAccounts) {
169
- const { txsToUpdate, utxos, ordinalsUtxos } = await this.#scanner.rescanOnNewBlock({
169
+ const { txsToUpdate, utxos } = await this.#scanner.rescanOnNewBlock({
170
170
  walletAccount,
171
171
  })
172
172
 
173
173
  const newData = {}
174
174
  if (utxos) newData.utxos = utxos
175
- if (ordinalsUtxos) newData.ordinalsUtxos = ordinalsUtxos
176
175
 
177
176
  if (txsToUpdate.length > 0) {
178
177
  await this.updateTxLog({ assetName, walletAccount, logItems: txsToUpdate })
@@ -237,7 +236,7 @@ export class Monitor extends BaseMonitor {
237
236
  // wait for all wallet accounts to load
238
237
  await aci.getWalletAccounts({ assetName })
239
238
 
240
- const { txsToAdd, txsToUpdate, utxos, ordinalsUtxos, changedUnusedAddressIndexes } =
239
+ const { txsToAdd, txsToUpdate, utxos, changedUnusedAddressIndexes } =
241
240
  await this.#scanner.rescanBlockchainInsight({
242
241
  walletAccount,
243
242
  refresh,
@@ -245,7 +244,6 @@ export class Monitor extends BaseMonitor {
245
244
 
246
245
  const newData = {}
247
246
  if (utxos) newData.utxos = utxos
248
- if (ordinalsUtxos) newData.ordinalsUtxos = ordinalsUtxos
249
247
 
250
248
  if (!isEmpty(changedUnusedAddressIndexes)) {
251
249
  // Only for mobile atm, browser and hydra calculates from the latest txLogs