@exodus/bitcoin-api 2.9.0 → 2.9.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bitcoin-api",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"description": "Exodus bitcoin-api",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@scure/btc-signer": "^1.1.0",
|
|
43
43
|
"jest-when": "^3.5.1"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "1f96673b2977e792373f9f3c4eb98c778817b2b6"
|
|
46
46
|
}
|
package/src/account-state.js
CHANGED
|
@@ -603,6 +603,7 @@ export class BitcoinMonitorScanner {
|
|
|
603
603
|
ordinalAddress,
|
|
604
604
|
knownBalanceUtxoIds: latestAccountState.knownBalanceUtxoIds,
|
|
605
605
|
mustAvoidUtxoIds: latestAccountState.mustAvoidUtxoIds,
|
|
606
|
+
additionalInscriptions: latestAccountState.additionalInscriptions,
|
|
606
607
|
})
|
|
607
608
|
: {}
|
|
608
609
|
|
|
@@ -674,6 +675,7 @@ export class BitcoinMonitorScanner {
|
|
|
674
675
|
ordinalAddress: ordinalAddress,
|
|
675
676
|
knownBalanceUtxoIds: latestAccountState.knownBalanceUtxoIds,
|
|
676
677
|
mustAvoidUtxoIds: latestAccountState.mustAvoidUtxoIds,
|
|
678
|
+
additionalInscriptions: latestAccountState.additionalInscriptions,
|
|
677
679
|
})
|
|
678
680
|
|
|
679
681
|
return {
|
|
@@ -168,13 +168,10 @@ export class Monitor extends BaseMonitor {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
if (txsToUpdate.length) {
|
|
171
|
-
const accountState = await aci.getAccountState({ assetName, walletAccount })
|
|
172
171
|
await this.updateTxLog({ assetName, walletAccount, logItems: txsToUpdate })
|
|
173
|
-
if (['bitcoin', 'bitcoinregtest', 'bitcointestnet'].includes(assetName)) {
|
|
172
|
+
if (utxos && ['bitcoin', 'bitcoinregtest', 'bitcointestnet'].includes(assetName)) {
|
|
174
173
|
const unconfirmedTxAncestor = await resolveUnconfirmedAncestorData({
|
|
175
|
-
|
|
176
|
-
accountState,
|
|
177
|
-
walletAccount,
|
|
174
|
+
utxos,
|
|
178
175
|
insightClient: this.#insightClient,
|
|
179
176
|
})
|
|
180
177
|
newData.mem = { unconfirmedTxAncestor }
|
|
@@ -269,12 +266,9 @@ export class Monitor extends BaseMonitor {
|
|
|
269
266
|
}
|
|
270
267
|
|
|
271
268
|
// Move to after tick
|
|
272
|
-
if (['bitcoin', 'bitcoinregtest', 'bitcointestnet'].includes(assetName)) {
|
|
273
|
-
const accountState = await aci.getAccountState({ assetName, walletAccount })
|
|
269
|
+
if (utxos && ['bitcoin', 'bitcoinregtest', 'bitcointestnet'].includes(assetName)) {
|
|
274
270
|
const unconfirmedTxAncestor = await resolveUnconfirmedAncestorData({
|
|
275
|
-
|
|
276
|
-
accountState,
|
|
277
|
-
walletAccount,
|
|
271
|
+
utxos,
|
|
278
272
|
insightClient: this.#insightClient,
|
|
279
273
|
})
|
|
280
274
|
newData.mem = { unconfirmedTxAncestor }
|
package/src/tx-utils.js
CHANGED
|
@@ -11,13 +11,7 @@ export const findUnconfirmedSentRbfTxs = (txSet) =>
|
|
|
11
11
|
tx.data.inputs
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
export const findLargeUnconfirmedTxs = ({
|
|
15
|
-
assetName,
|
|
16
|
-
txSet,
|
|
17
|
-
feeRate,
|
|
18
|
-
maxFee,
|
|
19
|
-
unconfirmedTxAncestor,
|
|
20
|
-
}) =>
|
|
14
|
+
export const findLargeUnconfirmedTxs = ({ txSet, feeRate, maxFee, unconfirmedTxAncestor }) =>
|
|
21
15
|
!txSet
|
|
22
16
|
? new Set()
|
|
23
17
|
: new Set(
|
|
@@ -25,7 +19,6 @@ export const findLargeUnconfirmedTxs = ({
|
|
|
25
19
|
.filter((tx) => {
|
|
26
20
|
if (!tx.pending) return false
|
|
27
21
|
const extraFee = resolveExtraFeeOfTx({
|
|
28
|
-
assetName,
|
|
29
22
|
feeRate,
|
|
30
23
|
txId: tx.txId,
|
|
31
24
|
unconfirmedTxAncestor,
|
|
@@ -1,28 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from 'minimalistic-assert'
|
|
2
2
|
|
|
3
|
-
export async function resolveUnconfirmedAncestorData({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const dataMap = getUnconfirmedTxAncestorMap({ accountState })
|
|
10
|
-
Object.entries(dataMap).forEach(([txId, stored]) => {
|
|
11
|
-
if (stored.walletAccount === walletAccount && stored.assetName === asset.name)
|
|
12
|
-
delete dataMap[txId]
|
|
3
|
+
export async function resolveUnconfirmedAncestorData({ utxos, insightClient }) {
|
|
4
|
+
assert(utxos, 'utxos is required')
|
|
5
|
+
assert(insightClient, 'insightClient is required')
|
|
6
|
+
const dataMap = Object.create(null)
|
|
7
|
+
const unconfirmedUtxos = utxos.toArray().filter((data) => {
|
|
8
|
+
return !data.confirmations || data.confirmations <= 0
|
|
13
9
|
})
|
|
14
|
-
|
|
15
|
-
const utxos = getUtxos({ accountState, asset })
|
|
16
|
-
.toArray()
|
|
17
|
-
.filter((data) => {
|
|
18
|
-
return !data.confirmations || data.confirmations <= 0
|
|
19
|
-
})
|
|
20
|
-
const txIds = new Set(utxos.map(({ txId }) => txId))
|
|
10
|
+
const txIds = new Set(unconfirmedUtxos.map(({ txId }) => txId))
|
|
21
11
|
for (const txId of txIds) {
|
|
22
12
|
try {
|
|
23
13
|
const { size, fees } = await insightClient.fetchUnconfirmedAncestorData(txId)
|
|
24
14
|
if (size !== 0) {
|
|
25
|
-
dataMap[txId] = {
|
|
15
|
+
dataMap[txId] = { size, fees }
|
|
26
16
|
}
|
|
27
17
|
} catch (e) {
|
|
28
18
|
console.warn(e)
|
|
@@ -32,19 +22,11 @@ export async function resolveUnconfirmedAncestorData({
|
|
|
32
22
|
}
|
|
33
23
|
|
|
34
24
|
export function getUnconfirmedTxAncestorMap({ accountState }) {
|
|
35
|
-
return accountState?.mem?.unconfirmedTxAncestor ||
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function getUnconfirmedAncestorData({ txId, assetName, unconfirmedTxAncestor = {} }) {
|
|
39
|
-
const stored = unconfirmedTxAncestor[txId]
|
|
40
|
-
if (stored?.assetName === assetName) {
|
|
41
|
-
return { size: stored.size, fees: stored.fees }
|
|
42
|
-
}
|
|
43
|
-
return undefined
|
|
25
|
+
return accountState?.mem?.unconfirmedTxAncestor || Object.create(null)
|
|
44
26
|
}
|
|
45
27
|
|
|
46
|
-
export function resolveExtraFeeOfTx({
|
|
47
|
-
const data =
|
|
28
|
+
export function resolveExtraFeeOfTx({ feeRate, txId, unconfirmedTxAncestor }) {
|
|
29
|
+
const data = unconfirmedTxAncestor?.[txId]
|
|
48
30
|
if (!data) return 0
|
|
49
31
|
const { fees, size } = data
|
|
50
32
|
// Get the difference in fee rate between ancestors and current estimate
|
package/src/utxos-utils.js
CHANGED
|
@@ -122,17 +122,54 @@ function isOrdinalUtxo({
|
|
|
122
122
|
return hasOrdinals
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
export function mergeAdditionalInscriptions({ allUtxos, additionalInscriptions }) {
|
|
126
|
+
return UtxoCollection.fromArray(
|
|
127
|
+
allUtxos.toArray().map((utxo) => {
|
|
128
|
+
const inscriptions = additionalInscriptions
|
|
129
|
+
.filter((additionalInscription) => {
|
|
130
|
+
const forUtxo =
|
|
131
|
+
additionalInscription.vout === utxo.vout && additionalInscription.txId === utxo.txId
|
|
132
|
+
if (forUtxo) {
|
|
133
|
+
// avoid duplicated
|
|
134
|
+
return !utxo.inscriptions?.find(
|
|
135
|
+
(existingInscription) =>
|
|
136
|
+
existingInscription.inscriptionId === additionalInscription.inscriptionId
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
return forUtxo
|
|
140
|
+
})
|
|
141
|
+
.map((additionalInscription) => ({
|
|
142
|
+
inscriptionId: additionalInscription.inscriptionId,
|
|
143
|
+
offset: additionalInscription.offset || 0,
|
|
144
|
+
}))
|
|
145
|
+
if (inscriptions.length) {
|
|
146
|
+
utxo.inscriptions = [...(utxo.inscriptions || []), ...inscriptions]
|
|
147
|
+
}
|
|
148
|
+
return utxo
|
|
149
|
+
}),
|
|
150
|
+
{
|
|
151
|
+
currency: allUtxos.currency,
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
125
156
|
export function partitionUtxos({
|
|
126
157
|
allUtxos,
|
|
127
158
|
ordinalsEnabled,
|
|
128
159
|
knownBalanceUtxoIds,
|
|
129
160
|
ordinalAddress,
|
|
130
161
|
mustAvoidUtxoIds,
|
|
162
|
+
additionalInscriptions,
|
|
131
163
|
}) {
|
|
132
164
|
assert(allUtxos, 'allUtxos is required')
|
|
133
165
|
if (ordinalsEnabled) assert(ordinalAddress, 'ordinalAddress is required')
|
|
166
|
+
|
|
167
|
+
const expandedAllUtxos = ordinalsEnabled
|
|
168
|
+
? mergeAdditionalInscriptions({ allUtxos, additionalInscriptions })
|
|
169
|
+
: allUtxos
|
|
170
|
+
|
|
134
171
|
return {
|
|
135
|
-
utxos:
|
|
172
|
+
utxos: expandedAllUtxos.filter(
|
|
136
173
|
(utxo) =>
|
|
137
174
|
!isOrdinalUtxo({
|
|
138
175
|
utxo,
|
|
@@ -142,7 +179,7 @@ export function partitionUtxos({
|
|
|
142
179
|
mustAvoidUtxoIds,
|
|
143
180
|
})
|
|
144
181
|
),
|
|
145
|
-
ordinalsUtxos:
|
|
182
|
+
ordinalsUtxos: expandedAllUtxos.filter((utxo) =>
|
|
146
183
|
isOrdinalUtxo({
|
|
147
184
|
utxo,
|
|
148
185
|
ordinalsEnabled,
|
|
@@ -191,7 +228,6 @@ export function getUsableUtxos({ asset, utxos, feeData, txSet, unconfirmedTxAnce
|
|
|
191
228
|
assert(typeof maxFee === 'number' && !Number.isNaN(maxFee), 'maxFee must be a number')
|
|
192
229
|
|
|
193
230
|
const largeUnconfirmedTxs = findLargeUnconfirmedTxs({
|
|
194
|
-
assetName: asset.name,
|
|
195
231
|
txSet,
|
|
196
232
|
feeRate,
|
|
197
233
|
maxFee,
|