@exodus/bip322-js 2.2.0 → 3.0.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,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
+ ## [3.0.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/bip322-js@2.2.0...@exodus/bip322-js@3.0.0) (2025-09-10)
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ - drop sign() in favor of signAsync() (#13794)
11
+
12
+ ### Features
13
+
14
+ - feat!: drop sign() in favor of signAsync() (#13794)
15
+
6
16
  ## [2.2.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/bip322-js@2.1.0...@exodus/bip322-js@2.2.0) (2025-09-09)
7
17
 
8
18
  ### Features
package/dist/Signer.d.ts CHANGED
@@ -1,8 +1,21 @@
1
1
  import * as bitcoin from '@exodus/bitcoinjs';
2
2
  import type { Signer as AssetSigner } from '@exodus/asset-types/src/signer';
3
+ export declare const createSigner: (encodedKey: string | Buffer, network: bitcoin.Network) => {
4
+ signer: {
5
+ getPublicKey: () => Promise<any>;
6
+ sign: ({ data, signatureType, enc, tweak, extraEntropy }: {
7
+ data: any;
8
+ signatureType: any;
9
+ enc: any;
10
+ tweak: any;
11
+ extraEntropy?: null | undefined;
12
+ }) => Promise<any>;
13
+ };
14
+ compressed: any;
15
+ };
3
16
  declare class Signer {
4
- static sign(privateKeyOrWIF: string | Buffer, address: string, message: string, network?: bitcoin.Network): any;
5
- static signAsync(signer: string | Buffer | AssetSigner, address: string, message: string, network?: bitcoin.Network): Promise<any>;
17
+ #private;
18
+ static signAsync(signerOrKey: string | Buffer | AssetSigner, address: string, message: string, network?: bitcoin.Network): Promise<any>;
6
19
  private static checkPubKeyCorrespondToAddress;
7
20
  }
8
21
  export default Signer;
package/dist/Signer.js CHANGED
@@ -2,60 +2,66 @@ import Address from './Address.js';
2
2
  import BIP322 from './BIP322.js';
3
3
  import * as bitcoin from '@exodus/bitcoinjs';
4
4
  import * as bitcoinMessage from '@exodus/bitcoinjs/message';
5
- import { tiny_secp256k1_compat as ecc } from '@exodus/crypto/secp256k1';
6
- import { ECPairFactory } from 'ecpair';
5
+ import * as secp256k1 from '@exodus/crypto/secp256k1';
6
+ import { hash } from '@exodus/crypto/hash';
7
7
  import assert from 'minimalistic-assert';
8
- const ECPair = ECPairFactory(ecc);
9
- const createAsyncSigner = ({ signer, publicKey, tweak }) => {
10
- return {
11
- publicKey,
12
- getPublicKey: () => publicKey,
13
- sign: async (data) => signer.sign({ signatureType: 'ecdsa', data, enc: 'sig' }),
14
- signSchnorr: async (hash) => signer.sign({
15
- signatureType: 'schnorr',
16
- data: hash,
17
- tweak,
18
- }),
8
+ import wif from 'wif';
9
+ export const createSigner = (encodedKey, network) => {
10
+ let decoded;
11
+ if (typeof encodedKey === 'string') {
12
+ decoded = wif.decode(encodedKey);
13
+ const version = decoded.version;
14
+ if (version !== network.wif)
15
+ throw new Error('Invalid network version');
16
+ }
17
+ else {
18
+ decoded = { privateKey: encodedKey, compressed: true };
19
+ }
20
+ const { privateKey, compressed } = decoded;
21
+ const publicKey = secp256k1.privateKeyToPublicKey({ privateKey, compressed, format: 'buffer' });
22
+ const tweakPrivateKey = (tweak) => secp256k1.privateKeyTweakAdd({
23
+ privateKey: publicKey[0] === 3 ? secp256k1.privateKeyTweakNegate({ privateKey }) : privateKey,
24
+ tweak,
25
+ });
26
+ const signer = {
27
+ getPublicKey: async () => publicKey,
28
+ sign: async ({ data, signatureType, enc, tweak, extraEntropy = null }) => {
29
+ if (signatureType === 'schnorr') {
30
+ return secp256k1.schnorrSign({
31
+ data,
32
+ privateKey: tweak ? tweakPrivateKey(tweak) : privateKey,
33
+ extraEntropy,
34
+ format: 'buffer',
35
+ });
36
+ }
37
+ assert(signatureType === 'ecdsa');
38
+ assert(enc === 'sig' || enc === 'sig,rec');
39
+ return secp256k1.ecdsaSignHash({
40
+ hash: data,
41
+ privateKey,
42
+ extraEntropy,
43
+ recovery: enc !== 'sig',
44
+ format: 'buffer',
45
+ });
46
+ },
19
47
  };
48
+ return { signer, compressed };
20
49
  };
50
+ const createAsyncSigner = ({ signer, publicKey, tweak }) => ({
51
+ publicKey,
52
+ getPublicKey: () => publicKey,
53
+ sign: async (data) => signer.sign({ signatureType: 'ecdsa', data, enc: 'sig' }),
54
+ signSchnorr: async (hash) => signer.sign({ signatureType: 'schnorr', data: hash, tweak }),
55
+ });
21
56
  class Signer {
22
- static sign(privateKeyOrWIF, address, message, network = bitcoin.networks.bitcoin) {
23
- let signer = Buffer.isBuffer(privateKeyOrWIF)
24
- ? ECPair.fromPrivateKey(privateKeyOrWIF)
25
- : ECPair.fromWIF(privateKeyOrWIF, network);
26
- if (!this.checkPubKeyCorrespondToAddress(signer.publicKey, address)) {
27
- throw new Error(`Invalid private key provided for signing message for ${address}.`);
28
- }
29
- if (Address.isP2PKH(address)) {
30
- return bitcoinMessage.signSync(message, signer.privateKey, signer.compressed);
31
- }
32
- const scriptPubKey = Address.convertAdressToScriptPubkey(address);
33
- const toSpendTx = BIP322.buildToSpendTx(message, scriptPubKey);
34
- let toSignTx;
35
- if (Address.isP2SH(address)) {
36
- const redeemScript = bitcoin.payments.p2wpkh({
37
- hash: bitcoin.crypto.hash160(signer.publicKey),
38
- network,
39
- }).output;
40
- toSignTx = BIP322.buildToSignTx(toSpendTx.getId(), redeemScript, true);
41
- }
42
- else if (Address.isP2WPKH(address)) {
43
- toSignTx = BIP322.buildToSignTx(toSpendTx.getId(), scriptPubKey);
57
+ static async signAsync(signerOrKey, address, message, network = bitcoin.networks.bitcoin) {
58
+ if (typeof signerOrKey === 'string' || Buffer.isBuffer(signerOrKey)) {
59
+ const { signer, compressed } = createSigner(signerOrKey, network);
60
+ return this.#signAsyncInternal(signer, address, message, network, compressed);
44
61
  }
45
- else {
46
- const internalPublicKey = signer.publicKey.subarray(1, 33);
47
- signer = signer.tweak(bitcoin.crypto.taggedHash('TapTweak', signer.publicKey.subarray(1, 33)));
48
- toSignTx = BIP322.buildToSignTx(toSpendTx.getId(), scriptPubKey, false, internalPublicKey);
49
- }
50
- const toSignTxSigned = toSignTx
51
- .signAllInputs(signer, [bitcoin.Transaction.SIGHASH_ALL, bitcoin.Transaction.SIGHASH_DEFAULT])
52
- .finalizeAllInputs();
53
- return BIP322.encodeWitness(toSignTxSigned);
62
+ return this.#signAsyncInternal(signerOrKey, address, message, network, true);
54
63
  }
55
- static async signAsync(signer, address, message, network = bitcoin.networks.bitcoin) {
56
- if (typeof signer === 'string' || Buffer.isBuffer(signer)) {
57
- return this.sign(signer, address, message, network);
58
- }
64
+ static async #signAsyncInternal(signer, address, message, network = bitcoin.networks.bitcoin, compressed) {
59
65
  const publicKey = await signer.getPublicKey();
60
66
  assert(this.checkPubKeyCorrespondToAddress(publicKey, address), `Invalid signer for address "${address}".`);
61
67
  if (Address.isP2PKH(address)) {
@@ -69,7 +75,7 @@ class Signer {
69
75
  });
70
76
  },
71
77
  };
72
- return bitcoinMessage.signAsync(message, asyncSigner, true);
78
+ return bitcoinMessage.signAsync(message, asyncSigner, compressed);
73
79
  }
74
80
  const scriptPubKey = Address.convertAdressToScriptPubkey(address);
75
81
  const toSpendTx = BIP322.buildToSpendTx(message, scriptPubKey);
@@ -77,7 +83,7 @@ class Signer {
77
83
  let tweak;
78
84
  if (Address.isP2SH(address)) {
79
85
  const redeemScript = bitcoin.payments.p2wpkh({
80
- hash: bitcoin.crypto.hash160(publicKey),
86
+ hash: await hash('hash160', publicKey, 'buffer'),
81
87
  network,
82
88
  }).output;
83
89
  toSignTx = BIP322.buildToSignTx(toSpendTx.getId(), redeemScript, true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bip322-js",
3
- "version": "2.2.0",
3
+ "version": "3.0.0",
4
4
  "description": "A Javascript library that provides utility functions related to the BIP-322 signature scheme",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -41,6 +41,7 @@
41
41
  "bech32": "^1.1.3",
42
42
  "bs58check": "^3.0.1",
43
43
  "buffer-equals": "^1.0.3",
44
+ "ecpair": "^2.0.1",
44
45
  "typedoc": "^0.24.8",
45
46
  "typescript": "^5.1.3",
46
47
  "varuint-bitcoin": "^1.0.1"
@@ -49,12 +50,12 @@
49
50
  "@exodus/asset-types": "^0.3.0",
50
51
  "@exodus/bitcoinjs": "^1.4.0",
51
52
  "@exodus/crypto": "^1.0.0-rc.14",
52
- "ecpair": "^2.0.1",
53
- "minimalistic-assert": "^1.0.1"
53
+ "minimalistic-assert": "^1.0.1",
54
+ "wif": "^4.0.0"
54
55
  },
55
56
  "homepage": "https://github.com/ExodusMovement/exodus-hydra/tree/master/libraries/bip322-js",
56
57
  "bugs": {
57
58
  "url": "https://github.com/ExodusMovement/exodus-hydra/issues?q=is%3Aissue+is%3Aopen+label%3Abip322-js"
58
59
  },
59
- "gitHead": "90ec3f786bb430800fae41568e71ec2b67cd9009"
60
+ "gitHead": "91ee7841b5a4bf6b8762aa04ba621746b86fef87"
60
61
  }