@exodus/bitcoin-api 2.34.1 → 3.1.0

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,28 @@
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
+ ## [3.1.0](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@3.0.0...@exodus/bitcoin-api@3.1.0) (2025-07-15)
7
+
8
+
9
+ ### Features
10
+
11
+
12
+ * feat: enable buffer signing in decred (#5881)
13
+
14
+
15
+
16
+ ## [3.0.0](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@2.34.1...@exodus/bitcoin-api@3.0.0) (2025-07-11)
17
+
18
+
19
+ ### ⚠ BREAKING CHANGES
20
+
21
+ * remove deprecated asset.getSpendableBalance and asset.getAvailableBalance (#6013)
22
+
23
+
24
+ * refactor!: remove deprecated asset.getSpendableBalance and asset.getAvailableBalance (#6013)
25
+
26
+
27
+
6
28
  ## [2.34.1](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@2.34.0...@exodus/bitcoin-api@2.34.1) (2025-07-04)
7
29
 
8
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bitcoin-api",
3
- "version": "2.34.1",
3
+ "version": "3.1.0",
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",
@@ -36,6 +36,7 @@
36
36
  "bip32-path": "^0.4.2",
37
37
  "bs58check": "^3.0.1",
38
38
  "delay": "^4.0.1",
39
+ "events": "^3.3.0",
39
40
  "lodash": "^4.17.21",
40
41
  "minimalistic-assert": "^1.0.1",
41
42
  "ms": "^2.1.1",
@@ -56,5 +57,5 @@
56
57
  "type": "git",
57
58
  "url": "git+https://github.com/ExodusMovement/assets.git"
58
59
  },
59
- "gitHead": "5257fdf0f08e1c8f22849ed6c190f083f4393efb"
60
+ "gitHead": "229692f08cdae6009bb5bb2abbe9d708f6b2ab11"
60
61
  }
package/src/balances.js CHANGED
@@ -1,11 +1,24 @@
1
1
  import { getUnconfirmedSentBalance } from '@exodus/asset-lib'
2
2
  import assert from 'minimalistic-assert'
3
3
 
4
- import { getUnconfirmedUtxos, getUtxos } from './utxos-utils.js'
4
+ import { getUnconfirmedTxAncestorMap } from './unconfirmed-ancestor-data.js'
5
+ import {
6
+ getConfirmedOrRfbDisabledUtxos,
7
+ getUnconfirmedUtxos,
8
+ getUsableUtxos,
9
+ getUtxos,
10
+ } from './utxos-utils.js'
5
11
 
6
- export const getBalancesFactory = ({ feeData: defaultFeeData, getSpendableBalance }) => {
12
+ export const getBalancesFactory = ({
13
+ feeData: defaultFeeData,
14
+ allowUnconfirmedRbfEnabledUtxos,
15
+ }) => {
7
16
  assert(defaultFeeData, 'default feeData is required')
8
- assert(getSpendableBalance, 'getSpendableBalance is required')
17
+ assert(
18
+ typeof allowUnconfirmedRbfEnabledUtxos === 'boolean',
19
+ 'allowUnconfirmedRbfEnabledUtxos is required'
20
+ )
21
+
9
22
  return ({ asset, accountState, txLog, feeData = defaultFeeData }) => {
10
23
  assert(asset, 'asset is required')
11
24
  assert(accountState, 'accountState is required')
@@ -14,13 +27,25 @@ export const getBalancesFactory = ({ feeData: defaultFeeData, getSpendableBalanc
14
27
 
15
28
  const utxos = getUtxos({ asset, accountState })
16
29
  const balance = utxos.value
17
- const spendableBalance = getSpendableBalance({
30
+
31
+ const unconfirmedTxAncestor = getUnconfirmedTxAncestorMap({ accountState })
32
+
33
+ const usableUtxos = getUsableUtxos({
18
34
  asset,
19
- accountState,
20
- txSet: txLog,
35
+ utxos,
21
36
  feeData,
37
+ txSet: txLog,
38
+ unconfirmedTxAncestor,
22
39
  })
23
40
 
41
+ const spendableUtxos = getConfirmedOrRfbDisabledUtxos({
42
+ asset,
43
+ utxos: usableUtxos,
44
+ allowUnconfirmedRbfEnabledUtxos,
45
+ })
46
+
47
+ const spendableBalance = spendableUtxos.value
48
+
24
49
  const unconfirmedUtxos = getUnconfirmedUtxos({ utxos })
25
50
  const unconfirmedSent = getUnconfirmedSentBalance({ asset, txLog })
26
51
  return {
@@ -66,39 +66,6 @@ export class GetFeeResolver {
66
66
  return { fee, unspendableFee, extraFeeData }
67
67
  }
68
68
 
69
- getAvailableBalance = ({
70
- asset,
71
- accountState,
72
- txSet,
73
- feeData,
74
- amount,
75
- customFee,
76
- isSendAll,
77
- taprootInputWitnessSize,
78
- }) => {
79
- return this.#getUtxosData({
80
- asset,
81
- accountState,
82
- txSet,
83
- feeData,
84
- customFee,
85
- isSendAll,
86
- amount,
87
- taprootInputWitnessSize,
88
- }).availableBalance
89
- }
90
-
91
- getSpendableBalance = ({ asset, accountState, txSet, feeData, taprootInputWitnessSize }) => {
92
- return this.#getUtxosData({
93
- asset,
94
- accountState,
95
- txSet,
96
- feeData,
97
- isSendAll: true,
98
- taprootInputWitnessSize,
99
- }).spendableBalance
100
- }
101
-
102
69
  #getUtxosData = ({
103
70
  asset,
104
71
  accountState,
@@ -1,4 +1,4 @@
1
- import { EventEmitter } from 'events'
1
+ import EventEmitter from 'events/events.js'
2
2
  import io from 'socket.io-client'
3
3
 
4
4
  export default class InsightWSClient extends EventEmitter {
@@ -13,6 +13,7 @@ export const createGetKeyWithMetadata = ({
13
13
  privateKeysAddressMap,
14
14
  coinInfo,
15
15
  getKeyIdentifier,
16
+ getPrivateKeyFromMap = standardGetPrivateKeyFromMap,
16
17
  }) =>
17
18
  memoize(
18
19
  ({ address, derivationPath }) => {
@@ -36,7 +37,7 @@ export const createGetKeyWithMetadata = ({
36
37
  ({ address, derivationPath }) => address + '_' + derivationPath
37
38
  )
38
39
 
39
- function getPrivateKeyFromMap(privateKeysAddressMap, networkInfo, purpose, address) {
40
+ function standardGetPrivateKeyFromMap(privateKeysAddressMap, networkInfo, purpose, address) {
40
41
  const privateWif = getOwnProperty(privateKeysAddressMap, address, 'string')
41
42
  assert(privateWif, `there is no private key for address ${address}`)
42
43
 
@@ -12,6 +12,7 @@ export function createSignWithWallet({
12
12
  addressPathsMap,
13
13
  coinInfo,
14
14
  getKeyIdentifier,
15
+ getPrivateKeyFromMap,
15
16
  }) {
16
17
  const getKeyWithMetadata = createGetKeyWithMetadata({
17
18
  signer,
@@ -21,6 +22,7 @@ export function createSignWithWallet({
21
22
  addressPathsMap,
22
23
  coinInfo,
23
24
  getKeyIdentifier,
25
+ getPrivateKeyFromMap,
24
26
  })
25
27
 
26
28
  return async (psbt, inputsToSign, skipFinalize) => {
@@ -11,6 +11,7 @@ export const signTxFactory = ({
11
11
  coinInfo,
12
12
  network,
13
13
  getKeyIdentifier,
14
+ getPrivateKeyFromMap,
14
15
  Psbt = DefaultPsbt,
15
16
  Transaction = DefaultTransaction,
16
17
  }) => {
@@ -43,6 +44,7 @@ export const signTxFactory = ({
43
44
  hdkeys,
44
45
  resolvePurpose,
45
46
  privateKeysAddressMap,
47
+ getPrivateKeyFromMap,
46
48
  addressPathsMap,
47
49
  coinInfo,
48
50
  network,
@@ -84,6 +84,8 @@ function createPsbtFromTxData({
84
84
  writePsbtBlockHeight(psbt, blockHeight)
85
85
  }
86
86
 
87
+ const assetRequiresUtxoInInput = !['zcash', 'decred'].includes(assetName)
88
+
87
89
  // Fill tx
88
90
  for (const { txId, vout, address, value, script, sequence, tapLeafScript } of inputs) {
89
91
  // TODO: don't use the purpose as intermediate variable
@@ -92,11 +94,10 @@ function createPsbtFromTxData({
92
94
 
93
95
  const isSegwitAddress = purpose === 84
94
96
  const isTaprootAddress = purpose === 86
95
- const isZcashAsset = assetName === 'zcash'
96
97
 
97
98
  const txIn = { hash: txId, index: vout, sequence }
98
99
 
99
- if (isZcashAsset) {
100
+ if (!assetRequiresUtxoInInput) {
100
101
  txIn.script = script
101
102
  txIn.value = value
102
103
  }
@@ -112,7 +113,7 @@ function createPsbtFromTxData({
112
113
 
113
114
  const rawTx = (rawTxs || []).find((t) => t.txId === txId)
114
115
 
115
- if (!isTaprootAddress && !isZcashAsset) {
116
+ if (!isTaprootAddress && assetRequiresUtxoInInput) {
116
117
  assert(!!rawTx?.rawData, `Non-taproot outputs require the full previous transaction.`)
117
118
 
118
119
  const rawTxBuffer = Buffer.from(rawTx.rawData, 'hex')