@exodus/bitcoin-api 2.9.6 → 2.10.1
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 +3 -4
- package/src/bitcoinjs-lib/ecc/desktop.js +2 -10
- package/src/bitcoinjs-lib/script-classify/index.js +1 -1
- package/src/btc-like-address.js +1 -1
- package/src/btc-like-keys.js +1 -1
- package/src/fee/can-bump-tx.js +3 -0
- package/src/fee/get-fee-resolver.js +5 -1
- package/src/fee/utxo-selector.js +25 -5
- package/src/insight-api-client/index.js +4 -16
- package/src/parse-unsigned-tx.js +1 -1
- package/src/tx-send/dogecoin.js +2 -2
- package/src/tx-send/index.js +3 -1
- package/src/tx-sign/create-sign-with-wallet.js +1 -1
- package/src/tx-sign/default-prepare-for-signing.js +1 -1
- package/src/tx-sign/taproot.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bitcoin-api",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.1",
|
|
4
4
|
"description": "Exodus bitcoin-api",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -22,17 +22,16 @@
|
|
|
22
22
|
"@exodus/basic-utils": "^2.1.0",
|
|
23
23
|
"@exodus/bip44-constants": "^195.0.0",
|
|
24
24
|
"@exodus/bitcoin-lib": "2.3.0",
|
|
25
|
+
"@exodus/bitcoinjs-lib": "^6.1.5-exodus.1",
|
|
25
26
|
"@exodus/currency": "^2.3.2",
|
|
26
27
|
"@exodus/fetch": "^1.3.0",
|
|
27
28
|
"@exodus/models": "^11.0.0",
|
|
28
29
|
"@exodus/secp256k1": "4.0.2-exodus.0",
|
|
29
30
|
"@exodus/simple-retry": "0.0.6",
|
|
30
31
|
"@exodus/timer": "^1.0.0",
|
|
31
|
-
"@noble/hashes": "^1.3.3",
|
|
32
32
|
"@noble/secp256k1": "~1.7.1",
|
|
33
33
|
"bech32": "^1.1.3",
|
|
34
34
|
"bip32-path": "^0.4.2",
|
|
35
|
-
"bitcoinjs-lib": "^6.1.5",
|
|
36
35
|
"bn.js": "4.12.0",
|
|
37
36
|
"bs58check": "^2.1.2",
|
|
38
37
|
"coininfo": "5.1.0",
|
|
@@ -58,5 +57,5 @@
|
|
|
58
57
|
"jest-when": "^3.5.1",
|
|
59
58
|
"safe-buffer": "^5.2.1"
|
|
60
59
|
},
|
|
61
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "59489f1962adac06d14642120d7fe97e2a4f6d43"
|
|
62
61
|
}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
import { initEccLib } from 'bitcoinjs-lib'
|
|
2
|
-
import {
|
|
1
|
+
import { initEccLib } from '@exodus/bitcoinjs-lib'
|
|
2
|
+
import { Point, schnorr, sign } from '@noble/secp256k1'
|
|
3
3
|
import { common, toPubKey } from './common'
|
|
4
4
|
|
|
5
|
-
import { hmac } from '@noble/hashes/hmac'
|
|
6
|
-
import { sha256 } from '@noble/hashes/sha256'
|
|
7
|
-
|
|
8
|
-
// hijack to avoid the usage of crypto.subtle, not present in RN atm
|
|
9
|
-
utils.hmacSha256 = (key, ...msgs) => hmac(sha256, key, utils.concatBytes(...msgs))
|
|
10
|
-
|
|
11
|
-
utils.sha256 = (...msgs) => sha256(utils.concatBytes(...msgs))
|
|
12
|
-
|
|
13
5
|
/**
|
|
14
6
|
* Wrapper around `secp256k1` in order to follow the bitcoinjs-lib `TinySecp256k1Interface`
|
|
15
7
|
* Schnorr signatures are offered by @noble/secp256k1
|
package/src/btc-like-address.js
CHANGED
|
@@ -2,7 +2,7 @@ import bs58check from 'bs58check'
|
|
|
2
2
|
import * as bech32 from 'bech32'
|
|
3
3
|
import assert from 'minimalistic-assert'
|
|
4
4
|
import { identity, pickBy } from 'lodash'
|
|
5
|
-
import * as bitcoinjsOriginal from 'bitcoinjs-lib'
|
|
5
|
+
import * as bitcoinjsOriginal from '@exodus/bitcoinjs-lib'
|
|
6
6
|
|
|
7
7
|
export const createBtcLikeAddress = ({
|
|
8
8
|
versions,
|
package/src/btc-like-keys.js
CHANGED
|
@@ -3,7 +3,7 @@ import wif from 'wif'
|
|
|
3
3
|
import * as bech32 from 'bech32'
|
|
4
4
|
import assert from 'minimalistic-assert'
|
|
5
5
|
import { identity, pickBy } from 'lodash'
|
|
6
|
-
import * as defaultBitcoinjsLib from 'bitcoinjs-lib'
|
|
6
|
+
import * as defaultBitcoinjsLib from '@exodus/bitcoinjs-lib'
|
|
7
7
|
import secp256k1 from 'secp256k1'
|
|
8
8
|
import { hash160 } from './hash-utils'
|
|
9
9
|
import { toXOnly } from './bitcoinjs-lib/ecc-utils'
|
package/src/fee/can-bump-tx.js
CHANGED
|
@@ -17,6 +17,7 @@ const _canBumpTx = ({
|
|
|
17
17
|
feeData,
|
|
18
18
|
getFeeEstimator,
|
|
19
19
|
allowUnconfirmedRbfEnabledUtxos,
|
|
20
|
+
utxosDescendingOrder,
|
|
20
21
|
}) => {
|
|
21
22
|
assert(asset, 'asset must be provided')
|
|
22
23
|
assert(tx, 'tx must be provided')
|
|
@@ -91,6 +92,7 @@ const _canBumpTx = ({
|
|
|
91
92
|
getFeeEstimator,
|
|
92
93
|
allowUnconfirmedRbfEnabledUtxos,
|
|
93
94
|
unconfirmedTxAncestor,
|
|
95
|
+
utxosDescendingOrder,
|
|
94
96
|
})
|
|
95
97
|
if (replaceTx) return { bumpType: BumpType.RBF, bumpFee: fee.sub(replaceTx.feeAmount) }
|
|
96
98
|
}
|
|
@@ -104,6 +106,7 @@ const _canBumpTx = ({
|
|
|
104
106
|
mustSpendUtxos: changeUtxos,
|
|
105
107
|
allowUnconfirmedRbfEnabledUtxos,
|
|
106
108
|
unconfirmedTxAncestor,
|
|
109
|
+
utxosDescendingOrder,
|
|
107
110
|
})
|
|
108
111
|
|
|
109
112
|
return fee ? { bumpType: BumpType.CPFP, bumpFee: fee } : { errorMessage: 'insufficient funds' }
|
|
@@ -8,12 +8,14 @@ import { getUnconfirmedTxAncestorMap } from '../unconfirmed-ancestor-data'
|
|
|
8
8
|
export class GetFeeResolver {
|
|
9
9
|
#getFeeEstimator
|
|
10
10
|
#allowUnconfirmedRbfEnabledUtxos
|
|
11
|
+
#utxosDescendingOrder
|
|
11
12
|
|
|
12
|
-
constructor({ getFeeEstimator, allowUnconfirmedRbfEnabledUtxos }) {
|
|
13
|
+
constructor({ getFeeEstimator, allowUnconfirmedRbfEnabledUtxos, utxosDescendingOrder }) {
|
|
13
14
|
assert(getFeeEstimator, 'getFeeEstimator must be provided')
|
|
14
15
|
this.#getFeeEstimator = (asset, { feePerKB, ...options }) =>
|
|
15
16
|
getFeeEstimator(asset, feePerKB, options)
|
|
16
17
|
this.#allowUnconfirmedRbfEnabledUtxos = allowUnconfirmedRbfEnabledUtxos
|
|
18
|
+
this.#utxosDescendingOrder = utxosDescendingOrder
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
getFee = ({
|
|
@@ -120,6 +122,7 @@ export class GetFeeResolver {
|
|
|
120
122
|
getFeeEstimator: this.#getFeeEstimator,
|
|
121
123
|
allowUnconfirmedRbfEnabledUtxos: this.#allowUnconfirmedRbfEnabledUtxos,
|
|
122
124
|
unconfirmedTxAncestor,
|
|
125
|
+
utxosDescendingOrder: this.#utxosDescendingOrder,
|
|
123
126
|
})
|
|
124
127
|
}
|
|
125
128
|
|
|
@@ -132,6 +135,7 @@ export class GetFeeResolver {
|
|
|
132
135
|
feeData,
|
|
133
136
|
getFeeEstimator: this.#getFeeEstimator,
|
|
134
137
|
allowUnconfirmedRbfEnabledUtxos: this.#allowUnconfirmedRbfEnabledUtxos,
|
|
138
|
+
utxosDescendingOrder: this.#utxosDescendingOrder,
|
|
135
139
|
})
|
|
136
140
|
}
|
|
137
141
|
}
|
package/src/fee/utxo-selector.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UtxoCollection } from '@exodus/models'
|
|
2
2
|
import NumberUnit from '@exodus/currency'
|
|
3
|
+
import { sortBy } from 'lodash'
|
|
3
4
|
import assert from 'minimalistic-assert'
|
|
4
5
|
import { getExtraFee } from './fee-utils'
|
|
5
6
|
import { getConfirmedUtxos, getConfirmedOrRfbDisabledUtxos } from '../utxos-utils'
|
|
@@ -20,6 +21,7 @@ const getBestReceiveAddresses = ({ asset, receiveAddress, inscriptionIds }) => {
|
|
|
20
21
|
|
|
21
22
|
export const selectUtxos = ({
|
|
22
23
|
asset,
|
|
24
|
+
utxosDescendingOrder,
|
|
23
25
|
usableUtxos,
|
|
24
26
|
replaceableTxs,
|
|
25
27
|
amount,
|
|
@@ -163,7 +165,10 @@ export const selectUtxos = ({
|
|
|
163
165
|
allowUnconfirmedRbfEnabledUtxos,
|
|
164
166
|
})
|
|
165
167
|
|
|
166
|
-
const utxosArray =
|
|
168
|
+
const utxosArray = _toPriorityOrderedArray({
|
|
169
|
+
utxosDescendingOrder,
|
|
170
|
+
utxos: spendableUtxos.union(ourRbfUtxos),
|
|
171
|
+
})
|
|
167
172
|
|
|
168
173
|
if (isSendAll) {
|
|
169
174
|
const selectedUtxos = UtxoCollection.fromArray(utxosArray, { currency })
|
|
@@ -181,10 +186,10 @@ export const selectUtxos = ({
|
|
|
181
186
|
(total, utxo) => total.add(utxo.value),
|
|
182
187
|
currency.ZERO
|
|
183
188
|
)
|
|
184
|
-
const remainingUtxosArray =
|
|
185
|
-
|
|
186
|
-
.difference(mustSpendUtxos)
|
|
187
|
-
|
|
189
|
+
const remainingUtxosArray = _toPriorityOrderedArray({
|
|
190
|
+
utxosDescendingOrder,
|
|
191
|
+
utxos: spendableUtxos.union(ourRbfUtxos).difference(mustSpendUtxos),
|
|
192
|
+
})
|
|
188
193
|
|
|
189
194
|
while (selectedUtxosValue.lte(amount) && remainingUtxosArray.length > 0) {
|
|
190
195
|
const newUtxo = remainingUtxosArray.shift()
|
|
@@ -236,6 +241,7 @@ export const getUtxosData = ({
|
|
|
236
241
|
allowUnconfirmedRbfEnabledUtxos,
|
|
237
242
|
inscriptionIds,
|
|
238
243
|
unconfirmedTxAncestor,
|
|
244
|
+
utxosDescendingOrder,
|
|
239
245
|
}) => {
|
|
240
246
|
const { selectedUtxos, replaceTx, fee } = selectUtxos({
|
|
241
247
|
asset,
|
|
@@ -251,6 +257,7 @@ export const getUtxosData = ({
|
|
|
251
257
|
allowUnconfirmedRbfEnabledUtxos,
|
|
252
258
|
unconfirmedTxAncestor,
|
|
253
259
|
inscriptionIds,
|
|
260
|
+
utxosDescendingOrder,
|
|
254
261
|
})
|
|
255
262
|
|
|
256
263
|
const resolvedFee = replaceTx ? fee.sub(replaceTx.feeAmount) : fee
|
|
@@ -286,3 +293,16 @@ export const getUtxosData = ({
|
|
|
286
293
|
extraFee,
|
|
287
294
|
}
|
|
288
295
|
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Replacing the `toPriorityOrderedArray` from @exodus/models
|
|
299
|
+
* Adding the functionality to sort utxos by ascending / descending order
|
|
300
|
+
*/
|
|
301
|
+
const _toPriorityOrderedArray = ({ utxosDescendingOrder = false, utxos }) => {
|
|
302
|
+
return sortBy(
|
|
303
|
+
utxos.toArray(),
|
|
304
|
+
(utxo) => !utxo.confirmations && utxo.rbfEnabled,
|
|
305
|
+
(utxo) => !utxo.confirmations,
|
|
306
|
+
(utxo) => utxo.value.toBaseNumber() * (utxosDescendingOrder ? -1 : 1)
|
|
307
|
+
)
|
|
308
|
+
}
|
|
@@ -3,6 +3,7 @@ import delay from 'delay'
|
|
|
3
3
|
import { isEmpty } from 'lodash'
|
|
4
4
|
|
|
5
5
|
import { fetch } from '@exodus/fetch'
|
|
6
|
+
import { retry } from '@exodus/simple-retry'
|
|
6
7
|
|
|
7
8
|
const getTextFromResponse = async (response) => {
|
|
8
9
|
try {
|
|
@@ -24,23 +25,10 @@ const fetchJson = async (url, fetchOptions) => {
|
|
|
24
25
|
return response.json()
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
// TODO: use p-retry
|
|
28
28
|
async function fetchJsonRetry(url, fetchOptions) {
|
|
29
|
-
const waitTimes = [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
while (true) {
|
|
33
|
-
try {
|
|
34
|
-
return await fetchJson(url, fetchOptions)
|
|
35
|
-
} catch (e) {
|
|
36
|
-
if (i < waitTimes.length) {
|
|
37
|
-
await delay(waitTimes[i])
|
|
38
|
-
i++
|
|
39
|
-
} else {
|
|
40
|
-
throw e
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
29
|
+
const waitTimes = ['5s', '10s', '20s', '30s']
|
|
30
|
+
const fetchWithRetry = retry(fetchJson, { delayTimesMs: waitTimes })
|
|
31
|
+
return fetchWithRetry(url, fetchOptions)
|
|
44
32
|
}
|
|
45
33
|
|
|
46
34
|
export default class InsightAPIClient {
|
package/src/parse-unsigned-tx.js
CHANGED
|
@@ -2,7 +2,7 @@ import assert from 'minimalistic-assert'
|
|
|
2
2
|
import BIPPath from 'bip32-path'
|
|
3
3
|
import BN from 'bn.js'
|
|
4
4
|
import lodash from 'lodash'
|
|
5
|
-
import { Transaction as BitcoinTransactionClass } from 'bitcoinjs-lib'
|
|
5
|
+
import { Transaction as BitcoinTransactionClass } from '@exodus/bitcoinjs-lib'
|
|
6
6
|
|
|
7
7
|
export const parseUnsignedTxFactory =
|
|
8
8
|
({ Transaction = BitcoinTransactionClass } = {}) =>
|
package/src/tx-send/dogecoin.js
CHANGED
|
@@ -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.
|
|
6
|
+
value: utxo.value.toBaseBufferLE(8),
|
|
7
7
|
}))
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export function createOutput(address, sendAmount) {
|
|
11
|
-
return [address, sendAmount.
|
|
11
|
+
return [address, sendAmount.toBaseBufferLE(8)]
|
|
12
12
|
}
|
package/src/tx-send/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
getUtxos,
|
|
22
22
|
} from '../utxos-utils'
|
|
23
23
|
|
|
24
|
-
import * as defaultBitcoinjsLib from 'bitcoinjs-lib'
|
|
24
|
+
import * as defaultBitcoinjsLib from '@exodus/bitcoinjs-lib'
|
|
25
25
|
import { getUnconfirmedTxAncestorMap } from '../unconfirmed-ancestor-data'
|
|
26
26
|
|
|
27
27
|
const ASSETS_SUPPORTED_BIP_174 = new Set([
|
|
@@ -137,6 +137,7 @@ export const createAndBroadcastTXFactory =
|
|
|
137
137
|
getSizeAndChangeScript = getSizeAndChangeScriptFactory(), // for decred customizations
|
|
138
138
|
allowUnconfirmedRbfEnabledUtxos,
|
|
139
139
|
ordinalsEnabled = false,
|
|
140
|
+
utxosDescendingOrder,
|
|
140
141
|
}) =>
|
|
141
142
|
async (
|
|
142
143
|
{ asset: maybeToken, walletAccount, address, amount: tokenAmount, options },
|
|
@@ -268,6 +269,7 @@ export const createAndBroadcastTXFactory =
|
|
|
268
269
|
allowUnconfirmedRbfEnabledUtxos,
|
|
269
270
|
unconfirmedTxAncestor,
|
|
270
271
|
inscriptionIds,
|
|
272
|
+
utxosDescendingOrder,
|
|
271
273
|
})
|
|
272
274
|
|
|
273
275
|
if (!selectedUtxos && !replaceTx) throw new Error('Not enough funds.')
|
package/src/tx-sign/taproot.js
CHANGED