@exodus/bitcoin-api 4.14.6 → 4.14.7

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.14.7](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.14.6...@exodus/bitcoin-api@4.14.7) (2026-05-11)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix(bitcoin-api): respect custom overrides in createBtcLikeKeys (#7921)
13
+
14
+
15
+
6
16
  ## [4.14.6](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@4.14.5...@exodus/bitcoin-api@4.14.6) (2026-04-24)
7
17
 
8
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bitcoin-api",
3
- "version": "4.14.6",
3
+ "version": "4.14.7",
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",
@@ -63,5 +63,5 @@
63
63
  "type": "git",
64
64
  "url": "git+https://github.com/ExodusMovement/assets.git"
65
65
  },
66
- "gitHead": "2cecf114ca8d8516413cf6e8b654d239e4373c96"
66
+ "gitHead": "241709879859db46e15f71aa02898c7d23b282b8"
67
67
  }
@@ -48,8 +48,10 @@ export const createBtcLikeKeys = ({
48
48
  return encodePublicPurpose44(publicKey)
49
49
  })
50
50
  const encodePublicBech32 =
51
- encodePublicBech32Custom || versions.bech32 !== undefined
52
- ? (publicKey) => {
51
+ encodePublicBech32Custom ||
52
+ (versions.bech32 === undefined
53
+ ? undefined
54
+ : (publicKey) => {
53
55
  const pubKeyHash = hash160(publicKey)
54
56
  const witnessVersion = Buffer.from([0])
55
57
  const witnessProgram = Buffer.concat([
@@ -57,10 +59,10 @@ export const createBtcLikeKeys = ({
57
59
  Buffer.from(bech32.toWords(pubKeyHash)),
58
60
  ])
59
61
  return bech32.encode(versions.bech32, witnessProgram)
60
- }
61
- : undefined
62
+ })
62
63
  const encodePublicBech32FromWIF =
63
- encodePublicBech32FromWIFCustom || encodePublicBech32
64
+ encodePublicBech32FromWIFCustom ||
65
+ (encodePublicBech32
64
66
  ? (privateKeyWIF) => {
65
67
  // NOTE: No password support here
66
68
  const { versions } = coinInfo
@@ -68,10 +70,11 @@ export const createBtcLikeKeys = ({
68
70
  const publicKey = secp256k1.privateKeyToPublicKey({ privateKey, compressed })
69
71
  return encodePublicBech32(publicKey)
70
72
  }
71
- : undefined
73
+ : undefined)
72
74
 
73
75
  const encodeNestedP2WPKH =
74
- encodeNestedP2WPKHCustom || bitcoinjsLib
76
+ encodeNestedP2WPKHCustom ||
77
+ (bitcoinjsLib
75
78
  ? (publicKey) => {
76
79
  const pubkey = secp256k1.publicKeyConvert({
77
80
  publicKey,
@@ -88,7 +91,7 @@ export const createBtcLikeKeys = ({
88
91
  coinInfo.versions.scripthash
89
92
  )
90
93
  }
91
- : undefined
94
+ : undefined)
92
95
 
93
96
  const encodePublicTaproot =
94
97
  encodePublicTaprootCustom ||
package/src/index.js CHANGED
@@ -15,7 +15,6 @@ export * from './fee/index.js'
15
15
  export * from './utxos-utils.js'
16
16
  export * from './tx-log/index.js'
17
17
  export * from './unconfirmed-ancestor-data.js'
18
- export * from './parse-unsigned-tx.js'
19
18
  export { getCreateBatchTransaction } from './tx-send/batch-tx.js'
20
19
  export { createPsbtToUnsignedTx } from './psbt-utils.js'
21
20
  export { createTxFactory } from './tx-create/create-tx.js'
@@ -1,96 +0,0 @@
1
- import { Transaction as BitcoinTransactionClass } from '@exodus/bitcoinjs'
2
- import BIPPath from 'bip32-path'
3
- import lodash from 'lodash'
4
- import assert from 'minimalistic-assert'
5
-
6
- export const parseUnsignedTxFactory =
7
- ({ Transaction = BitcoinTransactionClass } = {}) =>
8
- async ({ asset, unsignedTx, getAddress }) => {
9
- const assetName = asset.name
10
-
11
- const toNumberUnit = (value) => {
12
- const parsed = Buffer.isBuffer(value) ? BigInt('0x' + value.reverse().toString('hex')) : value // handle Dogecoin buffer values
13
- return asset.currency.baseUnit(parsed)
14
- }
15
-
16
- const parseAddress = assetName === 'bcash' ? asset.address.toCashAddress : (address) => address
17
-
18
- const { inputs, outputs } = unsignedTx.txData
19
-
20
- const from = lodash.uniq(inputs.map(({ address }) => parseAddress(address)))
21
- const outputAddresses = lodash.uniq(outputs.map(([address]) => address))
22
- const inputTxIds = lodash.uniq(inputs.map(({ txId }) => txId))
23
- const insightClient = asset.baseAsset.insightClient
24
- const inputTxsRaw = await Promise.all(inputTxIds.map((txId) => insightClient.fetchRawTx(txId)))
25
- const inputTxsById = new Map(
26
- inputTxsRaw.map((hex) => {
27
- const tx = Transaction.fromHex(hex)
28
- return [tx.getId(), tx]
29
- })
30
- )
31
-
32
- inputs.forEach(({ txId, vout, value }) => {
33
- const tx = inputTxsById.get(txId)
34
- const output = tx.outs[vout]
35
- const expected = output.value
36
- assert(
37
- lodash.isEqual(expected, value),
38
- `${txId} tx input has invalid value. Expected: ${expected} , Actual: ${value}`
39
- )
40
- })
41
-
42
- const { addressPathsMap } = unsignedTx.txMeta
43
- const [changeOutputAddresses, toOutputAddresses] = lodash.partition(
44
- outputAddresses,
45
- (address) => {
46
- const path = addressPathsMap[address]
47
- if (!path) return false
48
-
49
- const [chain, index] = BIPPath.fromString(path).path
50
- const isOurs = getAddress({ chain, index }).toString() === address
51
- return isOurs && chain === 1
52
- }
53
- )
54
-
55
- // the user is explicitly sending to a change address, so take a wild guess
56
- if (toOutputAddresses.length === 0) {
57
- toOutputAddresses.push(changeOutputAddresses.pop())
58
- }
59
-
60
- const [changeOutputs, sendOutputs] = lodash.partition(outputs, ([address]) =>
61
- changeOutputAddresses.includes(address)
62
- )
63
-
64
- const sum = (arr) => arr.reduce((a, b) => a.add(b), asset.currency.ZERO)
65
- const sumOutputs = (outputs) => sum(outputs.map(([_, value]) => toNumberUnit(value)))
66
-
67
- // sum(inputs) = intendedSendAmount + fee + change
68
- // sum(outputs) = intendedSendAmount + change
69
-
70
- const inputsNF = inputs.map(({ value }) => toNumberUnit(value))
71
- const outputsNF = outputs.map(([_, value]) => toNumberUnit(value))
72
- const changeAmount = sumOutputs(changeOutputs)
73
- const amount = sumOutputs(sendOutputs)
74
-
75
- const inputsTotal = sum(inputsNF)
76
- const outputsTotal = sum(outputsNF)
77
- const fee = inputsTotal.sub(outputsTotal)
78
-
79
- const changeAddress =
80
- changeOutputAddresses.length > 0 ? parseAddress(changeOutputAddresses[0]) : null
81
- // TODO: return entire toOutputAddresses array
82
- assert(toOutputAddresses.length === 1, 'multiple outputs not supported yet in 2fa mode')
83
-
84
- const to = parseAddress(toOutputAddresses[0])
85
- return {
86
- asset,
87
- from,
88
- to,
89
- amount,
90
- changeAddress,
91
- changeAmount,
92
- fee,
93
- }
94
- }
95
-
96
- export const parseUnsignedTx = parseUnsignedTxFactory()