@exodus/bitcoin-api 2.9.2 → 2.9.3-hotfix

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.
Files changed (35) hide show
  1. package/package.json +2 -3
  2. package/src/bitcoinjs-lib/ecc/common.js +1 -1
  3. package/src/bitcoinjs-lib/ecc/mobile.js +3 -3
  4. package/src/bitcoinjs-lib/script-classify/index.js +1 -1
  5. package/src/btc-like-address.js +3 -4
  6. package/src/btc-like-keys.js +4 -0
  7. package/src/constants/bip44.js +2 -2
  8. package/src/fee/can-bump-tx.js +3 -1
  9. package/src/fee/fee-estimator.js +5 -1
  10. package/src/fee/fee-utils.js +6 -5
  11. package/src/fee/get-fee-resolver.js +2 -1
  12. package/src/fee/script-classifier.js +5 -10
  13. package/src/fee/utxo-selector.js +10 -3
  14. package/src/hash-utils.js +4 -9
  15. package/src/insight-api-client/index.js +14 -12
  16. package/src/insight-api-client/util.js +16 -15
  17. package/src/insight-api-client/ws.js +1 -1
  18. package/src/move-funds.js +17 -17
  19. package/src/ordinals-utils.js +2 -2
  20. package/src/parse-unsigned-tx.js +80 -81
  21. package/src/tx-log/bitcoin-monitor-scanner.js +50 -38
  22. package/src/tx-log/bitcoin-monitor.js +14 -13
  23. package/src/tx-log/ordinals-indexer-utils.js +6 -0
  24. package/src/tx-send/dogecoin.js +2 -2
  25. package/src/tx-send/index.js +426 -418
  26. package/src/tx-sign/common.js +9 -9
  27. package/src/tx-sign/create-get-key-and-purpose.js +2 -2
  28. package/src/tx-sign/create-sign-with-wallet.js +3 -3
  29. package/src/tx-sign/default-entropy.js +1 -3
  30. package/src/tx-sign/default-prepare-for-signing.js +16 -18
  31. package/src/tx-sign/default-sign-hardware.js +2 -1
  32. package/src/tx-sign/taproot.js +4 -0
  33. package/src/tx-utils.js +5 -5
  34. package/src/unconfirmed-ancestor-data.js +1 -0
  35. package/src/utxos-utils.js +12 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bitcoin-api",
3
- "version": "2.9.2",
3
+ "version": "2.9.3-hotfix",
4
4
  "description": "Exodus bitcoin-api",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -57,6 +57,5 @@
57
57
  "bigi": "^1.4.2",
58
58
  "jest-when": "^3.5.1",
59
59
  "safe-buffer": "^5.2.1"
60
- },
61
- "gitHead": "b282e5087dda77c80fc63947ccc0020e6aa7db93"
60
+ }
62
61
  }
@@ -51,7 +51,7 @@ export const common = {
51
51
  parity: t[0] === 0x02 ? 0 : 1,
52
52
  xOnlyPubkey: toXOnly(t),
53
53
  }
54
- } catch (err) {
54
+ } catch {
55
55
  return null
56
56
  }
57
57
  },
@@ -53,7 +53,7 @@ export const mobileEcc = {
53
53
  try {
54
54
  schnorr.verify(message, publicKey, signature)
55
55
  return true
56
- } catch (e) {
56
+ } catch {
57
57
  return false
58
58
  }
59
59
  },
@@ -75,7 +75,7 @@ export const mobileEcc = {
75
75
  try {
76
76
  // temp solution secp256k1 does not actually verify the value range, only the data length
77
77
  return isPoint(Buffer.from(publicKey))
78
- } catch (err) {
78
+ } catch {
79
79
  return false
80
80
  }
81
81
  },
@@ -88,7 +88,7 @@ export const mobileEcc = {
88
88
  try {
89
89
  // temp solution secp256k1 does not actually verify the value range, only the data length
90
90
  return isPoint(Buffer.from(toPubKey(publicKey)))
91
- } catch (err) {
91
+ } catch {
92
92
  return false
93
93
  }
94
94
  },
