@cheny56/node-client 1.0.11 → 1.0.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cheny56/node-client",
3
- "version": "1.0.11",
3
+ "version": "1.0.14",
4
4
  "description": "Client library for Quorum blockchain with Post-Quantum Cryptography (PQC) and Zero-Knowledge Proof (ZK) support",
5
5
  "main": "./src/index.js",
6
6
  "types": "src/index.d.ts",
package/src/contract.js CHANGED
@@ -161,9 +161,7 @@ class ERC20Token extends Contract {
161
161
  async transferPQC(wallet, provider, to, amount, txOptions = {}) {
162
162
  const data = this.encodeFunctionData('transfer', [to, amount]);
163
163
  // Ensure wallet is initialized
164
- if (!wallet._initialized) {
165
- await wallet._ensureKeyPair();
166
- }
164
+ await wallet._initPromise;
167
165
  const nonce = await provider.getTransactionCount(wallet.address, 'pending');
168
166
 
169
167
  const tx = new PQCLegacyTransaction({
@@ -93,15 +93,15 @@ class PQCLegacyTransaction extends BaseTransaction {
93
93
  getSigningHash() {
94
94
  const nonceBytes = this.nonce === 0n || this.nonce === 0
95
95
  ? new Uint8Array(0)
96
- : ethers.getBytes(ethers.toBeHex(this.nonce));
96
+ : ethers.utils.arrayify(ethers.utils.hexlify(this.nonce));
97
97
  const gasLimitBytes = this.gasLimit === 0n || this.gasLimit === 0
98
98
  ? new Uint8Array(0)
99
- : ethers.getBytes(ethers.toBeHex(this.gasLimit));
99
+ : ethers.utils.arrayify(ethers.utils.hexlify(this.gasLimit));
100
100
  const chainIdBytes = this.chainId === 0n || this.chainId === 0
101
101
  ? new Uint8Array(0)
102
- : ethers.getBytes(ethers.toBeHex(this.chainId));
102
+ : ethers.utils.arrayify(ethers.utils.hexlify(this.chainId));
103
103
 
104
- const encoded = ethers.encodeRlp([
104
+ const encoded = ethers.utils.RLP.encode([
105
105
  nonceBytes,
106
106
  this.gasPrice === 0n ? new Uint8Array(0) : ethers.getBytes(ethers.toBeHex(this.gasPrice)),
107
107
  gasLimitBytes,
@@ -112,7 +112,7 @@ class PQCLegacyTransaction extends BaseTransaction {
112
112
  new Uint8Array(0),
113
113
  new Uint8Array(0),
114
114
  ]);
115
- return ethers.keccak256(encoded);
115
+ return ethers.utils.keccak256(encoded);
116
116
  }
117
117
 
118
118
  /**
@@ -122,11 +122,9 @@ class PQCLegacyTransaction extends BaseTransaction {
122
122
  */
123
123
  async sign(wallet) {
124
124
  // Ensure wallet is initialized
125
- if (!wallet._initialized) {
126
- await wallet._ensureKeyPair();
127
- }
125
+ await wallet._initPromise;
128
126
 
129
- const hash = ethers.getBytes(this.getSigningHash());
127
+ const hash = ethers.utils.arrayify(this.getSigningHash());
130
128
  this.pqcPubKey = wallet.publicKey;
131
129
  // Use wallet's sign method which handles the async properly
132
130
  this.pqcSig = await wallet.sign(hash);
@@ -138,7 +136,7 @@ class PQCLegacyTransaction extends BaseTransaction {
138
136
 
139
137
  async verify() {
140
138
  if (!this.pqcSig || !this.pqcPubKey) return false;
141
- const hash = ethers.getBytes(this.getSigningHash());
139
+ const hash = ethers.utils.arrayify(this.getSigningHash());
142
140
  // Use dilithium verify directly
143
141
  if (dilithium.verify) {
144
142
  return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
@@ -165,7 +163,7 @@ class PQCLegacyTransaction extends BaseTransaction {
165
163
  const sHex = encodeSignature(this.s || '0x0');
166
164
  const pqcTypeHex = encodeUint64(this.pqcType);
167
165
 
168
- const encoded = ethers.encodeRlp([
166
+ const encoded = ethers.utils.RLP.encode([
169
167
  nonceHex,
170
168
  gasPriceHex,
171
169
  gasLimitHex,
@@ -179,11 +177,11 @@ class PQCLegacyTransaction extends BaseTransaction {
179
177
  this.pqcPubKey,
180
178
  this.pqcSig,
181
179
  ]);
182
- return ethers.getBytes(encoded);
180
+ return ethers.utils.arrayify(encoded);
183
181
  }
184
182
 
185
183
  getHex() {
186
- return ethers.hexlify(this.serialize());
184
+ return ethers.utils.hexlify(this.serialize());
187
185
  }
188
186
  }
189
187
 
@@ -207,15 +205,15 @@ class HybridLegacyTransaction extends BaseTransaction {
207
205
  getSigningHash() {
208
206
  const nonceBytes = this.nonce === 0n || this.nonce === 0
209
207
  ? new Uint8Array(0)
210
- : ethers.getBytes(ethers.toBeHex(this.nonce));
208
+ : ethers.utils.arrayify(ethers.utils.hexlify(this.nonce));
211
209
  const gasLimitBytes = this.gasLimit === 0n || this.gasLimit === 0
212
210
  ? new Uint8Array(0)
213
- : ethers.getBytes(ethers.toBeHex(this.gasLimit));
211
+ : ethers.utils.arrayify(ethers.utils.hexlify(this.gasLimit));
214
212
  const chainIdBytes = this.chainId === 0n || this.chainId === 0
215
213
  ? new Uint8Array(0)
216
- : ethers.getBytes(ethers.toBeHex(this.chainId));
214
+ : ethers.utils.arrayify(ethers.utils.hexlify(this.chainId));
217
215
 
218
- const encoded = ethers.encodeRlp([
216
+ const encoded = ethers.utils.RLP.encode([
219
217
  nonceBytes,
220
218
  this.gasPrice === 0n ? new Uint8Array(0) : ethers.getBytes(ethers.toBeHex(this.gasPrice)),
221
219
  gasLimitBytes,
@@ -226,7 +224,7 @@ class HybridLegacyTransaction extends BaseTransaction {
226
224
  new Uint8Array(0),
227
225
  new Uint8Array(0),
228
226
  ]);
229
- return ethers.keccak256(encoded);
227
+ return ethers.utils.keccak256(encoded);
230
228
  }
231
229
 
232
230
  /**
@@ -237,12 +235,10 @@ class HybridLegacyTransaction extends BaseTransaction {
237
235
  */
238
236
  async sign(ecdsaWallet, pqcWallet) {
239
237
  // Ensure PQC wallet is initialized
240
- if (!pqcWallet._initialized) {
241
- await pqcWallet._ensureKeyPair();
242
- }
238
+ await pqcWallet._initPromise;
243
239
 
244
240
  const hash = this.getSigningHash();
245
- const hashBytes = ethers.getBytes(hash);
241
+ const hashBytes = ethers.utils.arrayify(hash);
246
242
 
247
243
  // ECDSA signature
248
244
  const ecdsaSig = ecdsaWallet.wallet.signingKey.sign(hash);
@@ -260,7 +256,7 @@ class HybridLegacyTransaction extends BaseTransaction {
260
256
 
261
257
  verify() {
262
258
  if (!this.pqcSig || !this.pqcPubKey) return false;
263
- const hash = ethers.getBytes(this.getSigningHash());
259
+ const hash = ethers.utils.arrayify(this.getSigningHash());
264
260
  if (dilithium.verify) {
265
261
  return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
266
262
  } else if (dilithium.verifyWithContext) {
@@ -286,7 +282,7 @@ class HybridLegacyTransaction extends BaseTransaction {
286
282
  const sHex = encodeSignature(this.s);
287
283
  const pqcTypeHex = encodeUint64(this.pqcType);
288
284
 
289
- const encoded = ethers.encodeRlp([
285
+ const encoded = ethers.utils.RLP.encode([
290
286
  nonceHex,
291
287
  gasPriceHex,
292
288
  gasLimitHex,
@@ -300,11 +296,11 @@ class HybridLegacyTransaction extends BaseTransaction {
300
296
  this.pqcPubKey,
301
297
  this.pqcSig,
302
298
  ]);
303
- return ethers.getBytes(encoded);
299
+ return ethers.utils.arrayify(encoded);
304
300
  }
305
301
 
306
302
  getHex() {
307
- return ethers.hexlify(this.serialize());
303
+ return ethers.utils.hexlify(this.serialize());
308
304
  }
309
305
  }
310
306
 
@@ -359,11 +355,11 @@ class PQCAccessListTransaction extends BaseTransaction {
359
355
  }
360
356
 
361
357
  getSigningHash() {
362
- const chainIdHex = this.chainId === 0n || this.chainId === 0 ? '0x' : ethers.toBeHex(this.chainId);
363
- const nonceHex = this.nonce === 0n || this.nonce === 0 ? '0x' : ethers.toBeHex(this.nonce);
364
- const gasPriceHex = this.gasPrice === 0n || this.gasPrice === 0 ? '0x' : ethers.toBeHex(this.gasPrice);
365
- const gasHex = this.gasLimit === 0n || this.gasLimit === 0 ? '0x' : ethers.toBeHex(this.gasLimit);
366
- const valueHex = this.value === 0n || this.value === 0 ? '0x' : ethers.toBeHex(this.value);
358
+ const chainIdHex = this.chainId === 0n || this.chainId === 0 ? '0x' : ethers.utils.hexlify(this.chainId);
359
+ const nonceHex = this.nonce === 0n || this.nonce === 0 ? '0x' : ethers.utils.hexlify(this.nonce);
360
+ const gasPriceHex = this.gasPrice === 0n || this.gasPrice === 0 ? '0x' : ethers.utils.hexlify(this.gasPrice);
361
+ const gasHex = this.gasLimit === 0n || this.gasLimit === 0 ? '0x' : ethers.utils.hexlify(this.gasLimit);
362
+ const valueHex = this.value === 0n || this.value === 0 ? '0x' : ethers.utils.hexlify(this.value);
367
363
 
368
364
  const rlpData = [
369
365
  chainIdHex,
@@ -376,24 +372,22 @@ class PQCAccessListTransaction extends BaseTransaction {
376
372
  this.accessList || [],
377
373
  ];
378
374
 
379
- const encodedHex = ethers.encodeRlp(rlpData);
380
- const encoded = ethers.getBytes(encodedHex);
375
+ const encodedHex = ethers.utils.RLP.encode(rlpData);
376
+ const encoded = ethers.utils.arrayify(encodedHex);
381
377
 
382
378
  const typeByte = TX_TYPE.ACCESS_LIST;
383
379
  const prefixed = new Uint8Array(1 + encoded.length);
384
380
  prefixed[0] = typeByte;
385
381
  prefixed.set(encoded, 1);
386
382
 
387
- return ethers.keccak256(ethers.hexlify(prefixed));
383
+ return ethers.utils.keccak256(ethers.utils.hexlify(prefixed));
388
384
  }
389
385
 
390
386
  async sign(wallet) {
391
387
  // Ensure wallet is initialized
392
- if (!wallet._initialized) {
393
- await wallet._ensureKeyPair();
394
- }
388
+ await wallet._initPromise;
395
389
 
396
- const hash = ethers.getBytes(this.getSigningHash());
390
+ const hash = ethers.utils.arrayify(this.getSigningHash());
397
391
  this.pqcPubKey = wallet.publicKey;
398
392
  this.pqcSig = await wallet.sign(hash);
399
393
  return this;
@@ -401,7 +395,7 @@ class PQCAccessListTransaction extends BaseTransaction {
401
395
 
402
396
  async verify() {
403
397
  if (!this.pqcSig || !this.pqcPubKey) return false;
404
- const hash = ethers.getBytes(this.getSigningHash());
398
+ const hash = ethers.utils.arrayify(this.getSigningHash());
405
399
  if (dilithium.verify) {
406
400
  return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
407
401
  } else if (dilithium.verifyWithContext) {
@@ -429,7 +423,7 @@ class PQCAccessListTransaction extends BaseTransaction {
429
423
  const sHex = encodeSignature(this.s || '0x0');
430
424
  const pqcTypeHex = encodeUint64(this.pqcType);
431
425
 
432
- const encoded = ethers.encodeRlp([
426
+ const encoded = ethers.utils.RLP.encode([
433
427
  chainIdHex,
434
428
  nonceHex,
435
429
  gasPriceHex,
@@ -446,7 +440,7 @@ class PQCAccessListTransaction extends BaseTransaction {
446
440
  this.pqcSig,
447
441
  ]);
448
442
 
449
- const encodedBytes = ethers.getBytes(encoded);
443
+ const encodedBytes = ethers.utils.arrayify(encoded);
450
444
  const typeByte = new Uint8Array([TX_TYPE.ACCESS_LIST]);
451
445
  const prefixed = new Uint8Array(typeByte.length + encodedBytes.length);
452
446
  prefixed.set(typeByte, 0);
@@ -456,7 +450,7 @@ class PQCAccessListTransaction extends BaseTransaction {
456
450
  }
457
451
 
458
452
  getHex() {
459
- return ethers.hexlify(this.serialize());
453
+ return ethers.utils.hexlify(this.serialize());
460
454
  }
461
455
  }
462
456
 
@@ -516,8 +510,8 @@ class PQCDynamicFeeTransaction extends BaseTransaction {
516
510
  getSigningHash() {
517
511
  const chainIdHex = this.chainId === 0n || this.chainId === 0 ? '0x' : ethers.toBeHex(this.chainId);
518
512
  const nonceHex = this.nonce === 0n || this.nonce === 0 ? '0x' : ethers.toBeHex(this.nonce);
519
- const gasTipCapHex = this.maxPriorityFeePerGas === 0n || this.maxPriorityFeePerGas === 0 ? '0x' : ethers.toBeHex(this.maxPriorityFeePerGas);
520
- const gasFeeCapHex = this.maxFeePerGas === 0n || this.maxFeePerGas === 0 ? '0x' : ethers.toBeHex(this.maxFeePerGas);
513
+ const gasTipCapHex = this.maxPriorityFeePerGas === 0n || this.maxPriorityFeePerGas === 0 ? '0x' : ethers.utils.hexlify(this.maxPriorityFeePerGas);
514
+ const gasFeeCapHex = this.maxFeePerGas === 0n || this.maxFeePerGas === 0 ? '0x' : ethers.utils.hexlify(this.maxFeePerGas);
521
515
  const gasHex = this.gasLimit === 0n || this.gasLimit === 0 ? '0x' : ethers.toBeHex(this.gasLimit);
522
516
  const valueHex = this.value === 0n || this.value === 0 ? '0x' : ethers.toBeHex(this.value);
523
517
 
@@ -533,24 +527,22 @@ class PQCDynamicFeeTransaction extends BaseTransaction {
533
527
  this.accessList || [],
534
528
  ];
535
529
 
536
- const encodedHex = ethers.encodeRlp(rlpData);
537
- const encoded = ethers.getBytes(encodedHex);
530
+ const encodedHex = ethers.utils.RLP.encode(rlpData);
531
+ const encoded = ethers.utils.arrayify(encodedHex);
538
532
 
539
533
  const typeByte = TX_TYPE.DYNAMIC_FEE;
540
534
  const prefixed = new Uint8Array(1 + encoded.length);
541
535
  prefixed[0] = typeByte;
542
536
  prefixed.set(encoded, 1);
543
537
 
544
- return ethers.keccak256(ethers.hexlify(prefixed));
538
+ return ethers.utils.keccak256(ethers.utils.hexlify(prefixed));
545
539
  }
546
540
 
547
541
  async sign(wallet) {
548
542
  // Ensure wallet is initialized
549
- if (!wallet._initialized) {
550
- await wallet._ensureKeyPair();
551
- }
543
+ await wallet._initPromise;
552
544
 
553
- const hash = ethers.getBytes(this.getSigningHash());
545
+ const hash = ethers.utils.arrayify(this.getSigningHash());
554
546
  this.pqcPubKey = wallet.publicKey;
555
547
  this.pqcSig = await wallet.sign(hash);
556
548
  return this;
@@ -558,7 +550,7 @@ class PQCDynamicFeeTransaction extends BaseTransaction {
558
550
 
559
551
  async verify() {
560
552
  if (!this.pqcSig || !this.pqcPubKey) return false;
561
- const hash = ethers.getBytes(this.getSigningHash());
553
+ const hash = ethers.utils.arrayify(this.getSigningHash());
562
554
  if (dilithium.verify) {
563
555
  return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
564
556
  } else if (dilithium.verifyWithContext) {
@@ -587,7 +579,7 @@ class PQCDynamicFeeTransaction extends BaseTransaction {
587
579
  const sHex = encodeSignature(this.s || '0x0');
588
580
  const pqcTypeHex = encodeUint64(this.pqcType);
589
581
 
590
- const encoded = ethers.encodeRlp([
582
+ const encoded = ethers.utils.RLP.encode([
591
583
  chainIdHex,
592
584
  nonceHex,
593
585
  gasTipCapHex,
@@ -605,7 +597,7 @@ class PQCDynamicFeeTransaction extends BaseTransaction {
605
597
  this.pqcSig,
606
598
  ]);
607
599
 
608
- const encodedBytes = ethers.getBytes(encoded);
600
+ const encodedBytes = ethers.utils.arrayify(encoded);
609
601
  const typeByte = new Uint8Array([TX_TYPE.DYNAMIC_FEE]);
610
602
  const prefixed = new Uint8Array(typeByte.length + encodedBytes.length);
611
603
  prefixed.set(typeByte, 0);
@@ -615,7 +607,7 @@ class PQCDynamicFeeTransaction extends BaseTransaction {
615
607
  }
616
608
 
617
609
  getHex() {
618
- return ethers.hexlify(this.serialize());
610
+ return ethers.utils.hexlify(this.serialize());
619
611
  }
620
612
  }
621
613
 
@@ -11,8 +11,8 @@ const { ethers } = require('ethers');
11
11
  * @returns {string} Ethereum address
12
12
  */
13
13
  function derivePQCAddress(publicKey) {
14
- const hash = ethers.keccak256(publicKey);
15
- return ethers.getAddress('0x' + hash.slice(-40));
14
+ const hash = ethers.utils.keccak256(publicKey);
15
+ return ethers.utils.getAddress('0x' + hash.slice(-40));
16
16
  }
17
17
 
18
18
  /**
@@ -34,8 +34,8 @@ function deriveHybridAddress(ecdsaPublicKey, dilithiumPublicKey) {
34
34
  concat.set(dilithiumPublicKey, ecdsaBytes.length);
35
35
 
36
36
  // Hash and derive address
37
- const hash = ethers.keccak256(concat);
38
- return ethers.getAddress('0x' + hash.slice(-40));
37
+ const hash = ethers.utils.keccak256(concat);
38
+ return ethers.utils.getAddress('0x' + hash.slice(-40));
39
39
  }
40
40
 
41
41
  /**
package/src/utils/rlp.js CHANGED
@@ -14,7 +14,7 @@ function encodeUint64(value) {
14
14
  return '0x';
15
15
  }
16
16
  const bigValue = typeof value === 'bigint' ? value : BigInt(value);
17
- return ethers.toBeHex(bigValue);
17
+ return ethers.utils.hexlify(bigValue);
18
18
  }
19
19
 
20
20
  /**
@@ -26,7 +26,7 @@ function encodeBigInt(value) {
26
26
  return '0x';
27
27
  }
28
28
  const bigValue = typeof value === 'bigint' ? value : BigInt(value);
29
- return ethers.toBeHex(bigValue);
29
+ return ethers.utils.hexlify(bigValue);
30
30
  }
31
31
 
32
32
  /**
@@ -39,7 +39,7 @@ function encodeSignature(value) {
39
39
  }
40
40
 
41
41
  const hex = value.startsWith('0x') ? value : '0x' + value;
42
- let bytes = ethers.getBytes(hex);
42
+ let bytes = ethers.utils.arrayify(hex);
43
43
 
44
44
  // Remove leading zeros for canonical form
45
45
  let startIdx = 0;
@@ -52,7 +52,7 @@ function encodeSignature(value) {
52
52
  }
53
53
 
54
54
  bytes = bytes.slice(startIdx);
55
- return ethers.hexlify(bytes);
55
+ return ethers.utils.hexlify(bytes);
56
56
  }
57
57
 
58
58
  module.exports = {
package/src/wallet.js CHANGED
@@ -68,6 +68,7 @@ class PQCWallet {
68
68
  this.publicKey = publicKey instanceof Uint8Array ? publicKey : new Uint8Array(publicKey);
69
69
  this.address = derivePQCAddress(this.publicKey);
70
70
  this._initialized = true;
71
+ this._initPromise = Promise.resolve();
71
72
  } else {
72
73
  // Generate new key pair using dilithium-crystals
73
74
  // dilithium-crystals uses keyPair() which is async and returns { publicKey, secretKey }
@@ -75,9 +76,21 @@ class PQCWallet {
75
76
  this.publicKey = null;
76
77
  this.address = null;
77
78
  this._initialized = false;
79
+ // Start initialization immediately
80
+ this._initPromise = this._ensureKeyPair();
78
81
  }
79
82
  }
80
83
 
84
+ /**
85
+ * Create a new PQC wallet with initialized keys (static factory method)
86
+ * @returns {Promise<PQCWallet>} Initialized wallet
87
+ */
88
+ static async create() {
89
+ const wallet = new PQCWallet();
90
+ await wallet._initPromise;
91
+ return wallet;
92
+ }
93
+
81
94
  /**
82
95
  * Initialize key pair if not already done (async)
83
96
  * @private
@@ -98,6 +111,15 @@ class PQCWallet {
98
111
  this._initialized = true;
99
112
  }
100
113
 
114
+ /**
115
+ * Get address (will initialize keys if needed)
116
+ * @returns {Promise<string>} Wallet address
117
+ */
118
+ async getAddress() {
119
+ await this._initPromise;
120
+ return this.address;
121
+ }
122
+
101
123
  /**
102
124
  * Create wallet from secret key
103
125
  * Note: In practice, you would derive the public key from the secret key.
@@ -110,8 +132,8 @@ class PQCWallet {
110
132
  if (!secretKey || !publicKey) {
111
133
  throw new Error('Both secretKey and publicKey are required');
112
134
  }
113
- const secret = secretKey instanceof Uint8Array ? secretKey : ethers.getBytes(secretKey);
114
- const pub = publicKey instanceof Uint8Array ? publicKey : ethers.getBytes(publicKey);
135
+ const secret = secretKey instanceof Uint8Array ? secretKey : ethers.utils.arrayify(secretKey);
136
+ const pub = publicKey instanceof Uint8Array ? publicKey : ethers.utils.arrayify(publicKey);
115
137
  return new PQCWallet(secret, pub);
116
138
  }
117
139
 
@@ -122,9 +144,7 @@ class PQCWallet {
122
144
  */
123
145
  async sign(hash) {
124
146
  // Ensure key pair is initialized
125
- if (!this._initialized) {
126
- await this._ensureKeyPair();
127
- }
147
+ await this._initPromise;
128
148
 
129
149
  // dilithium-crystals API: sign(secretKey, message)
130
150
  // Some implementations may require context, but we'll try without first
@@ -146,9 +166,7 @@ class PQCWallet {
146
166
  */
147
167
  async verify(hash, signature) {
148
168
  // Ensure key pair is initialized
149
- if (!this._initialized) {
150
- await this._ensureKeyPair();
151
- }
169
+ await this._initPromise;
152
170
 
153
171
  // dilithium-crystals API: verify(publicKey, message, signature)
154
172
  if (dilithium.verify) {
@@ -166,10 +184,8 @@ class PQCWallet {
166
184
  * @returns {Promise<string>} Public key (hex)
167
185
  */
168
186
  async getPublicKeyHex() {
169
- if (!this._initialized) {
170
- await this._ensureKeyPair();
171
- }
172
- return ethers.hexlify(this.publicKey);
187
+ await this._initPromise;
188
+ return ethers.utils.hexlify(this.publicKey);
173
189
  }
174
190
 
175
191
  /**
@@ -177,10 +193,8 @@ class PQCWallet {
177
193
  * @returns {Promise<string>} Secret key (hex)
178
194
  */
179
195
  async getSecretKeyHex() {
180
- if (!this._initialized) {
181
- await this._ensureKeyPair();
182
- }
183
- return ethers.hexlify(this.secretKey);
196
+ await this._initPromise;
197
+ return ethers.utils.hexlify(this.secretKey);
184
198
  }
185
199
  }
186
200
 
@@ -198,6 +212,24 @@ class HybridWallet {
198
212
  this._initialized = false;
199
213
  }
200
214
 
215
+ /**
216
+ * Create a new Hybrid wallet with initialized keys (static factory method)
217
+ * @param {ECDSAWallet|string} ecdsaWallet - ECDSA wallet or private key
218
+ * @returns {Promise<HybridWallet>} Initialized hybrid wallet
219
+ */
220
+ static async create(ecdsaWallet) {
221
+ const ecdsa = ecdsaWallet instanceof ECDSAWallet ? ecdsaWallet : new ECDSAWallet(ecdsaWallet);
222
+ const pqc = new PQCWallet();
223
+ await pqc._initPromise; // Wait for PQC keys to be generated
224
+ const wallet = new HybridWallet(ecdsa, pqc);
225
+ wallet.address = deriveHybridAddress(
226
+ ethers.utils.arrayify(ecdsa.getPublicKey()),
227
+ pqc.publicKey
228
+ );
229
+ wallet._initialized = true;
230
+ return wallet;
231
+ }
232
+
201
233
  /**
202
234
  * Get the hybrid address (computed from ECDSA + PQC public keys)
203
235
  * @returns {Promise<string>} Hybrid address
@@ -208,12 +240,10 @@ class HybridWallet {
208
240
  }
209
241
 
210
242
  // Ensure PQC wallet has keys
211
- if (!this.pqcWallet._initialized) {
212
- await this.pqcWallet._ensureKeyPair();
213
- }
243
+ await this.pqcWallet._initPromise;
214
244
 
215
245
  this.address = deriveHybridAddress(
216
- ethers.getBytes(this.ecdsaWallet.getPublicKey()),
246
+ ethers.utils.arrayify(this.ecdsaWallet.getPublicKey()),
217
247
  this.pqcWallet.publicKey
218
248
  );
219
249
  this._initialized = true;
@@ -232,7 +262,7 @@ class HybridWallet {
232
262
  const pqcWallet = new PQCWallet(pqcSecretKey, pqcPublicKey);
233
263
  const wallet = new HybridWallet(ecdsaWallet, pqcWallet);
234
264
  wallet.address = deriveHybridAddress(
235
- ethers.getBytes(ecdsaWallet.getPublicKey()),
265
+ ethers.utils.arrayify(ecdsaWallet.getPublicKey()),
236
266
  pqcWallet.publicKey
237
267
  );
238
268
  wallet._initialized = true;
@@ -51,27 +51,27 @@ class ZKTransaction {
51
51
  };
52
52
 
53
53
  if (this.to) args.to = this.to;
54
- if (this.value) args.value = ethers.toBeHex(this.value);
55
- if (this.gasLimit) args.gas = ethers.toBeHex(this.gasLimit);
56
- if (this.gasPrice) args.gasPrice = ethers.toBeHex(this.gasPrice);
54
+ if (this.value) args.value = ethers.utils.hexlify(this.value);
55
+ if (this.gasLimit) args.gas = ethers.utils.hexlify(this.gasLimit);
56
+ if (this.gasPrice) args.gasPrice = ethers.utils.hexlify(this.gasPrice);
57
57
  if (this.data) args.data = this.data;
58
- if (this.nonce) args.nonce = ethers.toBeHex(this.nonce);
59
- if (this.chainId) args.chainId = ethers.toBeHex(this.chainId);
58
+ if (this.nonce) args.nonce = ethers.utils.hexlify(this.nonce);
59
+ if (this.chainId) args.chainId = ethers.utils.hexlify(this.chainId);
60
60
  if (this.accessList && this.accessList.length > 0) args.accessList = this.accessList;
61
61
  if (this.zkPublicInputs && this.zkPublicInputs.length > 0) {
62
62
  args.zkPublicInputs = this.zkPublicInputs.map(pi =>
63
- typeof pi === 'string' ? pi : ethers.hexlify(pi)
63
+ typeof pi === 'string' ? pi : ethers.utils.hexlify(pi)
64
64
  );
65
65
  }
66
66
  if (this.zkVerificationKeyHash) {
67
67
  args.zkVerificationKeyHash = typeof this.zkVerificationKeyHash === 'string'
68
68
  ? this.zkVerificationKeyHash
69
- : ethers.hexlify(this.zkVerificationKeyHash);
69
+ : ethers.utils.hexlify(this.zkVerificationKeyHash);
70
70
  }
71
71
  if (this.encryptedPayload) {
72
72
  args.encryptedPayload = typeof this.encryptedPayload === 'string'
73
73
  ? this.encryptedPayload
74
- : ethers.hexlify(this.encryptedPayload);
74
+ : ethers.utils.hexlify(this.encryptedPayload);
75
75
  }
76
76
  if (this.recipients && this.recipients.length > 0) {
77
77
  args.recipients = this.recipients;