@exodus/bitcoin-api 4.14.2 → 4.14.4
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 +24 -0
- package/package.json +2 -2
- package/src/fee/fee-utils.js +1 -1
- package/src/fee/script-classifier.js +1 -1
- package/src/insight-api-client/util.js +12 -3
- package/src/move-funds.js +2 -2
- package/src/tx-log/bitcoin-monitor-scanner.js +0 -7
- package/src/tx-log/bitcoin-monitor.js +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
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.14.4](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.14.3...@exodus/bitcoin-api@4.14.4) (2026-04-23)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* fix: append valid path for btc mempool websocket url (#7851)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## [4.14.3](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.14.2...@exodus/bitcoin-api@4.14.3) (2026-04-15)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
* fix(bitcoin-api): anchor isHex regex to correctly validate hex strings (#7774)
|
|
23
|
+
|
|
24
|
+
* fix(bitcoin-api): fix assert call that failed to validate address (#7772)
|
|
25
|
+
|
|
26
|
+
* fix(bitcoin-api): remove yieldToUI from BitcoinMonitorScanner (#7773)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
6
30
|
## [4.14.2](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.14.1...@exodus/bitcoin-api@4.14.2) (2026-04-04)
|
|
7
31
|
|
|
8
32
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bitcoin-api",
|
|
3
|
-
"version": "4.14.
|
|
3
|
+
"version": "4.14.4",
|
|
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",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"type": "git",
|
|
64
64
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "b71dc8274c76060519eb7b2cebdccbc7919cd144"
|
|
67
67
|
}
|
package/src/fee/fee-utils.js
CHANGED
|
@@ -6,7 +6,7 @@ import assert from 'minimalistic-assert'
|
|
|
6
6
|
import { resolveExtraFeeOfTx } from '../unconfirmed-ancestor-data.js'
|
|
7
7
|
import { isUtxoConfirmed } from '../utxos-utils.js'
|
|
8
8
|
|
|
9
|
-
export const isHex = (s) => typeof s === 'string' &&
|
|
9
|
+
export const isHex = (s) => typeof s === 'string' && /^[\da-f]+$/.test(s.toLowerCase())
|
|
10
10
|
|
|
11
11
|
export function getExtraFee({ asset, inputs, feePerKB, unconfirmedTxAncestor }) {
|
|
12
12
|
let extraFee = 0
|
|
@@ -30,7 +30,7 @@ export const scriptClassifierFactory = ({ addressApi }) => {
|
|
|
30
30
|
const classifyAddress = memoizeLruCache(
|
|
31
31
|
({ assetName, address }) => {
|
|
32
32
|
assert(assetName, 'assetName is required')
|
|
33
|
-
assert(
|
|
33
|
+
assert(address, 'address is required')
|
|
34
34
|
if (addressApi.isP2PKH(address)) return P2PKH
|
|
35
35
|
if (addressApi.isP2SH(address)) return P2SH
|
|
36
36
|
if (addressApi.isP2WPKH && addressApi.isP2WPKH(address)) return P2WPKH
|
|
@@ -80,12 +80,12 @@ export function orderTxs(txs) {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
|
-
*
|
|
83
|
+
* Strips a service URL down to its origin while preserving the scheme.
|
|
84
84
|
*
|
|
85
85
|
* https://somebtc.a.exodus.io/insight/ => https://somebtc.a.exodus.io
|
|
86
86
|
*
|
|
87
87
|
* @param {string} apiUrl the original apiUrl
|
|
88
|
-
* @returns {string} a
|
|
88
|
+
* @returns {string} a service origin URL.
|
|
89
89
|
*/
|
|
90
90
|
export function toWSUrl(apiUrl) {
|
|
91
91
|
if (!apiUrl) {
|
|
@@ -106,12 +106,21 @@ export function toWSUrl(apiUrl) {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
export function toMempoolWebSocketUrl(apiUrl) {
|
|
110
|
+
const wsUrl = toWSUrl(apiUrl)
|
|
111
|
+
if (typeof wsUrl !== 'string') {
|
|
112
|
+
return wsUrl
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return `${wsUrl}/api/v1/ws`
|
|
116
|
+
}
|
|
117
|
+
|
|
109
118
|
export function normalizeInsightConfig(config, monitorType) {
|
|
110
119
|
const apiUrl = config?.insightServers?.[0]
|
|
111
120
|
const mempoolApiUrl = config?.mempoolServer
|
|
112
121
|
const wsUrl =
|
|
113
122
|
monitorType === 'mempool'
|
|
114
|
-
? config?.mempoolServerWS ||
|
|
123
|
+
? config?.mempoolServerWS || toMempoolWebSocketUrl(mempoolApiUrl)
|
|
115
124
|
: config?.insightServersWS?.[0] || toWSUrl(apiUrl)
|
|
116
125
|
return { apiUrl, mempoolApiUrl, wsUrl }
|
|
117
126
|
}
|
package/src/move-funds.js
CHANGED
|
@@ -66,6 +66,7 @@ export const moveFundsFactory = ({
|
|
|
66
66
|
signTx,
|
|
67
67
|
address,
|
|
68
68
|
getAddressesFromPrivateKey,
|
|
69
|
+
assetClientInterface,
|
|
69
70
|
shouldExcludeVoutUtxo = () => false,
|
|
70
71
|
}) => {
|
|
71
72
|
assert(asset, 'asset is required')
|
|
@@ -74,6 +75,7 @@ export const moveFundsFactory = ({
|
|
|
74
75
|
assert(address, 'address is required')
|
|
75
76
|
assert(signTx, 'signTx is required')
|
|
76
77
|
assert(getAddressesFromPrivateKey, 'getAddressesFromPrivateKey is required')
|
|
78
|
+
assert(assetClientInterface, 'assetClientInterface is required')
|
|
77
79
|
assert(typeof shouldExcludeVoutUtxo === 'function', 'shouldExcludeVoutUtxo must be a function')
|
|
78
80
|
|
|
79
81
|
async function prepareSendFundsTx({
|
|
@@ -81,13 +83,11 @@ export const moveFundsFactory = ({
|
|
|
81
83
|
walletAccount,
|
|
82
84
|
input,
|
|
83
85
|
toAddress,
|
|
84
|
-
assetClientInterface,
|
|
85
86
|
MoveFundsError,
|
|
86
87
|
}) {
|
|
87
88
|
assert(asset.name === assetName, `expected asset ${asset.name} but got assetName ${assetName}`)
|
|
88
89
|
assert(walletAccount, 'walletAccount is required')
|
|
89
90
|
assert(toAddress, 'toAddress is required')
|
|
90
|
-
assert(assetClientInterface, 'assetClientInterface is required')
|
|
91
91
|
assert(MoveFundsError, 'MoveFundsError is required') // should we move MoveFundsError to asset libs?
|
|
92
92
|
|
|
93
93
|
const formatProps = {
|
|
@@ -20,7 +20,6 @@ export class BitcoinMonitorScanner {
|
|
|
20
20
|
#assetClientInterface
|
|
21
21
|
#txFetchLimitResolver
|
|
22
22
|
#shouldExcludeVoutUtxo
|
|
23
|
-
#yieldToUI
|
|
24
23
|
#extraChainIndexEnabled
|
|
25
24
|
#extraChainIndex
|
|
26
25
|
#gapLimit
|
|
@@ -29,7 +28,6 @@ export class BitcoinMonitorScanner {
|
|
|
29
28
|
asset,
|
|
30
29
|
assetClientInterface,
|
|
31
30
|
insightClient,
|
|
32
|
-
yieldToUI = () => {},
|
|
33
31
|
shouldExcludeVoutUtxo = () => false,
|
|
34
32
|
txFetchLimitResolver = ({ refresh }) => (refresh ? 50 : 10),
|
|
35
33
|
extraChainIndexEnabled,
|
|
@@ -40,7 +38,6 @@ export class BitcoinMonitorScanner {
|
|
|
40
38
|
assert(asset, 'asset is required!')
|
|
41
39
|
assert(assetClientInterface, 'assetClientInterface is required!')
|
|
42
40
|
assert(insightClient, 'insightClient is required')
|
|
43
|
-
assert(typeof yieldToUI === 'function', 'yieldToUI must be a function')
|
|
44
41
|
assert(typeof txFetchLimitResolver === 'function', 'txFetchLimitResolver must be a function')
|
|
45
42
|
assert(typeof shouldExcludeVoutUtxo === 'function', 'shouldExcludeVoutUtxo must be a function')
|
|
46
43
|
assert(typeof gapLimit === 'number', 'gapLimit must be a number')
|
|
@@ -65,7 +62,6 @@ export class BitcoinMonitorScanner {
|
|
|
65
62
|
async rescanBlockchainInsight({ walletAccount, refresh }) {
|
|
66
63
|
const asset = this.#asset
|
|
67
64
|
const assetClientInterface = this.#assetClientInterface
|
|
68
|
-
const yieldToUI = this.#yieldToUI
|
|
69
65
|
const insightClient = this.#insightClient
|
|
70
66
|
const txFetchLimit = this.#txFetchLimitResolver({ assetName: asset.name, refresh })
|
|
71
67
|
const assetName = asset.name
|
|
@@ -366,9 +362,6 @@ export class BitcoinMonitorScanner {
|
|
|
366
362
|
return addressIndex + resolvedGapLimit
|
|
367
363
|
})
|
|
368
364
|
})
|
|
369
|
-
|
|
370
|
-
// Safety check. Slow down if after 100 iterations txs are still being fetched.
|
|
371
|
-
if (fetchCount > 100) await yieldToUI(1000)
|
|
372
365
|
}
|
|
373
366
|
|
|
374
367
|
allTxs = orderTxs(allTxs)
|
|
@@ -5,7 +5,11 @@ import assert from 'minimalistic-assert'
|
|
|
5
5
|
import ms from 'ms'
|
|
6
6
|
|
|
7
7
|
import MempoolWSClient from '../insight-api-client/mempool-ws-client.js'
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
normalizeInsightConfig,
|
|
10
|
+
toMempoolWebSocketUrl,
|
|
11
|
+
toWSUrl,
|
|
12
|
+
} from '../insight-api-client/util.js'
|
|
9
13
|
import InsightWSClient from '../insight-api-client/ws.js'
|
|
10
14
|
import { resolveUnconfirmedAncestorData } from '../unconfirmed-ancestor-data.js'
|
|
11
15
|
import { BitcoinMonitorScanner } from './bitcoin-monitor-scanner.js'
|
|
@@ -50,7 +54,7 @@ export class Monitor extends BaseMonitor {
|
|
|
50
54
|
super({ asset, interval, assetClientInterface, logger, runner })
|
|
51
55
|
assert(insightClient, 'insightClient is required!')
|
|
52
56
|
assert(apiUrl, 'apiUrl is required')
|
|
53
|
-
assert(yieldToUI, 'yieldToUI
|
|
57
|
+
assert(typeof yieldToUI === 'function', 'yieldToUI must be a function')
|
|
54
58
|
this.#wsInterval = wsInterval
|
|
55
59
|
this.#ws = null
|
|
56
60
|
this.#apiUrl = apiUrl
|
|
@@ -69,7 +73,6 @@ export class Monitor extends BaseMonitor {
|
|
|
69
73
|
asset,
|
|
70
74
|
assetClientInterface,
|
|
71
75
|
insightClient,
|
|
72
|
-
yieldToUI,
|
|
73
76
|
...extraScannerParams,
|
|
74
77
|
})
|
|
75
78
|
|
|
@@ -104,7 +107,9 @@ export class Monitor extends BaseMonitor {
|
|
|
104
107
|
this.#connectWS(
|
|
105
108
|
wsUrl ||
|
|
106
109
|
this.#wsUrl ||
|
|
107
|
-
|
|
110
|
+
(this.#monitorType === 'mempool'
|
|
111
|
+
? toMempoolWebSocketUrl(this.#mempoolApiUrl)
|
|
112
|
+
: toWSUrl(this.#apiUrl))
|
|
108
113
|
)
|
|
109
114
|
}
|
|
110
115
|
}
|