hd-wallet-wasm 0.1.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/src/index.mjs ADDED
@@ -0,0 +1,2479 @@
1
+ /**
2
+ * HD Wallet WASM - JavaScript ES6 Wrapper
3
+ *
4
+ * Comprehensive HD wallet implementation with:
5
+ * - BIP-32/39/44/49/84 support
6
+ * - Multi-curve cryptography (secp256k1, Ed25519, P-256, P-384, X25519)
7
+ * - Multi-chain support (Bitcoin, Ethereum, Solana, Cosmos, Polkadot)
8
+ * - Hardware wallet abstraction (requires bridge)
9
+ * - Transaction building and signing
10
+ *
11
+ * @module hd-wallet-wasm
12
+ * @version 0.1.0
13
+ */
14
+
15
+ // =============================================================================
16
+ // Enums (matching TypeScript definitions)
17
+ // =============================================================================
18
+
19
+ /**
20
+ * Elliptic curve types
21
+ * @readonly
22
+ * @enum {number}
23
+ */
24
+ export const Curve = Object.freeze({
25
+ SECP256K1: 0,
26
+ ED25519: 1,
27
+ P256: 2,
28
+ P384: 3,
29
+ X25519: 4
30
+ });
31
+
32
+ /**
33
+ * SLIP-44 coin types
34
+ * @readonly
35
+ * @enum {number}
36
+ */
37
+ export const CoinType = Object.freeze({
38
+ BITCOIN: 0,
39
+ BITCOIN_TESTNET: 1,
40
+ LITECOIN: 2,
41
+ DOGECOIN: 3,
42
+ ETHEREUM: 60,
43
+ ETHEREUM_CLASSIC: 61,
44
+ COSMOS: 118,
45
+ STELLAR: 148,
46
+ BITCOIN_CASH: 145,
47
+ POLKADOT: 354,
48
+ KUSAMA: 434,
49
+ SOLANA: 501,
50
+ BINANCE: 714,
51
+ CARDANO: 1815
52
+ });
53
+
54
+ /**
55
+ * BIP-39 wordlist languages
56
+ * @readonly
57
+ * @enum {number}
58
+ */
59
+ export const Language = Object.freeze({
60
+ ENGLISH: 0,
61
+ JAPANESE: 1,
62
+ KOREAN: 2,
63
+ SPANISH: 3,
64
+ CHINESE_SIMPLIFIED: 4,
65
+ CHINESE_TRADITIONAL: 5,
66
+ FRENCH: 6,
67
+ ITALIAN: 7,
68
+ CZECH: 8,
69
+ PORTUGUESE: 9
70
+ });
71
+
72
+ /**
73
+ * WASI feature flags
74
+ * @readonly
75
+ * @enum {number}
76
+ */
77
+ export const WasiFeature = Object.freeze({
78
+ RANDOM: 0,
79
+ FILESYSTEM: 1,
80
+ NETWORK: 2,
81
+ USB_HID: 3,
82
+ CLOCK: 4,
83
+ ENVIRONMENT: 5
84
+ });
85
+
86
+ /**
87
+ * WASI warning codes
88
+ * @readonly
89
+ * @enum {number}
90
+ */
91
+ export const WasiWarning = Object.freeze({
92
+ NONE: 0,
93
+ NEEDS_ENTROPY: 1,
94
+ NEEDS_BRIDGE: 2,
95
+ NOT_AVAILABLE_WASI: 3,
96
+ DISABLED_FIPS: 4,
97
+ NEEDS_CAPABILITY: 5
98
+ });
99
+
100
+ /**
101
+ * Entropy status
102
+ * @readonly
103
+ * @enum {number}
104
+ */
105
+ export const EntropyStatus = Object.freeze({
106
+ NOT_INITIALIZED: 0,
107
+ INITIALIZED: 1,
108
+ SUFFICIENT: 2
109
+ });
110
+
111
+ /**
112
+ * Bitcoin address types
113
+ * @readonly
114
+ * @enum {number}
115
+ */
116
+ export const BitcoinAddressType = Object.freeze({
117
+ P2PKH: 0,
118
+ P2SH: 1,
119
+ P2WPKH: 2,
120
+ P2WSH: 3,
121
+ P2TR: 4
122
+ });
123
+
124
+ /**
125
+ * Network type
126
+ * @readonly
127
+ * @enum {number}
128
+ */
129
+ export const Network = Object.freeze({
130
+ MAINNET: 0,
131
+ TESTNET: 1
132
+ });
133
+
134
+ // =============================================================================
135
+ // Error handling
136
+ // =============================================================================
137
+
138
+ /**
139
+ * HD Wallet error codes
140
+ * @readonly
141
+ * @enum {number}
142
+ */
143
+ const ErrorCode = Object.freeze({
144
+ OK: 0,
145
+ UNKNOWN: 1,
146
+ INVALID_ARGUMENT: 2,
147
+ NOT_SUPPORTED: 3,
148
+ OUT_OF_MEMORY: 4,
149
+ INTERNAL: 5,
150
+ NO_ENTROPY: 100,
151
+ INSUFFICIENT_ENTROPY: 101,
152
+ INVALID_WORD: 200,
153
+ INVALID_CHECKSUM: 201,
154
+ INVALID_MNEMONIC_LENGTH: 202,
155
+ INVALID_ENTROPY_LENGTH: 203,
156
+ INVALID_SEED: 300,
157
+ INVALID_PATH: 301,
158
+ INVALID_CHILD_INDEX: 302,
159
+ HARDENED_FROM_PUBLIC: 303,
160
+ INVALID_EXTENDED_KEY: 304,
161
+ INVALID_PRIVATE_KEY: 400,
162
+ INVALID_PUBLIC_KEY: 401,
163
+ INVALID_SIGNATURE: 402,
164
+ VERIFICATION_FAILED: 403,
165
+ KEY_DERIVATION_FAILED: 404,
166
+ INVALID_TRANSACTION: 500,
167
+ INSUFFICIENT_FUNDS: 501,
168
+ INVALID_ADDRESS: 502,
169
+ DEVICE_NOT_CONNECTED: 600,
170
+ DEVICE_COMM_ERROR: 601,
171
+ USER_CANCELLED: 602,
172
+ DEVICE_BUSY: 603,
173
+ DEVICE_NOT_SUPPORTED: 604,
174
+ BRIDGE_NOT_SET: 700,
175
+ BRIDGE_FAILED: 701,
176
+ NEEDS_BRIDGE: 702,
177
+ FIPS_NOT_ALLOWED: 800
178
+ });
179
+
180
+ /**
181
+ * Error message map
182
+ */
183
+ const ERROR_MESSAGES = {
184
+ [ErrorCode.OK]: 'Success',
185
+ [ErrorCode.UNKNOWN]: 'Unknown error',
186
+ [ErrorCode.INVALID_ARGUMENT]: 'Invalid argument',
187
+ [ErrorCode.NOT_SUPPORTED]: 'Operation not supported',
188
+ [ErrorCode.OUT_OF_MEMORY]: 'Out of memory',
189
+ [ErrorCode.INTERNAL]: 'Internal error',
190
+ [ErrorCode.NO_ENTROPY]: 'No entropy available - call injectEntropy() first',
191
+ [ErrorCode.INSUFFICIENT_ENTROPY]: 'Insufficient entropy',
192
+ [ErrorCode.INVALID_WORD]: 'Invalid mnemonic word',
193
+ [ErrorCode.INVALID_CHECKSUM]: 'Invalid mnemonic checksum',
194
+ [ErrorCode.INVALID_MNEMONIC_LENGTH]: 'Invalid mnemonic length',
195
+ [ErrorCode.INVALID_ENTROPY_LENGTH]: 'Invalid entropy length',
196
+ [ErrorCode.INVALID_SEED]: 'Invalid seed',
197
+ [ErrorCode.INVALID_PATH]: 'Invalid derivation path',
198
+ [ErrorCode.INVALID_CHILD_INDEX]: 'Invalid child index',
199
+ [ErrorCode.HARDENED_FROM_PUBLIC]: 'Cannot derive hardened child from public key',
200
+ [ErrorCode.INVALID_EXTENDED_KEY]: 'Invalid extended key format',
201
+ [ErrorCode.INVALID_PRIVATE_KEY]: 'Invalid private key',
202
+ [ErrorCode.INVALID_PUBLIC_KEY]: 'Invalid public key',
203
+ [ErrorCode.INVALID_SIGNATURE]: 'Invalid signature',
204
+ [ErrorCode.VERIFICATION_FAILED]: 'Signature verification failed',
205
+ [ErrorCode.KEY_DERIVATION_FAILED]: 'Key derivation failed',
206
+ [ErrorCode.INVALID_TRANSACTION]: 'Invalid transaction',
207
+ [ErrorCode.INSUFFICIENT_FUNDS]: 'Insufficient funds',
208
+ [ErrorCode.INVALID_ADDRESS]: 'Invalid address',
209
+ [ErrorCode.DEVICE_NOT_CONNECTED]: 'Hardware device not connected',
210
+ [ErrorCode.DEVICE_COMM_ERROR]: 'Hardware device communication error',
211
+ [ErrorCode.USER_CANCELLED]: 'Operation cancelled by user',
212
+ [ErrorCode.DEVICE_BUSY]: 'Hardware device busy',
213
+ [ErrorCode.DEVICE_NOT_SUPPORTED]: 'Operation not supported by this device',
214
+ [ErrorCode.BRIDGE_NOT_SET]: 'Bridge callback not set',
215
+ [ErrorCode.BRIDGE_FAILED]: 'Bridge callback failed',
216
+ [ErrorCode.NEEDS_BRIDGE]: 'Feature requires WASI bridge',
217
+ [ErrorCode.FIPS_NOT_ALLOWED]: 'Algorithm not allowed in FIPS mode'
218
+ };
219
+
220
+ /**
221
+ * HD Wallet Error class
222
+ */
223
+ class HDWalletError extends Error {
224
+ /**
225
+ * @param {number} code - Error code
226
+ * @param {string} [message] - Optional custom message
227
+ */
228
+ constructor(code, message) {
229
+ super(message || ERROR_MESSAGES[code] || `Error code: ${code}`);
230
+ this.name = 'HDWalletError';
231
+ this.code = code;
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Check result and throw if error
237
+ * @param {number} result - Result code from WASM function
238
+ * @throws {HDWalletError} If result is non-zero
239
+ */
240
+ function checkResult(result) {
241
+ if (result !== 0) {
242
+ throw new HDWalletError(result);
243
+ }
244
+ }
245
+
246
+ // =============================================================================
247
+ // Memory Helpers
248
+ // =============================================================================
249
+
250
+ /**
251
+ * Allocate memory and copy data
252
+ * @param {WebAssembly.Module} wasm - WASM module
253
+ * @param {Uint8Array} data - Data to copy
254
+ * @returns {number} Pointer to allocated memory
255
+ */
256
+ function allocAndCopy(wasm, data) {
257
+ const ptr = wasm._hd_alloc(data.length);
258
+ if (!ptr) throw new HDWalletError(ErrorCode.OUT_OF_MEMORY);
259
+ wasm.HEAPU8.set(data, ptr);
260
+ return ptr;
261
+ }
262
+
263
+ /**
264
+ * Allocate memory for string and copy
265
+ * @param {WebAssembly.Module} wasm - WASM module
266
+ * @param {string} str - String to copy
267
+ * @returns {number} Pointer to allocated memory
268
+ */
269
+ function allocString(wasm, str) {
270
+ const len = wasm.lengthBytesUTF8(str) + 1;
271
+ const ptr = wasm._hd_alloc(len);
272
+ if (!ptr) throw new HDWalletError(ErrorCode.OUT_OF_MEMORY);
273
+ wasm.stringToUTF8(str, ptr, len);
274
+ return ptr;
275
+ }
276
+
277
+ /**
278
+ * Read bytes from WASM memory
279
+ * @param {WebAssembly.Module} wasm - WASM module
280
+ * @param {number} ptr - Pointer to memory
281
+ * @param {number} len - Number of bytes to read
282
+ * @returns {Uint8Array} Copy of the data
283
+ */
284
+ function readBytes(wasm, ptr, len) {
285
+ return new Uint8Array(wasm.HEAPU8.buffer, ptr, len).slice();
286
+ }
287
+
288
+ /**
289
+ * Read null-terminated string from WASM memory
290
+ * @param {WebAssembly.Module} wasm - WASM module
291
+ * @param {number} ptr - Pointer to string
292
+ * @returns {string} JavaScript string
293
+ */
294
+ function readString(wasm, ptr) {
295
+ return wasm.UTF8ToString(ptr);
296
+ }
297
+
298
+ // =============================================================================
299
+ // HDKey Class
300
+ // =============================================================================
301
+
302
+ /**
303
+ * BIP-32 HD Key
304
+ * Represents a node in the HD key derivation tree.
305
+ */
306
+ class HDKey {
307
+ /**
308
+ * @param {WebAssembly.Module} wasm - WASM module
309
+ * @param {number} handle - Native key handle
310
+ * @param {string} [path='m'] - Derivation path
311
+ */
312
+ constructor(wasm, handle, path = 'm') {
313
+ /** @private */
314
+ this._wasm = wasm;
315
+ /** @private */
316
+ this._handle = handle;
317
+ /** @private */
318
+ this._path = path;
319
+ /** @private */
320
+ this._destroyed = false;
321
+ }
322
+
323
+ /**
324
+ * Derivation path
325
+ * @type {string}
326
+ */
327
+ get path() {
328
+ return this._path;
329
+ }
330
+
331
+ /**
332
+ * Key depth in derivation tree
333
+ * @type {number}
334
+ */
335
+ get depth() {
336
+ this._checkDestroyed();
337
+ return this._wasm._hd_key_get_depth(this._handle);
338
+ }
339
+
340
+ /**
341
+ * Parent fingerprint
342
+ * @type {number}
343
+ */
344
+ get parentFingerprint() {
345
+ this._checkDestroyed();
346
+ return this._wasm._hd_key_get_parent_fingerprint(this._handle);
347
+ }
348
+
349
+ /**
350
+ * Child index
351
+ * @type {number}
352
+ */
353
+ get childIndex() {
354
+ this._checkDestroyed();
355
+ return this._wasm._hd_key_get_child_index(this._handle);
356
+ }
357
+
358
+ /**
359
+ * Is this a neutered (public-only) key?
360
+ * @type {boolean}
361
+ */
362
+ get isNeutered() {
363
+ this._checkDestroyed();
364
+ return this._wasm._hd_key_is_neutered(this._handle) !== 0;
365
+ }
366
+
367
+ /**
368
+ * Elliptic curve (currently always secp256k1)
369
+ * @type {number}
370
+ */
371
+ get curve() {
372
+ return Curve.SECP256K1;
373
+ }
374
+
375
+ /**
376
+ * Check if key has been destroyed
377
+ * @private
378
+ */
379
+ _checkDestroyed() {
380
+ if (this._destroyed) {
381
+ throw new HDWalletError(ErrorCode.INVALID_ARGUMENT, 'Key has been destroyed');
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Get private key bytes
387
+ * @returns {Uint8Array} 32-byte private key
388
+ * @throws {HDWalletError} If key is neutered
389
+ */
390
+ privateKey() {
391
+ this._checkDestroyed();
392
+ const ptr = this._wasm._hd_alloc(32);
393
+ try {
394
+ const result = this._wasm._hd_key_get_private(this._handle, ptr, 32);
395
+ checkResult(result);
396
+ return readBytes(this._wasm, ptr, 32);
397
+ } finally {
398
+ this._wasm._hd_dealloc(ptr);
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Get compressed public key bytes
404
+ * @returns {Uint8Array} 33-byte compressed public key
405
+ */
406
+ publicKey() {
407
+ this._checkDestroyed();
408
+ const ptr = this._wasm._hd_alloc(33);
409
+ try {
410
+ const result = this._wasm._hd_key_get_public(this._handle, ptr, 33);
411
+ checkResult(result);
412
+ return readBytes(this._wasm, ptr, 33);
413
+ } finally {
414
+ this._wasm._hd_dealloc(ptr);
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Get uncompressed public key bytes
420
+ * @returns {Uint8Array} 65-byte uncompressed public key
421
+ */
422
+ publicKeyUncompressed() {
423
+ this._checkDestroyed();
424
+ const compressed = this.publicKey();
425
+ const inPtr = allocAndCopy(this._wasm, compressed);
426
+ const outPtr = this._wasm._hd_alloc(65);
427
+ try {
428
+ const result = this._wasm._hd_curve_decompress_pubkey(inPtr, Curve.SECP256K1, outPtr, 65);
429
+ checkResult(result);
430
+ return readBytes(this._wasm, outPtr, 65);
431
+ } finally {
432
+ this._wasm._hd_dealloc(inPtr);
433
+ this._wasm._hd_dealloc(outPtr);
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Get chain code bytes
439
+ * @returns {Uint8Array} 32-byte chain code
440
+ */
441
+ chainCode() {
442
+ this._checkDestroyed();
443
+ const ptr = this._wasm._hd_alloc(32);
444
+ try {
445
+ const result = this._wasm._hd_key_get_chain_code(this._handle, ptr, 32);
446
+ checkResult(result);
447
+ return readBytes(this._wasm, ptr, 32);
448
+ } finally {
449
+ this._wasm._hd_dealloc(ptr);
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Get key fingerprint
455
+ * @returns {number} Fingerprint (first 4 bytes of HASH160 of public key)
456
+ */
457
+ fingerprint() {
458
+ this._checkDestroyed();
459
+ return this._wasm._hd_key_get_fingerprint(this._handle);
460
+ }
461
+
462
+ /**
463
+ * Derive child key at index
464
+ * @param {number} index - Child index
465
+ * @returns {HDKey} Derived child key
466
+ */
467
+ deriveChild(index) {
468
+ this._checkDestroyed();
469
+ const childHandle = this._wasm._hd_key_derive_child(this._handle, index);
470
+ if (!childHandle) {
471
+ throw new HDWalletError(ErrorCode.KEY_DERIVATION_FAILED);
472
+ }
473
+ const childPath = `${this._path}/${index}`;
474
+ return new HDKey(this._wasm, childHandle, childPath);
475
+ }
476
+
477
+ /**
478
+ * Derive hardened child key
479
+ * @param {number} index - Child index (will be hardened)
480
+ * @returns {HDKey} Derived child key
481
+ */
482
+ deriveHardened(index) {
483
+ this._checkDestroyed();
484
+ const childHandle = this._wasm._hd_key_derive_hardened(this._handle, index);
485
+ if (!childHandle) {
486
+ throw new HDWalletError(ErrorCode.KEY_DERIVATION_FAILED);
487
+ }
488
+ const childPath = `${this._path}/${index}'`;
489
+ return new HDKey(this._wasm, childHandle, childPath);
490
+ }
491
+
492
+ /**
493
+ * Derive key at path
494
+ * @param {string} path - Derivation path (e.g., "m/44'/60'/0'/0/0")
495
+ * @returns {HDKey} Derived key
496
+ */
497
+ derivePath(path) {
498
+ this._checkDestroyed();
499
+ const pathPtr = allocString(this._wasm, path);
500
+ try {
501
+ const childHandle = this._wasm._hd_key_derive_path(this._handle, pathPtr);
502
+ if (!childHandle) {
503
+ throw new HDWalletError(ErrorCode.INVALID_PATH);
504
+ }
505
+ // Compute resulting path
506
+ let resultPath = path;
507
+ if (path.startsWith('m/') || path === 'm') {
508
+ resultPath = path;
509
+ } else if (path.startsWith('/')) {
510
+ resultPath = this._path + path;
511
+ } else {
512
+ resultPath = this._path + '/' + path;
513
+ }
514
+ return new HDKey(this._wasm, childHandle, resultPath);
515
+ } finally {
516
+ this._wasm._hd_dealloc(pathPtr);
517
+ }
518
+ }
519
+
520
+ /**
521
+ * Get neutered (public-only) version
522
+ * @returns {HDKey} Neutered key
523
+ */
524
+ neutered() {
525
+ this._checkDestroyed();
526
+ const neuteredHandle = this._wasm._hd_key_neutered(this._handle);
527
+ if (!neuteredHandle) {
528
+ throw new HDWalletError(ErrorCode.INTERNAL);
529
+ }
530
+ return new HDKey(this._wasm, neuteredHandle, this._path);
531
+ }
532
+
533
+ /**
534
+ * Serialize as extended private key (xprv)
535
+ * @returns {string} Base58Check-encoded xprv
536
+ * @throws {HDWalletError} If key is neutered
537
+ */
538
+ toXprv() {
539
+ this._checkDestroyed();
540
+ const ptr = this._wasm._hd_alloc(128);
541
+ try {
542
+ const result = this._wasm._hd_key_serialize_xprv(this._handle, ptr, 128);
543
+ checkResult(result);
544
+ return readString(this._wasm, ptr);
545
+ } finally {
546
+ this._wasm._hd_dealloc(ptr);
547
+ }
548
+ }
549
+
550
+ /**
551
+ * Serialize as extended public key (xpub)
552
+ * @returns {string} Base58Check-encoded xpub
553
+ */
554
+ toXpub() {
555
+ this._checkDestroyed();
556
+ const ptr = this._wasm._hd_alloc(128);
557
+ try {
558
+ const result = this._wasm._hd_key_serialize_xpub(this._handle, ptr, 128);
559
+ checkResult(result);
560
+ return readString(this._wasm, ptr);
561
+ } finally {
562
+ this._wasm._hd_dealloc(ptr);
563
+ }
564
+ }
565
+
566
+ /**
567
+ * Securely wipe key from memory
568
+ */
569
+ wipe() {
570
+ if (!this._destroyed && this._handle) {
571
+ this._wasm._hd_key_wipe(this._handle);
572
+ this._wasm._hd_key_destroy(this._handle);
573
+ this._handle = null;
574
+ this._destroyed = true;
575
+ }
576
+ }
577
+
578
+ /**
579
+ * Clone key
580
+ * @returns {HDKey} Independent copy
581
+ */
582
+ clone() {
583
+ this._checkDestroyed();
584
+ const clonedHandle = this._wasm._hd_key_clone(this._handle);
585
+ if (!clonedHandle) {
586
+ throw new HDWalletError(ErrorCode.OUT_OF_MEMORY);
587
+ }
588
+ return new HDKey(this._wasm, clonedHandle, this._path);
589
+ }
590
+ }
591
+
592
+ // =============================================================================
593
+ // Module Initialization
594
+ // =============================================================================
595
+
596
+ /**
597
+ * WASM module loader URL resolver
598
+ * @param {string} [wasmPath] - Optional path to WASM file
599
+ * @returns {Promise<Function>} WASM module factory
600
+ */
601
+ async function loadWasmModule(wasmPath) {
602
+ // Try to import the Emscripten-generated module
603
+ let HDWalletWasm;
604
+
605
+ try {
606
+ // Try dynamic import (works in Node.js and bundlers)
607
+ const module = await import('./hd-wallet.js');
608
+ HDWalletWasm = module.default;
609
+ } catch (e) {
610
+ // Fallback for browsers without ES module support
611
+ if (typeof window !== 'undefined' && window.HDWalletWasm) {
612
+ HDWalletWasm = window.HDWalletWasm;
613
+ } else {
614
+ throw new Error(
615
+ 'Failed to load HD Wallet WASM module. ' +
616
+ 'Make sure hd-wallet.js is accessible or set it on window.HDWalletWasm'
617
+ );
618
+ }
619
+ }
620
+
621
+ // Initialize the WASM module
622
+ const wasmOptions = {};
623
+ if (wasmPath) {
624
+ wasmOptions.locateFile = (path) => {
625
+ if (path.endsWith('.wasm')) {
626
+ return wasmPath;
627
+ }
628
+ return path;
629
+ };
630
+ }
631
+
632
+ return HDWalletWasm(wasmOptions);
633
+ }
634
+
635
+ /**
636
+ * Create the HD Wallet module instance
637
+ * @param {Object} wasm - Initialized WASM module
638
+ * @returns {Object} HDWalletModule API
639
+ */
640
+ function createModule(wasm) {
641
+ // ==========================================================================
642
+ // Mnemonic API
643
+ // ==========================================================================
644
+
645
+ /**
646
+ * BIP-39 Mnemonic API
647
+ * @type {Object}
648
+ */
649
+ const mnemonic = {
650
+ /**
651
+ * Generate a random mnemonic phrase
652
+ * @param {number} [wordCount=24] - Number of words (12, 15, 18, 21, or 24)
653
+ * @param {number} [language=Language.ENGLISH] - Wordlist language
654
+ * @returns {string} Mnemonic phrase
655
+ * @throws {HDWalletError} If entropy not available
656
+ */
657
+ generate(wordCount = 24, language = Language.ENGLISH) {
658
+ const ptr = wasm._hd_alloc(1024);
659
+ try {
660
+ const result = wasm._hd_mnemonic_generate(ptr, 1024, wordCount, language);
661
+ checkResult(result);
662
+ return readString(wasm, ptr);
663
+ } finally {
664
+ wasm._hd_dealloc(ptr);
665
+ }
666
+ },
667
+
668
+ /**
669
+ * Validate a mnemonic phrase
670
+ * @param {string} mnemonicStr - Mnemonic phrase to validate
671
+ * @param {number} [language=Language.ENGLISH] - Wordlist language
672
+ * @returns {boolean} True if valid
673
+ */
674
+ validate(mnemonicStr, language = Language.ENGLISH) {
675
+ const ptr = allocString(wasm, mnemonicStr);
676
+ try {
677
+ const result = wasm._hd_mnemonic_validate(ptr, language);
678
+ return result === 0;
679
+ } finally {
680
+ wasm._hd_dealloc(ptr);
681
+ }
682
+ },
683
+
684
+ /**
685
+ * Convert mnemonic to 64-byte seed
686
+ * @param {string} mnemonicStr - Mnemonic phrase
687
+ * @param {string} [passphrase=''] - Optional passphrase
688
+ * @returns {Uint8Array} 64-byte seed
689
+ */
690
+ toSeed(mnemonicStr, passphrase = '') {
691
+ const mnemonicPtr = allocString(wasm, mnemonicStr);
692
+ const passphrasePtr = allocString(wasm, passphrase);
693
+ const seedPtr = wasm._hd_alloc(64);
694
+ try {
695
+ const result = wasm._hd_mnemonic_to_seed(mnemonicPtr, passphrasePtr, seedPtr, 64);
696
+ checkResult(result);
697
+ return readBytes(wasm, seedPtr, 64);
698
+ } finally {
699
+ wasm._hd_secure_wipe(seedPtr, 64);
700
+ wasm._hd_dealloc(mnemonicPtr);
701
+ wasm._hd_dealloc(passphrasePtr);
702
+ wasm._hd_dealloc(seedPtr);
703
+ }
704
+ },
705
+
706
+ /**
707
+ * Convert mnemonic to entropy bytes
708
+ * @param {string} mnemonicStr - Mnemonic phrase
709
+ * @param {number} [language=Language.ENGLISH] - Wordlist language
710
+ * @returns {Uint8Array} Entropy bytes
711
+ */
712
+ toEntropy(mnemonicStr, language = Language.ENGLISH) {
713
+ const mnemonicPtr = allocString(wasm, mnemonicStr);
714
+ const entropyPtr = wasm._hd_alloc(33);
715
+ const sizePtr = wasm._hd_alloc(4);
716
+ try {
717
+ wasm.setValue(sizePtr, 33, 'i32');
718
+ const result = wasm._hd_mnemonic_to_entropy(mnemonicPtr, language, entropyPtr, sizePtr);
719
+ checkResult(result);
720
+ const size = wasm.getValue(sizePtr, 'i32');
721
+ return readBytes(wasm, entropyPtr, size);
722
+ } finally {
723
+ wasm._hd_dealloc(mnemonicPtr);
724
+ wasm._hd_dealloc(entropyPtr);
725
+ wasm._hd_dealloc(sizePtr);
726
+ }
727
+ },
728
+
729
+ /**
730
+ * Convert entropy to mnemonic
731
+ * @param {Uint8Array} entropy - Entropy bytes (16, 20, 24, 28, or 32 bytes)
732
+ * @param {number} [language=Language.ENGLISH] - Wordlist language
733
+ * @returns {string} Mnemonic phrase
734
+ */
735
+ fromEntropy(entropy, language = Language.ENGLISH) {
736
+ const entropyPtr = allocAndCopy(wasm, entropy);
737
+ const outputPtr = wasm._hd_alloc(1024);
738
+ try {
739
+ const result = wasm._hd_entropy_to_mnemonic(entropyPtr, entropy.length, language, outputPtr, 1024);
740
+ checkResult(result);
741
+ return readString(wasm, outputPtr);
742
+ } finally {
743
+ wasm._hd_dealloc(entropyPtr);
744
+ wasm._hd_dealloc(outputPtr);
745
+ }
746
+ },
747
+
748
+ /**
749
+ * Get wordlist for language
750
+ * @param {number} [language=Language.ENGLISH] - Wordlist language
751
+ * @returns {string[]} Array of 2048 words
752
+ */
753
+ getWordlist(language = Language.ENGLISH) {
754
+ const ptr = wasm._hd_mnemonic_get_wordlist(language);
755
+ const json = readString(wasm, ptr);
756
+ return JSON.parse(json);
757
+ },
758
+
759
+ /**
760
+ * Get word suggestions for autocomplete
761
+ * @param {string} prefix - Word prefix
762
+ * @param {number} [language=Language.ENGLISH] - Wordlist language
763
+ * @param {number} [maxSuggestions=5] - Maximum suggestions
764
+ * @returns {string[]} Suggested words
765
+ */
766
+ suggestWords(prefix, language = Language.ENGLISH, maxSuggestions = 5) {
767
+ const prefixPtr = allocString(wasm, prefix);
768
+ const outputPtr = wasm._hd_alloc(1024);
769
+ try {
770
+ wasm._hd_mnemonic_suggest_word(prefixPtr, language, outputPtr, 1024, maxSuggestions);
771
+ const json = readString(wasm, outputPtr);
772
+ return JSON.parse(json);
773
+ } finally {
774
+ wasm._hd_dealloc(prefixPtr);
775
+ wasm._hd_dealloc(outputPtr);
776
+ }
777
+ },
778
+
779
+ /**
780
+ * Check if word is in wordlist
781
+ * @param {string} word - Word to check
782
+ * @param {number} [language=Language.ENGLISH] - Wordlist language
783
+ * @returns {boolean} True if word is in wordlist
784
+ */
785
+ checkWord(word, language = Language.ENGLISH) {
786
+ const wordPtr = allocString(wasm, word);
787
+ try {
788
+ const result = wasm._hd_mnemonic_check_word(wordPtr, language);
789
+ return result >= 0;
790
+ } finally {
791
+ wasm._hd_dealloc(wordPtr);
792
+ }
793
+ }
794
+ };
795
+
796
+ // ==========================================================================
797
+ // HDKey API
798
+ // ==========================================================================
799
+
800
+ /**
801
+ * BIP-32 HD Key API
802
+ * @type {Object}
803
+ */
804
+ const hdkey = {
805
+ /**
806
+ * Create master key from seed
807
+ * @param {Uint8Array} seed - 64-byte seed
808
+ * @param {number} [curve=Curve.SECP256K1] - Elliptic curve
809
+ * @returns {HDKey} Master HD key
810
+ */
811
+ fromSeed(seed, curve = Curve.SECP256K1) {
812
+ if (seed.length !== 64) {
813
+ throw new HDWalletError(ErrorCode.INVALID_SEED, 'Seed must be 64 bytes');
814
+ }
815
+ const seedPtr = allocAndCopy(wasm, seed);
816
+ try {
817
+ const handle = wasm._hd_key_from_seed(seedPtr, 64, curve);
818
+ if (!handle) {
819
+ throw new HDWalletError(ErrorCode.INVALID_SEED);
820
+ }
821
+ return new HDKey(wasm, handle, 'm');
822
+ } finally {
823
+ wasm._hd_secure_wipe(seedPtr, 64);
824
+ wasm._hd_dealloc(seedPtr);
825
+ }
826
+ },
827
+
828
+ /**
829
+ * Parse extended private key
830
+ * @param {string} xprv - Base58Check-encoded xprv
831
+ * @returns {HDKey} HD key
832
+ */
833
+ fromXprv(xprv) {
834
+ const xprvPtr = allocString(wasm, xprv);
835
+ try {
836
+ const handle = wasm._hd_key_from_xprv(xprvPtr);
837
+ if (!handle) {
838
+ throw new HDWalletError(ErrorCode.INVALID_EXTENDED_KEY);
839
+ }
840
+ return new HDKey(wasm, handle);
841
+ } finally {
842
+ wasm._hd_dealloc(xprvPtr);
843
+ }
844
+ },
845
+
846
+ /**
847
+ * Parse extended public key
848
+ * @param {string} xpub - Base58Check-encoded xpub
849
+ * @returns {HDKey} HD key (neutered)
850
+ */
851
+ fromXpub(xpub) {
852
+ const xpubPtr = allocString(wasm, xpub);
853
+ try {
854
+ const handle = wasm._hd_key_from_xpub(xpubPtr);
855
+ if (!handle) {
856
+ throw new HDWalletError(ErrorCode.INVALID_EXTENDED_KEY);
857
+ }
858
+ return new HDKey(wasm, handle);
859
+ } finally {
860
+ wasm._hd_dealloc(xpubPtr);
861
+ }
862
+ },
863
+
864
+ /**
865
+ * Build BIP-44 path
866
+ * @param {number} purpose - Purpose (44, 49, 84)
867
+ * @param {number} coinType - SLIP-44 coin type
868
+ * @param {number} [account=0] - Account index
869
+ * @param {number} [change=0] - Change (0=external, 1=internal)
870
+ * @param {number} [index=0] - Address index
871
+ * @returns {string} Derivation path
872
+ */
873
+ buildPath(purpose, coinType, account = 0, change = 0, index = 0) {
874
+ const ptr = wasm._hd_alloc(128);
875
+ try {
876
+ const result = wasm._hd_path_build(ptr, 128, purpose, coinType, account, change, index);
877
+ checkResult(result);
878
+ return readString(wasm, ptr);
879
+ } finally {
880
+ wasm._hd_dealloc(ptr);
881
+ }
882
+ },
883
+
884
+ /**
885
+ * Parse BIP-44 path
886
+ * @param {string} path - Derivation path
887
+ * @returns {Object} Parsed path components
888
+ */
889
+ parsePath(path) {
890
+ const pathPtr = allocString(wasm, path);
891
+ const purposePtr = wasm._hd_alloc(4);
892
+ const coinTypePtr = wasm._hd_alloc(4);
893
+ const accountPtr = wasm._hd_alloc(4);
894
+ const changePtr = wasm._hd_alloc(4);
895
+ const indexPtr = wasm._hd_alloc(4);
896
+ try {
897
+ const result = wasm._hd_path_parse(pathPtr, purposePtr, coinTypePtr, accountPtr, changePtr, indexPtr);
898
+ checkResult(result);
899
+ return {
900
+ purpose: wasm.getValue(purposePtr, 'i32'),
901
+ coinType: wasm.getValue(coinTypePtr, 'i32'),
902
+ account: wasm.getValue(accountPtr, 'i32'),
903
+ change: wasm.getValue(changePtr, 'i32'),
904
+ index: wasm.getValue(indexPtr, 'i32')
905
+ };
906
+ } finally {
907
+ wasm._hd_dealloc(pathPtr);
908
+ wasm._hd_dealloc(purposePtr);
909
+ wasm._hd_dealloc(coinTypePtr);
910
+ wasm._hd_dealloc(accountPtr);
911
+ wasm._hd_dealloc(changePtr);
912
+ wasm._hd_dealloc(indexPtr);
913
+ }
914
+ }
915
+ };
916
+
917
+ // ==========================================================================
918
+ // Curves API
919
+ // ==========================================================================
920
+
921
+ /**
922
+ * Multi-curve cryptography API
923
+ * @type {Object}
924
+ */
925
+ const curves = {
926
+ /**
927
+ * Derive public key from private key
928
+ * @param {Uint8Array} privateKey - Private key bytes
929
+ * @param {number} curve - Curve type
930
+ * @returns {Uint8Array} Compressed public key
931
+ */
932
+ publicKeyFromPrivate(privateKey, curve) {
933
+ const privPtr = allocAndCopy(wasm, privateKey);
934
+ const pubPtr = wasm._hd_alloc(65);
935
+ try {
936
+ const result = wasm._hd_curve_pubkey_from_privkey(privPtr, curve, pubPtr, 65);
937
+ checkResult(result);
938
+ return readBytes(wasm, pubPtr, 33);
939
+ } finally {
940
+ wasm._hd_secure_wipe(privPtr, privateKey.length);
941
+ wasm._hd_dealloc(privPtr);
942
+ wasm._hd_dealloc(pubPtr);
943
+ }
944
+ },
945
+
946
+ /**
947
+ * Compress public key
948
+ * @param {Uint8Array} publicKey - Uncompressed public key (65 bytes)
949
+ * @param {number} curve - Curve type
950
+ * @returns {Uint8Array} Compressed public key (33 bytes)
951
+ */
952
+ compressPublicKey(publicKey, curve) {
953
+ const inPtr = allocAndCopy(wasm, publicKey);
954
+ const outPtr = wasm._hd_alloc(33);
955
+ try {
956
+ const result = wasm._hd_curve_compress_pubkey(inPtr, curve, outPtr, 33);
957
+ checkResult(result);
958
+ return readBytes(wasm, outPtr, 33);
959
+ } finally {
960
+ wasm._hd_dealloc(inPtr);
961
+ wasm._hd_dealloc(outPtr);
962
+ }
963
+ },
964
+
965
+ /**
966
+ * Decompress public key
967
+ * @param {Uint8Array} publicKey - Compressed public key (33 bytes)
968
+ * @param {number} curve - Curve type
969
+ * @returns {Uint8Array} Uncompressed public key (65 bytes)
970
+ */
971
+ decompressPublicKey(publicKey, curve) {
972
+ const inPtr = allocAndCopy(wasm, publicKey);
973
+ const outPtr = wasm._hd_alloc(65);
974
+ try {
975
+ const result = wasm._hd_curve_decompress_pubkey(inPtr, curve, outPtr, 65);
976
+ checkResult(result);
977
+ return readBytes(wasm, outPtr, 65);
978
+ } finally {
979
+ wasm._hd_dealloc(inPtr);
980
+ wasm._hd_dealloc(outPtr);
981
+ }
982
+ },
983
+
984
+ /**
985
+ * secp256k1 ECDSA operations
986
+ */
987
+ secp256k1: {
988
+ /**
989
+ * Sign message with secp256k1
990
+ * @param {Uint8Array} message - Message to sign (typically 32-byte hash)
991
+ * @param {Uint8Array} privateKey - 32-byte private key
992
+ * @returns {Uint8Array} Signature
993
+ */
994
+ sign(message, privateKey) {
995
+ const msgPtr = allocAndCopy(wasm, message);
996
+ const keyPtr = allocAndCopy(wasm, privateKey);
997
+ const sigPtr = wasm._hd_alloc(72);
998
+ try {
999
+ const len = wasm._hd_secp256k1_sign(msgPtr, message.length, keyPtr, sigPtr, 72);
1000
+ if (len < 0) throw new HDWalletError(len);
1001
+ return readBytes(wasm, sigPtr, len);
1002
+ } finally {
1003
+ wasm._hd_secure_wipe(keyPtr, 32);
1004
+ wasm._hd_dealloc(msgPtr);
1005
+ wasm._hd_dealloc(keyPtr);
1006
+ wasm._hd_dealloc(sigPtr);
1007
+ }
1008
+ },
1009
+
1010
+ /**
1011
+ * Sign message with recovery ID
1012
+ * @param {Uint8Array} message - Message to sign
1013
+ * @param {Uint8Array} privateKey - Private key
1014
+ * @returns {Object} { signature: Uint8Array, recoveryId: number }
1015
+ */
1016
+ signRecoverable(message, privateKey) {
1017
+ const msgPtr = allocAndCopy(wasm, message);
1018
+ const keyPtr = allocAndCopy(wasm, privateKey);
1019
+ const sigPtr = wasm._hd_alloc(65);
1020
+ try {
1021
+ const recoveryId = wasm._hd_secp256k1_sign_recoverable(msgPtr, message.length, keyPtr, sigPtr, 65);
1022
+ if (recoveryId < 0) throw new HDWalletError(recoveryId);
1023
+ return {
1024
+ signature: readBytes(wasm, sigPtr, 64),
1025
+ recoveryId
1026
+ };
1027
+ } finally {
1028
+ wasm._hd_secure_wipe(keyPtr, 32);
1029
+ wasm._hd_dealloc(msgPtr);
1030
+ wasm._hd_dealloc(keyPtr);
1031
+ wasm._hd_dealloc(sigPtr);
1032
+ }
1033
+ },
1034
+
1035
+ /**
1036
+ * Verify secp256k1 signature
1037
+ * @param {Uint8Array} message - Original message
1038
+ * @param {Uint8Array} signature - Signature to verify
1039
+ * @param {Uint8Array} publicKey - Public key
1040
+ * @returns {boolean} True if valid
1041
+ */
1042
+ verify(message, signature, publicKey) {
1043
+ const msgPtr = allocAndCopy(wasm, message);
1044
+ const sigPtr = allocAndCopy(wasm, signature);
1045
+ const pubPtr = allocAndCopy(wasm, publicKey);
1046
+ try {
1047
+ const result = wasm._hd_secp256k1_verify(msgPtr, message.length, sigPtr, signature.length, pubPtr, publicKey.length);
1048
+ return result === 1;
1049
+ } finally {
1050
+ wasm._hd_dealloc(msgPtr);
1051
+ wasm._hd_dealloc(sigPtr);
1052
+ wasm._hd_dealloc(pubPtr);
1053
+ }
1054
+ },
1055
+
1056
+ /**
1057
+ * Recover public key from signature
1058
+ * @param {Uint8Array} message - Original message
1059
+ * @param {Uint8Array} signature - Signature
1060
+ * @param {number} recoveryId - Recovery ID (0-3)
1061
+ * @returns {Uint8Array} Recovered public key
1062
+ */
1063
+ recover(message, signature, recoveryId) {
1064
+ const msgPtr = allocAndCopy(wasm, message);
1065
+ const sigPtr = allocAndCopy(wasm, signature);
1066
+ const pubPtr = wasm._hd_alloc(65);
1067
+ try {
1068
+ const result = wasm._hd_secp256k1_recover(msgPtr, message.length, sigPtr, signature.length, recoveryId, pubPtr, 65);
1069
+ checkResult(result);
1070
+ return readBytes(wasm, pubPtr, 65);
1071
+ } finally {
1072
+ wasm._hd_dealloc(msgPtr);
1073
+ wasm._hd_dealloc(sigPtr);
1074
+ wasm._hd_dealloc(pubPtr);
1075
+ }
1076
+ },
1077
+
1078
+ /**
1079
+ * ECDH shared secret
1080
+ * @param {Uint8Array} privateKey - Own private key
1081
+ * @param {Uint8Array} publicKey - Other party's public key
1082
+ * @returns {Uint8Array} Shared secret
1083
+ */
1084
+ ecdh(privateKey, publicKey) {
1085
+ const privPtr = allocAndCopy(wasm, privateKey);
1086
+ const pubPtr = allocAndCopy(wasm, publicKey);
1087
+ const secretPtr = wasm._hd_alloc(32);
1088
+ try {
1089
+ const result = wasm._hd_ecdh_secp256k1(privPtr, pubPtr, publicKey.length, secretPtr, 32);
1090
+ if (result < 0) throw new HDWalletError(result);
1091
+ return readBytes(wasm, secretPtr, 32);
1092
+ } finally {
1093
+ wasm._hd_secure_wipe(privPtr, 32);
1094
+ wasm._hd_secure_wipe(secretPtr, 32);
1095
+ wasm._hd_dealloc(privPtr);
1096
+ wasm._hd_dealloc(pubPtr);
1097
+ wasm._hd_dealloc(secretPtr);
1098
+ }
1099
+ }
1100
+ },
1101
+
1102
+ /**
1103
+ * Ed25519 EdDSA operations
1104
+ */
1105
+ ed25519: {
1106
+ /**
1107
+ * Sign message with Ed25519
1108
+ * @param {Uint8Array} message - Message to sign
1109
+ * @param {Uint8Array} privateKey - 32-byte private key
1110
+ * @returns {Uint8Array} 64-byte signature
1111
+ */
1112
+ sign(message, privateKey) {
1113
+ const msgPtr = allocAndCopy(wasm, message);
1114
+ const keyPtr = allocAndCopy(wasm, privateKey);
1115
+ const sigPtr = wasm._hd_alloc(64);
1116
+ try {
1117
+ const len = wasm._hd_ed25519_sign(msgPtr, message.length, keyPtr, sigPtr, 64);
1118
+ if (len < 0) throw new HDWalletError(len);
1119
+ return readBytes(wasm, sigPtr, 64);
1120
+ } finally {
1121
+ wasm._hd_secure_wipe(keyPtr, 32);
1122
+ wasm._hd_dealloc(msgPtr);
1123
+ wasm._hd_dealloc(keyPtr);
1124
+ wasm._hd_dealloc(sigPtr);
1125
+ }
1126
+ },
1127
+
1128
+ /**
1129
+ * Verify Ed25519 signature
1130
+ * @param {Uint8Array} message - Original message
1131
+ * @param {Uint8Array} signature - 64-byte signature
1132
+ * @param {Uint8Array} publicKey - 32-byte public key
1133
+ * @returns {boolean} True if valid
1134
+ */
1135
+ verify(message, signature, publicKey) {
1136
+ const msgPtr = allocAndCopy(wasm, message);
1137
+ const sigPtr = allocAndCopy(wasm, signature);
1138
+ const pubPtr = allocAndCopy(wasm, publicKey);
1139
+ try {
1140
+ const result = wasm._hd_ed25519_verify(msgPtr, message.length, sigPtr, signature.length, pubPtr, publicKey.length);
1141
+ return result === 1;
1142
+ } finally {
1143
+ wasm._hd_dealloc(msgPtr);
1144
+ wasm._hd_dealloc(sigPtr);
1145
+ wasm._hd_dealloc(pubPtr);
1146
+ }
1147
+ }
1148
+ },
1149
+
1150
+ /**
1151
+ * P-256 (secp256r1) ECDSA operations
1152
+ */
1153
+ p256: {
1154
+ sign(message, privateKey) {
1155
+ const msgPtr = allocAndCopy(wasm, message);
1156
+ const keyPtr = allocAndCopy(wasm, privateKey);
1157
+ const sigPtr = wasm._hd_alloc(72);
1158
+ try {
1159
+ const len = wasm._hd_p256_sign(msgPtr, message.length, keyPtr, sigPtr, 72);
1160
+ if (len < 0) throw new HDWalletError(len);
1161
+ return readBytes(wasm, sigPtr, len);
1162
+ } finally {
1163
+ wasm._hd_secure_wipe(keyPtr, 32);
1164
+ wasm._hd_dealloc(msgPtr);
1165
+ wasm._hd_dealloc(keyPtr);
1166
+ wasm._hd_dealloc(sigPtr);
1167
+ }
1168
+ },
1169
+
1170
+ verify(message, signature, publicKey) {
1171
+ const msgPtr = allocAndCopy(wasm, message);
1172
+ const sigPtr = allocAndCopy(wasm, signature);
1173
+ const pubPtr = allocAndCopy(wasm, publicKey);
1174
+ try {
1175
+ const result = wasm._hd_p256_verify(msgPtr, message.length, sigPtr, signature.length, pubPtr, publicKey.length);
1176
+ return result === 1;
1177
+ } finally {
1178
+ wasm._hd_dealloc(msgPtr);
1179
+ wasm._hd_dealloc(sigPtr);
1180
+ wasm._hd_dealloc(pubPtr);
1181
+ }
1182
+ },
1183
+
1184
+ ecdh(privateKey, publicKey) {
1185
+ const privPtr = allocAndCopy(wasm, privateKey);
1186
+ const pubPtr = allocAndCopy(wasm, publicKey);
1187
+ const secretPtr = wasm._hd_alloc(32);
1188
+ try {
1189
+ const result = wasm._hd_ecdh_p256(privPtr, pubPtr, publicKey.length, secretPtr, 32);
1190
+ if (result < 0) throw new HDWalletError(result);
1191
+ return readBytes(wasm, secretPtr, 32);
1192
+ } finally {
1193
+ wasm._hd_secure_wipe(privPtr, 32);
1194
+ wasm._hd_secure_wipe(secretPtr, 32);
1195
+ wasm._hd_dealloc(privPtr);
1196
+ wasm._hd_dealloc(pubPtr);
1197
+ wasm._hd_dealloc(secretPtr);
1198
+ }
1199
+ }
1200
+ },
1201
+
1202
+ /**
1203
+ * P-384 (secp384r1) ECDSA operations
1204
+ */
1205
+ p384: {
1206
+ sign(message, privateKey) {
1207
+ const msgPtr = allocAndCopy(wasm, message);
1208
+ const keyPtr = allocAndCopy(wasm, privateKey);
1209
+ const sigPtr = wasm._hd_alloc(104);
1210
+ try {
1211
+ const len = wasm._hd_p384_sign(msgPtr, message.length, keyPtr, sigPtr, 104);
1212
+ if (len < 0) throw new HDWalletError(len);
1213
+ return readBytes(wasm, sigPtr, len);
1214
+ } finally {
1215
+ wasm._hd_secure_wipe(keyPtr, 48);
1216
+ wasm._hd_dealloc(msgPtr);
1217
+ wasm._hd_dealloc(keyPtr);
1218
+ wasm._hd_dealloc(sigPtr);
1219
+ }
1220
+ },
1221
+
1222
+ verify(message, signature, publicKey) {
1223
+ const msgPtr = allocAndCopy(wasm, message);
1224
+ const sigPtr = allocAndCopy(wasm, signature);
1225
+ const pubPtr = allocAndCopy(wasm, publicKey);
1226
+ try {
1227
+ const result = wasm._hd_p384_verify(msgPtr, message.length, sigPtr, signature.length, pubPtr, publicKey.length);
1228
+ return result === 1;
1229
+ } finally {
1230
+ wasm._hd_dealloc(msgPtr);
1231
+ wasm._hd_dealloc(sigPtr);
1232
+ wasm._hd_dealloc(pubPtr);
1233
+ }
1234
+ },
1235
+
1236
+ ecdh(privateKey, publicKey) {
1237
+ const privPtr = allocAndCopy(wasm, privateKey);
1238
+ const pubPtr = allocAndCopy(wasm, publicKey);
1239
+ const secretPtr = wasm._hd_alloc(48);
1240
+ try {
1241
+ const result = wasm._hd_ecdh_p384(privPtr, pubPtr, publicKey.length, secretPtr, 48);
1242
+ if (result < 0) throw new HDWalletError(result);
1243
+ return readBytes(wasm, secretPtr, 48);
1244
+ } finally {
1245
+ wasm._hd_secure_wipe(privPtr, 48);
1246
+ wasm._hd_secure_wipe(secretPtr, 48);
1247
+ wasm._hd_dealloc(privPtr);
1248
+ wasm._hd_dealloc(pubPtr);
1249
+ wasm._hd_dealloc(secretPtr);
1250
+ }
1251
+ }
1252
+ },
1253
+
1254
+ /**
1255
+ * X25519 key exchange
1256
+ */
1257
+ x25519: {
1258
+ ecdh(privateKey, publicKey) {
1259
+ const privPtr = allocAndCopy(wasm, privateKey);
1260
+ const pubPtr = allocAndCopy(wasm, publicKey);
1261
+ const secretPtr = wasm._hd_alloc(32);
1262
+ try {
1263
+ const result = wasm._hd_ecdh_x25519(privPtr, pubPtr, secretPtr, 32);
1264
+ if (result < 0) throw new HDWalletError(result);
1265
+ return readBytes(wasm, secretPtr, 32);
1266
+ } finally {
1267
+ wasm._hd_secure_wipe(privPtr, 32);
1268
+ wasm._hd_secure_wipe(secretPtr, 32);
1269
+ wasm._hd_dealloc(privPtr);
1270
+ wasm._hd_dealloc(pubPtr);
1271
+ wasm._hd_dealloc(secretPtr);
1272
+ }
1273
+ }
1274
+ }
1275
+ };
1276
+
1277
+ // ==========================================================================
1278
+ // Bitcoin API
1279
+ // ==========================================================================
1280
+
1281
+ /**
1282
+ * Bitcoin API
1283
+ * @type {Object}
1284
+ */
1285
+ const bitcoin = {
1286
+ /**
1287
+ * Get Bitcoin address from public key
1288
+ * @param {Uint8Array} publicKey - Public key
1289
+ * @param {number} type - Address type (P2PKH, P2SH, P2WPKH, P2WSH, P2TR)
1290
+ * @param {number} [network=Network.MAINNET] - Network
1291
+ * @returns {string} Bitcoin address
1292
+ */
1293
+ getAddress(publicKey, type, network = Network.MAINNET) {
1294
+ const pubPtr = allocAndCopy(wasm, publicKey);
1295
+ const outPtr = wasm._hd_alloc(128);
1296
+ try {
1297
+ let result;
1298
+ switch (type) {
1299
+ case BitcoinAddressType.P2PKH:
1300
+ result = wasm._hd_btc_get_address_p2pkh(pubPtr, publicKey.length, network, outPtr, 128);
1301
+ break;
1302
+ case BitcoinAddressType.P2SH:
1303
+ result = wasm._hd_btc_get_address_p2sh(pubPtr, publicKey.length, network, outPtr, 128);
1304
+ break;
1305
+ case BitcoinAddressType.P2WPKH:
1306
+ result = wasm._hd_btc_get_address_p2wpkh(pubPtr, publicKey.length, network, outPtr, 128);
1307
+ break;
1308
+ case BitcoinAddressType.P2WSH:
1309
+ result = wasm._hd_btc_get_address_p2wsh(pubPtr, publicKey.length, network, outPtr, 128);
1310
+ break;
1311
+ case BitcoinAddressType.P2TR:
1312
+ result = wasm._hd_btc_get_address_taproot(pubPtr, publicKey.length, network, outPtr, 128);
1313
+ break;
1314
+ default:
1315
+ throw new HDWalletError(ErrorCode.INVALID_ARGUMENT, 'Invalid address type');
1316
+ }
1317
+ checkResult(result);
1318
+ return readString(wasm, outPtr);
1319
+ } finally {
1320
+ wasm._hd_dealloc(pubPtr);
1321
+ wasm._hd_dealloc(outPtr);
1322
+ }
1323
+ },
1324
+
1325
+ /**
1326
+ * Validate Bitcoin address
1327
+ * @param {string} address - Address to validate
1328
+ * @returns {boolean} True if valid
1329
+ */
1330
+ validateAddress(address) {
1331
+ const addrPtr = allocString(wasm, address);
1332
+ try {
1333
+ const result = wasm._hd_btc_validate_address(addrPtr);
1334
+ return result === 0;
1335
+ } finally {
1336
+ wasm._hd_dealloc(addrPtr);
1337
+ }
1338
+ },
1339
+
1340
+ /**
1341
+ * Decode Bitcoin address
1342
+ * @param {string} address - Address to decode
1343
+ * @returns {Object} { type, hash, network }
1344
+ */
1345
+ decodeAddress(address) {
1346
+ const addrPtr = allocString(wasm, address);
1347
+ const typePtr = wasm._hd_alloc(4);
1348
+ const hashPtr = wasm._hd_alloc(32);
1349
+ const hashLenPtr = wasm._hd_alloc(4);
1350
+ const networkPtr = wasm._hd_alloc(4);
1351
+ try {
1352
+ wasm.setValue(hashLenPtr, 32, 'i32');
1353
+ const result = wasm._hd_btc_decode_address(addrPtr, typePtr, hashPtr, hashLenPtr, networkPtr);
1354
+ checkResult(result);
1355
+ const hashLen = wasm.getValue(hashLenPtr, 'i32');
1356
+ return {
1357
+ type: wasm.getValue(typePtr, 'i32'),
1358
+ hash: readBytes(wasm, hashPtr, hashLen),
1359
+ network: wasm.getValue(networkPtr, 'i32')
1360
+ };
1361
+ } finally {
1362
+ wasm._hd_dealloc(addrPtr);
1363
+ wasm._hd_dealloc(typePtr);
1364
+ wasm._hd_dealloc(hashPtr);
1365
+ wasm._hd_dealloc(hashLenPtr);
1366
+ wasm._hd_dealloc(networkPtr);
1367
+ }
1368
+ },
1369
+
1370
+ /**
1371
+ * Sign message (Bitcoin Signed Message format)
1372
+ * @param {string} message - Message to sign
1373
+ * @param {Uint8Array} privateKey - Private key
1374
+ * @returns {string} Base64-encoded signature
1375
+ */
1376
+ signMessage(message, privateKey) {
1377
+ const msgPtr = allocString(wasm, message);
1378
+ const keyPtr = allocAndCopy(wasm, privateKey);
1379
+ const sigPtr = wasm._hd_alloc(256);
1380
+ try {
1381
+ const result = wasm._hd_btc_sign_message(msgPtr, keyPtr, sigPtr, 256);
1382
+ checkResult(result);
1383
+ return readString(wasm, sigPtr);
1384
+ } finally {
1385
+ wasm._hd_secure_wipe(keyPtr, 32);
1386
+ wasm._hd_dealloc(msgPtr);
1387
+ wasm._hd_dealloc(keyPtr);
1388
+ wasm._hd_dealloc(sigPtr);
1389
+ }
1390
+ },
1391
+
1392
+ /**
1393
+ * Verify signed message
1394
+ * @param {string} message - Original message
1395
+ * @param {string} signature - Base64-encoded signature
1396
+ * @param {string} address - Expected address
1397
+ * @returns {boolean} True if valid
1398
+ */
1399
+ verifyMessage(message, signature, address) {
1400
+ const msgPtr = allocString(wasm, message);
1401
+ const sigPtr = allocString(wasm, signature);
1402
+ const addrPtr = allocString(wasm, address);
1403
+ try {
1404
+ const result = wasm._hd_btc_verify_message(msgPtr, sigPtr, addrPtr);
1405
+ return result === 1;
1406
+ } finally {
1407
+ wasm._hd_dealloc(msgPtr);
1408
+ wasm._hd_dealloc(sigPtr);
1409
+ wasm._hd_dealloc(addrPtr);
1410
+ }
1411
+ },
1412
+
1413
+ /**
1414
+ * Transaction builder
1415
+ */
1416
+ tx: {
1417
+ create() {
1418
+ const handle = wasm._hd_btc_tx_create();
1419
+ if (!handle) throw new HDWalletError(ErrorCode.NOT_SUPPORTED);
1420
+
1421
+ return {
1422
+ _handle: handle,
1423
+
1424
+ addInput(txid, vout, sequence = 0xffffffff) {
1425
+ const txidPtr = allocString(wasm, txid);
1426
+ try {
1427
+ const result = wasm._hd_btc_tx_add_input(this._handle, txidPtr, vout, sequence);
1428
+ checkResult(result);
1429
+ } finally {
1430
+ wasm._hd_dealloc(txidPtr);
1431
+ }
1432
+ return this;
1433
+ },
1434
+
1435
+ addOutput(address, amount) {
1436
+ const addrPtr = allocString(wasm, address);
1437
+ try {
1438
+ const result = wasm._hd_btc_tx_add_output(this._handle, addrPtr, BigInt(amount));
1439
+ checkResult(result);
1440
+ } finally {
1441
+ wasm._hd_dealloc(addrPtr);
1442
+ }
1443
+ return this;
1444
+ },
1445
+
1446
+ sign(inputIndex, privateKey, redeemScript) {
1447
+ const keyPtr = allocAndCopy(wasm, privateKey);
1448
+ const scriptPtr = redeemScript ? allocAndCopy(wasm, redeemScript) : 0;
1449
+ try {
1450
+ const result = wasm._hd_btc_tx_sign(this._handle, inputIndex, keyPtr, scriptPtr, redeemScript?.length || 0);
1451
+ checkResult(result);
1452
+ } finally {
1453
+ wasm._hd_secure_wipe(keyPtr, 32);
1454
+ wasm._hd_dealloc(keyPtr);
1455
+ if (scriptPtr) wasm._hd_dealloc(scriptPtr);
1456
+ }
1457
+ return this;
1458
+ },
1459
+
1460
+ serialize() {
1461
+ const outPtr = wasm._hd_alloc(65536);
1462
+ const sizePtr = wasm._hd_alloc(4);
1463
+ try {
1464
+ wasm.setValue(sizePtr, 65536, 'i32');
1465
+ const result = wasm._hd_btc_tx_serialize(this._handle, outPtr, sizePtr);
1466
+ checkResult(result);
1467
+ const size = wasm.getValue(sizePtr, 'i32');
1468
+ return readBytes(wasm, outPtr, size);
1469
+ } finally {
1470
+ wasm._hd_dealloc(outPtr);
1471
+ wasm._hd_dealloc(sizePtr);
1472
+ }
1473
+ },
1474
+
1475
+ getTxid() {
1476
+ const ptr = wasm._hd_btc_tx_get_txid(this._handle);
1477
+ return readString(wasm, ptr);
1478
+ },
1479
+
1480
+ getSize() {
1481
+ return wasm._hd_btc_tx_get_size(this._handle);
1482
+ },
1483
+
1484
+ getVsize() {
1485
+ return wasm._hd_btc_tx_get_vsize(this._handle);
1486
+ },
1487
+
1488
+ destroy() {
1489
+ if (this._handle) {
1490
+ wasm._hd_btc_tx_destroy(this._handle);
1491
+ this._handle = null;
1492
+ }
1493
+ }
1494
+ };
1495
+ }
1496
+ }
1497
+ };
1498
+
1499
+ // ==========================================================================
1500
+ // Ethereum API
1501
+ // ==========================================================================
1502
+
1503
+ /**
1504
+ * Ethereum API
1505
+ * @type {Object}
1506
+ */
1507
+ const ethereum = {
1508
+ /**
1509
+ * Get Ethereum address from public key
1510
+ * @param {Uint8Array} publicKey - Uncompressed public key (65 bytes)
1511
+ * @returns {string} Ethereum address (with 0x prefix)
1512
+ */
1513
+ getAddress(publicKey) {
1514
+ const pubPtr = allocAndCopy(wasm, publicKey);
1515
+ const outPtr = wasm._hd_alloc(64);
1516
+ try {
1517
+ const result = wasm._hd_eth_get_address(pubPtr, publicKey.length, outPtr, 64);
1518
+ checkResult(result);
1519
+ return readString(wasm, outPtr);
1520
+ } finally {
1521
+ wasm._hd_dealloc(pubPtr);
1522
+ wasm._hd_dealloc(outPtr);
1523
+ }
1524
+ },
1525
+
1526
+ /**
1527
+ * Get checksummed address (EIP-55)
1528
+ * @param {string} address - Address to checksum
1529
+ * @returns {string} Checksummed address
1530
+ */
1531
+ getChecksumAddress(address) {
1532
+ const addrPtr = allocString(wasm, address);
1533
+ const outPtr = wasm._hd_alloc(64);
1534
+ try {
1535
+ const result = wasm._hd_eth_get_address_checksum(addrPtr, outPtr, 64);
1536
+ checkResult(result);
1537
+ return readString(wasm, outPtr);
1538
+ } finally {
1539
+ wasm._hd_dealloc(addrPtr);
1540
+ wasm._hd_dealloc(outPtr);
1541
+ }
1542
+ },
1543
+
1544
+ /**
1545
+ * Validate Ethereum address
1546
+ * @param {string} address - Address to validate
1547
+ * @returns {boolean} True if valid
1548
+ */
1549
+ validateAddress(address) {
1550
+ const addrPtr = allocString(wasm, address);
1551
+ try {
1552
+ const result = wasm._hd_eth_validate_address(addrPtr);
1553
+ return result === 0;
1554
+ } finally {
1555
+ wasm._hd_dealloc(addrPtr);
1556
+ }
1557
+ },
1558
+
1559
+ /**
1560
+ * Sign message (EIP-191)
1561
+ * @param {string} message - Message to sign
1562
+ * @param {Uint8Array} privateKey - Private key
1563
+ * @returns {string} Hex-encoded signature
1564
+ */
1565
+ signMessage(message, privateKey) {
1566
+ const msgPtr = allocString(wasm, message);
1567
+ const keyPtr = allocAndCopy(wasm, privateKey);
1568
+ const sigPtr = wasm._hd_alloc(256);
1569
+ try {
1570
+ const result = wasm._hd_eth_sign_message(msgPtr, keyPtr, sigPtr, 256);
1571
+ checkResult(result);
1572
+ return readString(wasm, sigPtr);
1573
+ } finally {
1574
+ wasm._hd_secure_wipe(keyPtr, 32);
1575
+ wasm._hd_dealloc(msgPtr);
1576
+ wasm._hd_dealloc(keyPtr);
1577
+ wasm._hd_dealloc(sigPtr);
1578
+ }
1579
+ },
1580
+
1581
+ /**
1582
+ * Sign typed data (EIP-712)
1583
+ * @param {Object} typedData - Typed data object
1584
+ * @param {Uint8Array} privateKey - Private key
1585
+ * @returns {string} Hex-encoded signature
1586
+ */
1587
+ signTypedData(typedData, privateKey) {
1588
+ const jsonPtr = allocString(wasm, JSON.stringify(typedData));
1589
+ const keyPtr = allocAndCopy(wasm, privateKey);
1590
+ const sigPtr = wasm._hd_alloc(256);
1591
+ try {
1592
+ const result = wasm._hd_eth_sign_typed_data(jsonPtr, keyPtr, sigPtr, 256);
1593
+ checkResult(result);
1594
+ return readString(wasm, sigPtr);
1595
+ } finally {
1596
+ wasm._hd_secure_wipe(keyPtr, 32);
1597
+ wasm._hd_dealloc(jsonPtr);
1598
+ wasm._hd_dealloc(keyPtr);
1599
+ wasm._hd_dealloc(sigPtr);
1600
+ }
1601
+ },
1602
+
1603
+ /**
1604
+ * Verify message signature and recover address
1605
+ * @param {string} message - Original message
1606
+ * @param {string} signature - Hex-encoded signature
1607
+ * @returns {string} Recovered address
1608
+ */
1609
+ verifyMessage(message, signature) {
1610
+ const msgPtr = allocString(wasm, message);
1611
+ const sigPtr = allocString(wasm, signature);
1612
+ const addrPtr = wasm._hd_alloc(64);
1613
+ try {
1614
+ const result = wasm._hd_eth_verify_message(msgPtr, sigPtr, addrPtr, 64);
1615
+ checkResult(result);
1616
+ return readString(wasm, addrPtr);
1617
+ } finally {
1618
+ wasm._hd_dealloc(msgPtr);
1619
+ wasm._hd_dealloc(sigPtr);
1620
+ wasm._hd_dealloc(addrPtr);
1621
+ }
1622
+ },
1623
+
1624
+ /**
1625
+ * Transaction builder
1626
+ */
1627
+ tx: {
1628
+ create(params) {
1629
+ // Implementation placeholder
1630
+ throw new HDWalletError(ErrorCode.NOT_SUPPORTED);
1631
+ },
1632
+
1633
+ createEIP1559(params) {
1634
+ // Implementation placeholder
1635
+ throw new HDWalletError(ErrorCode.NOT_SUPPORTED);
1636
+ }
1637
+ }
1638
+ };
1639
+
1640
+ // ==========================================================================
1641
+ // Cosmos API
1642
+ // ==========================================================================
1643
+
1644
+ /**
1645
+ * Cosmos/Tendermint API
1646
+ * @type {Object}
1647
+ */
1648
+ const cosmos = {
1649
+ getAddress(publicKey, prefix = 'cosmos') {
1650
+ const pubPtr = allocAndCopy(wasm, publicKey);
1651
+ const prefixPtr = allocString(wasm, prefix);
1652
+ const outPtr = wasm._hd_alloc(128);
1653
+ try {
1654
+ const result = wasm._hd_cosmos_get_address(pubPtr, publicKey.length, prefixPtr, outPtr, 128);
1655
+ checkResult(result);
1656
+ return readString(wasm, outPtr);
1657
+ } finally {
1658
+ wasm._hd_dealloc(pubPtr);
1659
+ wasm._hd_dealloc(prefixPtr);
1660
+ wasm._hd_dealloc(outPtr);
1661
+ }
1662
+ },
1663
+
1664
+ validateAddress(address) {
1665
+ const addrPtr = allocString(wasm, address);
1666
+ try {
1667
+ return wasm._hd_cosmos_validate_address(addrPtr) === 0;
1668
+ } finally {
1669
+ wasm._hd_dealloc(addrPtr);
1670
+ }
1671
+ },
1672
+
1673
+ signAmino(doc, privateKey) {
1674
+ const docPtr = allocString(wasm, JSON.stringify(doc));
1675
+ const keyPtr = allocAndCopy(wasm, privateKey);
1676
+ const outPtr = wasm._hd_alloc(1024);
1677
+ try {
1678
+ const result = wasm._hd_cosmos_sign_amino(docPtr, keyPtr, outPtr, 1024);
1679
+ checkResult(result);
1680
+ return JSON.parse(readString(wasm, outPtr));
1681
+ } finally {
1682
+ wasm._hd_secure_wipe(keyPtr, 32);
1683
+ wasm._hd_dealloc(docPtr);
1684
+ wasm._hd_dealloc(keyPtr);
1685
+ wasm._hd_dealloc(outPtr);
1686
+ }
1687
+ },
1688
+
1689
+ signDirect(bodyBytes, authInfoBytes, chainId, accountNumber, privateKey) {
1690
+ const bodyPtr = allocAndCopy(wasm, bodyBytes);
1691
+ const authPtr = allocAndCopy(wasm, authInfoBytes);
1692
+ const chainPtr = allocString(wasm, chainId);
1693
+ const keyPtr = allocAndCopy(wasm, privateKey);
1694
+ const outPtr = wasm._hd_alloc(1024);
1695
+ try {
1696
+ const result = wasm._hd_cosmos_sign_direct(
1697
+ bodyPtr, bodyBytes.length,
1698
+ authPtr, authInfoBytes.length,
1699
+ chainPtr, BigInt(accountNumber),
1700
+ keyPtr, outPtr, 1024
1701
+ );
1702
+ checkResult(result);
1703
+ return JSON.parse(readString(wasm, outPtr));
1704
+ } finally {
1705
+ wasm._hd_secure_wipe(keyPtr, 32);
1706
+ wasm._hd_dealloc(bodyPtr);
1707
+ wasm._hd_dealloc(authPtr);
1708
+ wasm._hd_dealloc(chainPtr);
1709
+ wasm._hd_dealloc(keyPtr);
1710
+ wasm._hd_dealloc(outPtr);
1711
+ }
1712
+ },
1713
+
1714
+ verify(signature, message, publicKey) {
1715
+ const sigPtr = allocAndCopy(wasm, signature);
1716
+ const msgPtr = allocAndCopy(wasm, message);
1717
+ const pubPtr = allocAndCopy(wasm, publicKey);
1718
+ try {
1719
+ return wasm._hd_cosmos_verify(sigPtr, signature.length, msgPtr, message.length, pubPtr, publicKey.length) === 1;
1720
+ } finally {
1721
+ wasm._hd_dealloc(sigPtr);
1722
+ wasm._hd_dealloc(msgPtr);
1723
+ wasm._hd_dealloc(pubPtr);
1724
+ }
1725
+ }
1726
+ };
1727
+
1728
+ // ==========================================================================
1729
+ // Solana API
1730
+ // ==========================================================================
1731
+
1732
+ /**
1733
+ * Solana API
1734
+ * @type {Object}
1735
+ */
1736
+ const solana = {
1737
+ getAddress(publicKey) {
1738
+ const pubPtr = allocAndCopy(wasm, publicKey);
1739
+ const outPtr = wasm._hd_alloc(64);
1740
+ try {
1741
+ const result = wasm._hd_sol_get_address(pubPtr, publicKey.length, outPtr, 64);
1742
+ checkResult(result);
1743
+ return readString(wasm, outPtr);
1744
+ } finally {
1745
+ wasm._hd_dealloc(pubPtr);
1746
+ wasm._hd_dealloc(outPtr);
1747
+ }
1748
+ },
1749
+
1750
+ validateAddress(address) {
1751
+ const addrPtr = allocString(wasm, address);
1752
+ try {
1753
+ return wasm._hd_sol_validate_address(addrPtr) === 0;
1754
+ } finally {
1755
+ wasm._hd_dealloc(addrPtr);
1756
+ }
1757
+ },
1758
+
1759
+ signMessage(message, privateKey) {
1760
+ const msgPtr = allocAndCopy(wasm, message);
1761
+ const keyPtr = allocAndCopy(wasm, privateKey);
1762
+ const sigPtr = wasm._hd_alloc(64);
1763
+ try {
1764
+ const result = wasm._hd_sol_sign_message(msgPtr, message.length, keyPtr, sigPtr, 64);
1765
+ checkResult(result);
1766
+ return readBytes(wasm, sigPtr, 64);
1767
+ } finally {
1768
+ wasm._hd_secure_wipe(keyPtr, 32);
1769
+ wasm._hd_dealloc(msgPtr);
1770
+ wasm._hd_dealloc(keyPtr);
1771
+ wasm._hd_dealloc(sigPtr);
1772
+ }
1773
+ },
1774
+
1775
+ verifyMessage(message, signature, publicKey) {
1776
+ const msgPtr = allocAndCopy(wasm, message);
1777
+ const sigPtr = allocAndCopy(wasm, signature);
1778
+ const pubPtr = allocAndCopy(wasm, publicKey);
1779
+ try {
1780
+ return wasm._hd_sol_verify_message(msgPtr, message.length, sigPtr, signature.length, pubPtr, publicKey.length) === 1;
1781
+ } finally {
1782
+ wasm._hd_dealloc(msgPtr);
1783
+ wasm._hd_dealloc(sigPtr);
1784
+ wasm._hd_dealloc(pubPtr);
1785
+ }
1786
+ }
1787
+ };
1788
+
1789
+ // ==========================================================================
1790
+ // Polkadot API
1791
+ // ==========================================================================
1792
+
1793
+ /**
1794
+ * Polkadot/Substrate API
1795
+ * @type {Object}
1796
+ */
1797
+ const polkadot = {
1798
+ getAddress(publicKey, ss58Prefix = 0) {
1799
+ const pubPtr = allocAndCopy(wasm, publicKey);
1800
+ const outPtr = wasm._hd_alloc(64);
1801
+ try {
1802
+ const result = wasm._hd_dot_get_address(pubPtr, publicKey.length, ss58Prefix, outPtr, 64);
1803
+ checkResult(result);
1804
+ return readString(wasm, outPtr);
1805
+ } finally {
1806
+ wasm._hd_dealloc(pubPtr);
1807
+ wasm._hd_dealloc(outPtr);
1808
+ }
1809
+ },
1810
+
1811
+ validateAddress(address) {
1812
+ const addrPtr = allocString(wasm, address);
1813
+ try {
1814
+ return wasm._hd_dot_validate_address(addrPtr) === 0;
1815
+ } finally {
1816
+ wasm._hd_dealloc(addrPtr);
1817
+ }
1818
+ },
1819
+
1820
+ signMessage(message, privateKey) {
1821
+ const msgPtr = allocAndCopy(wasm, message);
1822
+ const keyPtr = allocAndCopy(wasm, privateKey);
1823
+ const sigPtr = wasm._hd_alloc(64);
1824
+ try {
1825
+ const result = wasm._hd_dot_sign_message(msgPtr, message.length, keyPtr, sigPtr, 64);
1826
+ checkResult(result);
1827
+ return readBytes(wasm, sigPtr, 64);
1828
+ } finally {
1829
+ wasm._hd_secure_wipe(keyPtr, 32);
1830
+ wasm._hd_dealloc(msgPtr);
1831
+ wasm._hd_dealloc(keyPtr);
1832
+ wasm._hd_dealloc(sigPtr);
1833
+ }
1834
+ },
1835
+
1836
+ verifyMessage(message, signature, publicKey) {
1837
+ const msgPtr = allocAndCopy(wasm, message);
1838
+ const sigPtr = allocAndCopy(wasm, signature);
1839
+ const pubPtr = allocAndCopy(wasm, publicKey);
1840
+ try {
1841
+ return wasm._hd_dot_verify_message(msgPtr, message.length, sigPtr, signature.length, pubPtr, publicKey.length) === 1;
1842
+ } finally {
1843
+ wasm._hd_dealloc(msgPtr);
1844
+ wasm._hd_dealloc(sigPtr);
1845
+ wasm._hd_dealloc(pubPtr);
1846
+ }
1847
+ }
1848
+ };
1849
+
1850
+ // ==========================================================================
1851
+ // Hardware Wallet API
1852
+ // ==========================================================================
1853
+
1854
+ /**
1855
+ * Hardware Wallet API (requires WASI bridge)
1856
+ * @type {Object}
1857
+ */
1858
+ const hardware = {
1859
+ /**
1860
+ * Check if hardware wallet support is available
1861
+ * @returns {boolean}
1862
+ */
1863
+ isAvailable() {
1864
+ return wasm._hd_wasi_has_feature(WasiFeature.USB_HID) !== 0;
1865
+ },
1866
+
1867
+ /**
1868
+ * Enumerate connected hardware wallets
1869
+ * @returns {Promise<Object[]>} Array of device descriptors
1870
+ */
1871
+ async enumerate() {
1872
+ const ptr = wasm._hd_hw_enumerate();
1873
+ const json = readString(wasm, ptr);
1874
+ return JSON.parse(json);
1875
+ },
1876
+
1877
+ /**
1878
+ * Connect to a hardware wallet
1879
+ * @param {string} devicePath - Device path from enumeration
1880
+ * @returns {Promise<Object>} Hardware wallet interface
1881
+ */
1882
+ async connect(devicePath) {
1883
+ const pathPtr = allocString(wasm, devicePath);
1884
+ try {
1885
+ const handle = wasm._hd_hw_connect(pathPtr);
1886
+ if (!handle) {
1887
+ throw new HDWalletError(ErrorCode.DEVICE_NOT_CONNECTED);
1888
+ }
1889
+
1890
+ return {
1891
+ _handle: handle,
1892
+
1893
+ get vendor() {
1894
+ const ptr = wasm._hd_hw_get_vendor(this._handle);
1895
+ return readString(wasm, ptr);
1896
+ },
1897
+
1898
+ get model() {
1899
+ const ptr = wasm._hd_hw_get_model(this._handle);
1900
+ return readString(wasm, ptr);
1901
+ },
1902
+
1903
+ get firmwareVersion() {
1904
+ const ptr = wasm._hd_hw_get_firmware_version(this._handle);
1905
+ return readString(wasm, ptr);
1906
+ },
1907
+
1908
+ get isConnected() {
1909
+ return wasm._hd_hw_is_connected(this._handle) !== 0;
1910
+ },
1911
+
1912
+ async getPublicKey(path, curve = Curve.SECP256K1) {
1913
+ const pathPtr = allocString(wasm, path);
1914
+ const outPtr = wasm._hd_alloc(65);
1915
+ try {
1916
+ const result = wasm._hd_hw_get_public_key(this._handle, pathPtr, curve, outPtr, 65);
1917
+ checkResult(result);
1918
+ return readBytes(wasm, outPtr, 33);
1919
+ } finally {
1920
+ wasm._hd_dealloc(pathPtr);
1921
+ wasm._hd_dealloc(outPtr);
1922
+ }
1923
+ },
1924
+
1925
+ async signTransaction(path, transaction) {
1926
+ const pathPtr = allocString(wasm, path);
1927
+ const txPtr = allocAndCopy(wasm, transaction);
1928
+ const sigPtr = wasm._hd_alloc(128);
1929
+ try {
1930
+ const result = wasm._hd_hw_sign_transaction(this._handle, pathPtr, txPtr, transaction.length, sigPtr, 128);
1931
+ checkResult(result);
1932
+ return readBytes(wasm, sigPtr, 64);
1933
+ } finally {
1934
+ wasm._hd_dealloc(pathPtr);
1935
+ wasm._hd_dealloc(txPtr);
1936
+ wasm._hd_dealloc(sigPtr);
1937
+ }
1938
+ },
1939
+
1940
+ async signMessage(path, message) {
1941
+ const pathPtr = allocString(wasm, path);
1942
+ const msgPtr = allocString(wasm, message);
1943
+ const sigPtr = wasm._hd_alloc(128);
1944
+ try {
1945
+ const result = wasm._hd_hw_sign_message(this._handle, pathPtr, msgPtr, sigPtr, 128);
1946
+ checkResult(result);
1947
+ return readBytes(wasm, sigPtr, 64);
1948
+ } finally {
1949
+ wasm._hd_dealloc(pathPtr);
1950
+ wasm._hd_dealloc(msgPtr);
1951
+ wasm._hd_dealloc(sigPtr);
1952
+ }
1953
+ },
1954
+
1955
+ async ping() {
1956
+ return wasm._hd_hw_ping(this._handle) === 0;
1957
+ },
1958
+
1959
+ disconnect() {
1960
+ if (this._handle) {
1961
+ wasm._hd_hw_disconnect(this._handle);
1962
+ this._handle = null;
1963
+ }
1964
+ }
1965
+ };
1966
+ } finally {
1967
+ wasm._hd_dealloc(pathPtr);
1968
+ }
1969
+ }
1970
+ };
1971
+
1972
+ // ==========================================================================
1973
+ // Keyring API
1974
+ // ==========================================================================
1975
+
1976
+ /**
1977
+ * Keyring API
1978
+ * @type {Object}
1979
+ */
1980
+ const keyring = {
1981
+ /**
1982
+ * Create a new keyring
1983
+ * @returns {Object} Keyring instance
1984
+ */
1985
+ create() {
1986
+ const handle = wasm._hd_keyring_create();
1987
+
1988
+ return {
1989
+ _handle: handle,
1990
+
1991
+ addWallet(seed, name) {
1992
+ const seedPtr = allocAndCopy(wasm, seed);
1993
+ const namePtr = name ? allocString(wasm, name) : 0;
1994
+ try {
1995
+ const ptr = wasm._hd_keyring_add_wallet(this._handle, seedPtr, seed.length, namePtr);
1996
+ return readString(wasm, ptr);
1997
+ } finally {
1998
+ wasm._hd_secure_wipe(seedPtr, seed.length);
1999
+ wasm._hd_dealloc(seedPtr);
2000
+ if (namePtr) wasm._hd_dealloc(namePtr);
2001
+ }
2002
+ },
2003
+
2004
+ removeWallet(id) {
2005
+ const idPtr = allocString(wasm, id);
2006
+ try {
2007
+ const result = wasm._hd_keyring_remove_wallet(this._handle, idPtr);
2008
+ checkResult(result);
2009
+ } finally {
2010
+ wasm._hd_dealloc(idPtr);
2011
+ }
2012
+ },
2013
+
2014
+ getWalletCount() {
2015
+ return wasm._hd_keyring_get_wallet_count(this._handle);
2016
+ },
2017
+
2018
+ getAccounts(walletId, coinType, count = 10) {
2019
+ const idPtr = allocString(wasm, walletId);
2020
+ try {
2021
+ const ptr = wasm._hd_keyring_get_accounts(this._handle, idPtr, coinType, count);
2022
+ return JSON.parse(readString(wasm, ptr));
2023
+ } finally {
2024
+ wasm._hd_dealloc(idPtr);
2025
+ }
2026
+ },
2027
+
2028
+ signTransaction(walletId, path, transaction) {
2029
+ const idPtr = allocString(wasm, walletId);
2030
+ const pathPtr = allocString(wasm, path);
2031
+ const txPtr = allocAndCopy(wasm, transaction);
2032
+ const sigPtr = wasm._hd_alloc(128);
2033
+ try {
2034
+ const result = wasm._hd_keyring_sign_transaction(this._handle, idPtr, pathPtr, txPtr, transaction.length, sigPtr, 128);
2035
+ checkResult(result);
2036
+ return readBytes(wasm, sigPtr, 64);
2037
+ } finally {
2038
+ wasm._hd_dealloc(idPtr);
2039
+ wasm._hd_dealloc(pathPtr);
2040
+ wasm._hd_dealloc(txPtr);
2041
+ wasm._hd_dealloc(sigPtr);
2042
+ }
2043
+ },
2044
+
2045
+ signMessage(walletId, path, message) {
2046
+ const idPtr = allocString(wasm, walletId);
2047
+ const pathPtr = allocString(wasm, path);
2048
+ const msgPtr = allocAndCopy(wasm, message);
2049
+ const sigPtr = wasm._hd_alloc(128);
2050
+ try {
2051
+ const result = wasm._hd_keyring_sign_message(this._handle, idPtr, pathPtr, msgPtr, message.length, sigPtr, 128);
2052
+ checkResult(result);
2053
+ return readBytes(wasm, sigPtr, 64);
2054
+ } finally {
2055
+ wasm._hd_dealloc(idPtr);
2056
+ wasm._hd_dealloc(pathPtr);
2057
+ wasm._hd_dealloc(msgPtr);
2058
+ wasm._hd_dealloc(sigPtr);
2059
+ }
2060
+ },
2061
+
2062
+ destroy() {
2063
+ if (this._handle) {
2064
+ wasm._hd_keyring_destroy(this._handle);
2065
+ this._handle = null;
2066
+ }
2067
+ }
2068
+ };
2069
+ }
2070
+ };
2071
+
2072
+ // ==========================================================================
2073
+ // Utils API
2074
+ // ==========================================================================
2075
+
2076
+ /**
2077
+ * Utility functions
2078
+ * @type {Object}
2079
+ */
2080
+ const utils = {
2081
+ // Hashing
2082
+ sha256(data) {
2083
+ const dataPtr = allocAndCopy(wasm, data);
2084
+ const hashPtr = wasm._hd_alloc(32);
2085
+ try {
2086
+ const result = wasm._hd_hash_sha256(dataPtr, data.length, hashPtr, 32);
2087
+ if (result < 0) throw new HDWalletError(result);
2088
+ return readBytes(wasm, hashPtr, 32);
2089
+ } finally {
2090
+ wasm._hd_dealloc(dataPtr);
2091
+ wasm._hd_dealloc(hashPtr);
2092
+ }
2093
+ },
2094
+
2095
+ sha512(data) {
2096
+ const dataPtr = allocAndCopy(wasm, data);
2097
+ const hashPtr = wasm._hd_alloc(64);
2098
+ try {
2099
+ const result = wasm._hd_hash_sha512(dataPtr, data.length, hashPtr, 64);
2100
+ if (result < 0) throw new HDWalletError(result);
2101
+ return readBytes(wasm, hashPtr, 64);
2102
+ } finally {
2103
+ wasm._hd_dealloc(dataPtr);
2104
+ wasm._hd_dealloc(hashPtr);
2105
+ }
2106
+ },
2107
+
2108
+ keccak256(data) {
2109
+ const dataPtr = allocAndCopy(wasm, data);
2110
+ const hashPtr = wasm._hd_alloc(32);
2111
+ try {
2112
+ const result = wasm._hd_hash_keccak256(dataPtr, data.length, hashPtr, 32);
2113
+ if (result < 0) throw new HDWalletError(result);
2114
+ return readBytes(wasm, hashPtr, 32);
2115
+ } finally {
2116
+ wasm._hd_dealloc(dataPtr);
2117
+ wasm._hd_dealloc(hashPtr);
2118
+ }
2119
+ },
2120
+
2121
+ ripemd160(data) {
2122
+ const dataPtr = allocAndCopy(wasm, data);
2123
+ const hashPtr = wasm._hd_alloc(20);
2124
+ try {
2125
+ const result = wasm._hd_hash_ripemd160(dataPtr, data.length, hashPtr, 20);
2126
+ if (result < 0) throw new HDWalletError(result);
2127
+ return readBytes(wasm, hashPtr, 20);
2128
+ } finally {
2129
+ wasm._hd_dealloc(dataPtr);
2130
+ wasm._hd_dealloc(hashPtr);
2131
+ }
2132
+ },
2133
+
2134
+ hash160(data) {
2135
+ const dataPtr = allocAndCopy(wasm, data);
2136
+ const hashPtr = wasm._hd_alloc(20);
2137
+ try {
2138
+ const result = wasm._hd_hash_hash160(dataPtr, data.length, hashPtr, 20);
2139
+ if (result < 0) throw new HDWalletError(result);
2140
+ return readBytes(wasm, hashPtr, 20);
2141
+ } finally {
2142
+ wasm._hd_dealloc(dataPtr);
2143
+ wasm._hd_dealloc(hashPtr);
2144
+ }
2145
+ },
2146
+
2147
+ blake2b(data, outputLength = 32) {
2148
+ const dataPtr = allocAndCopy(wasm, data);
2149
+ const hashPtr = wasm._hd_alloc(64);
2150
+ try {
2151
+ const result = wasm._hd_hash_blake2b(dataPtr, data.length, hashPtr, 64, outputLength);
2152
+ if (result < 0) throw new HDWalletError(result);
2153
+ return readBytes(wasm, hashPtr, outputLength);
2154
+ } finally {
2155
+ wasm._hd_dealloc(dataPtr);
2156
+ wasm._hd_dealloc(hashPtr);
2157
+ }
2158
+ },
2159
+
2160
+ blake2s(data, outputLength = 32) {
2161
+ const dataPtr = allocAndCopy(wasm, data);
2162
+ const hashPtr = wasm._hd_alloc(32);
2163
+ try {
2164
+ const result = wasm._hd_hash_blake2s(dataPtr, data.length, hashPtr, 32, outputLength);
2165
+ if (result < 0) throw new HDWalletError(result);
2166
+ return readBytes(wasm, hashPtr, outputLength);
2167
+ } finally {
2168
+ wasm._hd_dealloc(dataPtr);
2169
+ wasm._hd_dealloc(hashPtr);
2170
+ }
2171
+ },
2172
+
2173
+ // Key derivation
2174
+ hkdf(ikm, salt, info, length) {
2175
+ const ikmPtr = allocAndCopy(wasm, ikm);
2176
+ const saltPtr = allocAndCopy(wasm, salt);
2177
+ const infoPtr = allocAndCopy(wasm, info);
2178
+ const outPtr = wasm._hd_alloc(length);
2179
+ try {
2180
+ const result = wasm._hd_kdf_hkdf(ikmPtr, ikm.length, saltPtr, salt.length, infoPtr, info.length, outPtr, length);
2181
+ if (result < 0) throw new HDWalletError(result);
2182
+ return readBytes(wasm, outPtr, length);
2183
+ } finally {
2184
+ wasm._hd_secure_wipe(ikmPtr, ikm.length);
2185
+ wasm._hd_dealloc(ikmPtr);
2186
+ wasm._hd_dealloc(saltPtr);
2187
+ wasm._hd_dealloc(infoPtr);
2188
+ wasm._hd_dealloc(outPtr);
2189
+ }
2190
+ },
2191
+
2192
+ pbkdf2(password, salt, iterations, length) {
2193
+ const pwdPtr = allocAndCopy(wasm, password);
2194
+ const saltPtr = allocAndCopy(wasm, salt);
2195
+ const outPtr = wasm._hd_alloc(length);
2196
+ try {
2197
+ const result = wasm._hd_kdf_pbkdf2(pwdPtr, password.length, saltPtr, salt.length, iterations, outPtr, length);
2198
+ if (result < 0) throw new HDWalletError(result);
2199
+ return readBytes(wasm, outPtr, length);
2200
+ } finally {
2201
+ wasm._hd_secure_wipe(pwdPtr, password.length);
2202
+ wasm._hd_dealloc(pwdPtr);
2203
+ wasm._hd_dealloc(saltPtr);
2204
+ wasm._hd_dealloc(outPtr);
2205
+ }
2206
+ },
2207
+
2208
+ scrypt(password, salt, n, r, p, length) {
2209
+ const pwdPtr = allocAndCopy(wasm, password);
2210
+ const saltPtr = allocAndCopy(wasm, salt);
2211
+ const outPtr = wasm._hd_alloc(length);
2212
+ try {
2213
+ const result = wasm._hd_kdf_scrypt(pwdPtr, password.length, saltPtr, salt.length, BigInt(n), r, p, outPtr, length);
2214
+ if (result < 0) throw new HDWalletError(result);
2215
+ return readBytes(wasm, outPtr, length);
2216
+ } finally {
2217
+ wasm._hd_secure_wipe(pwdPtr, password.length);
2218
+ wasm._hd_dealloc(pwdPtr);
2219
+ wasm._hd_dealloc(saltPtr);
2220
+ wasm._hd_dealloc(outPtr);
2221
+ }
2222
+ },
2223
+
2224
+ // Encoding
2225
+ encodeBase58(data) {
2226
+ const dataPtr = allocAndCopy(wasm, data);
2227
+ try {
2228
+ const ptr = wasm._hd_encode_base58(dataPtr, data.length);
2229
+ return readString(wasm, ptr);
2230
+ } finally {
2231
+ wasm._hd_dealloc(dataPtr);
2232
+ }
2233
+ },
2234
+
2235
+ decodeBase58(str) {
2236
+ const strPtr = allocString(wasm, str);
2237
+ const outPtr = wasm._hd_alloc(256);
2238
+ const sizePtr = wasm._hd_alloc(4);
2239
+ try {
2240
+ wasm.setValue(sizePtr, 256, 'i32');
2241
+ const result = wasm._hd_decode_base58(strPtr, outPtr, sizePtr);
2242
+ checkResult(result);
2243
+ const size = wasm.getValue(sizePtr, 'i32');
2244
+ return readBytes(wasm, outPtr, size);
2245
+ } finally {
2246
+ wasm._hd_dealloc(strPtr);
2247
+ wasm._hd_dealloc(outPtr);
2248
+ wasm._hd_dealloc(sizePtr);
2249
+ }
2250
+ },
2251
+
2252
+ encodeBase58Check(data) {
2253
+ const dataPtr = allocAndCopy(wasm, data);
2254
+ try {
2255
+ const ptr = wasm._hd_encode_base58check(dataPtr, data.length);
2256
+ return readString(wasm, ptr);
2257
+ } finally {
2258
+ wasm._hd_dealloc(dataPtr);
2259
+ }
2260
+ },
2261
+
2262
+ decodeBase58Check(str) {
2263
+ const strPtr = allocString(wasm, str);
2264
+ const outPtr = wasm._hd_alloc(256);
2265
+ const sizePtr = wasm._hd_alloc(4);
2266
+ try {
2267
+ wasm.setValue(sizePtr, 256, 'i32');
2268
+ const result = wasm._hd_decode_base58check(strPtr, outPtr, sizePtr);
2269
+ checkResult(result);
2270
+ const size = wasm.getValue(sizePtr, 'i32');
2271
+ return readBytes(wasm, outPtr, size);
2272
+ } finally {
2273
+ wasm._hd_dealloc(strPtr);
2274
+ wasm._hd_dealloc(outPtr);
2275
+ wasm._hd_dealloc(sizePtr);
2276
+ }
2277
+ },
2278
+
2279
+ encodeBech32(hrp, data) {
2280
+ const hrpPtr = allocString(wasm, hrp);
2281
+ const dataPtr = allocAndCopy(wasm, data);
2282
+ try {
2283
+ const ptr = wasm._hd_encode_bech32(hrpPtr, dataPtr, data.length);
2284
+ return readString(wasm, ptr);
2285
+ } finally {
2286
+ wasm._hd_dealloc(hrpPtr);
2287
+ wasm._hd_dealloc(dataPtr);
2288
+ }
2289
+ },
2290
+
2291
+ decodeBech32(str) {
2292
+ const strPtr = allocString(wasm, str);
2293
+ const hrpPtr = wasm._hd_alloc(128);
2294
+ const dataPtr = wasm._hd_alloc(256);
2295
+ const sizePtr = wasm._hd_alloc(4);
2296
+ try {
2297
+ wasm.setValue(sizePtr, 256, 'i32');
2298
+ const result = wasm._hd_decode_bech32(strPtr, hrpPtr, 128, dataPtr, sizePtr);
2299
+ checkResult(result);
2300
+ const size = wasm.getValue(sizePtr, 'i32');
2301
+ return {
2302
+ hrp: readString(wasm, hrpPtr),
2303
+ data: readBytes(wasm, dataPtr, size)
2304
+ };
2305
+ } finally {
2306
+ wasm._hd_dealloc(strPtr);
2307
+ wasm._hd_dealloc(hrpPtr);
2308
+ wasm._hd_dealloc(dataPtr);
2309
+ wasm._hd_dealloc(sizePtr);
2310
+ }
2311
+ },
2312
+
2313
+ encodeHex(data) {
2314
+ const dataPtr = allocAndCopy(wasm, data);
2315
+ try {
2316
+ const ptr = wasm._hd_encode_hex(dataPtr, data.length);
2317
+ return readString(wasm, ptr);
2318
+ } finally {
2319
+ wasm._hd_dealloc(dataPtr);
2320
+ }
2321
+ },
2322
+
2323
+ decodeHex(str) {
2324
+ const strPtr = allocString(wasm, str);
2325
+ const outPtr = wasm._hd_alloc(str.length / 2);
2326
+ const sizePtr = wasm._hd_alloc(4);
2327
+ try {
2328
+ wasm.setValue(sizePtr, str.length / 2, 'i32');
2329
+ const result = wasm._hd_decode_hex(strPtr, outPtr, sizePtr);
2330
+ checkResult(result);
2331
+ const size = wasm.getValue(sizePtr, 'i32');
2332
+ return readBytes(wasm, outPtr, size);
2333
+ } finally {
2334
+ wasm._hd_dealloc(strPtr);
2335
+ wasm._hd_dealloc(outPtr);
2336
+ wasm._hd_dealloc(sizePtr);
2337
+ }
2338
+ },
2339
+
2340
+ encodeBase64(data) {
2341
+ const dataPtr = allocAndCopy(wasm, data);
2342
+ try {
2343
+ const ptr = wasm._hd_encode_base64(dataPtr, data.length);
2344
+ return readString(wasm, ptr);
2345
+ } finally {
2346
+ wasm._hd_dealloc(dataPtr);
2347
+ }
2348
+ },
2349
+
2350
+ decodeBase64(str) {
2351
+ const strPtr = allocString(wasm, str);
2352
+ const outPtr = wasm._hd_alloc(str.length);
2353
+ const sizePtr = wasm._hd_alloc(4);
2354
+ try {
2355
+ wasm.setValue(sizePtr, str.length, 'i32');
2356
+ const result = wasm._hd_decode_base64(strPtr, outPtr, sizePtr);
2357
+ checkResult(result);
2358
+ const size = wasm.getValue(sizePtr, 'i32');
2359
+ return readBytes(wasm, outPtr, size);
2360
+ } finally {
2361
+ wasm._hd_dealloc(strPtr);
2362
+ wasm._hd_dealloc(outPtr);
2363
+ wasm._hd_dealloc(sizePtr);
2364
+ }
2365
+ },
2366
+
2367
+ // Memory
2368
+ secureWipe(data) {
2369
+ if (data instanceof Uint8Array) {
2370
+ // Wipe in-place
2371
+ for (let i = 0; i < data.length; i++) {
2372
+ data[i] = 0;
2373
+ }
2374
+ }
2375
+ }
2376
+ };
2377
+
2378
+ // ==========================================================================
2379
+ // Return the module API
2380
+ // ==========================================================================
2381
+
2382
+ return {
2383
+ // Module info
2384
+ getVersion() {
2385
+ const ptr = wasm._hd_get_version_string();
2386
+ return readString(wasm, ptr);
2387
+ },
2388
+
2389
+ hasCryptopp() {
2390
+ return wasm._hd_has_cryptopp() !== 0;
2391
+ },
2392
+
2393
+ isFipsMode() {
2394
+ return wasm._hd_is_fips_mode() !== 0;
2395
+ },
2396
+
2397
+ getSupportedCoins() {
2398
+ const ptr = wasm._hd_get_supported_coins();
2399
+ return JSON.parse(readString(wasm, ptr));
2400
+ },
2401
+
2402
+ getSupportedCurves() {
2403
+ const ptr = wasm._hd_get_supported_curves();
2404
+ return JSON.parse(readString(wasm, ptr));
2405
+ },
2406
+
2407
+ // WASI bridge
2408
+ wasiHasFeature(feature) {
2409
+ return wasm._hd_wasi_has_feature(feature) !== 0;
2410
+ },
2411
+
2412
+ wasiGetWarning(feature) {
2413
+ return wasm._hd_wasi_get_warning(feature);
2414
+ },
2415
+
2416
+ wasiGetWarningMessage(feature) {
2417
+ const ptr = wasm._hd_wasi_get_warning_message(feature);
2418
+ return readString(wasm, ptr);
2419
+ },
2420
+
2421
+ // Entropy
2422
+ injectEntropy(entropy) {
2423
+ const entropyPtr = allocAndCopy(wasm, entropy);
2424
+ try {
2425
+ wasm._hd_inject_entropy(entropyPtr, entropy.length);
2426
+ } finally {
2427
+ wasm._hd_secure_wipe(entropyPtr, entropy.length);
2428
+ wasm._hd_dealloc(entropyPtr);
2429
+ }
2430
+ },
2431
+
2432
+ getEntropyStatus() {
2433
+ return wasm._hd_get_entropy_status();
2434
+ },
2435
+
2436
+ // APIs
2437
+ mnemonic,
2438
+ hdkey,
2439
+ curves,
2440
+ bitcoin,
2441
+ ethereum,
2442
+ cosmos,
2443
+ solana,
2444
+ polkadot,
2445
+ hardware,
2446
+ keyring,
2447
+ utils
2448
+ };
2449
+ }
2450
+
2451
+ // =============================================================================
2452
+ // Module Export
2453
+ // =============================================================================
2454
+
2455
+ /**
2456
+ * Initialize the HD Wallet WASM module
2457
+ * @param {string} [wasmPath] - Optional path to WASM file
2458
+ * @returns {Promise<Object>} Initialized HDWalletModule
2459
+ */
2460
+ export default async function init(wasmPath) {
2461
+ const wasm = await loadWasmModule(wasmPath);
2462
+ return createModule(wasm);
2463
+ }
2464
+
2465
+ /**
2466
+ * Create HD Wallet instance (alternative syntax)
2467
+ * @param {string} [wasmPath] - Optional path to WASM file
2468
+ * @returns {Promise<Object>} Initialized HDWalletModule
2469
+ */
2470
+ export async function createHDWallet(wasmPath) {
2471
+ return init(wasmPath);
2472
+ }
2473
+
2474
+ // Export types and enums
2475
+ export {
2476
+ HDKey,
2477
+ HDWalletError,
2478
+ ErrorCode
2479
+ };