@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 +10 -0
- package/dist/Signer.d.ts +15 -2
- package/dist/Signer.js +56 -50
- package/package.json +5 -4
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
|
-
|
|
5
|
-
static signAsync(
|
|
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
|
|
6
|
-
import {
|
|
5
|
+
import * as secp256k1 from '@exodus/crypto/secp256k1';
|
|
6
|
+
import { hash } from '@exodus/crypto/hash';
|
|
7
7
|
import assert from 'minimalistic-assert';
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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:
|
|
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": "
|
|
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
|
-
"
|
|
53
|
-
"
|
|
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": "
|
|
60
|
+
"gitHead": "91ee7841b5a4bf6b8762aa04ba621746b86fef87"
|
|
60
61
|
}
|