@cheny56/node-client 1.0.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/wallet.js ADDED
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Wallet Classes
3
+ * Supports ECDSA, PQC (Dilithium), and Hybrid wallets
4
+ */
5
+
6
+ import { ethers } from 'ethers';
7
+ import { ml_dsa65 } from '@noble/post-quantum/ml-dsa';
8
+ import { derivePQCAddress, deriveHybridAddress } from './utils/address.js';
9
+
10
+ /**
11
+ * ECDSA Wallet (standard Ethereum wallet)
12
+ */
13
+ export class ECDSAWallet {
14
+ constructor(privateKey, provider = null) {
15
+ this.wallet = new ethers.Wallet(privateKey, provider);
16
+ this.address = this.wallet.address;
17
+ this.privateKey = privateKey;
18
+ this.provider = provider;
19
+ }
20
+
21
+ /**
22
+ * Connect wallet to a provider
23
+ * @param {QuorumProvider} provider - Provider instance
24
+ * @returns {ECDSAWallet} New wallet instance connected to provider
25
+ */
26
+ connect(provider) {
27
+ return new ECDSAWallet(this.privateKey, provider);
28
+ }
29
+
30
+ /**
31
+ * Get public key
32
+ * @returns {string} Public key (hex)
33
+ */
34
+ getPublicKey() {
35
+ return this.wallet.publicKey;
36
+ }
37
+
38
+ /**
39
+ * Sign a message
40
+ * @param {string|Uint8Array} message - Message to sign
41
+ * @returns {Promise<string>} Signature
42
+ */
43
+ async signMessage(message) {
44
+ return await this.wallet.signMessage(message);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * PQC Wallet (Dilithium/ML-DSA-65)
50
+ */
51
+ export class PQCWallet {
52
+ constructor(secretKey = null, publicKey = null) {
53
+ if (secretKey && publicKey) {
54
+ this.secretKey = secretKey instanceof Uint8Array ? secretKey : new Uint8Array(secretKey);
55
+ this.publicKey = publicKey instanceof Uint8Array ? publicKey : new Uint8Array(publicKey);
56
+ } else {
57
+ // Generate new key pair
58
+ const keyPair = ml_dsa65.keygen();
59
+ this.secretKey = keyPair.secretKey;
60
+ this.publicKey = keyPair.publicKey;
61
+ }
62
+ this.address = derivePQCAddress(this.publicKey);
63
+ }
64
+
65
+ /**
66
+ * Create wallet from secret key
67
+ * Note: In practice, you would derive the public key from the secret key.
68
+ * This is a placeholder - full implementation would use key derivation.
69
+ * @param {Uint8Array|string} secretKey - Secret key
70
+ * @param {Uint8Array|string} publicKey - Public key (required if secretKey provided)
71
+ * @returns {PQCWallet} Wallet instance
72
+ */
73
+ static fromSecretKey(secretKey, publicKey) {
74
+ if (!secretKey || !publicKey) {
75
+ throw new Error('Both secretKey and publicKey are required');
76
+ }
77
+ const secret = secretKey instanceof Uint8Array ? secretKey : ethers.getBytes(secretKey);
78
+ const pub = publicKey instanceof Uint8Array ? publicKey : ethers.getBytes(publicKey);
79
+ return new PQCWallet(secret, pub);
80
+ }
81
+
82
+ /**
83
+ * Sign a message hash
84
+ * @param {Uint8Array} hash - Message hash (32 bytes)
85
+ * @returns {Uint8Array} Signature
86
+ */
87
+ sign(hash) {
88
+ const ctx = new TextEncoder().encode('ML-DSA-65');
89
+ return ml_dsa65.sign(this.secretKey, hash, ctx);
90
+ }
91
+
92
+ /**
93
+ * Verify a signature
94
+ * @param {Uint8Array} hash - Message hash
95
+ * @param {Uint8Array} signature - Signature to verify
96
+ * @returns {boolean} True if signature is valid
97
+ */
98
+ verify(hash, signature) {
99
+ const ctx = new TextEncoder().encode('ML-DSA-65');
100
+ return ml_dsa65.verify(this.publicKey, hash, signature, ctx);
101
+ }
102
+
103
+ /**
104
+ * Get public key as hex string
105
+ * @returns {string} Public key (hex)
106
+ */
107
+ getPublicKeyHex() {
108
+ return ethers.hexlify(this.publicKey);
109
+ }
110
+
111
+ /**
112
+ * Get secret key as hex string (use with caution!)
113
+ * @returns {string} Secret key (hex)
114
+ */
115
+ getSecretKeyHex() {
116
+ return ethers.hexlify(this.secretKey);
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Hybrid Wallet (ECDSA + PQC)
122
+ */
123
+ export class HybridWallet {
124
+ constructor(ecdsaWallet, pqcWallet) {
125
+ if (!ecdsaWallet || !pqcWallet) {
126
+ throw new Error('Both ECDSA and PQC wallets are required for Hybrid wallet');
127
+ }
128
+ this.ecdsaWallet = ecdsaWallet instanceof ECDSAWallet ? ecdsaWallet : new ECDSAWallet(ecdsaWallet);
129
+ this.pqcWallet = pqcWallet instanceof PQCWallet ? pqcWallet : new PQCWallet();
130
+ this.address = deriveHybridAddress(
131
+ ethers.getBytes(this.ecdsaWallet.getPublicKey()),
132
+ this.pqcWallet.publicKey
133
+ );
134
+ }
135
+
136
+ /**
137
+ * Create hybrid wallet from ECDSA private key and PQC key pair
138
+ * @param {string} ecdsaPrivateKey - ECDSA private key (hex)
139
+ * @param {Uint8Array} pqcSecretKey - PQC secret key
140
+ * @param {Uint8Array} pqcPublicKey - PQC public key
141
+ * @returns {HybridWallet} Hybrid wallet instance
142
+ */
143
+ static fromKeys(ecdsaPrivateKey, pqcSecretKey, pqcPublicKey) {
144
+ const ecdsaWallet = new ECDSAWallet(ecdsaPrivateKey);
145
+ const pqcWallet = new PQCWallet(pqcSecretKey, pqcPublicKey);
146
+ return new HybridWallet(ecdsaWallet, pqcWallet);
147
+ }
148
+
149
+ /**
150
+ * Connect wallet to a provider
151
+ * @param {QuorumProvider} provider - Provider instance
152
+ * @returns {HybridWallet} New wallet instance connected to provider
153
+ */
154
+ connect(provider) {
155
+ const connectedECDSA = this.ecdsaWallet.connect(provider);
156
+ return new HybridWallet(connectedECDSA, this.pqcWallet);
157
+ }
158
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Zero-Knowledge Proof Transaction Support
3
+ */
4
+
5
+ import { ethers } from 'ethers';
6
+ import { TX_TYPE, ZK_PROOF_SYSTEM } from './constants.js';
7
+
8
+ /**
9
+ * ZK Transaction Builder
10
+ * Creates transactions with zero-knowledge proofs
11
+ */
12
+ export class ZKTransaction {
13
+ constructor(params) {
14
+ this.type = TX_TYPE.ZK_PRIVATE;
15
+ this.chainId = params.chainId || 1337;
16
+ this.nonce = params.nonce || 0;
17
+ this.gasPrice = params.gasPrice || 0n;
18
+ this.gasLimit = params.gasLimit || 21000n;
19
+ this.to = params.to;
20
+ this.value = params.value || 0n;
21
+ this.data = params.data || '0x';
22
+ this.accessList = params.accessList || [];
23
+
24
+ // ZK-specific fields
25
+ this.zkProofSystem = params.zkProofSystem || ZK_PROOF_SYSTEM.GROTH16;
26
+ this.zkProof = params.zkProof || null;
27
+ this.zkPublicInputs = params.zkPublicInputs || [];
28
+ this.zkVerificationKeyHash = params.zkVerificationKeyHash || null;
29
+ this.encryptedPayload = params.encryptedPayload || null;
30
+ this.recipients = params.recipients || [];
31
+
32
+ // Private transaction fields (Quorum)
33
+ this.privateFrom = params.privateFrom || null;
34
+ this.privateFor = params.privateFor || null;
35
+ }
36
+
37
+ /**
38
+ * Create ZK transaction arguments for RPC call
39
+ * @param {string} from - Sender address
40
+ * @returns {Object} ZK transaction arguments
41
+ */
42
+ toZKTxArgs(from) {
43
+ if (!this.zkProof || !this.zkProofSystem) {
44
+ throw new Error('ZK proof and proof system are required');
45
+ }
46
+
47
+ const args = {
48
+ from: from,
49
+ zkProofSystem: this.zkProofSystem,
50
+ zkProof: this.zkProof,
51
+ };
52
+
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);
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);
60
+ if (this.accessList && this.accessList.length > 0) args.accessList = this.accessList;
61
+ if (this.zkPublicInputs && this.zkPublicInputs.length > 0) {
62
+ args.zkPublicInputs = this.zkPublicInputs.map(pi =>
63
+ typeof pi === 'string' ? pi : ethers.hexlify(pi)
64
+ );
65
+ }
66
+ if (this.zkVerificationKeyHash) {
67
+ args.zkVerificationKeyHash = typeof this.zkVerificationKeyHash === 'string'
68
+ ? this.zkVerificationKeyHash
69
+ : ethers.hexlify(this.zkVerificationKeyHash);
70
+ }
71
+ if (this.encryptedPayload) {
72
+ args.encryptedPayload = typeof this.encryptedPayload === 'string'
73
+ ? this.encryptedPayload
74
+ : ethers.hexlify(this.encryptedPayload);
75
+ }
76
+ if (this.recipients && this.recipients.length > 0) {
77
+ args.recipients = this.recipients;
78
+ }
79
+ if (this.privateFrom) args.privateFrom = this.privateFrom;
80
+ if (this.privateFor) args.privateFor = this.privateFor;
81
+
82
+ return args;
83
+ }
84
+
85
+ /**
86
+ * Send ZK transaction via RPC
87
+ * @param {QuorumProvider} provider - Provider instance
88
+ * @param {string} from - Sender address
89
+ * @returns {Promise<string>} Transaction hash
90
+ */
91
+ async send(provider, from) {
92
+ const args = this.toZKTxArgs(from);
93
+ return await provider.send('quorum_sendZKTransaction', [args]);
94
+ }
95
+ }