@exodus/bip322-js 3.0.0 → 3.2.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 +12 -0
- package/dist/Signer.js +2 -2
- package/dist/Verifier.d.ts +8 -0
- package/dist/Verifier.js +127 -0
- package/dist/bitcoinjs/DecodeScriptSignature.d.ts +6 -0
- package/dist/bitcoinjs/DecodeScriptSignature.js +57 -0
- package/dist/bitcoinjs-message-verify.d.ts +1 -0
- package/dist/bitcoinjs-message-verify.js +87 -0
- package/dist/helpers/BIP137.d.ts +6 -0
- package/dist/helpers/BIP137.js +27 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +11 -11
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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.2.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/bip322-js@3.1.0...@exodus/bip322-js@3.2.0) (2025-12-26)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- feat(bip322-js): export Verifier for BIP-322 signature verification (#14641)
|
|
11
|
+
|
|
12
|
+
## [3.1.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/bip322-js@3.0.0...@exodus/bip322-js@3.1.0) (2025-09-16)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- feat: update bip322-js and bitcoinjs (#13812)
|
|
17
|
+
|
|
6
18
|
## [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
19
|
|
|
8
20
|
### ⚠ BREAKING CHANGES
|
package/dist/Signer.js
CHANGED
|
@@ -34,8 +34,8 @@ export const createSigner = (encodedKey, network) => {
|
|
|
34
34
|
format: 'buffer',
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
assert(signatureType === 'ecdsa');
|
|
38
|
-
assert(enc === 'sig' || enc === 'sig,rec');
|
|
37
|
+
assert(signatureType === 'ecdsa', 'Invalid signature type');
|
|
38
|
+
assert(enc === 'sig' || enc === 'sig,rec', 'Invalid encoding');
|
|
39
39
|
return secp256k1.ecdsaSignHash({
|
|
40
40
|
hash: data,
|
|
41
41
|
privateKey,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare class Verifier {
|
|
2
|
+
static verifySignature(signerAddress: string, message: string, signature: Buffer): Promise<boolean>;
|
|
3
|
+
private static verifyBIP137Signature;
|
|
4
|
+
private static getHashForSigP2WPKH;
|
|
5
|
+
private static getHashForSigP2SHInP2WPKH;
|
|
6
|
+
private static getHashForSigP2TR;
|
|
7
|
+
}
|
|
8
|
+
export default Verifier;
|
package/dist/Verifier.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as bitcoin from '@exodus/bitcoinjs';
|
|
2
|
+
import { ecdsaVerifyHashSync, schnorrVerify } from '@exodus/crypto/secp256k1';
|
|
3
|
+
import Address from './Address.js';
|
|
4
|
+
import BIP322 from './BIP322.js';
|
|
5
|
+
import { decodeScriptSignature } from './bitcoinjs/DecodeScriptSignature.js';
|
|
6
|
+
import * as bitcoinMessage from './bitcoinjs-message-verify.js';
|
|
7
|
+
import BIP137 from './helpers/BIP137.js';
|
|
8
|
+
class Verifier {
|
|
9
|
+
static async verifySignature(signerAddress, message, signature) {
|
|
10
|
+
if (!Buffer.isBuffer(signature)) {
|
|
11
|
+
throw new TypeError('signature must be a Buffer');
|
|
12
|
+
}
|
|
13
|
+
if (Address.isP2PKH(signerAddress) || BIP137.isBIP137Signature(signature)) {
|
|
14
|
+
return this.verifyBIP137Signature(signerAddress, message, signature);
|
|
15
|
+
}
|
|
16
|
+
const scriptPubKey = Address.convertAdressToScriptPubkey(signerAddress);
|
|
17
|
+
const toSpendTx = BIP322.buildToSpendTx(message, scriptPubKey);
|
|
18
|
+
const toSignTx = BIP322.buildToSignTx(toSpendTx.getId(), scriptPubKey);
|
|
19
|
+
toSignTx.updateInput(0, {
|
|
20
|
+
finalScriptWitness: signature,
|
|
21
|
+
});
|
|
22
|
+
const witness = toSignTx.extractTransaction().ins[0].witness;
|
|
23
|
+
const encodedSignature = witness[0];
|
|
24
|
+
if (Address.isP2WPKHWitness(witness)) {
|
|
25
|
+
const publicKey = witness[1];
|
|
26
|
+
const { signature } = decodeScriptSignature(encodedSignature);
|
|
27
|
+
const hashedPubkey = bitcoin.crypto.hash160(publicKey);
|
|
28
|
+
let hashToSign;
|
|
29
|
+
if (Address.isP2SH(signerAddress)) {
|
|
30
|
+
hashToSign = this.getHashForSigP2SHInP2WPKH(toSignTx, hashedPubkey);
|
|
31
|
+
const lockingScript = Buffer.concat([Buffer.from([0x00, 0x14]), hashedPubkey]);
|
|
32
|
+
const hashedLockingScript = bitcoin.crypto.hash160(lockingScript);
|
|
33
|
+
const hashedLockingScriptInScriptPubKey = scriptPubKey.subarray(2, -1);
|
|
34
|
+
if (Buffer.compare(hashedLockingScript, hashedLockingScriptInScriptPubKey) !== 0) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
hashToSign = this.getHashForSigP2WPKH(toSignTx);
|
|
40
|
+
const hashedPubkeyInScriptPubkey = scriptPubKey.subarray(2);
|
|
41
|
+
if (Buffer.compare(hashedPubkey, hashedPubkeyInScriptPubkey) !== 0) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return ecdsaVerifyHashSync({ hash: hashToSign, publicKey, signature });
|
|
46
|
+
}
|
|
47
|
+
if (Address.isP2TR(signerAddress)) {
|
|
48
|
+
if (!Address.isSingleKeyP2TRWitness(witness)) {
|
|
49
|
+
throw new Error('BIP-322 verification from script-spend P2TR is unsupported.');
|
|
50
|
+
}
|
|
51
|
+
const publicKey = scriptPubKey.subarray(2);
|
|
52
|
+
let hashToSign;
|
|
53
|
+
let signature;
|
|
54
|
+
if (encodedSignature.byteLength === 64) {
|
|
55
|
+
hashToSign = this.getHashForSigP2TR(toSignTx, 0x00);
|
|
56
|
+
signature = encodedSignature;
|
|
57
|
+
}
|
|
58
|
+
else if (encodedSignature.byteLength === 65) {
|
|
59
|
+
hashToSign = this.getHashForSigP2TR(toSignTx, encodedSignature[64]);
|
|
60
|
+
signature = encodedSignature.subarray(0, -1);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw new Error('Invalid Schnorr signature provided.');
|
|
64
|
+
}
|
|
65
|
+
return schnorrVerify({ data: hashToSign, xOnly: publicKey, signature });
|
|
66
|
+
}
|
|
67
|
+
throw new Error('Only P2WPKH, P2SH-P2WPKH, and single-key-spend P2TR BIP-322 verification is supported. Unsupported address is provided.');
|
|
68
|
+
}
|
|
69
|
+
static verifyBIP137Signature(signerAddress, message, signature) {
|
|
70
|
+
if (Address.isP2PKH(signerAddress)) {
|
|
71
|
+
return bitcoinMessage.verify(message, signerAddress, signature);
|
|
72
|
+
}
|
|
73
|
+
const publicKeySigned = BIP137.derivePubKey(message, signature);
|
|
74
|
+
const legacySigningAddress = Address.convertPubKeyIntoAddress(publicKeySigned, 'p2pkh').mainnet;
|
|
75
|
+
if (Address.isP2SH(signerAddress)) {
|
|
76
|
+
const p2shAddressDerived = Address.convertPubKeyIntoAddress(publicKeySigned, 'p2sh-p2wpkh');
|
|
77
|
+
if (p2shAddressDerived.mainnet !== signerAddress &&
|
|
78
|
+
p2shAddressDerived.testnet !== signerAddress) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if (Address.isP2WPKH(signerAddress)) {
|
|
83
|
+
const p2wpkhAddressDerived = Address.convertPubKeyIntoAddress(publicKeySigned, 'p2wpkh');
|
|
84
|
+
if (p2wpkhAddressDerived.mainnet !== signerAddress &&
|
|
85
|
+
p2wpkhAddressDerived.testnet !== signerAddress) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (Address.isP2TR(signerAddress)) {
|
|
90
|
+
const p2trAddressDerived = Address.convertPubKeyIntoAddress(publicKeySigned, 'p2tr');
|
|
91
|
+
if (p2trAddressDerived.mainnet !== signerAddress &&
|
|
92
|
+
p2trAddressDerived.testnet !== signerAddress) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return bitcoinMessage.verify(message, legacySigningAddress, signature);
|
|
100
|
+
}
|
|
101
|
+
static getHashForSigP2WPKH(toSignTx) {
|
|
102
|
+
const signingScript = bitcoin.payments.p2pkh({
|
|
103
|
+
hash: toSignTx.data.inputs[0].witnessUtxo.script.subarray(2),
|
|
104
|
+
}).output;
|
|
105
|
+
return toSignTx
|
|
106
|
+
.extractTransaction()
|
|
107
|
+
.hashForWitnessV0(0, signingScript, 0, bitcoin.Transaction.SIGHASH_ALL);
|
|
108
|
+
}
|
|
109
|
+
static getHashForSigP2SHInP2WPKH(toSignTx, hashedPubkey) {
|
|
110
|
+
const signingScript = bitcoin.payments.p2pkh({
|
|
111
|
+
hash: hashedPubkey,
|
|
112
|
+
}).output;
|
|
113
|
+
return toSignTx
|
|
114
|
+
.extractTransaction()
|
|
115
|
+
.hashForWitnessV0(0, signingScript, 0, bitcoin.Transaction.SIGHASH_ALL);
|
|
116
|
+
}
|
|
117
|
+
static getHashForSigP2TR(toSignTx, hashType) {
|
|
118
|
+
if (hashType !== bitcoin.Transaction.SIGHASH_DEFAULT &&
|
|
119
|
+
hashType !== bitcoin.Transaction.SIGHASH_ALL) {
|
|
120
|
+
throw new Error('Invalid SIGHASH used in signature. Must be either SIGHASH_ALL or SIGHASH_DEFAULT.');
|
|
121
|
+
}
|
|
122
|
+
return toSignTx
|
|
123
|
+
.extractTransaction()
|
|
124
|
+
.hashForWitnessV1(0, [toSignTx.data.inputs[0].witnessUtxo.script], [0], hashType);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export default Verifier;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export function decodeScriptSignature(buffer) {
|
|
2
|
+
const hashType = buffer.readUInt8(buffer.length - 1);
|
|
3
|
+
const hashTypeMod = hashType & ~0x80;
|
|
4
|
+
if (hashTypeMod <= 0 || hashTypeMod >= 4)
|
|
5
|
+
throw new Error('Invalid hashType ' + hashType);
|
|
6
|
+
const decoded = decode2(buffer.slice(0, -1));
|
|
7
|
+
const r = fromDER(decoded.r);
|
|
8
|
+
const s = fromDER(decoded.s);
|
|
9
|
+
const signature = Buffer.concat([r, s], 64);
|
|
10
|
+
return { signature, hashType };
|
|
11
|
+
}
|
|
12
|
+
function fromDER(x) {
|
|
13
|
+
if (x[0] === 0x00)
|
|
14
|
+
x = x.slice(1);
|
|
15
|
+
const buffer = Buffer.alloc(32, 0);
|
|
16
|
+
const bstart = Math.max(0, 32 - x.length);
|
|
17
|
+
x.copy(buffer, bstart);
|
|
18
|
+
return buffer;
|
|
19
|
+
}
|
|
20
|
+
function decode2(buffer) {
|
|
21
|
+
if (buffer.length < 8)
|
|
22
|
+
throw new Error('DER sequence length is too short');
|
|
23
|
+
if (buffer.length > 72)
|
|
24
|
+
throw new Error('DER sequence length is too long');
|
|
25
|
+
if (buffer[0] !== 0x30)
|
|
26
|
+
throw new Error('Expected DER sequence');
|
|
27
|
+
if (buffer[1] !== buffer.length - 2)
|
|
28
|
+
throw new Error('DER sequence length is invalid');
|
|
29
|
+
if (buffer[2] !== 0x02)
|
|
30
|
+
throw new Error('Expected DER integer');
|
|
31
|
+
const lenR = buffer[3];
|
|
32
|
+
if (lenR === 0)
|
|
33
|
+
throw new Error('R length is zero');
|
|
34
|
+
if (5 + lenR >= buffer.length)
|
|
35
|
+
throw new Error('R length is too long');
|
|
36
|
+
if (buffer[4 + lenR] !== 0x02)
|
|
37
|
+
throw new Error('Expected DER integer (2)');
|
|
38
|
+
const lenS = buffer[5 + lenR];
|
|
39
|
+
if (lenS === 0)
|
|
40
|
+
throw new Error('S length is zero');
|
|
41
|
+
if (6 + lenR + lenS !== buffer.length)
|
|
42
|
+
throw new Error('S length is invalid');
|
|
43
|
+
if (buffer[4] & 0x80)
|
|
44
|
+
throw new Error('R value is negative');
|
|
45
|
+
if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80)) {
|
|
46
|
+
throw new Error('R value excessively padded');
|
|
47
|
+
}
|
|
48
|
+
if (buffer[lenR + 6] & 0x80)
|
|
49
|
+
throw new Error('S value is negative');
|
|
50
|
+
if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80)) {
|
|
51
|
+
throw new Error('S value excessively padded');
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
r: buffer.slice(4, 4 + lenR),
|
|
55
|
+
s: buffer.slice(6 + lenR),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function verify(message: string, address: string, signature: Buffer, messagePrefix?: string, checkSegwitAlways?: boolean): boolean;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { fromBase58checkSync } from '@exodus/bytes/base58check.js';
|
|
2
|
+
import { hashSync } from '@exodus/crypto/hash';
|
|
3
|
+
import { recoverPublicKey } from '@noble/secp256k1';
|
|
4
|
+
import bech32 from 'bech32';
|
|
5
|
+
import varuint from 'varuint-bitcoin';
|
|
6
|
+
const SEGWIT_TYPES = {
|
|
7
|
+
P2WPKH: 'p2wpkh',
|
|
8
|
+
P2SH_P2WPKH: 'p2sh(p2wpkh)',
|
|
9
|
+
};
|
|
10
|
+
const hash256 = (buffer) => hashSync('sha256', hashSync('sha256', buffer), 'buffer');
|
|
11
|
+
const hash160 = (buffer) => hashSync('hash160', buffer, 'buffer');
|
|
12
|
+
const bufferEquals = (buffer1, buffer2) => {
|
|
13
|
+
return Buffer.compare(buffer1, buffer2) === 0;
|
|
14
|
+
};
|
|
15
|
+
function decodeSignature(buffer) {
|
|
16
|
+
if (buffer.length !== 65)
|
|
17
|
+
throw new Error('Invalid signature length');
|
|
18
|
+
const flagByte = buffer.readUInt8(0) - 27;
|
|
19
|
+
if (flagByte > 15 || flagByte < 0)
|
|
20
|
+
throw new Error('Invalid signature parameter');
|
|
21
|
+
return {
|
|
22
|
+
compressed: !!(flagByte & 12),
|
|
23
|
+
segwitType: flagByte & 8 ? (flagByte & 4 ? SEGWIT_TYPES.P2WPKH : SEGWIT_TYPES.P2SH_P2WPKH) : null,
|
|
24
|
+
recovery: flagByte & 3,
|
|
25
|
+
signature: buffer.slice(1),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function magicHash(message, messagePrefix = '\u0018Bitcoin Signed Message:\n') {
|
|
29
|
+
if (!Buffer.isBuffer(messagePrefix))
|
|
30
|
+
messagePrefix = Buffer.from(messagePrefix, 'utf8');
|
|
31
|
+
if (!Buffer.isBuffer(message))
|
|
32
|
+
message = Buffer.from(message, 'utf8');
|
|
33
|
+
const messageVISize = varuint.encodingLength(message.length);
|
|
34
|
+
const buffer = Buffer.alloc(messagePrefix.length + messageVISize + message.length);
|
|
35
|
+
messagePrefix.copy(buffer, 0);
|
|
36
|
+
varuint.encode(message.length, buffer, messagePrefix.length);
|
|
37
|
+
message.copy(buffer, messagePrefix.length + messageVISize);
|
|
38
|
+
return hash256(buffer);
|
|
39
|
+
}
|
|
40
|
+
function segwitRedeemHash(publicKeyHash) {
|
|
41
|
+
const redeemScript = Buffer.concat([Buffer.from('0014', 'hex'), publicKeyHash]);
|
|
42
|
+
return hash160(redeemScript);
|
|
43
|
+
}
|
|
44
|
+
function decodeBech32(address) {
|
|
45
|
+
const result = bech32.decode(address);
|
|
46
|
+
const data = bech32.fromWords(result.words.slice(1));
|
|
47
|
+
return Buffer.from(data);
|
|
48
|
+
}
|
|
49
|
+
export function verify(message, address, signature, messagePrefix, checkSegwitAlways) {
|
|
50
|
+
if (!Buffer.isBuffer(signature)) {
|
|
51
|
+
throw new TypeError('signature must be a Buffer');
|
|
52
|
+
}
|
|
53
|
+
const parsed = decodeSignature(signature);
|
|
54
|
+
if (checkSegwitAlways && !parsed.compressed) {
|
|
55
|
+
throw new Error('checkSegwitAlways can only be used with a compressed pubkey signature flagbyte');
|
|
56
|
+
}
|
|
57
|
+
const hash = magicHash(message, messagePrefix);
|
|
58
|
+
const publicKey = Buffer.from(recoverPublicKey(hash, parsed.signature, parsed.recovery, parsed.compressed));
|
|
59
|
+
const publicKeyHash = hash160(publicKey);
|
|
60
|
+
let actual, expected;
|
|
61
|
+
if (parsed.segwitType) {
|
|
62
|
+
if (parsed.segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {
|
|
63
|
+
actual = segwitRedeemHash(publicKeyHash);
|
|
64
|
+
expected = Buffer.from(fromBase58checkSync(address).slice(1));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
actual = publicKeyHash;
|
|
68
|
+
expected = decodeBech32(address);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (checkSegwitAlways) {
|
|
72
|
+
try {
|
|
73
|
+
expected = decodeBech32(address);
|
|
74
|
+
return bufferEquals(publicKeyHash, expected);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
const redeemHash = segwitRedeemHash(publicKeyHash);
|
|
78
|
+
expected = Buffer.from(fromBase58checkSync(address).slice(1));
|
|
79
|
+
return bufferEquals(publicKeyHash, expected) || bufferEquals(redeemHash, expected);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
actual = publicKeyHash;
|
|
84
|
+
expected = Buffer.from(fromBase58checkSync(address).slice(1));
|
|
85
|
+
}
|
|
86
|
+
return bufferEquals(actual, expected);
|
|
87
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as bitcoinMessage from '@exodus/bitcoinjs/message';
|
|
2
|
+
import { recoverPublicKey } from '@noble/secp256k1';
|
|
3
|
+
class BIP137 {
|
|
4
|
+
static isBIP137Signature(signature) {
|
|
5
|
+
return signature.byteLength === 65;
|
|
6
|
+
}
|
|
7
|
+
static derivePubKey(message, signature) {
|
|
8
|
+
const messageHash = bitcoinMessage.magicHash(message);
|
|
9
|
+
const signatureDecoded = this.decodeSignature(signature);
|
|
10
|
+
const recoveredPublicKey = recoverPublicKey(messageHash, signatureDecoded.signature, signatureDecoded.recovery, signatureDecoded.compressed);
|
|
11
|
+
return Buffer.from(recoveredPublicKey);
|
|
12
|
+
}
|
|
13
|
+
static decodeSignature(signature) {
|
|
14
|
+
if (signature.length !== 65)
|
|
15
|
+
throw new Error('Invalid signature length');
|
|
16
|
+
const flagByte = signature.readUInt8(0) - 27;
|
|
17
|
+
if (flagByte > 19 || flagByte < 0) {
|
|
18
|
+
throw new Error('Invalid signature parameter');
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
compressed: !!(flagByte & 12),
|
|
22
|
+
recovery: flagByte & 3,
|
|
23
|
+
signature: signature.subarray(1),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export default BIP137;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bip322-js",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.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",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"publishConfig": {
|
|
9
|
-
"access": "public"
|
|
9
|
+
"access": "public",
|
|
10
|
+
"provenance": false
|
|
10
11
|
},
|
|
11
12
|
"files": [
|
|
12
13
|
"dist",
|
|
@@ -35,27 +36,26 @@
|
|
|
35
36
|
},
|
|
36
37
|
"license": "MIT",
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@noble/secp256k1": "^1.7.1",
|
|
39
39
|
"@types/minimalistic-assert": "^1.0.1",
|
|
40
40
|
"@types/node": "^20.2.5",
|
|
41
|
-
"bech32": "^1.1.3",
|
|
42
|
-
"bs58check": "^3.0.1",
|
|
43
|
-
"buffer-equals": "^1.0.3",
|
|
44
41
|
"ecpair": "^2.0.1",
|
|
45
42
|
"typedoc": "^0.24.8",
|
|
46
|
-
"typescript": "^5.1.3"
|
|
47
|
-
"varuint-bitcoin": "^1.0.1"
|
|
43
|
+
"typescript": "^5.1.3"
|
|
48
44
|
},
|
|
49
45
|
"dependencies": {
|
|
50
46
|
"@exodus/asset-types": "^0.3.0",
|
|
51
|
-
"@exodus/bitcoinjs": "^
|
|
52
|
-
"@exodus/
|
|
47
|
+
"@exodus/bitcoinjs": "^2.0.0",
|
|
48
|
+
"@exodus/bytes": "^1.0.0-rc.8",
|
|
49
|
+
"@exodus/crypto": "^1.0.0-rc.26",
|
|
50
|
+
"@noble/secp256k1": "^1.7.1",
|
|
51
|
+
"bech32": "^1.1.3",
|
|
53
52
|
"minimalistic-assert": "^1.0.1",
|
|
53
|
+
"varuint-bitcoin": "^1.0.1",
|
|
54
54
|
"wif": "^4.0.0"
|
|
55
55
|
},
|
|
56
56
|
"homepage": "https://github.com/ExodusMovement/exodus-hydra/tree/master/libraries/bip322-js",
|
|
57
57
|
"bugs": {
|
|
58
58
|
"url": "https://github.com/ExodusMovement/exodus-hydra/issues?q=is%3Aissue+is%3Aopen+label%3Abip322-js"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "dab4f446f30bf73babe598463627eaad6e14fa4b"
|
|
61
61
|
}
|