@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 +10 -0
- package/package.json +2 -2
- package/src/btc-like-keys.js +11 -8
- package/src/index.js +0 -1
- package/src/parse-unsigned-tx.js +0 -96
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.
|
|
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": "
|
|
66
|
+
"gitHead": "241709879859db46e15f71aa02898c7d23b282b8"
|
|
67
67
|
}
|
package/src/btc-like-keys.js
CHANGED
|
@@ -48,8 +48,10 @@ export const createBtcLikeKeys = ({
|
|
|
48
48
|
return encodePublicPurpose44(publicKey)
|
|
49
49
|
})
|
|
50
50
|
const encodePublicBech32 =
|
|
51
|
-
encodePublicBech32Custom ||
|
|
52
|
-
|
|
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 ||
|
|
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 ||
|
|
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'
|
package/src/parse-unsigned-tx.js
DELETED
|
@@ -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()
|