@btc-vision/transaction 1.7.0 → 1.7.2
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/browser/index.js +1 -1
- package/browser/src/_version.d.ts +1 -1
- package/browser/src/buffer/BinaryReader.d.ts +2 -2
- package/browser/src/deterministic/AddressMap.d.ts +12 -5
- package/browser/src/deterministic/AddressSet.d.ts +2 -1
- package/browser/src/deterministic/DeterministicMap.d.ts +1 -1
- package/browser/src/keypair/Address.d.ts +4 -0
- package/browser/src/mnemonic/BIPStandard.d.ts +8 -0
- package/browser/src/mnemonic/Mnemonic.d.ts +7 -2
- package/browser/src/opnet.d.ts +1 -0
- package/browser/src/utils/lengths.d.ts +15 -16
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/buffer/BinaryReader.d.ts +2 -2
- package/build/deterministic/AddressMap.d.ts +12 -5
- package/build/deterministic/AddressMap.js +51 -33
- package/build/deterministic/AddressSet.d.ts +2 -1
- package/build/deterministic/AddressSet.js +17 -21
- package/build/deterministic/DeterministicMap.d.ts +1 -1
- package/build/deterministic/DeterministicMap.js +15 -15
- package/build/keypair/Address.d.ts +4 -0
- package/build/keypair/Address.js +46 -2
- package/build/mnemonic/BIPStandard.d.ts +8 -0
- package/build/mnemonic/BIPStandard.js +24 -0
- package/build/mnemonic/Mnemonic.d.ts +7 -2
- package/build/mnemonic/Mnemonic.js +48 -6
- package/build/opnet.d.ts +1 -0
- package/build/opnet.js +1 -0
- package/build/utils/lengths.d.ts +15 -16
- package/build/utils/lengths.js +1 -1
- package/documentation/README.md +32 -0
- package/documentation/quantum-support/01-introduction.md +88 -0
- package/documentation/quantum-support/02-mnemonic-and-wallet.md +457 -0
- package/documentation/quantum-support/03-address-generation.md +329 -0
- package/documentation/quantum-support/04-message-signing.md +623 -0
- package/documentation/quantum-support/05-address-verification.md +307 -0
- package/documentation/quantum-support/README.md +65 -0
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/buffer/BinaryReader.ts +3 -3
- package/src/buffer/BinaryWriter.ts +2 -2
- package/src/deterministic/AddressMap.ts +64 -37
- package/src/deterministic/AddressSet.ts +20 -26
- package/src/deterministic/DeterministicMap.ts +16 -13
- package/src/keypair/Address.ts +136 -0
- package/src/mnemonic/BIPStandard.ts +92 -0
- package/src/mnemonic/Mnemonic.ts +133 -8
- package/src/opnet.ts +1 -0
- package/src/utils/lengths.ts +15 -17
- package/test/derivePath.test.ts +280 -1
- package/browser/src/deterministic/Map.d.ts +0 -15
- package/build/deterministic/Map.d.ts +0 -15
- package/build/deterministic/Map.js +0 -63
- package/doc/README.md +0 -0
- package/src/deterministic/Map.ts +0 -74
- /package/{doc → documentation}/addresses/P2OP.md +0 -0
- /package/{doc → documentation}/addresses/P2WDA.md +0 -0
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
export class DeterministicMap<K, V> {
|
|
2
2
|
private map: Map<K, V>;
|
|
3
|
-
|
|
3
|
+
private readonly compareFn: (a: K, b: K) => number;
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
#keyOrder: K[];
|
|
6
|
+
|
|
7
|
+
constructor(compareFn: (a: K, b: K) => number) {
|
|
6
8
|
this.map = new Map<K, V>();
|
|
7
|
-
this.#
|
|
9
|
+
this.#keyOrder = [];
|
|
10
|
+
this.compareFn = compareFn;
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
public get size(): number {
|
|
@@ -24,8 +27,8 @@ export class DeterministicMap<K, V> {
|
|
|
24
27
|
|
|
25
28
|
public set(key: K, value: V): void {
|
|
26
29
|
if (!this.map.has(key)) {
|
|
27
|
-
this.#
|
|
28
|
-
this.#
|
|
30
|
+
this.#keyOrder.push(key);
|
|
31
|
+
this.#keyOrder.sort(this.compareFn);
|
|
29
32
|
}
|
|
30
33
|
this.map.set(key, value);
|
|
31
34
|
}
|
|
@@ -35,17 +38,17 @@ export class DeterministicMap<K, V> {
|
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
public keys(): IterableIterator<K> {
|
|
38
|
-
return this.#
|
|
41
|
+
return this.#keyOrder.values();
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
public values(): IterableIterator<V> {
|
|
42
45
|
const values: V[] = [];
|
|
43
46
|
|
|
44
|
-
for (let i = 0; i < this.#
|
|
45
|
-
const key = this.#
|
|
47
|
+
for (let i = 0; i < this.#keyOrder.length; i++) {
|
|
48
|
+
const key = this.#keyOrder[i];
|
|
46
49
|
const value = this.map.get(key);
|
|
47
50
|
|
|
48
|
-
if (value) {
|
|
51
|
+
if (value !== undefined) {
|
|
49
52
|
values.push(value);
|
|
50
53
|
} else {
|
|
51
54
|
throw new Error('Value not found');
|
|
@@ -62,7 +65,7 @@ export class DeterministicMap<K, V> {
|
|
|
62
65
|
public delete(key: K): boolean {
|
|
63
66
|
if (this.map.has(key)) {
|
|
64
67
|
this.map.delete(key);
|
|
65
|
-
this.#
|
|
68
|
+
this.#keyOrder = this.#keyOrder.filter((k) => k !== key);
|
|
66
69
|
return true;
|
|
67
70
|
}
|
|
68
71
|
return false;
|
|
@@ -70,18 +73,18 @@ export class DeterministicMap<K, V> {
|
|
|
70
73
|
|
|
71
74
|
public clear(): void {
|
|
72
75
|
this.map.clear();
|
|
73
|
-
this.#
|
|
76
|
+
this.#keyOrder = [];
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
public forEach(callback: (value: V, key: K, map: DeterministicMap<K, V>) => void): void {
|
|
77
|
-
for (const key of this.#
|
|
80
|
+
for (const key of this.#keyOrder) {
|
|
78
81
|
const value = this.map.get(key) as V;
|
|
79
82
|
callback(value, key, this);
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
*[Symbol.iterator](): IterableIterator<[K, V]> {
|
|
84
|
-
for (const key of this.#
|
|
87
|
+
for (const key of this.#keyOrder) {
|
|
85
88
|
yield [key, this.map.get(key) as V];
|
|
86
89
|
}
|
|
87
90
|
}
|
package/src/keypair/Address.ts
CHANGED
|
@@ -30,6 +30,8 @@ export class Address extends Uint8Array {
|
|
|
30
30
|
#tweakedUncompressed: Buffer | undefined;
|
|
31
31
|
#p2wda: IP2WSHAddress | undefined;
|
|
32
32
|
#mldsaPublicKey: Uint8Array | undefined;
|
|
33
|
+
#cachedBigInt: bigint | undefined;
|
|
34
|
+
#cachedUint64Array: [bigint, bigint, bigint, bigint] | undefined;
|
|
33
35
|
|
|
34
36
|
private classicPublicKey: Uint8Array | undefined;
|
|
35
37
|
|
|
@@ -140,6 +142,109 @@ export class Address extends Uint8Array {
|
|
|
140
142
|
return compressed;
|
|
141
143
|
}
|
|
142
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Creates an Address instance from a BigInt value.
|
|
147
|
+
*
|
|
148
|
+
* Converts a 256-bit unsigned integer into a 32-byte address by splitting it
|
|
149
|
+
* into four 64-bit chunks and writing them in big-endian format using DataView.
|
|
150
|
+
* This is the inverse operation of toBigInt().
|
|
151
|
+
*
|
|
152
|
+
* @param {bigint} value - The 256-bit unsigned integer to convert (0 to 2^256-1)
|
|
153
|
+
* @returns {Address} A new Address instance containing the converted value
|
|
154
|
+
*
|
|
155
|
+
* @throws {RangeError} If the value is negative or exceeds 2^256-1
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const bigIntValue = 12345678901234567890n;
|
|
160
|
+
* const address = Address.fromBigInt(bigIntValue);
|
|
161
|
+
* console.log(address.toHex()); // 0x0000000000000000000000000000000000000000000000000000abc123...
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
public static fromBigInt(value: bigint): Address {
|
|
165
|
+
const buffer = new Uint8Array(32);
|
|
166
|
+
const view = new DataView(buffer.buffer);
|
|
167
|
+
|
|
168
|
+
view.setBigUint64(0, (value >> 192n) & 0xffffffffffffffffn, false);
|
|
169
|
+
view.setBigUint64(8, (value >> 128n) & 0xffffffffffffffffn, false);
|
|
170
|
+
view.setBigUint64(16, (value >> 64n) & 0xffffffffffffffffn, false);
|
|
171
|
+
view.setBigUint64(24, value & 0xffffffffffffffffn, false);
|
|
172
|
+
|
|
173
|
+
return new Address(buffer);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Creates an Address instance from four 64-bit unsigned integers.
|
|
178
|
+
*
|
|
179
|
+
* Constructs a 32-byte address by combining four 64-bit big-endian unsigned integers.
|
|
180
|
+
* This is the inverse operation of toUint64Array() and provides an efficient way
|
|
181
|
+
* to create addresses from word-aligned data.
|
|
182
|
+
*
|
|
183
|
+
* @param {bigint} w0 - Most significant 64 bits (bytes 0-7)
|
|
184
|
+
* @param {bigint} w1 - Second 64 bits (bytes 8-15)
|
|
185
|
+
* @param {bigint} w2 - Third 64 bits (bytes 16-23)
|
|
186
|
+
* @param {bigint} w3 - Least significant 64 bits (bytes 24-31)
|
|
187
|
+
* @returns {Address} A new Address instance containing the combined value
|
|
188
|
+
*
|
|
189
|
+
* @throws {RangeError} If any value exceeds 64 bits (2^64-1)
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const address = Address.fromUint64Array(
|
|
194
|
+
* 0x0123456789abcdefn,
|
|
195
|
+
* 0xfedcba9876543210n,
|
|
196
|
+
* 0x1111222233334444n,
|
|
197
|
+
* 0x5555666677778888n
|
|
198
|
+
* );
|
|
199
|
+
* console.log(address.toHex());
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
public static fromUint64Array(w0: bigint, w1: bigint, w2: bigint, w3: bigint): Address {
|
|
203
|
+
const buffer = new Uint8Array(32);
|
|
204
|
+
const view = new DataView(buffer.buffer);
|
|
205
|
+
|
|
206
|
+
view.setBigUint64(0, w0, false);
|
|
207
|
+
view.setBigUint64(8, w1, false);
|
|
208
|
+
view.setBigUint64(16, w2, false);
|
|
209
|
+
view.setBigUint64(24, w3, false);
|
|
210
|
+
|
|
211
|
+
return new Address(buffer);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Converts the address to four 64-bit unsigned integers.
|
|
216
|
+
*
|
|
217
|
+
* Splits the 32-byte (256-bit) address into four 64-bit big-endian unsigned integers.
|
|
218
|
+
* This representation is useful for efficient storage, comparison operations, or
|
|
219
|
+
* interfacing with systems that work with 64-bit word sizes.
|
|
220
|
+
*
|
|
221
|
+
* @returns {[bigint, bigint, bigint, bigint]} An array of four 64-bit unsigned integers
|
|
222
|
+
* representing the address from most significant to least significant bits
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```typescript
|
|
226
|
+
* const address = Address.fromString('0x0123456789abcdef...');
|
|
227
|
+
* const [w0, w1, w2, w3] = address.toUint64Array();
|
|
228
|
+
* console.log(w0); // Most significant 64 bits
|
|
229
|
+
* console.log(w3); // Least significant 64 bits
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
public toUint64Array(): [bigint, bigint, bigint, bigint] {
|
|
233
|
+
if (this.#cachedUint64Array !== undefined) {
|
|
234
|
+
return this.#cachedUint64Array;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const view = new DataView(this.buffer, this.byteOffset, 32);
|
|
238
|
+
this.#cachedUint64Array = [
|
|
239
|
+
view.getBigUint64(0, false),
|
|
240
|
+
view.getBigUint64(8, false),
|
|
241
|
+
view.getBigUint64(16, false),
|
|
242
|
+
view.getBigUint64(24, false),
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
return this.#cachedUint64Array;
|
|
246
|
+
}
|
|
247
|
+
|
|
143
248
|
/**
|
|
144
249
|
* Converts the address to a hex string
|
|
145
250
|
* @returns {string} The hex string
|
|
@@ -220,6 +325,37 @@ export class Address extends Uint8Array {
|
|
|
220
325
|
return Buffer.from(this.#originalPublicKey);
|
|
221
326
|
}
|
|
222
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Converts the address to a BigInt representation.
|
|
330
|
+
*
|
|
331
|
+
* This method uses an optimized DataView approach to read the 32-byte address
|
|
332
|
+
* as four 64-bit big-endian unsigned integers, then combines them using bitwise
|
|
333
|
+
* operations. This is approximately 10-20x faster than string-based conversion.
|
|
334
|
+
*
|
|
335
|
+
* @returns {bigint} The address as a 256-bit unsigned integer
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* const address = Address.fromString('0x0123456789abcdef...');
|
|
340
|
+
* const bigIntValue = address.toBigInt();
|
|
341
|
+
* console.log(bigIntValue); // 123456789...n
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
public toBigInt(): bigint {
|
|
345
|
+
if (this.#cachedBigInt !== undefined) {
|
|
346
|
+
return this.#cachedBigInt;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const view = new DataView(this.buffer, this.byteOffset, 32);
|
|
350
|
+
this.#cachedBigInt =
|
|
351
|
+
(view.getBigUint64(0, false) << 192n) |
|
|
352
|
+
(view.getBigUint64(8, false) << 128n) |
|
|
353
|
+
(view.getBigUint64(16, false) << 64n) |
|
|
354
|
+
view.getBigUint64(24, false);
|
|
355
|
+
|
|
356
|
+
return this.#cachedBigInt;
|
|
357
|
+
}
|
|
358
|
+
|
|
223
359
|
public equals(a: Address): boolean {
|
|
224
360
|
const b: Address = this as Address;
|
|
225
361
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BIP (Bitcoin Improvement Proposal) derivation path standards
|
|
3
|
+
*
|
|
4
|
+
* These define standardized derivation paths for different address types
|
|
5
|
+
* in hierarchical deterministic (HD) wallets.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/bitcoin/bips
|
|
8
|
+
*/
|
|
9
|
+
export enum BIPStandard {
|
|
10
|
+
/**
|
|
11
|
+
* BIP44: Multi-Account Hierarchy for Deterministic Wallets
|
|
12
|
+
*
|
|
13
|
+
* Path: m/44'/coin_type'/account'/change/address_index
|
|
14
|
+
* Original standard for P2PKH (legacy) addresses
|
|
15
|
+
* Widely used by wallets like Unisat for all address types
|
|
16
|
+
*
|
|
17
|
+
* @see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
|
18
|
+
*/
|
|
19
|
+
BIP44 = 44,
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* BIP49: Derivation scheme for P2WPKH-nested-in-P2SH based accounts
|
|
23
|
+
*
|
|
24
|
+
* Path: m/49'/coin_type'/account'/change/address_index
|
|
25
|
+
* For wrapped SegWit addresses (P2SH-P2WPKH starting with '3')
|
|
26
|
+
*
|
|
27
|
+
* @see https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki
|
|
28
|
+
*/
|
|
29
|
+
BIP49 = 49,
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* BIP84: Derivation scheme for P2WPKH based accounts
|
|
33
|
+
*
|
|
34
|
+
* Path: m/84'/coin_type'/account'/change/address_index
|
|
35
|
+
* For native SegWit addresses (P2WPKH starting with 'bc1q')
|
|
36
|
+
* DEFAULT for this library
|
|
37
|
+
*
|
|
38
|
+
* @see https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki
|
|
39
|
+
*/
|
|
40
|
+
BIP84 = 84,
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* BIP86: Derivation scheme for P2TR based accounts
|
|
44
|
+
*
|
|
45
|
+
* Path: m/86'/coin_type'/account'/change/address_index
|
|
46
|
+
* For Taproot addresses (P2TR starting with 'bc1p')
|
|
47
|
+
*
|
|
48
|
+
* @see https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
|
|
49
|
+
*/
|
|
50
|
+
BIP86 = 86,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get a human-readable description of a BIP standard
|
|
55
|
+
*
|
|
56
|
+
* @param standard - The BIP standard
|
|
57
|
+
* @returns A description of the standard and its typical use case
|
|
58
|
+
*/
|
|
59
|
+
export function getBIPDescription(standard: BIPStandard): string {
|
|
60
|
+
switch (standard) {
|
|
61
|
+
case BIPStandard.BIP44:
|
|
62
|
+
return 'BIP44: Legacy addresses (P2PKH), widely used by Unisat and other wallets';
|
|
63
|
+
case BIPStandard.BIP49:
|
|
64
|
+
return 'BIP49: Wrapped SegWit addresses (P2SH-P2WPKH)';
|
|
65
|
+
case BIPStandard.BIP84:
|
|
66
|
+
return 'BIP84: Native SegWit addresses (P2WPKH) - DEFAULT';
|
|
67
|
+
case BIPStandard.BIP86:
|
|
68
|
+
return 'BIP86: Taproot addresses (P2TR)';
|
|
69
|
+
default:
|
|
70
|
+
return 'Unknown BIP standard';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Build a derivation path for a given BIP standard
|
|
76
|
+
*
|
|
77
|
+
* @param standard - The BIP standard to use
|
|
78
|
+
* @param coinType - The coin type (0 for mainnet, 1 for testnet/regtest)
|
|
79
|
+
* @param account - The account index
|
|
80
|
+
* @param change - The change index (0 for receiving, 1 for change)
|
|
81
|
+
* @param addressIndex - The address index
|
|
82
|
+
* @returns The full derivation path
|
|
83
|
+
*/
|
|
84
|
+
export function buildBIPPath(
|
|
85
|
+
standard: BIPStandard,
|
|
86
|
+
coinType: number,
|
|
87
|
+
account: number,
|
|
88
|
+
change: number,
|
|
89
|
+
addressIndex: number,
|
|
90
|
+
): string {
|
|
91
|
+
return `m/${standard}'/${coinType}'/${account}'/${change}/${addressIndex}`;
|
|
92
|
+
}
|
package/src/mnemonic/Mnemonic.ts
CHANGED
|
@@ -10,11 +10,15 @@ import * as ecc from '@bitcoinerlab/secp256k1';
|
|
|
10
10
|
import { initEccLib, Network, networks } from '@btc-vision/bitcoin';
|
|
11
11
|
import { Wallet } from '../keypair/Wallet.js';
|
|
12
12
|
import { MnemonicStrength } from './MnemonicStrength.js';
|
|
13
|
+
import { BIPStandard, buildBIPPath } from './BIPStandard.js';
|
|
14
|
+
import { AddressTypes } from '../keypair/AddressVerificator.js';
|
|
13
15
|
|
|
14
16
|
initEccLib(ecc);
|
|
15
17
|
|
|
16
18
|
const bip32 = BIP32Factory(ecc);
|
|
17
19
|
|
|
20
|
+
export { BIPStandard, getBIPDescription } from './BIPStandard.js';
|
|
21
|
+
|
|
18
22
|
/**
|
|
19
23
|
* Mnemonic class for managing BIP39 mnemonic phrases with BIP360 quantum support
|
|
20
24
|
*
|
|
@@ -189,7 +193,7 @@ export class Mnemonic {
|
|
|
189
193
|
}
|
|
190
194
|
|
|
191
195
|
/**
|
|
192
|
-
* Derive a wallet at a specific index using BIP360 (quantum) and
|
|
196
|
+
* Derive a wallet at a specific index using BIP360 (quantum) and configurable BIP standard (classical) paths
|
|
193
197
|
*
|
|
194
198
|
* This method derives both classical ECDSA/Schnorr keys and quantum-resistant ML-DSA keys
|
|
195
199
|
* for the wallet, providing hybrid post-quantum security.
|
|
@@ -197,11 +201,29 @@ export class Mnemonic {
|
|
|
197
201
|
* @param index - The address index to derive (default: 0)
|
|
198
202
|
* @param account - The account index (default: 0)
|
|
199
203
|
* @param isChange - Whether this is a change address (default: false)
|
|
204
|
+
* @param bipStandard - The BIP standard to use for classical derivation (default: BIP84)
|
|
200
205
|
* @returns A Wallet instance with both classical and quantum keys
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* // Default: BIP84 (Native SegWit)
|
|
210
|
+
* const wallet1 = mnemonic.derive(0);
|
|
211
|
+
*
|
|
212
|
+
* // BIP44 (Compatible with Unisat)
|
|
213
|
+
* const wallet2 = mnemonic.derive(0, 0, false, BIPStandard.BIP44);
|
|
214
|
+
*
|
|
215
|
+
* // BIP86 (Taproot)
|
|
216
|
+
* const wallet3 = mnemonic.derive(0, 0, false, BIPStandard.BIP86);
|
|
217
|
+
* ```
|
|
201
218
|
*/
|
|
202
|
-
public derive(
|
|
203
|
-
|
|
204
|
-
|
|
219
|
+
public derive(
|
|
220
|
+
index: number = 0,
|
|
221
|
+
account: number = 0,
|
|
222
|
+
isChange: boolean = false,
|
|
223
|
+
bipStandard: BIPStandard = BIPStandard.BIP84,
|
|
224
|
+
): Wallet {
|
|
225
|
+
// Derive classical key using specified BIP standard
|
|
226
|
+
const classicalPath = this.buildClassicalPath(account, index, isChange, bipStandard);
|
|
205
227
|
const classicalChild = this._classicalRoot.derivePath(classicalPath);
|
|
206
228
|
|
|
207
229
|
if (!classicalChild.privateKey) {
|
|
@@ -225,6 +247,101 @@ export class Mnemonic {
|
|
|
225
247
|
);
|
|
226
248
|
}
|
|
227
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Derive a Unisat-compatible wallet
|
|
252
|
+
*
|
|
253
|
+
* Unisat uses different derivation paths based on address type:
|
|
254
|
+
* - Legacy (P2PKH): m/44'/coinType'/account'/change/index
|
|
255
|
+
* - Nested SegWit (P2SH-P2WPKH): m/49'/coinType'/account'/change/index
|
|
256
|
+
* - Native SegWit (P2WPKH): m/84'/coinType'/account'/change/index
|
|
257
|
+
* - Taproot (P2TR): m/86'/coinType'/account'/change/index
|
|
258
|
+
*
|
|
259
|
+
* @param addressType - The address type to generate
|
|
260
|
+
* @param index - The address index (default: 0)
|
|
261
|
+
* @param account - The account index (default: 0)
|
|
262
|
+
* @param isChange - Whether this is a change address (default: false)
|
|
263
|
+
* @returns A Wallet instance with both classical and quantum keys
|
|
264
|
+
*/
|
|
265
|
+
public deriveUnisat(
|
|
266
|
+
addressType: AddressTypes = AddressTypes.P2TR,
|
|
267
|
+
index: number = 0,
|
|
268
|
+
account: number = 0,
|
|
269
|
+
isChange: boolean = false,
|
|
270
|
+
): Wallet {
|
|
271
|
+
// Determine BIP purpose based on address type
|
|
272
|
+
let purpose: number;
|
|
273
|
+
switch (addressType) {
|
|
274
|
+
case AddressTypes.P2PKH:
|
|
275
|
+
purpose = 44;
|
|
276
|
+
break;
|
|
277
|
+
case AddressTypes.P2SH_OR_P2SH_P2WPKH:
|
|
278
|
+
purpose = 49;
|
|
279
|
+
break;
|
|
280
|
+
case AddressTypes.P2WPKH:
|
|
281
|
+
purpose = 84;
|
|
282
|
+
break;
|
|
283
|
+
case AddressTypes.P2TR:
|
|
284
|
+
purpose = 86;
|
|
285
|
+
break;
|
|
286
|
+
default:
|
|
287
|
+
throw new Error(`Unsupported address type: ${addressType}`);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Build classical derivation path for Unisat
|
|
291
|
+
const coinType = this.getCoinType();
|
|
292
|
+
const change = isChange ? 1 : 0;
|
|
293
|
+
const classicalPath = `m/${purpose}'/0'/${account}'/${change}/${index}`;
|
|
294
|
+
|
|
295
|
+
// Derive classical key
|
|
296
|
+
const classicalChild = this._classicalRoot.derivePath(classicalPath);
|
|
297
|
+
|
|
298
|
+
if (!classicalChild.privateKey) {
|
|
299
|
+
throw new Error(`Failed to derive classical private key at path ${classicalPath}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Derive quantum key using BIP360
|
|
303
|
+
const quantumPath = `m/360'/${coinType}'/${account}'/${change}/${index}`;
|
|
304
|
+
const quantumChild = this._quantumRoot.derivePath(quantumPath);
|
|
305
|
+
|
|
306
|
+
if (!quantumChild.privateKey) {
|
|
307
|
+
throw new Error(`Failed to derive quantum private key at path ${quantumPath}`);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Create wallet with both classical and quantum keys
|
|
311
|
+
return new Wallet(
|
|
312
|
+
Buffer.from(classicalChild.privateKey).toString('hex'),
|
|
313
|
+
Buffer.from(quantumChild.privateKey).toString('hex'),
|
|
314
|
+
this._network,
|
|
315
|
+
this._securityLevel,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Derive multiple Unisat-compatible wallets
|
|
321
|
+
*
|
|
322
|
+
* @param addressType - The address type to generate
|
|
323
|
+
* @param count - Number of wallets to derive
|
|
324
|
+
* @param startIndex - Starting index (default: 0)
|
|
325
|
+
* @param account - The account index (default: 0)
|
|
326
|
+
* @param isChange - Whether these are change addresses (default: false)
|
|
327
|
+
* @returns Array of Wallet instances
|
|
328
|
+
*/
|
|
329
|
+
public deriveMultipleUnisat(
|
|
330
|
+
addressType: AddressTypes = AddressTypes.P2TR,
|
|
331
|
+
count: number = 5,
|
|
332
|
+
startIndex: number = 0,
|
|
333
|
+
account: number = 0,
|
|
334
|
+
isChange: boolean = false,
|
|
335
|
+
): Wallet[] {
|
|
336
|
+
const wallets: Wallet[] = [];
|
|
337
|
+
|
|
338
|
+
for (let i = 0; i < count; i++) {
|
|
339
|
+
wallets.push(this.deriveUnisat(addressType, startIndex + i, account, isChange));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return wallets;
|
|
343
|
+
}
|
|
344
|
+
|
|
228
345
|
/**
|
|
229
346
|
* Derive multiple wallets with sequential indices
|
|
230
347
|
*
|
|
@@ -232,6 +349,7 @@ export class Mnemonic {
|
|
|
232
349
|
* @param startIndex - The starting address index (default: 0)
|
|
233
350
|
* @param account - The account index (default: 0)
|
|
234
351
|
* @param isChange - Whether these are change addresses (default: false)
|
|
352
|
+
* @param bipStandard - The BIP standard to use for classical derivation (default: BIP84)
|
|
235
353
|
* @returns An array of Wallet instances
|
|
236
354
|
*/
|
|
237
355
|
public deriveMultiple(
|
|
@@ -239,11 +357,12 @@ export class Mnemonic {
|
|
|
239
357
|
startIndex: number = 0,
|
|
240
358
|
account: number = 0,
|
|
241
359
|
isChange: boolean = false,
|
|
360
|
+
bipStandard: BIPStandard = BIPStandard.BIP84,
|
|
242
361
|
): Wallet[] {
|
|
243
362
|
const wallets: Wallet[] = [];
|
|
244
363
|
|
|
245
364
|
for (let i = 0; i < count; i++) {
|
|
246
|
-
wallets.push(this.derive(startIndex + i, account, isChange));
|
|
365
|
+
wallets.push(this.derive(startIndex + i, account, isChange, bipStandard));
|
|
247
366
|
}
|
|
248
367
|
|
|
249
368
|
return wallets;
|
|
@@ -296,17 +415,23 @@ export class Mnemonic {
|
|
|
296
415
|
}
|
|
297
416
|
|
|
298
417
|
/**
|
|
299
|
-
* Build a classical derivation path
|
|
418
|
+
* Build a classical derivation path using specified BIP standard
|
|
300
419
|
*
|
|
301
420
|
* @param account - The account index
|
|
302
421
|
* @param index - The address index
|
|
303
422
|
* @param isChange - Whether this is a change address
|
|
423
|
+
* @param bipStandard - The BIP standard to use (default: BIP84)
|
|
304
424
|
* @returns The derivation path string
|
|
305
425
|
*/
|
|
306
|
-
private buildClassicalPath(
|
|
426
|
+
private buildClassicalPath(
|
|
427
|
+
account: number,
|
|
428
|
+
index: number,
|
|
429
|
+
isChange: boolean,
|
|
430
|
+
bipStandard: BIPStandard = BIPStandard.BIP84,
|
|
431
|
+
): string {
|
|
307
432
|
const coinType = this.getCoinType();
|
|
308
433
|
const change = isChange ? 1 : 0;
|
|
309
|
-
return
|
|
434
|
+
return buildBIPPath(bipStandard, coinType, account, change, index);
|
|
310
435
|
}
|
|
311
436
|
|
|
312
437
|
/**
|
package/src/opnet.ts
CHANGED
package/src/utils/lengths.ts
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
export const ADDRESS_BYTE_LENGTH: number = 32;
|
|
2
|
+
export const SELECTOR_BYTE_LENGTH: number = 4;
|
|
2
3
|
|
|
3
|
-
export const
|
|
4
|
-
export const
|
|
4
|
+
export const U256_BYTE_LENGTH: number = 32;
|
|
5
|
+
export const U128_BYTE_LENGTH: number = 16;
|
|
6
|
+
export const U64_BYTE_LENGTH: number = 8;
|
|
7
|
+
export const U32_BYTE_LENGTH: number = 4;
|
|
8
|
+
export const U16_BYTE_LENGTH: number = 2;
|
|
9
|
+
export const U8_BYTE_LENGTH: number = 1;
|
|
5
10
|
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
10
|
-
export const
|
|
11
|
-
export const
|
|
11
|
+
export const I256_BYTE_LENGTH: number = 32;
|
|
12
|
+
export const I128_BYTE_LENGTH: number = 16;
|
|
13
|
+
export const I64_BYTE_LENGTH: number = 8;
|
|
14
|
+
export const number_BYTE_LENGTH: number = 4;
|
|
15
|
+
export const I16_BYTE_LENGTH: number = 2;
|
|
16
|
+
export const I8_BYTE_LENGTH: number = 1;
|
|
12
17
|
|
|
13
|
-
export const
|
|
14
|
-
export const I128_BYTE_LENGTH: i32 = 16;
|
|
15
|
-
export const I64_BYTE_LENGTH: i32 = 8;
|
|
16
|
-
export const I32_BYTE_LENGTH: i32 = 4;
|
|
17
|
-
export const I16_BYTE_LENGTH: i32 = 2;
|
|
18
|
-
export const I8_BYTE_LENGTH: i32 = 1;
|
|
19
|
-
|
|
20
|
-
export const BOOLEAN_BYTE_LENGTH: i32 = 1;
|
|
18
|
+
export const BOOLEAN_BYTE_LENGTH: number = 1;
|