@exodus/bitcoin-api 2.9.6 → 2.10.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bitcoin-api",
3
- "version": "2.9.6",
3
+ "version": "2.10.0",
4
4
  "description": "Exodus bitcoin-api",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -28,7 +28,6 @@
28
28
  "@exodus/secp256k1": "4.0.2-exodus.0",
29
29
  "@exodus/simple-retry": "0.0.6",
30
30
  "@exodus/timer": "^1.0.0",
31
- "@noble/hashes": "^1.3.3",
32
31
  "@noble/secp256k1": "~1.7.1",
33
32
  "bech32": "^1.1.3",
34
33
  "bip32-path": "^0.4.2",
@@ -58,5 +57,5 @@
58
57
  "jest-when": "^3.5.1",
59
58
  "safe-buffer": "^5.2.1"
60
59
  },
61
- "gitHead": "aa2228b4d986dacc2f2ce1975d75f81b48b22d9a"
60
+ "gitHead": "ec2ae412ef3401a8a451568382c9d7a6782cbd6a"
62
61
  }
@@ -1,15 +1,7 @@
1
1
  import { initEccLib } from 'bitcoinjs-lib'
2
- import { utils, Point, schnorr, sign } from '@noble/secp256k1'
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
@@ -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
  }
@@ -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 = spendableUtxos.union(ourRbfUtxos).toPriorityOrderedArray()
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 = spendableUtxos
185
- .union(ourRbfUtxos)
186
- .difference(mustSpendUtxos)
187
- .toPriorityOrderedArray()
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 = [5, 10, 20, 30].map((t) => t * 1000)
30
-
31
- let i = 0
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 {
@@ -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.')