@@ -5,7 +5,7 @@ function isPaymentFactory(payment) {
5
5
  try {
6
6
  payment({ output: script }, { eccLib })
7
7
  return true
8
- } catch (err) {
8
+ } catch {
9
9
  return false
10
10
  }
11
11
  }
@@ -34,9 +34,8 @@ export const createBtcLikeAddress = ({
34
34
  // NOTE: We only support version zero witness programs
35
35
  if (decoded.words[0] !== 0) return false
36
36
  // Ensure correct length
37
- if (bech32.fromWords(decoded.words.slice(1)).length !== length) return false
38
- return true
39
- } catch (e) {
37
+ return bech32.fromWords(decoded.words.slice(1)).length === length
38
+ } catch {
40
39
  return false
41
40
  }
42
41
  }
@@ -55,7 +54,7 @@ export const createBtcLikeAddress = ({
55
54
  const network = coinInfo.toBitcoinJS()
56
55
  bitcoinjsLibFork.payments.p2tr({ address: addr, network })
57
56
  return true
58
- } catch (e) {
57
+ } catch {
59
58
  return false
60
59
  }
61
60
  })) ||
@@ -103,18 +103,22 @@ export const createBtcLikeKeys = ({
103
103
  assert(encodePublicPurpose44, errorMessage)
104
104
  return encodePublicPurpose44(publicKey)
105
105
  }
106
+
106
107
  if (purpose === 49) {
107
108
  assert(encodeNestedP2WPKH, errorMessage)
108
109
  return encodeNestedP2WPKH(publicKey)
109
110
  }
111
+
110
112
  if (purpose === 84) {
111
113
  assert(encodePublicBech32, errorMessage)
112
114
  return encodePublicBech32(publicKey)
113
115
  }
116
+
114
117
  if (purpose === 86) {
115
118
  assert(encodePublicTaproot, errorMessage)
116
119
  return encodePublicTaproot(publicKey)
117
120
  }
121
+
118
122
  throw new Error(errorMessage)
119
123
  }
120
124
 
@@ -1,3 +1,3 @@
1
1
  // back compatibility. Use @exodus/bip44-constants/by-ticker instead
