@cheny56/node-client 1.0.8 → 1.0.10

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,14 +1,12 @@
1
1
  {
2
2
  "name": "@cheny56/node-client",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Client library for Quorum blockchain with Post-Quantum Cryptography (PQC) and Zero-Knowledge Proof (ZK) support",
5
- "main": "./index.cjs",
6
- "module": "./src/index.js",
5
+ "main": "./src/index.js",
7
6
  "types": "src/index.d.ts",
8
- "type": "module",
9
7
  "exports": {
10
8
  ".": {
11
- "require": "./index.cjs",
9
+ "require": "./src/index.js",
12
10
  "import": "./src/index.js",
13
11
  "types": "./src/index.d.ts",
14
12
  "default": "./src/index.js"
@@ -18,7 +16,6 @@
18
16
  "files": [
19
17
  "src/**/*.js",
20
18
  "src/**/*.d.ts",
21
- "index.cjs",
22
19
  "package.json",
23
20
  "README.md",
24
21
  "README-COMMONJS.md",
package/src/constants.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Transaction Type Constants
3
3
  */
4
- export const TX_TYPE = {
4
+ const TX_TYPE = {
5
5
  LEGACY: 0,
6
6
  ACCESS_LIST: 1,
7
7
  DYNAMIC_FEE: 2,
@@ -11,7 +11,7 @@ export const TX_TYPE = {
11
11
  /**
12
12
  * PQC Signature Type Constants
13
13
  */
14
- export const PQC_TYPE = {
14
+ const PQC_TYPE = {
15
15
  NONE: 0,
16
16
  DILITHIUM: 1,
17
17
  };
@@ -19,7 +19,7 @@ export const PQC_TYPE = {
19
19
  /**
20
20
  * ZK Proof System Constants
21
21
  */
22
- export const ZK_PROOF_SYSTEM = {
22
+ const ZK_PROOF_SYSTEM = {
23
23
  GROTH16: 1,
24
24
  PLONK: 2,
25
25
  STARK: 3,
@@ -28,4 +28,11 @@ export const ZK_PROOF_SYSTEM = {
28
28
  /**
29
29
  * Default Chain ID for Quorum
30
30
  */
31
- export const DEFAULT_CHAIN_ID = 1337;
31
+ const DEFAULT_CHAIN_ID = 1337;
32
+
33
+ module.exports = {
34
+ TX_TYPE,
35
+ PQC_TYPE,
36
+ ZK_PROOF_SYSTEM,
37
+ DEFAULT_CHAIN_ID,
38
+ };
package/src/contract.js CHANGED
@@ -3,13 +3,13 @@
3
3
  * Supports ERC20 token transfers and contract calls
4
4
  */
5
5
 
6
- import { ethers } from 'ethers';
7
- import { LegacyTransaction, PQCLegacyTransaction, HybridLegacyTransaction } from './transaction.js';
6
+ const { ethers } = require('ethers');
7
+ const { LegacyTransaction, PQCLegacyTransaction, HybridLegacyTransaction } = require('./transaction.js');
8
8
 
9
9
  /**
10
10
  * Contract class for interacting with smart contracts
11
11
  */
12
- export class Contract {
12
+ class Contract {
13
13
  constructor(address, abi, provider, wallet = null) {
14
14
  this.address = address;
15
15
  this.abi = abi;
@@ -81,7 +81,7 @@ export class Contract {
81
81
  * ERC20 Token Contract
82
82
  * Simplified interface for ERC20 token operations
83
83
  */
84
- export class ERC20Token extends Contract {
84
+ class ERC20Token extends Contract {
85
85
  constructor(address, provider, wallet = null) {
86
86
  const erc20Abi = [
87
87
  'function name() view returns (string)',
@@ -160,10 +160,6 @@ export class ERC20Token extends Contract {
160
160
  */
161
161
  async transferPQC(wallet, provider, to, amount, txOptions = {}) {
162
162
  const data = this.encodeFunctionData('transfer', [to, amount]);
163
- // Ensure wallet has address
164
- if (!wallet.address) {
165
- await wallet._ensureKeyPair();
166
- }
167
163
  const nonce = await provider.getTransactionCount(wallet.address, 'pending');
168
164
 
169
165
  const tx = new PQCLegacyTransaction({
@@ -176,7 +172,7 @@ export class ERC20Token extends Contract {
176
172
  data: data,
177
173
  });
178
174
 
179
- await tx.sign(wallet);
175
+ tx.sign(wallet);
180
176
  const serialized = tx.getHex();
181
177
  return await provider.sendRawTransaction(serialized);
182
178
  }
@@ -192,9 +188,7 @@ export class ERC20Token extends Contract {
192
188
  */
193
189
  async transferHybrid(wallet, provider, to, amount, txOptions = {}) {
194
190
  const data = this.encodeFunctionData('transfer', [to, amount]);
195
- // Ensure wallet has address
196
- const address = await wallet.getAddress();
197
- const nonce = await provider.getTransactionCount(address, 'pending');
191
+ const nonce = await provider.getTransactionCount(wallet.address, 'pending');
198
192
 
199
193
  const tx = new HybridLegacyTransaction({
200
194
  chainId: txOptions.chainId || 1337,
@@ -206,8 +200,13 @@ export class ERC20Token extends Contract {
206
200
  data: data,
207
201
  });
208
202
 
209
- await tx.sign(wallet.ecdsaWallet, wallet.pqcWallet);
203
+ tx.sign(wallet.ecdsaWallet, wallet.pqcWallet);
210
204
  const serialized = tx.getHex();
211
205
  return await provider.sendRawTransaction(serialized);
212
206
  }
213
207
  }
208
+
209
+ module.exports = {
210
+ Contract,
211
+ ERC20Token,
212
+ };
package/src/index.js CHANGED
@@ -4,13 +4,13 @@
4
4
  */
5
5
 
6
6
  // Providers
7
- export { QuorumProvider } from './provider.js';
7
+ const { QuorumProvider } = require('./provider.js');
8
8
 
9
9
  // Wallets
10
- export { ECDSAWallet, PQCWallet, HybridWallet } from './wallet.js';
10
+ const { ECDSAWallet, PQCWallet, HybridWallet } = require('./wallet.js');
11
11
 
12
12
  // Transactions
13
- export {
13
+ const {
14
14
  LegacyTransaction,
15
15
  PQCLegacyTransaction,
16
16
  HybridLegacyTransaction,
@@ -18,20 +18,63 @@ export {
18
18
  PQCAccessListTransaction,
19
19
  DynamicFeeTransaction,
20
20
  PQCDynamicFeeTransaction,
21
- } from './transaction.js';
21
+ } = require('./transaction.js');
22
22
 
23
23
  // ZK Transactions
24
- export { ZKTransaction } from './zk-transaction.js';
24
+ const { ZKTransaction } = require('./zk-transaction.js');
25
25
 
26
26
  // Contracts
27
- export { Contract, ERC20Token } from './contract.js';
27
+ const { Contract, ERC20Token } = require('./contract.js');
28
28
 
29
29
  // Constants
30
- export { TX_TYPE, PQC_TYPE, ZK_PROOF_SYSTEM, DEFAULT_CHAIN_ID } from './constants.js';
30
+ const { TX_TYPE, PQC_TYPE, ZK_PROOF_SYSTEM, DEFAULT_CHAIN_ID } = require('./constants.js');
31
31
 
32
32
  // Utilities
33
- export { derivePQCAddress, deriveHybridAddress, isValidAddress } from './utils/address.js';
34
- export { encodeUint64, encodeBigInt, encodeSignature } from './utils/rlp.js';
33
+ const { derivePQCAddress, deriveHybridAddress, isValidAddress } = require('./utils/address.js');
34
+ const { encodeUint64, encodeBigInt, encodeSignature } = require('./utils/rlp.js');
35
35
 
36
36
  // Re-export ethers utilities for convenience
37
- export { ethers } from 'ethers';
37
+ const { ethers } = require('ethers');
38
+
39
+ module.exports = {
40
+ // Providers
41
+ QuorumProvider,
42
+
43
+ // Wallets
44
+ ECDSAWallet,
45
+ PQCWallet,
46
+ HybridWallet,
47
+
48
+ // Transactions
49
+ LegacyTransaction,
50
+ PQCLegacyTransaction,
51
+ HybridLegacyTransaction,
52
+ AccessListTransaction,
53
+ PQCAccessListTransaction,
54
+ DynamicFeeTransaction,
55
+ PQCDynamicFeeTransaction,
56
+
57
+ // ZK Transactions
58
+ ZKTransaction,
59
+
60
+ // Contracts
61
+ Contract,
62
+ ERC20Token,
63
+
64
+ // Constants
65
+ TX_TYPE,
66
+ PQC_TYPE,
67
+ ZK_PROOF_SYSTEM,
68
+ DEFAULT_CHAIN_ID,
69
+
70
+ // Utilities
71
+ derivePQCAddress,
72
+ deriveHybridAddress,
73
+ isValidAddress,
74
+ encodeUint64,
75
+ encodeBigInt,
76
+ encodeSignature,
77
+
78
+ // Ethers
79
+ ethers,
80
+ };
package/src/provider.js CHANGED
@@ -3,9 +3,9 @@
3
3
  * Extends ethers.js JsonRpcProvider with Quorum-specific methods
4
4
  */
5
5
 
6
- import { ethers } from 'ethers';
6
+ const { ethers } = require('ethers');
7
7
 
8
- export class QuorumProvider extends ethers.providers.JsonRpcProvider {
8
+ class QuorumProvider extends ethers.providers.JsonRpcProvider {
9
9
  constructor(url, network) {
10
10
  super(url, network);
11
11
  this.url = url;
@@ -93,3 +93,7 @@ export class QuorumProvider extends ethers.providers.JsonRpcProvider {
93
93
  return await super.getBlock(blockNumber);
94
94
  }
95
95
  }
96
+
97
+ module.exports = {
98
+ QuorumProvider,
99
+ };
@@ -3,67 +3,21 @@
3
3
  * Supports Legacy, AccessList, DynamicFee transactions with ECDSA, PQC, and Hybrid signatures
4
4
  */
5
5
 
6
- import { ethers } from 'ethers';
7
- import { createRequire } from 'module';
8
- import { TX_TYPE, PQC_TYPE, DEFAULT_CHAIN_ID } from './constants.js';
9
- import { encodeUint64, encodeBigInt, encodeSignature } from './utils/rlp.js';
6
+ const { ethers } = require('ethers');
7
+ const { TX_TYPE, PQC_TYPE, DEFAULT_CHAIN_ID } = require('./constants.js');
8
+ const { encodeUint64, encodeBigInt, encodeSignature } = require('./utils/rlp.js');
10
9
 
11
10
  // Import dilithium-crystals package
12
- // Use createRequire to handle both ES modules and CommonJS
13
- const require = createRequire(import.meta.url);
14
-
15
- // Lazy load dilithium-crystals to avoid top-level await issues
16
- let dilithiumCache = null;
17
-
18
- async function getDilithium() {
19
- if (dilithiumCache) {
20
- return dilithiumCache;
21
- }
22
-
23
- try {
24
- // Try ES module import first
25
- const dilithiumModule = await import('dilithium-crystals');
26
- dilithiumCache = dilithiumModule.default || dilithiumModule;
27
- } catch (e) {
28
- // Fallback to CommonJS require
29
- try {
30
- dilithiumCache = require('dilithium-crystals');
31
- dilithiumCache = dilithiumCache.default || dilithiumCache;
32
- } catch (e2) {
33
- throw new Error(
34
- `Failed to import dilithium-crystals: ${e.message}\n` +
35
- `Please ensure dilithium-crystals is installed: npm install dilithium-crystals`
36
- );
37
- }
38
- }
39
-
40
- return dilithiumCache;
41
- }
42
-
43
- // Helper function to sign with dilithium
44
- async function signWithDilithium(secretKey, hash) {
45
- const dilithium = await getDilithium();
46
- if (dilithium.sign) {
47
- return dilithium.sign(secretKey, hash);
48
- } else if (dilithium.signWithContext) {
49
- const ctx = new TextEncoder().encode('ML-DSA-65');
50
- return dilithium.signWithContext(secretKey, hash, ctx);
51
- } else {
52
- throw new Error('dilithium-crystals does not expose sign method');
53
- }
54
- }
55
-
56
- // Helper function to verify with dilithium
57
- async function verifyWithDilithium(publicKey, hash, signature) {
58
- const dilithium = await getDilithium();
59
- if (dilithium.verify) {
60
- return dilithium.verify(publicKey, hash, signature);
61
- } else if (dilithium.verifyWithContext) {
62
- const ctx = new TextEncoder().encode('ML-DSA-65');
63
- return dilithium.verifyWithContext(publicKey, hash, signature, ctx);
64
- } else {
65
- throw new Error('dilithium-crystals does not expose verify method');
66
- }
11
+ let dilithium;
12
+ try {
13
+ dilithium = require('dilithium-crystals');
14
+ // Handle both default export and named export patterns
15
+ dilithium = dilithium.default || dilithium;
16
+ } catch (e) {
17
+ throw new Error(
18
+ `Failed to import dilithium-crystals: ${e.message}\n` +
19
+ `Please ensure dilithium-crystals is installed: npm install dilithium-crystals`
20
+ );
67
21
  }
68
22
 
69
23
  /**
@@ -82,7 +36,7 @@ class BaseTransaction {
82
36
  /**
83
37
  * Legacy ECDSA Transaction (Type 0)
84
38
  */
85
- export class LegacyTransaction extends BaseTransaction {
39
+ class LegacyTransaction extends BaseTransaction {
86
40
  constructor(params) {
87
41
  super(params);
88
42
  this.type = TX_TYPE.LEGACY;
@@ -122,7 +76,7 @@ export class LegacyTransaction extends BaseTransaction {
122
76
  /**
123
77
  * Legacy PQC-only Transaction (Type 0 with PQC)
124
78
  */
125
- export class PQCLegacyTransaction extends BaseTransaction {
79
+ class PQCLegacyTransaction extends BaseTransaction {
126
80
  constructor(params) {
127
81
  super(params);
128
82
  this.type = TX_TYPE.LEGACY;
@@ -164,22 +118,38 @@ export class PQCLegacyTransaction extends BaseTransaction {
164
118
  /**
165
119
  * Sign with PQC wallet
166
120
  * @param {PQCWallet} wallet - PQC wallet
167
- * @returns {Promise<PQCLegacyTransaction>} This transaction
121
+ * @returns {PQCLegacyTransaction} This transaction
168
122
  */
169
- async sign(wallet) {
123
+ sign(wallet) {
170
124
  const hash = ethers.getBytes(this.getSigningHash());
171
- this.pqcPubKey = wallet.publicKey || (await wallet._ensureKeyPair(), wallet.publicKey);
172
- this.pqcSig = await signWithDilithium(wallet.secretKey, hash);
125
+ this.pqcPubKey = wallet.publicKey;
126
+ // dilithium-crystals API: sign(secretKey, message) or signWithContext(secretKey, message, ctx)
127
+ if (dilithium.sign) {
128
+ this.pqcSig = dilithium.sign(wallet.secretKey, hash);
129
+ } else if (dilithium.signWithContext) {
130
+ const ctx = new TextEncoder().encode('ML-DSA-65');
131
+ this.pqcSig = dilithium.signWithContext(wallet.secretKey, hash, ctx);
132
+ } else {
133
+ throw new Error('dilithium-crystals does not expose sign method');
134
+ }
173
135
  this.v = Number(this.chainId) * 2 + 35;
174
136
  this.r = '0x0';
175
137
  this.s = '0x0';
176
138
  return this;
177
139
  }
178
140
 
179
- async verify() {
141
+ verify() {
180
142
  if (!this.pqcSig || !this.pqcPubKey) return false;
181
143
  const hash = ethers.getBytes(this.getSigningHash());
182
- return await verifyWithDilithium(this.pqcPubKey, hash, this.pqcSig);
144
+ // dilithium-crystals API: verify(publicKey, message, signature) or verifyWithContext
145
+ if (dilithium.verify) {
146
+ return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
147
+ } else if (dilithium.verifyWithContext) {
148
+ const ctx = new TextEncoder().encode('ML-DSA-65');
149
+ return dilithium.verifyWithContext(this.pqcPubKey, hash, this.pqcSig, ctx);
150
+ } else {
151
+ throw new Error('dilithium-crystals does not expose verify method');
152
+ }
183
153
  }
184
154
 
185
155
  serialize() {
@@ -222,7 +192,7 @@ export class PQCLegacyTransaction extends BaseTransaction {
222
192
  /**
223
193
  * Legacy Hybrid Transaction (Type 0 with ECDSA + PQC)
224
194
  */
225
- export class HybridLegacyTransaction extends BaseTransaction {
195
+ class HybridLegacyTransaction extends BaseTransaction {
226
196
  constructor(params) {
227
197
  super(params);
228
198
  this.type = TX_TYPE.LEGACY;
@@ -265,9 +235,9 @@ export class HybridLegacyTransaction extends BaseTransaction {
265
235
  * Sign with both ECDSA and PQC wallets
266
236
  * @param {ECDSAWallet} ecdsaWallet - ECDSA wallet
267
237
  * @param {PQCWallet} pqcWallet - PQC wallet
268
- * @returns {Promise<HybridLegacyTransaction>} This transaction
238
+ * @returns {HybridLegacyTransaction} This transaction
269
239
  */
270
- async sign(ecdsaWallet, pqcWallet) {
240
+ sign(ecdsaWallet, pqcWallet) {
271
241
  const hash = this.getSigningHash();
272
242
  const hashBytes = ethers.getBytes(hash);
273
243
 
@@ -279,19 +249,30 @@ export class HybridLegacyTransaction extends BaseTransaction {
279
249
  this.s = ecdsaSig.s;
280
250
 
281
251
  // PQC signature
282
- if (!pqcWallet.publicKey) {
283
- await pqcWallet._ensureKeyPair();
284
- }
285
252
  this.pqcPubKey = pqcWallet.publicKey;
286
- this.pqcSig = await signWithDilithium(pqcWallet.secretKey, hashBytes);
253
+ if (dilithium.sign) {
254
+ this.pqcSig = dilithium.sign(pqcWallet.secretKey, hashBytes);
255
+ } else if (dilithium.signWithContext) {
256
+ const ctx = new TextEncoder().encode('ML-DSA-65');
257
+ this.pqcSig = dilithium.signWithContext(pqcWallet.secretKey, hashBytes, ctx);
258
+ } else {
259
+ throw new Error('dilithium-crystals does not expose sign method');
260
+ }
287
261
 
288
262
  return this;
289
263
  }
290
264
 
291
- async verify() {
265
+ verify() {
292
266
  if (!this.pqcSig || !this.pqcPubKey) return false;
293
267
  const hash = ethers.getBytes(this.getSigningHash());
294
- return await verifyWithDilithium(this.pqcPubKey, hash, this.pqcSig);
268
+ if (dilithium.verify) {
269
+ return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
270
+ } else if (dilithium.verifyWithContext) {
271
+ const ctx = new TextEncoder().encode('ML-DSA-65');
272
+ return dilithium.verifyWithContext(this.pqcPubKey, hash, this.pqcSig, ctx);
273
+ } else {
274
+ throw new Error('dilithium-crystals does not expose verify method');
275
+ }
295
276
  }
296
277
 
297
278
  serialize() {
@@ -334,7 +315,7 @@ export class HybridLegacyTransaction extends BaseTransaction {
334
315
  /**
335
316
  * AccessList Transaction (Type 1) - ECDSA
336
317
  */
337
- export class AccessListTransaction extends BaseTransaction {
318
+ class AccessListTransaction extends BaseTransaction {
338
319
  constructor(params) {
339
320
  super(params);
340
321
  this.type = TX_TYPE.ACCESS_LIST;
@@ -366,7 +347,7 @@ export class AccessListTransaction extends BaseTransaction {
366
347
  /**
367
348
  * AccessList PQC Transaction (Type 1 with PQC)
368
349
  */
369
- export class PQCAccessListTransaction extends BaseTransaction {
350
+ class PQCAccessListTransaction extends BaseTransaction {
370
351
  constructor(params) {
371
352
  super(params);
372
353
  this.type = TX_TYPE.ACCESS_LIST;
@@ -410,20 +391,31 @@ export class PQCAccessListTransaction extends BaseTransaction {
410
391
  return ethers.keccak256(ethers.hexlify(prefixed));
411
392
  }
412
393
 
413
- async sign(wallet) {
394
+ sign(wallet) {
414
395
  const hash = ethers.getBytes(this.getSigningHash());
415
- if (!wallet.publicKey) {
416
- await wallet._ensureKeyPair();
417
- }
418
396
  this.pqcPubKey = wallet.publicKey;
419
- this.pqcSig = await signWithDilithium(wallet.secretKey, hash);
397
+ if (dilithium.sign) {
398
+ this.pqcSig = dilithium.sign(wallet.secretKey, hash);
399
+ } else if (dilithium.signWithContext) {
400
+ const ctx = new TextEncoder().encode('ML-DSA-65');
401
+ this.pqcSig = dilithium.signWithContext(wallet.secretKey, hash, ctx);
402
+ } else {
403
+ throw new Error('dilithium-crystals does not expose sign method');
404
+ }
420
405
  return this;
421
406
  }
422
407
 
423
- async verify() {
408
+ verify() {
424
409
  if (!this.pqcSig || !this.pqcPubKey) return false;
425
410
  const hash = ethers.getBytes(this.getSigningHash());
426
- return await verifyWithDilithium(this.pqcPubKey, hash, this.pqcSig);
411
+ if (dilithium.verify) {
412
+ return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
413
+ } else if (dilithium.verifyWithContext) {
414
+ const ctx = new TextEncoder().encode('ML-DSA-65');
415
+ return dilithium.verifyWithContext(this.pqcPubKey, hash, this.pqcSig, ctx);
416
+ } else {
417
+ throw new Error('dilithium-crystals does not expose verify method');
418
+ }
427
419
  }
428
420
 
429
421
  serialize() {
@@ -477,7 +469,7 @@ export class PQCAccessListTransaction extends BaseTransaction {
477
469
  /**
478
470
  * DynamicFee Transaction (Type 2) - ECDSA
479
471
  */
480
- export class DynamicFeeTransaction extends BaseTransaction {
472
+ class DynamicFeeTransaction extends BaseTransaction {
481
473
  constructor(params) {
482
474
  super(params);
483
475
  this.type = TX_TYPE.DYNAMIC_FEE;
@@ -511,7 +503,7 @@ export class DynamicFeeTransaction extends BaseTransaction {
511
503
  /**
512
504
  * DynamicFee PQC Transaction (Type 2 with PQC)
513
505
  */
514
- export class PQCDynamicFeeTransaction extends BaseTransaction {
506
+ class PQCDynamicFeeTransaction extends BaseTransaction {
515
507
  constructor(params) {
516
508
  super(params);
517
509
  this.type = TX_TYPE.DYNAMIC_FEE;
@@ -558,20 +550,31 @@ export class PQCDynamicFeeTransaction extends BaseTransaction {
558
550
  return ethers.keccak256(ethers.hexlify(prefixed));
559
551
  }
560
552
 
561
- async sign(wallet) {
553
+ sign(wallet) {
562
554
  const hash = ethers.getBytes(this.getSigningHash());
563
- if (!wallet.publicKey) {
564
- await wallet._ensureKeyPair();
565
- }
566
555
  this.pqcPubKey = wallet.publicKey;
567
- this.pqcSig = await signWithDilithium(wallet.secretKey, hash);
556
+ if (dilithium.sign) {
557
+ this.pqcSig = dilithium.sign(wallet.secretKey, hash);
558
+ } else if (dilithium.signWithContext) {
559
+ const ctx = new TextEncoder().encode('ML-DSA-65');
560
+ this.pqcSig = dilithium.signWithContext(wallet.secretKey, hash, ctx);
561
+ } else {
562
+ throw new Error('dilithium-crystals does not expose sign method');
563
+ }
568
564
  return this;
569
565
  }
570
566
 
571
- async verify() {
567
+ verify() {
572
568
  if (!this.pqcSig || !this.pqcPubKey) return false;
573
569
  const hash = ethers.getBytes(this.getSigningHash());
574
- return await verifyWithDilithium(this.pqcPubKey, hash, this.pqcSig);
570
+ if (dilithium.verify) {
571
+ return dilithium.verify(this.pqcPubKey, hash, this.pqcSig);
572
+ } else if (dilithium.verifyWithContext) {
573
+ const ctx = new TextEncoder().encode('ML-DSA-65');
574
+ return dilithium.verifyWithContext(this.pqcPubKey, hash, this.pqcSig, ctx);
575
+ } else {
576
+ throw new Error('dilithium-crystals does not expose verify method');
577
+ }
575
578
  }
576
579
 
577
580
  serialize() {
@@ -623,3 +626,13 @@ export class PQCDynamicFeeTransaction extends BaseTransaction {
623
626
  return ethers.hexlify(this.serialize());
624
627
  }
625
628
  }
629
+
630
+ module.exports = {
631
+ LegacyTransaction,
632
+ PQCLegacyTransaction,
633
+ HybridLegacyTransaction,
634
+ AccessListTransaction,
635
+ PQCAccessListTransaction,
636
+ DynamicFeeTransaction,
637
+ PQCDynamicFeeTransaction,
638
+ };
@@ -3,14 +3,14 @@
3
3
  * Handles address derivation for PQC and Hybrid addresses
4
4
  */
5
5
 
6
- import { ethers } from 'ethers';
6
+ const { ethers } = require('ethers');
7
7
 
8
8
  /**
9
9
  * Derive PQC address from Dilithium public key
10
10
  * @param {Uint8Array} publicKey - Dilithium public key
11
11
  * @returns {string} Ethereum address
12
12
  */
13
- export function derivePQCAddress(publicKey) {
13
+ function derivePQCAddress(publicKey) {
14
14
  const hash = ethers.keccak256(publicKey);
15
15
  return ethers.getAddress('0x' + hash.slice(-40));
16
16
  }
@@ -21,7 +21,7 @@ export function derivePQCAddress(publicKey) {
21
21
  * @param {Uint8Array} dilithiumPublicKey - Dilithium public key
22
22
  * @returns {string} Hybrid Ethereum address
23
23
  */
24
- export function deriveHybridAddress(ecdsaPublicKey, dilithiumPublicKey) {
24
+ function deriveHybridAddress(ecdsaPublicKey, dilithiumPublicKey) {
25
25
  // Remove 0x04 prefix from ECDSA public key if present
26
26
  let ecdsaBytes = ecdsaPublicKey;
27
27
  if (ecdsaBytes.length === 65 && ecdsaBytes[0] === 4) {
@@ -43,6 +43,12 @@ export function deriveHybridAddress(ecdsaPublicKey, dilithiumPublicKey) {
43
43
  * @param {string} address - Address to validate
44
44
  * @returns {boolean}
45
45
  */
46
- export function isValidAddress(address) {
46
+ function isValidAddress(address) {
47
47
  return ethers.utils.isAddress(address);
48
48
  }
49
+
50
+ module.exports = {
51
+ derivePQCAddress,
52
+ deriveHybridAddress,
53
+ isValidAddress,
54
+ };
package/src/utils/rlp.js CHANGED
@@ -3,13 +3,13 @@
3
3
  * Handles proper encoding for Go RLP compatibility
4
4
  */
5
5
 
6
- import { ethers } from 'ethers';
6
+ const { ethers } = require('ethers');
7
7
 
8
8
  /**
9
9
  * Encode uint64 value for RLP as hex string
10
10
  * In Go RLP, uint64(0) encodes as empty bytes, non-zero as canonical bytes
11
11
  */
12
- export function encodeUint64(value) {
12
+ function encodeUint64(value) {
13
13
  if (value === 0 || value === 0n || value === null || value === undefined) {
14
14
  return '0x';
15
15
  }
@@ -21,7 +21,7 @@ export function encodeUint64(value) {
21
21
  * Encode *big.Int value for RLP as hex string
22
22
  * Go RLP encodes *big.Int(0) as 0x80 (empty bytes), NOT 0x00!
23
23
  */
24
- export function encodeBigInt(value) {
24
+ function encodeBigInt(value) {
25
25
  if (value === 0 || value === 0n || value === null || value === undefined) {
26
26
  return '0x';
27
27
  }
@@ -33,7 +33,7 @@ export function encodeBigInt(value) {
33
33
  * Encode signature value (R, S) for RLP as hex string
34
34
  * Removes leading zeros for canonical form (required for *big.Int in Go RLP)
35
35
  */
36
- export function encodeSignature(value) {
36
+ function encodeSignature(value) {
37
37
  if (!value || value === '0x0' || value === '0x' || value === '0x00') {
38
38
  return '0x';
39
39
  }
@@ -54,3 +54,9 @@ export function encodeSignature(value) {
54
54
  bytes = bytes.slice(startIdx);
55
55
  return ethers.hexlify(bytes);
56
56
  }
57
+
58
+ module.exports = {
59
+ encodeUint64,
60
+ encodeBigInt,
61
+ encodeSignature,
62
+ };
package/src/wallet.js CHANGED
@@ -3,47 +3,27 @@
3
3
  * Supports ECDSA, PQC (Dilithium), and Hybrid wallets
4
4
  */
5
5
 
6
- import { ethers } from 'ethers';
7
- import { createRequire } from 'module';
8
- import { derivePQCAddress, deriveHybridAddress } from './utils/address.js';
6
+ const { ethers } = require('ethers');
7
+ const { derivePQCAddress, deriveHybridAddress } = require('./utils/address.js');
9
8
 
10
9
  // Import dilithium-crystals package
11
10
  // This package provides Dilithium3 (ML-DSA-65 equivalent) implementation
12
- // Use createRequire to handle both ES modules and CommonJS
13
- const require = createRequire(import.meta.url);
14
-
15
- // Lazy load dilithium-crystals to avoid top-level await issues
16
- let dilithiumCache = null;
17
-
18
- async function getDilithium() {
19
- if (dilithiumCache) {
20
- return dilithiumCache;
21
- }
22
-
23
- try {
24
- // Try ES module import first
25
- const dilithiumModule = await import('dilithium-crystals');
26
- dilithiumCache = dilithiumModule.default || dilithiumModule;
27
- } catch (e) {
28
- // Fallback to CommonJS require
29
- try {
30
- dilithiumCache = require('dilithium-crystals');
31
- dilithiumCache = dilithiumCache.default || dilithiumCache;
32
- } catch (e2) {
33
- throw new Error(
34
- `Failed to import dilithium-crystals: ${e.message}\n` +
35
- `Please ensure dilithium-crystals is installed: npm install dilithium-crystals`
36
- );
37
- }
38
- }
39
-
40
- return dilithiumCache;
11
+ let dilithium;
12
+ try {
13
+ dilithium = require('dilithium-crystals');
14
+ // Handle both default export and named export patterns
15
+ dilithium = dilithium.default || dilithium;
16
+ } catch (e) {
17
+ throw new Error(
18
+ `Failed to import dilithium-crystals: ${e.message}\n` +
19
+ `Please ensure dilithium-crystals is installed: npm install dilithium-crystals`
20
+ );
41
21
  }
42
22
 
43
23
  /**
44
24
  * ECDSA Wallet (standard Ethereum wallet)
45
25
  */
46
- export class ECDSAWallet {
26
+ class ECDSAWallet {
47
27
  constructor(privateKey, provider = null) {
48
28
  this.wallet = new ethers.Wallet(privateKey, provider);
49
29
  this.address = this.wallet.address;
@@ -81,35 +61,22 @@ export class ECDSAWallet {
81
61
  /**
82
62
  * PQC Wallet (Dilithium/ML-DSA-65)
83
63
  */
84
- export class PQCWallet {
64
+ class PQCWallet {
85
65
  constructor(secretKey = null, publicKey = null) {
86
66
  if (secretKey && publicKey) {
87
67
  this.secretKey = secretKey instanceof Uint8Array ? secretKey : new Uint8Array(secretKey);
88
68
  this.publicKey = publicKey instanceof Uint8Array ? publicKey : new Uint8Array(publicKey);
89
69
  } else {
90
- // Generate new key pair - will be done lazily on first use
91
- this.secretKey = null;
92
- this.publicKey = null;
93
- this._keyPairGenerated = false;
94
- }
95
- this.address = null; // Will be set after key generation
96
- }
97
-
98
- /**
99
- * Initialize key pair if not already done
100
- */
101
- async _ensureKeyPair() {
102
- if (this._keyPairGenerated) {
103
- return;
70
+ // Generate new key pair using dilithium-crystals
71
+ // dilithium-crystals uses keygen() which returns { publicKey, secretKey }
72
+ if (!dilithium.keygen) {
73
+ throw new Error('dilithium-crystals does not expose keygen method. Please check the package API.');
74
+ }
75
+ const keyPair = dilithium.keygen();
76
+ this.secretKey = keyPair.secretKey;
77
+ this.publicKey = keyPair.publicKey;
104
78
  }
105
-
106
- const dilithium = await getDilithium();
107
- // dilithium-crystals typically uses keygen() or generateKeyPair()
108
- const keyPair = dilithium.keygen ? dilithium.keygen() : dilithium.generateKeyPair();
109
- this.secretKey = keyPair.secretKey || keyPair.privateKey;
110
- this.publicKey = keyPair.publicKey;
111
79
  this.address = derivePQCAddress(this.publicKey);
112
- this._keyPairGenerated = true;
113
80
  }
114
81
 
115
82
  /**
@@ -126,24 +93,17 @@ export class PQCWallet {
126
93
  }
127
94
  const secret = secretKey instanceof Uint8Array ? secretKey : ethers.getBytes(secretKey);
128
95
  const pub = publicKey instanceof Uint8Array ? publicKey : ethers.getBytes(publicKey);
129
- const wallet = new PQCWallet(secret, pub);
130
- wallet.address = derivePQCAddress(wallet.publicKey);
131
- wallet._keyPairGenerated = true;
132
- return wallet;
96
+ return new PQCWallet(secret, pub);
133
97
  }
134
98
 
135
99
  /**
136
100
  * Sign a message hash
137
101
  * @param {Uint8Array} hash - Message hash (32 bytes)
138
- * @returns {Promise<Uint8Array>} Signature
102
+ * @returns {Uint8Array} Signature
139
103
  */
140
- async sign(hash) {
141
- if (!this.secretKey) {
142
- await this._ensureKeyPair();
143
- }
144
-
145
- const dilithium = await getDilithium();
146
- // dilithium-crystals API: sign(secretKey, message) or signWithContext(secretKey, message, ctx)
104
+ sign(hash) {
105
+ // dilithium-crystals API: sign(secretKey, message)
106
+ // Some implementations may require context, but we'll try without first
147
107
  if (dilithium.sign) {
148
108
  return dilithium.sign(this.secretKey, hash);
149
109
  } else if (dilithium.signWithContext) {
@@ -158,15 +118,10 @@ export class PQCWallet {
158
118
  * Verify a signature
159
119
  * @param {Uint8Array} hash - Message hash
160
120
  * @param {Uint8Array} signature - Signature to verify
161
- * @returns {Promise<boolean>} True if signature is valid
121
+ * @returns {boolean} True if signature is valid
162
122
  */
163
- async verify(hash, signature) {
164
- if (!this.publicKey) {
165
- throw new Error('Public key not set');
166
- }
167
-
168
- const dilithium = await getDilithium();
169
- // dilithium-crystals API: verify(publicKey, message, signature) or verifyWithContext
123
+ verify(hash, signature) {
124
+ // dilithium-crystals API: verify(publicKey, message, signature)
170
125
  if (dilithium.verify) {
171
126
  return dilithium.verify(this.publicKey, hash, signature);
172
127
  } else if (dilithium.verifyWithContext) {
@@ -179,23 +134,17 @@ export class PQCWallet {
179
134
 
180
135
  /**
181
136
  * Get public key as hex string
182
- * @returns {Promise<string>} Public key (hex)
137
+ * @returns {string} Public key (hex)
183
138
  */
184
- async getPublicKeyHex() {
185
- if (!this.publicKey) {
186
- await this._ensureKeyPair();
187
- }
139
+ getPublicKeyHex() {
188
140
  return ethers.hexlify(this.publicKey);
189
141
  }
190
142
 
191
143
  /**
192
144
  * Get secret key as hex string (use with caution!)
193
- * @returns {Promise<string>} Secret key (hex)
145
+ * @returns {string} Secret key (hex)
194
146
  */
195
- async getSecretKeyHex() {
196
- if (!this.secretKey) {
197
- await this._ensureKeyPair();
198
- }
147
+ getSecretKeyHex() {
199
148
  return ethers.hexlify(this.secretKey);
200
149
  }
201
150
  }
@@ -203,36 +152,17 @@ export class PQCWallet {
203
152
  /**
204
153
  * Hybrid Wallet (ECDSA + PQC)
205
154
  */
206
- export class HybridWallet {
155
+ class HybridWallet {
207
156
  constructor(ecdsaWallet, pqcWallet) {
208
157
  if (!ecdsaWallet || !pqcWallet) {
209
158
  throw new Error('Both ECDSA and PQC wallets are required for Hybrid wallet');
210
159
  }
211
160
  this.ecdsaWallet = ecdsaWallet instanceof ECDSAWallet ? ecdsaWallet : new ECDSAWallet(ecdsaWallet);
212
161
  this.pqcWallet = pqcWallet instanceof PQCWallet ? pqcWallet : new PQCWallet();
213
- // Address will be computed when PQC wallet is ready
214
- this.address = null;
215
- }
216
-
217
- /**
218
- * Get the hybrid address (computed from ECDSA + PQC public keys)
219
- * @returns {Promise<string>} Hybrid address
220
- */
221
- async getAddress() {
222
- if (this.address) {
223
- return this.address;
224
- }
225
-
226
- // Ensure PQC wallet has keys
227
- if (!this.pqcWallet.publicKey) {
228
- await this.pqcWallet._ensureKeyPair();
229
- }
230
-
231
162
  this.address = deriveHybridAddress(
232
163
  ethers.getBytes(this.ecdsaWallet.getPublicKey()),
233
164
  this.pqcWallet.publicKey
234
165
  );
235
- return this.address;
236
166
  }
237
167
 
238
168
  /**
@@ -245,12 +175,7 @@ export class HybridWallet {
245
175
  static fromKeys(ecdsaPrivateKey, pqcSecretKey, pqcPublicKey) {
246
176
  const ecdsaWallet = new ECDSAWallet(ecdsaPrivateKey);
247
177
  const pqcWallet = new PQCWallet(pqcSecretKey, pqcPublicKey);
248
- const wallet = new HybridWallet(ecdsaWallet, pqcWallet);
249
- wallet.address = deriveHybridAddress(
250
- ethers.getBytes(ecdsaWallet.getPublicKey()),
251
- pqcWallet.publicKey
252
- );
253
- return wallet;
178
+ return new HybridWallet(ecdsaWallet, pqcWallet);
254
179
  }
255
180
 
256
181
  /**
@@ -263,3 +188,9 @@ export class HybridWallet {
263
188
  return new HybridWallet(connectedECDSA, this.pqcWallet);
264
189
  }
265
190
  }
191
+
192
+ module.exports = {
193
+ ECDSAWallet,
194
+ PQCWallet,
195
+ HybridWallet,
196
+ };
@@ -2,14 +2,14 @@
2
2
  * Zero-Knowledge Proof Transaction Support
3
3
  */
4
4
 
5
- import { ethers } from 'ethers';
6
- import { TX_TYPE, ZK_PROOF_SYSTEM } from './constants.js';
5
+ const { ethers } = require('ethers');
6
+ const { TX_TYPE, ZK_PROOF_SYSTEM } = require('./constants.js');
7
7
 
8
8
  /**
9
9
  * ZK Transaction Builder
10
10
  * Creates transactions with zero-knowledge proofs
11
11
  */
12
- export class ZKTransaction {
12
+ class ZKTransaction {
13
13
  constructor(params) {
14
14
  this.type = TX_TYPE.ZK_PRIVATE;
15
15
  this.chainId = params.chainId || 1337;
@@ -93,3 +93,7 @@ export class ZKTransaction {
93
93
  return await provider.send('quorum_sendZKTransaction', [args]);
94
94
  }
95
95
  }
96
+
97
+ module.exports = {
98
+ ZKTransaction,
99
+ };
package/index.cjs DELETED
@@ -1,37 +0,0 @@
1
- /**
2
- * CommonJS entry point for @cheny56/node-client
3
- *
4
- * NOTE: This library is built as ES modules. For CommonJS compatibility,
5
- * you need to use dynamic import() instead of require().
6
- *
7
- * Example:
8
- * const { QuorumProvider } = await import('@cheny56/node-client');
9
- *
10
- * Or use ES modules in your project:
11
- * import { QuorumProvider } from '@cheny56/node-client';
12
- */
13
-
14
- // Re-export using dynamic import
15
- // This allows require() to work, but returns a Promise
16
- const modPromise = import('./src/index.js');
17
-
18
- // For synchronous require(), we need to throw a helpful error
19
- // and suggest using import() or ES modules
20
- module.exports = new Proxy({}, {
21
- get(target, prop) {
22
- if (prop === 'then' || prop === 'catch' || prop === 'finally') {
23
- // Make it thenable so it works with await import()
24
- return modPromise.then(mod => mod[prop]).bind(modPromise);
25
- }
26
-
27
- throw new Error(
28
- `Cannot access '${prop}' synchronously. ` +
29
- `This package uses ES modules. Please use:\n` +
30
- ` const { ${prop} } = await import('@cheny56/node-client');\n` +
31
- `Or switch your project to ES modules by adding "type": "module" to package.json`
32
- );
33
- }
34
- });
35
-
36
- // Also export as a Promise for await import() usage
37
- module.exports.default = modPromise;