@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 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.25.0",
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.7",
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": "823ab98b35624d4cc58dc75fa5d081e09fdc1ee6"
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 { balance: totalBalance }
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 { balance, spendableBalance }
43
+ return {
44
+ total: balance,
45
+ spendable: spendableBalance,
46
+ // legacy
47
+ balance,
48
+ spendableBalance,
49
+ }
40
50
  }
41
51
  }
@@ -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 = ecc.pointFromScalar(privateKey, compressed)
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 = ecc.pointFromScalar(privateKey, compressed)
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(publicKey, true)
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
- return bitcoinjsLib.payments.p2tr({ internalPubkey: toXOnly(publicKey), network }).address
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 { default as ecc, xOnlyPointFromPoint as toXOnly } from '@exodus/bitcoinerlab-secp256k1'
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
- return { compressed, publicKey: secp256k1.publicKeyCreate(privateKey, compressed) }
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(purpose === 49 ? secp256k1.publicKeyConvert(publicKey, true) : publicKey, {
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
  }
@@ -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 = defaultEcc.xOnlyPointFromPoint
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) || !ecc.isPointCompressed(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 = secp256k1.publicKeyCreate(key.privateKey, true)
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: toXOnly(publicKey) })
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
@@ -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'