@exodus/bip322-js 1.1.0-exodus.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.
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ // Import dependencies
30
+ const BIP322_1 = __importDefault(require("./BIP322"));
31
+ const helpers_1 = require("./helpers");
32
+ const bitcoin = __importStar(require("bitcoinjs-lib"));
33
+ const secp256k1_1 = __importDefault(require("@bitcoinerlab/secp256k1"));
34
+ const bitcoinMessage = __importStar(require("bitcoinjs-message"));
35
+ const bitcoinjs_1 = require("./bitcoinjs");
36
+ /**
37
+ * Class that handles BIP-322 signature verification.
38
+ * Reference: https://github.com/LegReq/bip0322-signatures/blob/master/BIP0322_verification.ipynb
39
+ */
40
+ class Verifier {
41
+ /**
42
+ * Verify a BIP-322 signature from P2WPKH, P2SH-P2WPKH, and single-key-spend P2TR address.
43
+ * @param signerAddress Address of the signing address
44
+ * @param message message_challenge signed by the address
45
+ * @param signatureBase64 Signature produced by the signing address
46
+ * @returns True if the provided signature is a valid BIP-322 signature for the given message and address, false if otherwise
47
+ * @throws If the provided signature fails basic validation, or if unsupported address and signature are provided
48
+ */
49
+ static verifySignature(signerAddress, message, signatureBase64) {
50
+ // Handle legacy BIP-137 signature
51
+ // For P2PKH address, assume the signature is also a legacy signature
52
+ if (helpers_1.Address.isP2PKH(signerAddress) || helpers_1.BIP137.isBIP137Signature(signatureBase64)) {
53
+ return this.verifyBIP137Signature(signerAddress, message, signatureBase64);
54
+ }
55
+ // Convert address into corresponding script pubkey
56
+ const scriptPubKey = helpers_1.Address.convertAdressToScriptPubkey(signerAddress);
57
+ // Draft corresponding toSpend and toSign transaction using the message and script pubkey
58
+ const toSpendTx = BIP322_1.default.buildToSpendTx(message, scriptPubKey);
59
+ const toSignTx = BIP322_1.default.buildToSignTx(toSpendTx.getId(), scriptPubKey);
60
+ // Add the witness stack into the toSignTx
61
+ toSignTx.updateInput(0, {
62
+ finalScriptWitness: Buffer.from(signatureBase64, 'base64')
63
+ });
64
+ // Obtain the signature within the witness components
65
+ const witness = toSignTx.extractTransaction().ins[0].witness;
66
+ const encodedSignature = witness[0];
67
+ // Branch depending on whether the signing address is a non-taproot or a taproot address
68
+ if (helpers_1.Address.isP2WPKHWitness(witness)) {
69
+ // For non-taproot segwit transaciton, public key is included as the second part of the witness data
70
+ const publicKey = witness[1];
71
+ const { signature } = (0, bitcoinjs_1.decodeScriptSignature)(encodedSignature);
72
+ // Compute OP_HASH160(publicKey)
73
+ const hashedPubkey = bitcoin.crypto.hash160(publicKey);
74
+ // Common path variable
75
+ let hashToSign; // Hash expected to be signed by the signing address
76
+ if (helpers_1.Address.isP2SH(signerAddress)) {
77
+ // P2SH-P2WPKH verification path
78
+ // Compute the hash that correspond to the toSignTx
79
+ hashToSign = this.getHashForSigP2SHInP2WPKH(toSignTx, hashedPubkey);
80
+ // The original locking script for P2SH-P2WPKH is OP_0 <PubKeyHash>
81
+ const lockingScript = Buffer.concat([Buffer.from([0x00, 0x14]), hashedPubkey]);
82
+ // Compute OP_HASH160(lockingScript)
83
+ const hashedLockingScript = bitcoin.crypto.hash160(lockingScript);
84
+ // For nested segwit (P2SH-P2WPKH) address, the hashed locking script is located from the 3rd byte to the last 2nd byte as OP_HASH160 <HASH> OP_EQUAL
85
+ const hashedLockingScriptInScriptPubKey = scriptPubKey.subarray(2, -1);
86
+ // Check if the P2SH locking script OP_HASH160 <HASH> OP_EQUAL is satisified
87
+ if (Buffer.compare(hashedLockingScript, hashedLockingScriptInScriptPubKey) !== 0) {
88
+ return false; // Reject signature if the hashed locking script is different from the hashed locking script in the scriptPubKey
89
+ }
90
+ }
91
+ else {
92
+ // P2WPKH verification path
93
+ // Compute the hash that correspond to the toSignTx
94
+ hashToSign = this.getHashForSigP2WPKH(toSignTx);
95
+ // For native segwit address, the hashed public key is located from the 3rd to the end as OP_0 <HASH>
96
+ const hashedPubkeyInScriptPubkey = scriptPubKey.subarray(2);
97
+ // Check if OP_HASH160(publicKey) === hashedPubkeyInScriptPubkey
98
+ if (Buffer.compare(hashedPubkey, hashedPubkeyInScriptPubkey) !== 0) {
99
+ return false; // Reject signature if the hashed public key did not match
100
+ }
101
+ }
102
+ // Computing OP_CHECKSIG in Javascript
103
+ return secp256k1_1.default.verify(hashToSign, publicKey, signature);
104
+ }
105
+ else if (helpers_1.Address.isP2TR(signerAddress)) {
106
+ // Check if the witness stack correspond to a single-key-spend P2TR address
107
+ if (!helpers_1.Address.isSingleKeyP2TRWitness(witness)) {
108
+ throw new Error('BIP-322 verification from script-spend P2TR is unsupported.');
109
+ }
110
+ // For taproot address, the public key is located starting from the 3rd byte of the script public key
111
+ const publicKey = scriptPubKey.subarray(2);
112
+ // Compute the hash to be signed by the signing address
113
+ // Reference: https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#user-content-Taproot_key_path_spending_signature_validation
114
+ let hashToSign;
115
+ let signature;
116
+ if (encodedSignature.byteLength === 64) {
117
+ // If a BIP-341 signature is 64 bytes, the signature is signed using SIGHASH_DEFAULT 0x00
118
+ hashToSign = this.getHashForSigP2TR(toSignTx, 0x00);
119
+ // And the entirety of the encoded signature is the actual signature
120
+ signature = encodedSignature;
121
+ }
122
+ else if (encodedSignature.byteLength === 65) {
123
+ // If a BIP-341 signature is 65 bytes, the signature is signed using SIGHASH included at the last byte of the signature
124
+ hashToSign = this.getHashForSigP2TR(toSignTx, encodedSignature[64]);
125
+ // And encodedSignature[0:64] holds the actual signature
126
+ signature = encodedSignature.subarray(0, -1);
127
+ }
128
+ else {
129
+ // Fail validation if the signature is not 64 or 65 bytes
130
+ throw new Error('Invalid Schnorr signature provided.');
131
+ }
132
+ // Computing OP_CHECKSIG in Javascript
133
+ return secp256k1_1.default.verifySchnorr(hashToSign, publicKey, signature);
134
+ }
135
+ else {
136
+ throw new Error('Only P2WPKH, P2SH-P2WPKH, and single-key-spend P2TR BIP-322 verification is supported. Unsupported address is provided.');
137
+ }
138
+ }
139
+ /**
140
+ * Verify a legacy BIP-137 signature.
141
+ * Note that a signature is considered valid for all types of addresses that can be derived from the recovered public key.
142
+ * @param signerAddress Address of the signing address
143
+ * @param message message_challenge signed by the address
144
+ * @param signatureBase64 Signature produced by the signing address
145
+ * @returns True if the provided signature is a valid BIP-137 signature for the given message and address, false if otherwise
146
+ * @throws If the provided signature fails basic validation, or if unsupported address and signature are provided
147
+ */
148
+ static verifyBIP137Signature(signerAddress, message, signatureBase64) {
149
+ if (helpers_1.Address.isP2PKH(signerAddress)) {
150
+ return bitcoinMessage.verify(message, signerAddress, signatureBase64);
151
+ }
152
+ else {
153
+ // Recover the public key associated with the signature
154
+ const publicKeySigned = helpers_1.BIP137.derivePubKey(message, signatureBase64);
155
+ // Set the equivalent legacy address to prepare for validation from bitcoinjs-message
156
+ const legacySigningAddress = helpers_1.Address.convertPubKeyIntoAddress(publicKeySigned, 'p2pkh').mainnet;
157
+ // Make sure that public key recovered corresponds to the claimed signing address
158
+ if (helpers_1.Address.isP2SH(signerAddress)) {
159
+ // Assume it is a P2SH-P2WPKH address, derive a P2SH-P2WPKH address based on the public key recovered
160
+ const p2shAddressDerived = helpers_1.Address.convertPubKeyIntoAddress(publicKeySigned, 'p2sh-p2wpkh');
161
+ // Assert that the derived address is identical to the claimed signing address
162
+ if (p2shAddressDerived.mainnet !== signerAddress && p2shAddressDerived.testnet !== signerAddress) {
163
+ return false; // Derived address did not match with the claimed signing address
164
+ }
165
+ }
166
+ else if (helpers_1.Address.isP2WPKH(signerAddress)) {
167
+ // Assume it is a P2WPKH address, derive a P2WPKH address based on the public key recovered
168
+ const p2wpkhAddressDerived = helpers_1.Address.convertPubKeyIntoAddress(publicKeySigned, 'p2wpkh');
169
+ // Assert that the derived address is identical to the claimed signing address
170
+ if (p2wpkhAddressDerived.mainnet !== signerAddress && p2wpkhAddressDerived.testnet !== signerAddress) {
171
+ return false; // Derived address did not match with the claimed signing address
172
+ }
173
+ }
174
+ else if (helpers_1.Address.isP2TR(signerAddress)) {
175
+ // Assume it is a P2TR address, derive a P2TR address based on the public key recovered
176
+ const p2trAddressDerived = helpers_1.Address.convertPubKeyIntoAddress(publicKeySigned, 'p2tr');
177
+ // Assert that the derived address is identical to the claimed signing address
178
+ if (p2trAddressDerived.mainnet !== signerAddress && p2trAddressDerived.testnet !== signerAddress) {
179
+ return false; // Derived address did not match with the claimed signing address
180
+ }
181
+ }
182
+ else {
183
+ return false; // Unsupported address type
184
+ }
185
+ // Validate the signature using bitcoinjs-message if address assertion succeeded
186
+ return bitcoinMessage.verify(message, legacySigningAddress, signatureBase64);
187
+ }
188
+ }
189
+ /**
190
+ * Compute the hash to be signed for a given P2WPKH BIP-322 toSign transaction.
191
+ * @param toSignTx PSBT instance of the toSign transaction
192
+ * @returns Computed transaction hash that requires signing
193
+ */
194
+ static getHashForSigP2WPKH(toSignTx) {
195
+ // Create a signing script to unlock the P2WPKH output based on the P2PKH template
196
+ // Reference: https://github.com/bitcoinjs/bitcoinjs-lib/blob/1a9119b53bcea4b83a6aa8b948f0e6370209b1b4/ts_src/psbt.ts#L1654
197
+ const signingScript = bitcoin.payments.p2pkh({
198
+ hash: toSignTx.data.inputs[0].witnessUtxo.script.subarray(2)
199
+ }).output;
200
+ // Return computed transaction hash to be signed
201
+ return toSignTx.extractTransaction().hashForWitnessV0(0, signingScript, 0, bitcoin.Transaction.SIGHASH_ALL);
202
+ }
203
+ /**
204
+ * Compute the hash to be signed for a given P2SH-P2WPKH BIP-322 toSign transaction.
205
+ * @param toSignTx PSBT instance of the toSign transaction
206
+ * @param hashedPubkey Hashed public key of the signing address
207
+ * @returns Computed transaction hash that requires signing
208
+ */
209
+ static getHashForSigP2SHInP2WPKH(toSignTx, hashedPubkey) {
210
+ // Create a signing script to unlock the P2WPKH output based on the P2PKH template
211
+ // Reference: https://github.com/bitcoinjs/bitcoinjs-lib/blob/1a9119b53bcea4b83a6aa8b948f0e6370209b1b4/ts_src/psbt.ts#L1654
212
+ // Like P2WPKH, the hash for deriving the meaningfulScript for a P2SH-P2WPKH transaction is its public key hash
213
+ // It can be derived by hashing the provided public key in the witness stack
214
+ const signingScript = bitcoin.payments.p2pkh({
215
+ hash: hashedPubkey
216
+ }).output;
217
+ // Return computed transaction hash to be signed
218
+ return toSignTx.extractTransaction().hashForWitnessV0(0, signingScript, 0, bitcoin.Transaction.SIGHASH_ALL);
219
+ }
220
+ /**
221
+ * Compute the hash to be signed for a given P2TR BIP-322 toSign transaction.
222
+ * @param toSignTx PSBT instance of the toSign transaction
223
+ * @param hashType Hash type used to sign the toSign transaction, must be either 0x00 or 0x01
224
+ * @returns Computed transaction hash that requires signing
225
+ * @throws Error if hashType is anything other than 0x00 or 0x01
226
+ */
227
+ static getHashForSigP2TR(toSignTx, hashType) {
228
+ // BIP-322 states that 'all signatures must use the SIGHASH_ALL flag'
229
+ // But, in BIP-341, SIGHASH_DEFAULT (0x00) is equivalent to SIGHASH_ALL (0x01) so both should be allowed
230
+ if (hashType !== bitcoin.Transaction.SIGHASH_DEFAULT && hashType !== bitcoin.Transaction.SIGHASH_ALL) {
231
+ // Throw error if hashType is neither SIGHASH_DEFAULT or SIGHASH_ALL
232
+ throw new Error('Invalid SIGHASH used in signature. Must be either SIGHASH_ALL or SIGHASH_DEFAULT.');
233
+ }
234
+ // Return computed transaction hash to be signed
235
+ return toSignTx.extractTransaction().hashForWitnessV1(0, [toSignTx.data.inputs[0].witnessUtxo.script], [0], hashType);
236
+ }
237
+ }
238
+ exports.default = Verifier;
239
+ //# sourceMappingURL=Verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Verifier.js","sourceRoot":"","sources":["../src/Verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /// <reference types="node" />
2
+ interface ScriptSignature {
3
+ signature: Buffer;
4
+ hashType: number;
5
+ }
6
+ export declare function decodeScriptSignature(buffer: Buffer): ScriptSignature;
7
+ export {};
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeScriptSignature = void 0;
4
+ // Taken from https://github.com/bitcoinjs/bitcoinjs-lib/blob/5d2ff1c61165932e2814d5f37630e6720168561c/ts_src/script_signature.ts#L29
5
+ function decodeScriptSignature(buffer) {
6
+ const hashType = buffer.readUInt8(buffer.length - 1);
7
+ const hashTypeMod = hashType & ~0x80;
8
+ if (hashTypeMod <= 0 || hashTypeMod >= 4)
9
+ throw new Error('Invalid hashType ' + hashType);
10
+ const decoded = decode2(buffer.slice(0, -1));
11
+ const r = fromDER(decoded.r);
12
+ const s = fromDER(decoded.s);
13
+ const signature = Buffer.concat([r, s], 64);
14
+ return { signature, hashType };
15
+ }
16
+ exports.decodeScriptSignature = decodeScriptSignature;
17
+ function fromDER(x) {
18
+ if (x[0] === 0x00)
19
+ x = x.slice(1);
20
+ const buffer = Buffer.alloc(32, 0);
21
+ const bstart = Math.max(0, 32 - x.length);
22
+ x.copy(buffer, bstart);
23
+ return buffer;
24
+ }
25
+ function decode2(buffer) {
26
+ if (buffer.length < 8)
27
+ throw new Error('DER sequence length is too short');
28
+ if (buffer.length > 72)
29
+ throw new Error('DER sequence length is too long');
30
+ if (buffer[0] !== 0x30)
31
+ throw new Error('Expected DER sequence');
32
+ if (buffer[1] !== buffer.length - 2)
33
+ throw new Error('DER sequence length is invalid');
34
+ if (buffer[2] !== 0x02)
35
+ throw new Error('Expected DER integer');
36
+ const lenR = buffer[3];
37
+ if (lenR === 0)
38
+ throw new Error('R length is zero');
39
+ if (5 + lenR >= buffer.length)
40
+ throw new Error('R length is too long');
41
+ if (buffer[4 + lenR] !== 0x02)
42
+ throw new Error('Expected DER integer (2)');
43
+ const lenS = buffer[5 + lenR];
44
+ if (lenS === 0)
45
+ throw new Error('S length is zero');
46
+ if (6 + lenR + lenS !== buffer.length)
47
+ throw new Error('S length is invalid');
48
+ if (buffer[4] & 0x80)
49
+ throw new Error('R value is negative');
50
+ if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80))
51
+ throw new Error('R value excessively padded');
52
+ if (buffer[lenR + 6] & 0x80)
53
+ throw new Error('S value is negative');
54
+ if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80))
55
+ throw new Error('S value excessively padded');
56
+ // non-BIP66 - extract R, S values
57
+ return {
58
+ r: buffer.slice(4, 4 + lenR),
59
+ s: buffer.slice(6 + lenR),
60
+ };
61
+ }
62
+ //# sourceMappingURL=DecodeScriptSignature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecodeScriptSignature.js","sourceRoot":"","sources":["../../src/bitcoinjs/DecodeScriptSignature.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { decodeScriptSignature } from "./DecodeScriptSignature";
2
+ export { decodeScriptSignature };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeScriptSignature = void 0;
4
+ const DecodeScriptSignature_1 = require("./DecodeScriptSignature");
5
+ Object.defineProperty(exports, "decodeScriptSignature", { enumerable: true, get: function () { return DecodeScriptSignature_1.decodeScriptSignature; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bitcoinjs/index.ts"],"names":[],"mappings":";;;AAAA,mEAAgE;AAEvD,sGAFA,6CAAqB,OAEA"}
@@ -0,0 +1,61 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * Class that implement address-related utility functions.
4
+ */
5
+ declare class Address {
6
+ /**
7
+ * Check if a given Bitcoin address is a pay-to-public-key-hash (p2pkh) address.
8
+ * @param address Bitcoin address to be checked
9
+ * @returns True if the provided address correspond to a valid P2PKH address, false if otherwise
10
+ */
11
+ static isP2PKH(address: string): boolean;
12
+ /**
13
+ * Check if a given Bitcoin address is a pay-to-script-hash (P2SH) address.
14
+ * @param address Bitcoin address to be checked
15
+ * @returns True if the provided address correspond to a valid P2SH address, false if otherwise
16
+ */
17
+ static isP2SH(address: string): boolean;
18
+ /**
19
+ * Check if a given Bitcoin address is a pay-to-witness-public-key-hash (P2WPKH) address.
20
+ * @param address Bitcoin address to be checked
21
+ * @returns True if the provided address correspond to a valid P2WPKH address, false if otherwise
22
+ */
23
+ static isP2WPKH(address: string): boolean;
24
+ /**
25
+ * Check if a given Bitcoin address is a taproot address.
26
+ * @param address Bitcoin address to be checked
27
+ * @returns True if the provided address is a taproot address, false if otherwise
28
+ */
29
+ static isP2TR(address: string): boolean;
30
+ /**
31
+ * Check if a given witness stack corresponds to a P2WPKH address.
32
+ * @param witness Witness data associated with the toSign BIP-322 transaction
33
+ * @returns True if the provided witness stack correspond to a valid P2WPKH address, false if otherwise
34
+ */
35
+ static isP2WPKHWitness(witness: Buffer[]): boolean;
36
+ /**
37
+ * Check if a given witness stack corresponds to a single-key-spend P2TR address.
38
+ * @param witness Witness data associated with the toSign BIP-322 transaction
39
+ * @returns True if the provided address and witness stack correspond to a valid single-key-spend P2TR address, false if otherwise
40
+ */
41
+ static isSingleKeyP2TRWitness(witness: Buffer[]): boolean;
42
+ /**
43
+ * Convert a given Bitcoin address into its corresponding script public key.
44
+ * Reference: https://github.com/buidl-bitcoin/buidl-python/blob/d79e9808e8ca60975d315be41293cb40d968626d/buidl/script.py#L607
45
+ * @param address Bitcoin address
46
+ * @returns Script public key of the given Bitcoin address
47
+ * @throws Error when the provided address is not a valid Bitcoin address
48
+ */
49
+ static convertAdressToScriptPubkey(address: string): Buffer;
50
+ /**
51
+ * Convert a given public key into a corresponding Bitcoin address.
52
+ * @param publicKey Public key for deriving the address, or internal public key for deriving taproot address
53
+ * @param addressType Bitcoin address type to be derived, must be either 'p2pkh', 'p2sh-p2wpkh', 'p2wpkh', or 'p2tr'
54
+ * @returns Bitcoin address that correspond to the given public key in both mainnet and testnet
55
+ */
56
+ static convertPubKeyIntoAddress(publicKey: Buffer, addressType: 'p2pkh' | 'p2sh-p2wpkh' | 'p2wpkh' | 'p2tr'): {
57
+ mainnet: string;
58
+ testnet: string;
59
+ };
60
+ }
61
+ export default Address;
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ // Import dependency
27
+ const bitcoin = __importStar(require("bitcoinjs-lib"));
28
+ /**
29
+ * Class that implement address-related utility functions.
30
+ */
31
+ class Address {
32
+ /**
33
+ * Check if a given Bitcoin address is a pay-to-public-key-hash (p2pkh) address.
34
+ * @param address Bitcoin address to be checked
35
+ * @returns True if the provided address correspond to a valid P2PKH address, false if otherwise
36
+ */
37
+ static isP2PKH(address) {
38
+ // Check if the provided address is a P2PKH address
39
+ if (address[0] === '1' || address[0] === 'm' || address[0] === 'n') {
40
+ return true; // P2PKH address
41
+ }
42
+ else {
43
+ return false;
44
+ }
45
+ }
46
+ /**
47
+ * Check if a given Bitcoin address is a pay-to-script-hash (P2SH) address.
48
+ * @param address Bitcoin address to be checked
49
+ * @returns True if the provided address correspond to a valid P2SH address, false if otherwise
50
+ */
51
+ static isP2SH(address) {
52
+ // Check if the provided address is a P2SH address
53
+ if (address[0] === '3' || address[0] === '2') {
54
+ return true; // P2SH address
55
+ }
56
+ else {
57
+ return false;
58
+ }
59
+ }
60
+ /**
61
+ * Check if a given Bitcoin address is a pay-to-witness-public-key-hash (P2WPKH) address.
62
+ * @param address Bitcoin address to be checked
63
+ * @returns True if the provided address correspond to a valid P2WPKH address, false if otherwise
64
+ */
65
+ static isP2WPKH(address) {
66
+ // Check if the provided address is a P2WPKH/P2WSH address
67
+ if (address.slice(0, 4) === 'bc1q' || address.slice(0, 4) === 'tb1q') {
68
+ // Either a P2WPKH / P2WSH address
69
+ // Convert the address into a scriptPubKey
70
+ const scriptPubKey = this.convertAdressToScriptPubkey(address);
71
+ // Check if the scriptPubKey is exactly 22 bytes since P2WPKH scriptPubKey should be 0014<20-BYTE-PUBKEY-HASH>
72
+ if (scriptPubKey.byteLength === 22) {
73
+ return true; // P2WPKH
74
+ }
75
+ else {
76
+ return false; // Not P2WPKH, probably P2WSH
77
+ }
78
+ }
79
+ else {
80
+ return false;
81
+ }
82
+ }
83
+ /**
84
+ * Check if a given Bitcoin address is a taproot address.
85
+ * @param address Bitcoin address to be checked
86
+ * @returns True if the provided address is a taproot address, false if otherwise
87
+ */
88
+ static isP2TR(address) {
89
+ if (address.slice(0, 4) === 'bc1p' || address.slice(0, 4) === 'tb1p') {
90
+ return true; // P2TR address
91
+ }
92
+ else {
93
+ return false;
94
+ }
95
+ }
96
+ /**
97
+ * Check if a given witness stack corresponds to a P2WPKH address.
98
+ * @param witness Witness data associated with the toSign BIP-322 transaction
99
+ * @returns True if the provided witness stack correspond to a valid P2WPKH address, false if otherwise
100
+ */
101
+ static isP2WPKHWitness(witness) {
102
+ // Check whether the witness stack is as expected for a P2WPKH address
103
+ // It should contain exactly two items, with the second item being a public key with 33 bytes, and the first byte must be either 0x02/0x03
104
+ if (witness.length === 2 && witness[1].byteLength === 33 && (witness[1][0] === 0x02 || witness[1][0] === 0x03)) {
105
+ return true;
106
+ }
107
+ else {
108
+ return false;
109
+ }
110
+ }
111
+ /**
112
+ * Check if a given witness stack corresponds to a single-key-spend P2TR address.
113
+ * @param witness Witness data associated with the toSign BIP-322 transaction
114
+ * @returns True if the provided address and witness stack correspond to a valid single-key-spend P2TR address, false if otherwise
115
+ */
116
+ static isSingleKeyP2TRWitness(witness) {
117
+ // Check whether the witness stack is as expected for a single-key-spend taproot address
118
+ // It should contain exactly one items which is the signature for the transaction
119
+ if (witness.length === 1) {
120
+ return true;
121
+ }
122
+ else {
123
+ return false;
124
+ }
125
+ }
126
+ /**
127
+ * Convert a given Bitcoin address into its corresponding script public key.
128
+ * Reference: https://github.com/buidl-bitcoin/buidl-python/blob/d79e9808e8ca60975d315be41293cb40d968626d/buidl/script.py#L607
129
+ * @param address Bitcoin address
130
+ * @returns Script public key of the given Bitcoin address
131
+ * @throws Error when the provided address is not a valid Bitcoin address
132
+ */
133
+ static convertAdressToScriptPubkey(address) {
134
+ if (address[0] === '1' || address[0] === 'm' || address[0] === 'n') {
135
+ // P2PKH address
136
+ return bitcoin.payments.p2pkh({
137
+ address: address,
138
+ network: (address[0] === '1') ? bitcoin.networks.bitcoin : bitcoin.networks.testnet
139
+ }).output;
140
+ }
141
+ else if (address[0] === '3' || address[0] === '2') {
142
+ // P2SH address
143
+ return bitcoin.payments.p2sh({
144
+ address: address,
145
+ network: (address[0] === '3') ? bitcoin.networks.bitcoin : bitcoin.networks.testnet
146
+ }).output;
147
+ }
148
+ else if (address.slice(0, 4) === 'bc1q' || address.slice(0, 4) === 'tb1q') {
149
+ // P2WPKH or P2WSH address
150
+ if (address.length === 42) {
151
+ // P2WPKH address
152
+ return bitcoin.payments.p2wpkh({
153
+ address: address,
154
+ network: (address.slice(0, 4) === 'bc1q') ? bitcoin.networks.bitcoin : bitcoin.networks.testnet
155
+ }).output;
156
+ }
157
+ else if (address.length === 62) {
158
+ // P2WSH address
159
+ return bitcoin.payments.p2wsh({
160
+ address: address,
161
+ network: (address.slice(0, 4) === 'bc1q') ? bitcoin.networks.bitcoin : bitcoin.networks.testnet
162
+ }).output;
163
+ }
164
+ }
165
+ else if (address.slice(0, 4) === 'bc1p' || address.slice(0, 4) === 'tb1p') {
166
+ if (address.length === 62) {
167
+ // P2TR address
168
+ return bitcoin.payments.p2tr({
169
+ address: address,
170
+ network: (address.slice(0, 4) === 'bc1p') ? bitcoin.networks.bitcoin : bitcoin.networks.testnet
171
+ }).output;
172
+ }
173
+ }
174
+ throw new Error("Unknown address type");
175
+ }
176
+ /**
177
+ * Convert a given public key into a corresponding Bitcoin address.
178
+ * @param publicKey Public key for deriving the address, or internal public key for deriving taproot address
179
+ * @param addressType Bitcoin address type to be derived, must be either 'p2pkh', 'p2sh-p2wpkh', 'p2wpkh', or 'p2tr'
180
+ * @returns Bitcoin address that correspond to the given public key in both mainnet and testnet
181
+ */
182
+ static convertPubKeyIntoAddress(publicKey, addressType) {
183
+ switch (addressType) {
184
+ case 'p2pkh':
185
+ return {
186
+ mainnet: bitcoin.payments.p2pkh({ pubkey: publicKey, network: bitcoin.networks.bitcoin }).address,
187
+ testnet: bitcoin.payments.p2pkh({ pubkey: publicKey, network: bitcoin.networks.testnet }).address
188
+ };
189
+ case 'p2sh-p2wpkh':
190
+ // Reference: https://github.com/bitcoinjs/bitcoinjs-lib/blob/1a9119b53bcea4b83a6aa8b948f0e6370209b1b4/test/integration/addresses.spec.ts#L70
191
+ return {
192
+ mainnet: bitcoin.payments.p2sh({
193
+ redeem: bitcoin.payments.p2wpkh({ pubkey: publicKey, network: bitcoin.networks.bitcoin }),
194
+ network: bitcoin.networks.bitcoin
195
+ }).address,
196
+ testnet: bitcoin.payments.p2sh({
197
+ redeem: bitcoin.payments.p2wpkh({ pubkey: publicKey, network: bitcoin.networks.testnet }),
198
+ network: bitcoin.networks.testnet
199
+ }).address
200
+ };
201
+ case 'p2wpkh':
202
+ return {
203
+ mainnet: bitcoin.payments.p2wpkh({ pubkey: publicKey, network: bitcoin.networks.bitcoin }).address,
204
+ testnet: bitcoin.payments.p2wpkh({ pubkey: publicKey, network: bitcoin.networks.testnet }).address
205
+ };
206
+ case 'p2tr':
207
+ // Convert full-length public key into internal public key if necessary
208
+ const internalPubkey = publicKey.byteLength === 33 ? publicKey.subarray(1, 33) : publicKey;
209
+ return {
210
+ mainnet: bitcoin.payments.p2tr({ internalPubkey: internalPubkey, network: bitcoin.networks.bitcoin }).address,
211
+ testnet: bitcoin.payments.p2tr({ internalPubkey: internalPubkey, network: bitcoin.networks.testnet }).address
212
+ };
213
+ default:
214
+ throw new Error('Cannot convert public key into unsupported address type.');
215
+ }
216
+ }
217
+ }
218
+ exports.default = Address;
219
+ //# sourceMappingURL=Address.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Address.js","sourceRoot":"","sources":["../../src/helpers/Address.ts"],"names":[],"mappings":"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"}