@exodus/bitcoin-api 4.9.1 → 4.9.2

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 CHANGED
@@ -3,6 +3,16 @@
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.9.2](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.9.1...@exodus/bitcoin-api@4.9.2) (2026-01-28)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix(bitcoin-api): Guard BTC-like send against duplicate broadcast (#7335)
13
+
14
+
15
+
6
16
  ## [4.9.1](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.9.0...@exodus/bitcoin-api@4.9.1) (2026-01-26)
7
17
 
8
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bitcoin-api",
3
- "version": "4.9.1",
3
+ "version": "4.9.2",
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",
@@ -61,5 +61,5 @@
61
61
  "type": "git",
62
62
  "url": "git+https://github.com/ExodusMovement/assets.git"
63
63
  },
64
- "gitHead": "481b327c2b57d6272c47807615be9f967ebb3d13"
64
+ "gitHead": "c4fddbe912ef8be359ae9952d8ff9945ed72c927"
65
65
  }
package/src/move-funds.js CHANGED
@@ -106,13 +106,13 @@ export const moveFundsFactory = ({
106
106
  assetName,
107
107
  walletAccount,
108
108
  })
109
- const recieveAddressesObjects = await assetClientInterface.getReceiveAddresses({
109
+ const receiveAddressesObjects = await assetClientInterface.getReceiveAddresses({
110
110
  walletAccount,
111
111
  assetName,
112
112
  multiAddressMode: config?.multiAddressMode ?? true,
113
113
  })
114
114
 
115
- const receiveAddresses = recieveAddressesObjects.map(
115
+ const receiveAddresses = receiveAddressesObjects.map(
116
116
  (receiveAddress) =>
117
117
  address.toLegacyAddress?.(receiveAddress.toString()) || receiveAddress.toString()
118
118
  )
@@ -6,6 +6,15 @@ import { extractTransactionContext } from '../psbt-parser.js'
6
6
  import { broadcastTransaction } from './broadcast-tx.js'
7
7
  import { updateAccountState, updateTransactionLog } from './update-state.js'
8
8
 
9
+ const checkTxExists = async ({ asset, txId }) => {
10
+ try {
11
+ const tx = await asset.insightClient.fetchTx(txId)
12
+ return Boolean(tx)
13
+ } catch {
14
+ return false
15
+ }
16
+ }
17
+
9
18
  const getSize = (tx) => {
10
19
  if (typeof tx.size === 'number') return tx.size
11
20
  if (typeof tx.virtualSize === 'function') {
@@ -199,15 +208,20 @@ export const sendTxFactory = ({
199
208
  try {
200
209
  await broadcastTransaction({ asset, rawTx })
201
210
  } catch (err) {
202
- if (/insight broadcast http error.*missing inputs/i.test(err.message)) {
203
- err.txInfo = JSON.stringify({
204
- amount: sendAmount.toDefaultString({ unit: true }),
205
- fee: ((fee && fee.toDefaultString({ unit: true })) || 0).toString(),
206
- allUtxos: usableUtxos.toJSON(),
207
- })
208
- }
211
+ const txExists = await checkTxExists({ asset, txId })
212
+ if (txExists) {
213
+ console.warn(`tx-send: ${assetName} tx already broadcast`, txId)
214
+ } else {
215
+ if (/insight broadcast http error.*missing inputs/i.test(err.message)) {
216
+ err.txInfo = JSON.stringify({
217
+ amount: sendAmount.toDefaultString({ unit: true }),
218
+ fee: ((fee && fee.toDefaultString({ unit: true })) || 0).toString(),
219
+ allUtxos: usableUtxos.toJSON(),
220
+ })
221
+ }
209
222
 
210
- throw err
223
+ throw err
224
+ }
211
225
  }
212
226
 
213
227
  const changeUtxoIndex = changeOutputIndex ?? -1