@exodus/bitcoin-api 2.6.8-hiro.0 → 2.6.8-hiro.2

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": "@exodus/bitcoin-api",
3
- "version": "2.6.8-hiro.0",
3
+ "version": "2.6.8-hiro.2",
4
4
  "description": "Exodus bitcoin-api",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -10,6 +10,7 @@ export function createAccountState({ asset, ordinalsEnabled = false, brc20Enable
10
10
 
11
11
  if (ordinalsEnabled) {
12
12
  defaults.ordinalsUtxos = empty
13
+ defaults.knownBalanceUtxoIds = []
13
14
  }
14
15
 
15
16
  if (brc20Enabled) {
@@ -533,16 +533,6 @@ export class BitcoinMonitorScanner {
533
533
  // Keep new utxos when they intersect with the stored utxos.
534
534
  utxoCol = utxoCol.union(currentStoredUtxos).difference(utxosToRemoveCol)
535
535
 
536
- if (this.#ordinalsEnabled) {
537
- // copy ordinalsChange over
538
- utxoCol.toArray().forEach((utxo) => {
539
- const storedUtxo = currentStoredUtxos
540
- .toArray()
541
- .find((u2) => u2.txid === utxos.txid && u2.vout === utxo.vout)
542
- utxo.ordinalsChange = storedUtxo?.ordinalsChange
543
- })
544
- }
545
-
546
536
  for (let tx of Object.values(unconfirmedTxsToCheck)) {
547
537
  existingTxs.push({ ...tx, dropped: true }) // TODO: this will decrease the chain index, it shouldn't be an issue considering the gap limit
548
538
  utxoCol = utxoCol.difference(utxoCol.getTxIdUtxos(tx.txId))
@@ -581,6 +571,7 @@ export class BitcoinMonitorScanner {
581
571
  allUtxos: utxoCol,
582
572
  ordinalsEnabled: this.#ordinalsEnabled,
583
573
  ordinalAddress,
574
+ knownBalanceUtxoIds: accountState.knownBalanceUtxoIds,
584
575
  })
585
576
  : {}
586
577
 
@@ -642,6 +633,7 @@ export class BitcoinMonitorScanner {
642
633
  allUtxos: txConfirmedUtxos,
643
634
  ordinalsEnabled: this.#ordinalsEnabled,
644
635
  ordinalAddress: await this.getOrdinalAddress({ walletAccount }),
636
+ knownBalanceUtxoIds: accountState.knownBalanceUtxoIds,
645
637
  })
646
638
 
647
639
  return {
@@ -428,6 +428,8 @@ export const createAndBroadcastTXFactory = ({
428
428
 
429
429
  const { script, size } = getSizeAndChangeScript({ assetName, tx, rawTx, changeUtxoIndex, txId })
430
430
 
431
+ // for ordinals, used to allow users spending change utxos even when unconfirmed and ordinals are unknown
432
+ const knownBalanceUtxoIds = accountState.knownBalanceUtxoIds || []
431
433
  let remainingUtxos = usableUtxos.difference(selectedUtxos)
432
434
  if (changeUtxoIndex !== -1) {
433
435
  const address = Address.create(ourAddress.address, ourAddress.meta)
@@ -439,8 +441,9 @@ export const createAndBroadcastTXFactory = ({
439
441
  value: change,
440
442
  confirmations: 0,
441
443
  rbfEnabled,
442
- ordinalsChange: ordinalsEnabled ? true : undefined,
443
444
  }
445
+
446
+ knownBalanceUtxoIds.push(`${changeUtxo.txId}:${changeUtxo.vout}`.toLowerCase())
444
447
  remainingUtxos = remainingUtxos.addUtxo(changeUtxo)
445
448
  }
446
449
  if (replaceTx) {
@@ -449,7 +452,7 @@ export const createAndBroadcastTXFactory = ({
449
452
 
450
453
  const remainingOrdinalsUtxos = transferOrdinalsUtxos
451
454
  ? currentOrdinalsUtxos.difference(transferOrdinalsUtxos)
452
- : undefined
455
+ : currentOrdinalsUtxos
453
456
 
454
457
  await assetClientInterface.updateAccountState({
455
458
  assetName,
@@ -457,6 +460,7 @@ export const createAndBroadcastTXFactory = ({
457
460
  newData: {
458
461
  utxos: remainingUtxos,
459
462
  ordinalsUtxos: remainingOrdinalsUtxos,
463
+ knownBalanceUtxoIds,
460
464
  },
461
465
  })
462
466
 
@@ -69,12 +69,14 @@ export function getValidInscriptions({ utxo }) {
69
69
  )
70
70
  }
71
71
 
72
- function isOrdinalUtxo({ utxo, ordinalsEnabled }) {
72
+ function isOrdinalUtxo({ utxo, ordinalsEnabled, knownBalanceUtxoIds }) {
73
73
  if (!ordinalsEnabled) {
74
74
  return false
75
75
  }
76
76
 
77
- if (utxo.ordinalsChange && !utxo.inscriptionsIndexed) {
77
+ const utxoId = `${utxo.txId}:${utxo.vout}`.toLowerCase()
78
+
79
+ if (knownBalanceUtxoIds?.includes(utxoId) && !utxo.inscriptionsIndexed) {
78
80
  return false // this allows users see and spend change balance after sending before hiro confirmation
79
81
  }
80
82
 
@@ -86,13 +88,16 @@ function isOrdinalUtxo({ utxo, ordinalsEnabled }) {
86
88
  return validInscriptions.length > 0
87
89
  }
88
90
 
89
- export function partitionUtxos({ allUtxos, ordinalsEnabled }) {
90
- assert(allUtxos, 'allUtxos is required')
91
+ export function partitionUtxos({ allUtxos, ordinalsEnabled, knownBalanceUtxoIds }) {
91
92
  assert(allUtxos, 'allUtxos is required')
92
93
  // assert(ordinalAddress, 'ordinalAddress is required') // not used atm we may need to tune by ordinalAddress when unconfirmed or rubbish inscriptions
93
94
  return {
94
- utxos: allUtxos.filter((utxo) => !isOrdinalUtxo({ utxo, ordinalsEnabled })),
95
- ordinalsUtxos: allUtxos.filter((utxo) => isOrdinalUtxo({ utxo, ordinalsEnabled })),
95
+ utxos: allUtxos.filter(
96
+ (utxo) => !isOrdinalUtxo({ utxo, ordinalsEnabled, knownBalanceUtxoIds })
97
+ ),
98
+ ordinalsUtxos: allUtxos.filter((utxo) =>
99
+ isOrdinalUtxo({ utxo, ordinalsEnabled, knownBalanceUtxoIds })
100
+ ),
96
101
  }
97
102
  }
98
103
 
@@ -113,12 +118,20 @@ export function getConfirmedOrRfbDisabledUtxos({ utxos, allowUnconfirmedRbfEnabl
113
118
  return utxos.filter((utxo) => utxo.confirmations > 0 || !utxo.rbfEnabled)
114
119
  }
115
120
 
121
+ function filterDustUtxos({ utxos, feeData }) {
122
+ if (feeData.utxoDustValue) {
123
+ return utxos.filter((utxo) => utxo.value.toBaseNumber() > feeData.utxoDustValue)
124
+ }
125
+ return utxos
126
+ }
127
+
116
128
  export function getUsableUtxos({ asset, utxos, feeData, txSet }) {
117
129
  assert(asset, 'asset is required')
118
130
  assert(utxos, 'utxos is required')
119
131
  assert(feeData, 'feeData is required')
120
132
  assert(txSet, 'txSet is required')
121
- if (!['bitcoin', 'bitcointestnet', 'bitcoinregtest'].includes(asset.name)) return utxos
133
+ if (!['bitcoin', 'bitcointestnet', 'bitcoinregtest'].includes(asset.name))
134
+ return filterDustUtxos({ utxos, feeData })
122
135
  const { fastestFee } = feeData
123
136
  const feeRate = fastestFee.toBaseNumber()
124
137
  const maxFee = feeData.maxExtraCpfpFee
@@ -130,7 +143,9 @@ export function getUsableUtxos({ asset, utxos, feeData, txSet }) {
130
143
  feeRate,
131
144
  maxFee,
132
145
  })
133
- return largeUnconfirmedTxs.size === 0
134
- ? utxos
135
- : utxos.filter((utxo) => !largeUnconfirmedTxs.has(utxo.txId))
146
+ const confirmedAndSmallUtxos =
147
+ largeUnconfirmedTxs.size === 0
148
+ ? utxos
149
+ : utxos.filter((utxo) => !largeUnconfirmedTxs.has(utxo.txId))
150
+ return filterDustUtxos({ utxos: confirmedAndSmallUtxos, feeData })
136
151
  }