2
- import bip44Constants from '@exodus/bip44-constants/by-ticker'
3
- export default bip44Constants
2
+
3
+ export { default } from '@exodus/bip44-constants/by-ticker'
@@ -42,7 +42,9 @@ const _canBumpTx = ({
42
42
  const feePerKB = tx.data.feePerKB ? asset.currency.baseUnit(tx.data.feePerKB) : undefined
43
43
  if (!feePerKB) {
44
44
  return { errorMessage: 'fee rate is high enough' }
45
- } else if (feeData.nextBlockMinimumFee) {
45
+ }
46
+
47
+ if (feeData.nextBlockMinimumFee) {
46
48
  if (feePerKB.gt(feeData.nextBlockMinimumFee.mul(1e3))) {
47
49
  return { errorMessage: 'fee rate is high enough' }
48
50
  }
@@ -60,8 +60,9 @@ export const getSizeFactory = ({ defaultOutputType, addressApi }) => {
60
60
 
61
61
  return (asset, inputs, outputs, { compressed = true } = {}) => {
62
62
  if (inputs instanceof UtxoCollection) {
63
- inputs = Array.from(inputs).map((utxo) => utxo.script || null)
63
+ inputs = [...inputs].map((utxo) => utxo.script || null)
64
64
  }
65
+
65
66
  const assetName = asset.name
66
67
  // other bitcoin-like assets
67
68
  const baseSize =
@@ -103,6 +104,7 @@ export const getSizeFactory = ({ defaultOutputType, addressApi }) => {
103
104
  address: output,
104
105
  })
105
106
  }
107
+
106
108
  assert(
107
109
  supportedTypes.includes(scriptType),
108
110
  `Only ${supportedTypes.join(', ')} outputs supported right now`
@@ -132,6 +134,7 @@ export const getSizeFactory = ({ defaultOutputType, addressApi }) => {
132
134
  signatureLength
133
135
  )
134
136
  }
137
+
135
138
  if ([P2TR].includes(utxoScriptType)) {
136
139
  // Only the 64 byte Schnorr signature is present for Taproot Key-Path spend
137
140
  const signatureLength = 64
@@ -163,4 +166,5 @@ const getFeeEstimatorFactory = ({ defaultOutputType, addressApi }) => {
163
166
  const getSize = getSizeFactory({ defaultOutputType, addressApi })
164
167
  return createDefaultFeeEstimator(getSize)
165
168
  }
169
+
166
170
  export default getFeeEstimatorFactory
@@ -3,7 +3,7 @@ import { resolveExtraFeeOfTx } from '../unconfirmed-ancestor-data'
3
3
  import { UtxoCollection } from '@exodus/models'
4
4
  import assert from 'minimalistic-assert'
5
5
 
6
- export const isHex = (s) => typeof s === 'string' && /[0-9a-f]*/.test(s.toLowerCase())
6
+ export const isHex = (s) => typeof s === 'string' && /[\da-f]*/.test(s.toLowerCase())
7
7
 
8
8
  export function getExtraFee({ asset, inputs, feePerKB, unconfirmedTxAncestor }) {
9
9
  let extraFee = 0
@@ -13,9 +13,7 @@ export function getExtraFee({ asset, inputs, feePerKB, unconfirmedTxAncestor })
13
13
  (inputs instanceof UtxoCollection || !Array.isArray(inputs))
14
14
  ) {
15
15
  const feeRate = feePerKB.toBaseNumber() / 1000
16
- const utxos = Array.from(inputs).filter(
17
- ({ confirmations }) => !confirmations || confirmations <= 0
18
- )
16
+ const utxos = [...inputs].filter(({ confirmations }) => !confirmations || confirmations <= 0)
19
17
  const txIds = new Set(utxos.map(({ txId }) => txId))
20
18
  for (const txId of txIds) {
21
19
  extraFee += resolveExtraFeeOfTx({
@@ -25,8 +23,10 @@ export function getExtraFee({ asset, inputs, feePerKB, unconfirmedTxAncestor })
25
23
  unconfirmedTxAncestor,
26
24
  })
27
25
  }
26
+
28
27
  extraFee = Math.ceil(extraFee)
29
28
  }
29
+
30
30
  return extraFee
31
31
  }
32
32
 
@@ -46,11 +46,12 @@ export default function createDefaultFeeEstimator(getSize) {
46
46
  }
47
47
  }
48
48
  }
49
+
49
50
  export function parseCurrency(val, currency) {
50
51
  assert(currency instanceof UnitType, 'Currency must be supples as a UnitType')
51
52
 
52
53
  if (isNumberUnit(val)) return val // TODO: consider checking if the unitType.equals(currency) (if currency is object)
53
54
 
54
55
  if (typeof val === 'string') return currency.parse(val)
55
- else return currency.parse(val.value + ' ' + val.unit)
56
+ return currency.parse(val.value + ' ' + val.unit)
56
57
  }
@@ -33,6 +33,7 @@ export class GetFeeResolver {
33
33
  assert(!isSendAll, 'isSendAll must not be provided when nft is provided!!!')
34
34
  assert(!brc20, 'brc20 must not be provided when nft is provided!!!')
35
35
  }
36
+
36
37
  if (brc20) {
37
38
  // assert(!amount, 'amount must not be provided when brc20 is provided!!!')
38
39
  assert(!isSendAll, 'isSendAll must not be provided when brc20 is provided!!!')
@@ -115,7 +116,7 @@ export class GetFeeResolver {
115
116
  feeRate: feePerKB,
116
117
  receiveAddress,
117
118
  inscriptionIds,
118
- isSendAll: isSendAll,
119
+ isSendAll,
119
120
  getFeeEstimator: this.#getFeeEstimator,
120
121
  allowUnconfirmedRbfEnabledUtxos: this.#allowUnconfirmedRbfEnabledUtxos,
121
122
  unconfirmedTxAncestor,
@@ -9,12 +9,7 @@ const { P2PKH, P2SH, P2WPKH, P2WSH, P2TR } = scriptClassify.types
9
9
  const cacheSize = 1000
10
10
  const maxSize = 30
11
11
  const hashStringIfTooBig = (str) =>
12
- str.length > maxSize
13
- ? createHash('sha256')
14
- .update(str)
15
- .digest('hex')
16
- .slice(0, maxSize)
17
- : str
12
+ str.length > maxSize ? createHash('sha256').update(str).digest('hex').slice(0, maxSize) : str
18
13
 
19
14
  export const scriptClassifierFactory = ({ addressApi }) => {
20
15
  assert(addressApi, 'addressApi is required')
@@ -36,10 +31,10 @@ export const scriptClassifierFactory = ({ addressApi }) => {
36
31
  assert(assetName, 'assetName is required')
37
32
  assert(assetName, address, 'address is required')
38
33
  if (addressApi.isP2PKH(address)) return P2PKH
39
- else if (addressApi.isP2SH(address)) return P2SH
40
- else if (addressApi.isP2WPKH && addressApi.isP2WPKH(address)) return P2WPKH
41
- else if (addressApi.isP2TR && addressApi.isP2TR(address)) return P2TR
42
- else if (addressApi.isP2WSH && addressApi.isP2WSH(address)) return P2WSH
34
+ if (addressApi.isP2SH(address)) return P2SH
35
+ if (addressApi.isP2WPKH && addressApi.isP2WPKH(address)) return P2WPKH
36
+ if (addressApi.isP2TR && addressApi.isP2TR(address)) return P2TR
37
+ if (addressApi.isP2WSH && addressApi.isP2WSH(address)) return P2WSH
43
38
  return classifyScriptHex({
44
39
  assetName,
45
40
  classifyOutput,
@@ -10,6 +10,7 @@ const getBestReceiveAddresses = ({ asset, receiveAddress, inscriptionIds }) => {
10
10
  if (inscriptionIds) {
11
11
  return receiveAddress || 'P2TR'
12
12
  }
13
+
13
14
  if (receiveAddress === null) {
14
15
  return null
15
16
  }
@@ -68,7 +69,7 @@ export const selectUtxos = ({
68
69
  (replaceableTxs.length === 1 && confirmedUtxosArray.length === usableUtxos.size - 1))
69
70
 
70
71
  if (canReplace) {
71
- for (let tx of replaceableTxs) {
72
+ for (const tx of replaceableTxs) {
72
73
  const changeUtxos = usableUtxos.getTxIdUtxos(tx.txId)
73
74
  // Don't replace a tx that has already been spent
74
75
  if (tx.data.changeAddress && changeUtxos.size === 0) continue
@@ -88,7 +89,7 @@ export const selectUtxos = ({
88
89
  ...tx.data.sent.map(({ address }) => address),
89
90
  tx.data.changeAddress?.address || changeAddressType,
90
91
  ]
91
- if (receiveAddresses.find(Boolean)) outputs.push(...receiveAddresses)
92
+ if (receiveAddresses.some(Boolean)) outputs.push(...receiveAddresses)
92
93
 
93
94
  let fee
94
95
  let additionalUtxos
@@ -114,6 +115,7 @@ export const selectUtxos = ({
114
115
  outputs: noChangeOutputs,
115
116
  })
116
117
  }
118
+
117
119
  break
118
120
  }
119
121
 
@@ -125,6 +127,7 @@ export const selectUtxos = ({
125
127
  })
126
128
  }
127
129
  }
130
+
128
131
  if (isSendAll || replaceTxAmount.add(additionalUtxos.value).gte(amount.add(fee))) {
129
132
  const chainOutputs = isSendAll ? receiveAddresses : [...receiveAddresses, changeAddressType]
130
133
  const chainFee = feeEstimator({
@@ -136,6 +139,7 @@ export const selectUtxos = ({
136
139
  if ((!amount.isZero || tx.data.changeAddress) && fee.sub(tx.feeAmount).gte(chainFee)) {
137
140
  continue
138
141
  }
142
+
139
143
  return { selectedUtxos: additionalUtxos, fee, replaceTx: tx }
140
144
  }
141
145
  }
@@ -146,7 +150,7 @@ export const selectUtxos = ({
146
150
  // We can still spend our rbf utxos, but put them last
147
151
  let ourRbfUtxos = UtxoCollection.createEmpty({ currency })
148
152
  if (replaceableTxs) {
149
- for (let tx of replaceableTxs) {
153
+ for (const tx of replaceableTxs) {
150
154
  if (!tx.data.changeAddress) continue
151
155
  const changeUtxos = usableUtxos.getTxIdUtxos(tx.txId)
152
156
  ourRbfUtxos = ourRbfUtxos.union(changeUtxos)
@@ -167,6 +171,7 @@ export const selectUtxos = ({
167
171
  if (selectedUtxos.value.lt(amount.add(fee))) {
168
172
  return { fee }
169
173
  }
174
+
170
175
  return { selectedUtxos, fee }
171
176
  }
172
177
 
@@ -209,9 +214,11 @@ export const selectUtxos = ({
209
214
  selectedUtxos = selectedUtxos.addUtxo(remainingUtxosArray.shift())
210
215
  fee = feeEstimator({ inputs: selectedUtxos, outputs })
211
216
  }
217
+
212
218
  if (selectedUtxos.value.lt(amount.add(fee))) {
213
219
  return { fee }
214
220
  }
221
+
215
222
  return { selectedUtxos, fee }
216
223
  }
217
224
 
package/src/hash-utils.js CHANGED
@@ -1,19 +1,14 @@
1
1
  import createHash from 'create-hash'
2
+
2
3
  export function hash160(buffer) {
3
4
  const sha256Hash = sha256(buffer)
4
5
  try {
5
- return createHash('ripemd160')
6
- .update(sha256Hash)
7
- .digest()
6
+ return createHash('ripemd160').update(sha256Hash).digest()
8
7
  } catch {
9
- return createHash('rmd160')
10
- .update(sha256Hash)
11
- .digest()
8
+ return createHash('rmd160').update(sha256Hash).digest()
12
9
  }
13
10
  }
14
11
 
15
12
  export function sha256(buffer) {
16
- return createHash('sha256')
17
- .update(buffer)
18
- .digest()
13
+ return createHash('sha256').update(buffer).digest()
19
14
  }
@@ -7,8 +7,8 @@ import { fetch } from '@exodus/fetch'
7
7
  const getTextFromResponse = async (response) => {
8
8
  try {
9
9
  const responseBody = await response.text()
10
- return responseBody.substring(0, 100)
11
- } catch (e) {
10
+ return responseBody.slice(0, 100)
11
+ } catch {
12
12
  return ''
13
13
  }
14
14
  }
@@ -17,8 +17,9 @@ const fetchJson = async (url, fetchOptions) => {
17
17
  const response = await fetch(url, fetchOptions)
18
18
  if (!response.ok)
19
19
  throw new Error(
20
- `${url} returned ${response.status}: ${response.statusText ||
21
- 'Unknown Status Text'}. Body: ${await getTextFromResponse(response)}`
20
+ `${url} returned ${response.status}: ${
21
+ response.statusText || 'Unknown Status Text'
22
+ }. Body: ${await getTextFromResponse(response)}`
22
23
  )
23
24
  return response.json()
24
25
  }
@@ -30,8 +31,7 @@ async function fetchJsonRetry(url, fetchOptions) {
30
31
  let i = 0
31
32
  while (true) {
32
33
  try {
33
- const data = await fetchJson(url, fetchOptions)
34
- return data
34
+ return await fetchJson(url, fetchOptions)
35
35
  } catch (e) {
36
36
  if (i < waitTimes.length) {
37
37
  await delay(waitTimes[i])
@@ -54,7 +54,7 @@ export default class InsightAPIClient {
54
54
 
55
55
  async isNetworkConnected() {
56
56
  const url = urlJoin(this._baseURL, '/peer')
57
- const peerStatus = await fetchJson(url, { timeout: 10000 })
57
+ const peerStatus = await fetchJson(url, { timeout: 10_000 })
58
58
  return !!peerStatus.connected
59
59
  }
60
60
 
@@ -66,15 +66,15 @@ export default class InsightAPIClient {
66
66
 
67
67
  async fetchBlockHeight() {
68
68
  const url = urlJoin(this._baseURL, '/status')
69
- const status = await fetchJson(url, { timeout: 10000 })
69
+ const status = await fetchJson(url, { timeout: 10_000 })
70
70
  return status.info.blocks
71
71
  }
72
72
 
73
- async fetchAddress(address, opts = { includeTxs: false }) {
73
+ async fetchAddress(address, opts) {
74
74
  const encodedAddress = encodeURIComponent(address)
75
75
  const url = urlJoin(
76
76
  this._baseURL,
77
- opts.includeTxs ? `/addr/${encodedAddress}` : `/addr/${encodedAddress}?noTxList=1`
77
+ opts?.includeTxs ? `/addr/${encodedAddress}` : `/addr/${encodedAddress}?noTxList=1`
78
78
  )
79
79
  return fetchJson(url)
80
80
  }
@@ -85,6 +85,7 @@ export default class InsightAPIClient {
85
85
  if (assetNames) {
86
86
  query.set('assetNames', assetNames.join(','))
87
87
  }
88
+
88
89
  const encodedAddresses = encodeURIComponent(addresses)
89
90
  const url = urlJoin(this._baseURL, `/addrs/${encodedAddresses}/utxo?${query}`)
90
91
  const utxos = await fetchJson(url)
@@ -119,6 +120,7 @@ export default class InsightAPIClient {
119
120
  if (isEmpty(object)) {
120
121
  return null
121
122
  }
123
+
122
124
  return object
123
125
  }
124
126
 
@@ -133,7 +135,7 @@ export default class InsightAPIClient {
133
135
  if (!Array.isArray(addrs) || addrs.length === 0) return { items: [], totalItems: 0 }
134
136
 
135
137
  options = { noScriptSig: 1, noAsm: 1, noSpent: 0, from: 0, to: 10, ...options }
136
- const url = `${urlJoin(this._baseURL, `/addrs/txs`)}?${new URLSearchParams(options)}`
138
+ const url = `${urlJoin(this._baseURL, '/addrs/txs')}?${new URLSearchParams(options)}`
137
139
 
138
140
  const fetchOptions = {
139
141
  method: 'post',
@@ -142,7 +144,7 @@ export default class InsightAPIClient {
142
144
  'Content-Type': 'application/json',
143
145
  },
144
146
  body: JSON.stringify({ addrs: addrs.join(',') }),
145
- timeout: 10000,
147
+ timeout: 10_000,
146
148
  }
147
149
 
148
150
  return fetchJsonRetry(url, fetchOptions)
@@ -31,41 +31,41 @@ export function orderTxs(txs) {
31
31
 
32
32
  // sort unique time keys
33
33
  const txTimes = Object.keys(txTimesMap)
34
- txTimes.sort((a, b) => ~~a - ~~b)
34
+ txTimes.sort((a, b) => Math.trunc(a) - Math.trunc(b))
35
35
 
36
- let rettxs = []
36
+ const rettxs = []
37
37
 
38
38
  txTimes.forEach((txTime) => {
39
- let txsAtTime = txTimesMap[txTime] // array of txs
39
+ const txsAtTime = txTimesMap[txTime] // array of txs
40
40
  // should always be an array, but just incase
41
41
  if (!Array.isArray(txsAtTime)) return
42
42
  if (txsAtTime.length === 1) return rettxs.push(txsAtTime[0])
43
43
 
44
44
  // existing order { txid: orderNum }
45
- let txOrderCol = []
46
- for (let i = 0; i < txsAtTime.length; ++i) {
47
- txOrderCol.push({ txid: txsAtTime[i].txid, order: i })
45
+ const txOrderCol = []
46
+ for (const [i, element] of txsAtTime.entries()) {
47
+ txOrderCol.push({ txid: element.txid, order: i })
48
48
  }
49
49
 
50
50
  // determine new orders, checks each vin and looks for max order,
51
51
  // want current tx greater than any vin
52
- const txsAtTimeClone = txsAtTime.slice(0)
52
+ const txsAtTimeClone = [...txsAtTime]
53
53
  while (txsAtTime.length > 0) {
54
- let tx = txsAtTime.shift()
54
+ const tx = txsAtTime.shift()
55
55
  let maxOrder = 0
56
56
  tx.vin.forEach((vin) => {
57
- let txOrderMatch = txOrderCol.find((opair) => opair.txid === vin.txid)
57
+ const txOrderMatch = txOrderCol.find((opair) => opair.txid === vin.txid)
58
58
  if (txOrderMatch && txOrderMatch.order > maxOrder) maxOrder = txOrderMatch.order
59
59
  })
60
60
  txOrderCol.find((opair) => opair.txid === tx.txid).order = maxOrder + 1
61
61
  }
62
62
 
63
- let baseTime = ~~txTime
63
+ const baseTime = Math.trunc(txTime)
64
64
  const newWorldOrder = sortBy(txOrderCol, ['order'])
65
65
  newWorldOrder.forEach((opair, i) => {
66
- let txid = opair.txid
66
+ const txid = opair.txid
67
67
 
68
- let tx = txsAtTimeClone.find((tx) => tx.txid === txid)
68
+ const tx = txsAtTimeClone.find((tx) => tx.txid === txid)
69
69
  assert(tx, 'InsightAPIClient.orderTxs() tx undefined.')
70
70
 
71
71
  // we must do this to preserve order outside of this algorithm, difference is negligible
@@ -89,16 +89,17 @@ export function toWSUrl(apiUrl) {
89
89
  if (!apiUrl) {
90
90
  return apiUrl
91
91
  }
92
+
92
93
  try {
93
94
  // Note, we are not using URL because URL is different between mobile, desktop and BE
94
95
  // Using hydra's networking modules is an overkill for this function.
95
96
  const firstSplit = apiUrl.split('://')
96
97
  if (firstSplit.length > 1) {
97
98
  return `${firstSplit[0]}://${firstSplit[1].split('/')[0]}`
98
- } else {
99
- return apiUrl
100
99
  }
101
- } catch (e) {
100
+
101
+ return apiUrl
102
+ } catch {
102
103
  return apiUrl
103
104
  }
104
105
  }
@@ -11,7 +11,7 @@ export default class InsightWSClient extends EventEmitter {
11
11
 
12
12
  connect(addresses, opts) {
13
13
  const options = Object.assign(
14
- { transports: ['websocket'], reconnectionDelayMax: 30000, reconnectionDelay: 10000 },
14
+ { transports: ['websocket'], reconnectionDelayMax: 30_000, reconnectionDelay: 10_000 },
15
15
  opts
16
16
  )
17
17
 
package/src/move-funds.js CHANGED
@@ -8,7 +8,7 @@ const isValidPrivateKey = (privateKey) => {
8
8
  try {
9
9
  wif.decode(privateKey)
10
10
  return true
11
- } catch (err) {
11
+ } catch {
12
12
  return false
13
13
  }
14
14
  }
@@ -21,6 +21,7 @@ const wifToPublicKey = ({ coinInfo, privateKeyWIF }) => {
21
21
  const { privateKey, compressed } = wif.decode(privateKeyWIF, versions.private)
22
22
  return { compressed, publicKey: secp256k1.publicKeyCreate(privateKey, compressed) }
23
23
  }
24
+
24
25
  export const getAddressesFromPrivateKeyFactory = ({ purposes, keys, coinInfo }) => {
25
26
  assert(purposes, 'purposes is required')
26
27
  assert(keys, 'keys is required')
@@ -30,6 +31,7 @@ export const getAddressesFromPrivateKeyFactory = ({ purposes, keys, coinInfo })
30
31
  if (!isValidPrivateKey(privateKey)) {
31
32
  return { invalid: true }
32
33
  }
34
+
33
35
  const { publicKey, compressed } = wifToPublicKey({ coinInfo, privateKeyWIF: privateKey })
34
36
  const addresses = purposes.map((purpose) =>
35
37
  keys.encodePublic(purpose === 49 ? secp256k1.publicKeyConvert(publicKey, true) : publicKey, {
@@ -41,12 +43,14 @@ export const getAddressesFromPrivateKeyFactory = ({ purposes, keys, coinInfo })
41
43
  }
42
44
 
43
45
  export const renderAddresses = (addresses) => {
44
- if (!addresses.length) {
46
+ if (addresses.length === 0) {
45
47
  return ''
46
48
  }
49
+
47
50
  if (addresses.length === 1) {
48
51
  return `${addresses[0]}`
49
52
  }
53
+
50
54
  return `${addresses.slice(0, -1).join(', ')}, or ${addresses[addresses.length - 1]}`
51
55
  }
52
56
 
@@ -82,29 +86,24 @@ export const moveFundsFactory = ({
82
86
  assert(MoveFundsError, 'MoveFundsError is required') // should we move MoveFundsError to asset libs?
83
87
 
84
88
  const formatProps = {
85
- asset,
86
- input,
89
+ assetName: asset.name,
87
90
  }
88
91
  // WIF format private key
89
92
  const privateKey = input
90
93
 
91
- const { addresses, compressed, invalid } = getAddressesFromPrivateKey({
92
- privateKey,
93
- formatProps,
94
- MoveFundsError,
95
- })
94
+ const { addresses, compressed, invalid } = getAddressesFromPrivateKey({ privateKey })
96
95
 
97
96
  if (invalid) {
98
97
  throw new MoveFundsError('private-key-invalid', formatProps)
99
98
  }
100
99
 
101
- const receiveAddresses = (
102
- await assetClientInterface.getReceiveAddresses({
103
- walletAccount,
104
- assetName,
105
- multiAddressMode: true,
106
- })
107
- ).map(
100
+ const recieveAddressesObjects = await assetClientInterface.getReceiveAddresses({
101
+ walletAccount,
102
+ assetName,
103
+ multiAddressMode: true,
104
+ })
105
+
106
+ const receiveAddresses = recieveAddressesObjects.map(
108
107
  (receiveAddress) =>
109
108
  address.toLegacyAddress?.(receiveAddress.toString()) || receiveAddress.toString()
110
109
  )
@@ -127,6 +126,7 @@ export const moveFundsFactory = ({
127
126
  return { fromAddress: currentAddress, utxos }
128
127
  }
129
128
  }
129
+
130
130
  throw new MoveFundsError('balance-zero', {
131
131
  ...formatProps,
132
132
  fromAddress: renderAddresses(addresses),
@@ -139,7 +139,7 @@ export const moveFundsFactory = ({
139
139
  const feeData = await assetClientInterface.getFeeConfig({ assetName })
140
140
  const { fee, sizeKB } = getFee({ asset, feeData, utxos, compressed })
141
141
 
142
- let amount = utxos.value.sub(fee)
142
+ const amount = utxos.value.sub(fee)
143
143
  if (amount.isNegative) {
144
144
  throw new MoveFundsError('balance-negative', formatProps)
145
145
  }
@@ -10,7 +10,7 @@ export async function getOrdinalAddress({
10
10
  assert(assetClientInterface, 'assetClientInterface is required')
11
11
  assert(walletAccount, 'walletAccount is required')
12
12
  if (ordinalChainIndex === undefined) {
13
- return undefined
13
+ return
14
14
  }
15
15
 
16
16
  const purposes = await assetClientInterface.getSupportedPurposes({
@@ -21,7 +21,7 @@ export async function getOrdinalAddress({
21
21
  const purpose = 86
22
22
 
23
23
  if (!purposes.includes(purpose)) {
24
- return undefined
24
+ return
25
25
  }
26
26
 
27
27
  return assetClientInterface.getAddress({