@exodus/bitcoin-api 2.25.0 → 2.26.0
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 +14 -0
- package/package.json +3 -5
- package/src/balances.js +12 -2
- package/src/btc-like-keys.js +10 -7
- package/src/index.js +3 -2
- package/src/move-funds.js +9 -5
- package/src/multisig-address.js +7 -8
- package/src/tx-sign/create-get-key-and-purpose.js +2 -2
- package/src/tx-sign/create-sign-with-wallet.js +2 -2
- package/src/tx-sign/taproot.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
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
|
+
## [2.26.0](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@2.25.0...@exodus/bitcoin-api@2.26.0) (2024-09-30)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **bitcoin-api:** switch to exodus/crypto for secp256k1 ([#4042](https://github.com/ExodusMovement/assets/issues/4042)) ([e462faf](https://github.com/ExodusMovement/assets/commit/e462faf83d430f9c5c109cc2f49edf5a1dcbd856))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* add new balance properties ([#4018](https://github.com/ExodusMovement/assets/issues/4018)) ([7aec845](https://github.com/ExodusMovement/assets/commit/7aec8453be559211fa5ec75ec18c89f7823f3382))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
6
20
|
## [2.25.0](https://github.com/ExodusMovement/assets/compare/@exodus/bitcoin-api@2.24.0...@exodus/bitcoin-api@2.25.0) (2024-09-25)
|
|
7
21
|
|
|
8
22
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bitcoin-api",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.26.0",
|
|
4
4
|
"description": "Exodus bitcoin-api",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -26,9 +26,8 @@
|
|
|
26
26
|
"@exodus/bip322-js": "^1.1.0",
|
|
27
27
|
"@exodus/bip44-constants": "^195.0.0",
|
|
28
28
|
"@exodus/bitcoin-lib": "^2.4.2",
|
|
29
|
-
"@exodus/bitcoinerlab-secp256k1": "^1.0.5-exodus.1",
|
|
30
29
|
"@exodus/bitcoinjs": "^1.1.0",
|
|
31
|
-
"@exodus/crypto": "^1.0.0-rc.
|
|
30
|
+
"@exodus/crypto": "^1.0.0-rc.12",
|
|
32
31
|
"@exodus/currency": "^5.0.2",
|
|
33
32
|
"@exodus/key-identifier": "^1.1.1",
|
|
34
33
|
"@exodus/models": "^12.0.1",
|
|
@@ -42,7 +41,6 @@
|
|
|
42
41
|
"lodash": "^4.17.21",
|
|
43
42
|
"minimalistic-assert": "^1.0.1",
|
|
44
43
|
"ms": "^2.1.1",
|
|
45
|
-
"secp256k1": "^3.0.1",
|
|
46
44
|
"socket.io-client": "^2.1.1",
|
|
47
45
|
"url-join": "^4.0.0",
|
|
48
46
|
"varuint-bitcoin": "^1.1.0",
|
|
@@ -61,5 +59,5 @@
|
|
|
61
59
|
"type": "git",
|
|
62
60
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
63
61
|
},
|
|
64
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "77b6f56d7d574270a6418492b1094ab527d63ceb"
|
|
65
63
|
}
|
package/src/balances.js
CHANGED
|
@@ -25,7 +25,11 @@ export const getBalancesFactory = ({ feeData, getSpendableBalance, ordinalsEnabl
|
|
|
25
25
|
const totalBalance = asset.currency.defaultUnit(
|
|
26
26
|
parsedBalances.reduce((sum, item) => sum.add(item), asset.currency.ZERO)
|
|
27
27
|
)
|
|
28
|
-
return {
|
|
28
|
+
return {
|
|
29
|
+
total: totalBalance,
|
|
30
|
+
// legacy
|
|
31
|
+
balance: totalBalance,
|
|
32
|
+
}
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
const utxos = getUtxos({ asset, accountState })
|
|
@@ -36,6 +40,12 @@ export const getBalancesFactory = ({ feeData, getSpendableBalance, ordinalsEnabl
|
|
|
36
40
|
txSet: txLog,
|
|
37
41
|
feeData,
|
|
38
42
|
})
|
|
39
|
-
return {
|
|
43
|
+
return {
|
|
44
|
+
total: balance,
|
|
45
|
+
spendable: spendableBalance,
|
|
46
|
+
// legacy
|
|
47
|
+
balance,
|
|
48
|
+
spendableBalance,
|
|
49
|
+
}
|
|
40
50
|
}
|
|
41
51
|
}
|
package/src/btc-like-keys.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import ecc from '@exodus/bitcoinerlab-secp256k1'
|
|
2
1
|
import * as defaultBitcoinjsLib from '@exodus/bitcoinjs'
|
|
2
|
+
import * as secp256k1 from '@exodus/crypto/secp256k1'
|
|
3
3
|
import * as bech32 from 'bech32'
|
|
4
4
|
import bs58check from 'bs58check'
|
|
5
5
|
import lodash from 'lodash'
|
|
6
6
|
import assert from 'minimalistic-assert'
|
|
7
|
-
import secp256k1 from 'secp256k1'
|
|
8
7
|
import wif from 'wif'
|
|
9
8
|
|
|
10
9
|
import { hash160 } from './hash-utils.js'
|
|
11
10
|
|
|
12
11
|
const { identity, pickBy } = lodash
|
|
13
|
-
const toXOnly = ecc.xOnlyPointFromPoint
|
|
14
12
|
|
|
15
13
|
export const publicKeyToHashFactory = (p2pkh) => (publicKey) => {
|
|
16
14
|
const payload = Buffer.concat([Buffer.from([p2pkh]), hash160(publicKey)])
|
|
@@ -46,7 +44,7 @@ export const createBtcLikeKeys = ({
|
|
|
46
44
|
encodePublicFromWIFCustom ||
|
|
47
45
|
((privateKeyWIF) => {
|
|
48
46
|
const { privateKey, compressed } = wif.decode(privateKeyWIF, coinInfo.versions.private)
|
|
49
|
-
const publicKey =
|
|
47
|
+
const publicKey = secp256k1.privateKeyToPublicKey({ privateKey, compressed })
|
|
50
48
|
return encodePublicPurpose44(publicKey)
|
|
51
49
|
})
|
|
52
50
|
const encodePublicBech32 =
|
|
@@ -67,7 +65,7 @@ export const createBtcLikeKeys = ({
|
|
|
67
65
|
// NOTE: No password support here
|
|
68
66
|
const { versions } = coinInfo
|
|
69
67
|
const { privateKey, compressed } = wif.decode(privateKeyWIF, versions.private)
|
|
70
|
-
const publicKey =
|
|
68
|
+
const publicKey = secp256k1.privateKeyToPublicKey({ privateKey, compressed })
|
|
71
69
|
return encodePublicBech32(publicKey)
|
|
72
70
|
}
|
|
73
71
|
: undefined
|
|
@@ -75,7 +73,11 @@ export const createBtcLikeKeys = ({
|
|
|
75
73
|
const encodeNestedP2WPKH =
|
|
76
74
|
encodeNestedP2WPKHCustom || bitcoinjsLib
|
|
77
75
|
? (publicKey) => {
|
|
78
|
-
const pubkey = secp256k1.publicKeyConvert(
|
|
76
|
+
const pubkey = secp256k1.publicKeyConvert({
|
|
77
|
+
publicKey,
|
|
78
|
+
compressed: true,
|
|
79
|
+
format: 'buffer',
|
|
80
|
+
})
|
|
79
81
|
const witnessProgram = bitcoinjsLib.payments.p2wpkh({
|
|
80
82
|
pubkey,
|
|
81
83
|
}).output
|
|
@@ -93,7 +95,8 @@ export const createBtcLikeKeys = ({
|
|
|
93
95
|
(useBip86
|
|
94
96
|
? (publicKey) => {
|
|
95
97
|
const network = coinInfo.toBitcoinJS()
|
|
96
|
-
|
|
98
|
+
const xOnly = secp256k1.publicKeyToX({ publicKey, format: 'buffer' })
|
|
99
|
+
return bitcoinjsLib.payments.p2tr({ internalPubkey: xOnly, network }).address
|
|
97
100
|
}
|
|
98
101
|
: undefined)
|
|
99
102
|
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import ecc from '@exodus/bitcoinerlab-secp256k1'
|
|
2
1
|
import { ECPair } from '@exodus/bitcoinjs'
|
|
2
|
+
import { tiny_secp256k1_compat as ecc } from '@exodus/crypto/secp256k1'
|
|
3
3
|
|
|
4
4
|
export * from './account-state.js'
|
|
5
5
|
export * from './balances.js'
|
|
@@ -27,6 +27,7 @@ export { signMessage } from './sign-message.js'
|
|
|
27
27
|
|
|
28
28
|
// TODO: remove these, kept for compat
|
|
29
29
|
export { scriptClassify } from '@exodus/bitcoinjs'
|
|
30
|
-
export {
|
|
30
|
+
export { tiny_secp256k1_compat as ecc } from '@exodus/crypto/secp256k1'
|
|
31
31
|
export const eccFactory = () => ecc
|
|
32
32
|
export const getECPair = () => ECPair
|
|
33
|
+
export const toXOnly = (publicKey) => publicKey.slice(1, 33)
|
package/src/move-funds.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { privateKeyToPublicKey, publicKeyConvert } from '@exodus/crypto/secp256k1'
|
|
1
2
|
import { Address, UtxoCollection } from '@exodus/models'
|
|
2
3
|
import assert from 'minimalistic-assert'
|
|
3
|
-
import secp256k1 from 'secp256k1'
|
|
4
4
|
import wif from 'wif'
|
|
5
5
|
|
|
6
6
|
import { createInputs, createOutput, getNonWitnessTxs } from './tx-send/index.js'
|
|
@@ -20,7 +20,8 @@ const wifToPublicKey = ({ coinInfo, privateKeyWIF }) => {
|
|
|
20
20
|
const { versions } = coinInfo
|
|
21
21
|
|
|
22
22
|
const { privateKey, compressed } = wif.decode(privateKeyWIF, versions.private)
|
|
23
|
-
|
|
23
|
+
const publicKey = privateKeyToPublicKey({ privateKey, compressed, format: 'buffer' })
|
|
24
|
+
return { compressed, publicKey }
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export const getAddressesFromPrivateKeyFactory = ({ purposes, keys, coinInfo }) => {
|
|
@@ -35,9 +36,12 @@ export const getAddressesFromPrivateKeyFactory = ({ purposes, keys, coinInfo })
|
|
|
35
36
|
|
|
36
37
|
const { publicKey, compressed } = wifToPublicKey({ coinInfo, privateKeyWIF: privateKey })
|
|
37
38
|
const addresses = purposes.map((purpose) =>
|
|
38
|
-
keys.encodePublic(
|
|
39
|
-
purpose
|
|
40
|
-
|
|
39
|
+
keys.encodePublic(
|
|
40
|
+
purpose === 49
|
|
41
|
+
? publicKeyConvert({ publicKey, compressed: true, format: 'buffer' })
|
|
42
|
+
: publicKey,
|
|
43
|
+
{ purpose }
|
|
44
|
+
)
|
|
41
45
|
)
|
|
42
46
|
return { addresses, compressed }
|
|
43
47
|
}
|
package/src/multisig-address.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import defaultEcc from '@exodus/bitcoinerlab-secp256k1'
|
|
2
1
|
import * as defaultBitcoinjsLib from '@exodus/bitcoinjs'
|
|
2
|
+
import { publicKeyIsValid, publicKeyToX } from '@exodus/crypto/secp256k1'
|
|
3
3
|
|
|
4
|
-
const toXOnly =
|
|
4
|
+
const toXOnly = (publicKey) => publicKeyToX({ publicKey, format: 'buffer' })
|
|
5
5
|
|
|
6
6
|
// Key to use when key path spending is disabled https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#constructing-and-spending-taproot-outputs
|
|
7
7
|
const DUMMY_TAPROOT_PUBKEY = Buffer.from(
|
|
@@ -16,11 +16,7 @@ const LEAF_VERSION_TAPSCRIPT = 192
|
|
|
16
16
|
const MAX_PUBKEYS = 20
|
|
17
17
|
|
|
18
18
|
export const createEncodeMultisigContract =
|
|
19
|
-
({
|
|
20
|
-
bitcoinjsLib = defaultBitcoinjsLib,
|
|
21
|
-
network = bitcoinjsLib.Network.bitcoin,
|
|
22
|
-
ecc = defaultEcc,
|
|
23
|
-
}) =>
|
|
19
|
+
({ bitcoinjsLib = defaultBitcoinjsLib, network = bitcoinjsLib.Network.bitcoin, ecc }) =>
|
|
24
20
|
(
|
|
25
21
|
publicKeys,
|
|
26
22
|
{
|
|
@@ -29,9 +25,12 @@ export const createEncodeMultisigContract =
|
|
|
29
25
|
internalPubkey = DUMMY_TAPROOT_PUBKEY,
|
|
30
26
|
} = Object.create(null)
|
|
31
27
|
) => {
|
|
28
|
+
const isPointCompressed = (publicKey) =>
|
|
29
|
+
ecc ? ecc.isPointCompressed(publicKey) : publicKeyIsValid({ publicKey, compressed: true })
|
|
30
|
+
|
|
32
31
|
if (
|
|
33
32
|
!Array.isArray(publicKeys) ||
|
|
34
|
-
publicKeys.some((k) => !Buffer.isBuffer(k) || !
|
|
33
|
+
publicKeys.some((k) => !Buffer.isBuffer(k) || !isPointCompressed(k))
|
|
35
34
|
) {
|
|
36
35
|
throw new Error('publicKeys must be an Array of Buffers representing compressed public keys')
|
|
37
36
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { getOwnProperty, memoize } from '@exodus/basic-utils'
|
|
2
2
|
import { ECPair } from '@exodus/bitcoinjs'
|
|
3
|
+
import { privateKeyToPublicKey } from '@exodus/crypto/secp256k1'
|
|
3
4
|
import KeyIdentifier from '@exodus/key-identifier'
|
|
4
5
|
import BipPath from 'bip32-path'
|
|
5
6
|
import assert from 'minimalistic-assert'
|
|
6
|
-
import secp256k1 from 'secp256k1'
|
|
7
7
|
|
|
8
8
|
export const createGetKeyWithMetadata = ({
|
|
9
9
|
signer,
|
|
@@ -33,7 +33,7 @@ function getPrivateKeyFromMap(privateKeysAddressMap, networkInfo, purpose, addre
|
|
|
33
33
|
const privateKey = getOwnProperty(privateKeysAddressMap, address, 'string')
|
|
34
34
|
assert(privateKey, `there is no private key for address ${address}`)
|
|
35
35
|
const key = ECPair.fromWIF(privateKey, networkInfo)
|
|
36
|
-
const publicKey =
|
|
36
|
+
const publicKey = privateKeyToPublicKey({ privateKey: key.privateKey, format: 'buffer' })
|
|
37
37
|
return { key, purpose, publicKey }
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { xOnlyPointFromPoint as toXOnly } from '@exodus/bitcoinerlab-secp256k1'
|
|
2
1
|
import { bip371, payments, Transaction } from '@exodus/bitcoinjs'
|
|
2
|
+
import { publicKeyToX } from '@exodus/crypto/secp256k1'
|
|
3
3
|
|
|
4
4
|
import { createGetKeyWithMetadata } from './create-get-key-and-purpose.js'
|
|
5
5
|
import { toAsyncBufferSigner, toAsyncSigner } from './taproot.js'
|
|
@@ -52,7 +52,7 @@ export function createSignWithWallet({
|
|
|
52
52
|
if (isTaprootKeySpend && !Buffer.isBuffer(input.tapInternalKey)) {
|
|
53
53
|
// tapInternalKey is metadata for signing and not part of the hash to sign.
|
|
54
54
|
// so modifying it here is fine.
|
|
55
|
-
psbt.updateInput(index, { tapInternalKey:
|
|
55
|
+
psbt.updateInput(index, { tapInternalKey: publicKeyToX({ publicKey, format: 'buffer' }) })
|
|
56
56
|
}
|
|
57
57
|
} else if (purpose === 49 && !skipFinalize) {
|
|
58
58
|
// If spending from a P2SH address, we assume the address is P2SH wrapping
|
package/src/tx-sign/taproot.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import ecc from '@exodus/bitcoinerlab-secp256k1'
|
|
2
1
|
import { crypto, ECPair } from '@exodus/bitcoinjs'
|
|
2
|
+
import { tiny_secp256k1_compat as ecc } from '@exodus/crypto/secp256k1'
|
|
3
3
|
import assert from 'minimalistic-assert'
|
|
4
4
|
|
|
5
5
|
import defaultEntropy from './default-entropy.cjs'
|