@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/README.md +293 -0
- package/package.json +32 -0
- package/src/constants.js +31 -0
- package/src/contract.js +207 -0
- package/src/index.js +37 -0
- package/src/provider.js +95 -0
- package/src/transaction.js +566 -0
- package/src/utils/address.js +48 -0
- package/src/utils/rlp.js +56 -0
- package/src/wallet.js +158 -0
- package/src/zk-transaction.js +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Quorum Client Library
|
|
2
|
+
|
|
3
|
+
A comprehensive JavaScript/TypeScript client library for interacting with Quorum blockchain nodes that support Post-Quantum Cryptography (PQC) and Zero-Knowledge Proofs (ZK).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Post-Quantum Cryptography (PQC)**: Full support for Dilithium/ML-DSA-65 signatures
|
|
8
|
+
- ✅ **Zero-Knowledge Proofs (ZK)**: Support for ZK-enhanced transactions
|
|
9
|
+
- ✅ **Hybrid Security**: ECDSA + PQC hybrid transactions for maximum security
|
|
10
|
+
- ✅ **Multiple Transaction Types**: Legacy (Type 0), AccessList (Type 1), DynamicFee (Type 2)
|
|
11
|
+
- ✅ **Token Support**: ERC20 token transfers with PQC and Hybrid signatures
|
|
12
|
+
- ✅ **Ethers.js Compatible**: Built on top of ethers.js for familiar API
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @quorum/client
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Basic Setup
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import { QuorumProvider, ECDSAWallet, PQCWallet, HybridWallet } from '@quorum/client';
|
|
26
|
+
|
|
27
|
+
// Connect to Quorum node
|
|
28
|
+
const provider = new QuorumProvider('http://localhost:8545');
|
|
29
|
+
|
|
30
|
+
// Create wallets
|
|
31
|
+
const ecdsaWallet = new ECDSAWallet('0x...', provider);
|
|
32
|
+
const pqcWallet = new PQCWallet(); // Generates new key pair
|
|
33
|
+
const hybridWallet = new HybridWallet(ecdsaWallet, pqcWallet);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Send Native Coin (ETH)
|
|
37
|
+
|
|
38
|
+
#### ECDSA Transaction
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import { LegacyTransaction } from '@quorum/client';
|
|
42
|
+
|
|
43
|
+
const tx = new LegacyTransaction({
|
|
44
|
+
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
|
|
45
|
+
value: ethers.utils.parseEther('1.0'),
|
|
46
|
+
gasPrice: 0n,
|
|
47
|
+
gasLimit: 21000n,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const signedTx = await tx.sign(ecdsaWallet);
|
|
51
|
+
const txHash = await provider.sendRawTransaction(signedTx);
|
|
52
|
+
const receipt = await provider.waitForTransaction(txHash);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### PQC Transaction
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
import { PQCLegacyTransaction } from '@quorum/client';
|
|
59
|
+
|
|
60
|
+
// Get nonce first
|
|
61
|
+
const nonce = await provider.getTransactionCount(pqcWallet.address, 'pending');
|
|
62
|
+
|
|
63
|
+
const tx = new PQCLegacyTransaction({
|
|
64
|
+
chainId: 1337,
|
|
65
|
+
nonce: nonce,
|
|
66
|
+
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
|
|
67
|
+
value: ethers.utils.parseEther('1.0'),
|
|
68
|
+
gasPrice: 0n,
|
|
69
|
+
gasLimit: 21000n,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
tx.sign(pqcWallet);
|
|
73
|
+
const serialized = tx.getHex();
|
|
74
|
+
const txHash = await provider.sendRawTransaction(serialized);
|
|
75
|
+
const receipt = await provider.waitForTransaction(txHash);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### Hybrid Transaction
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
import { HybridLegacyTransaction } from '@quorum/client';
|
|
82
|
+
|
|
83
|
+
const nonce = await provider.getTransactionCount(hybridWallet.address, 'pending');
|
|
84
|
+
|
|
85
|
+
const tx = new HybridLegacyTransaction({
|
|
86
|
+
chainId: 1337,
|
|
87
|
+
nonce: nonce,
|
|
88
|
+
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
|
|
89
|
+
value: ethers.utils.parseEther('1.0'),
|
|
90
|
+
gasPrice: 0n,
|
|
91
|
+
gasLimit: 21000n,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
tx.sign(hybridWallet.ecdsaWallet, hybridWallet.pqcWallet);
|
|
95
|
+
const serialized = tx.getHex();
|
|
96
|
+
const txHash = await provider.sendRawTransaction(serialized);
|
|
97
|
+
const receipt = await provider.waitForTransaction(txHash);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Send ERC20 Tokens
|
|
101
|
+
|
|
102
|
+
#### Using ECDSA
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
import { ERC20Token } from '@quorum/client';
|
|
106
|
+
|
|
107
|
+
const token = new ERC20Token(tokenAddress, provider, ecdsaWallet);
|
|
108
|
+
const tx = await token.transfer(recipientAddress, ethers.utils.parseEther('100'));
|
|
109
|
+
await tx.wait();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### Using PQC
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
import { ERC20Token } from '@quorum/client';
|
|
116
|
+
|
|
117
|
+
const token = new ERC20Token(tokenAddress, provider);
|
|
118
|
+
const txHash = await token.transferPQC(
|
|
119
|
+
pqcWallet,
|
|
120
|
+
provider,
|
|
121
|
+
recipientAddress,
|
|
122
|
+
ethers.utils.parseEther('100'),
|
|
123
|
+
{ chainId: 1337, gasPrice: 0n, gasLimit: 100000n }
|
|
124
|
+
);
|
|
125
|
+
const receipt = await provider.waitForTransaction(txHash);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Using Hybrid
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
import { ERC20Token } from '@quorum/client';
|
|
132
|
+
|
|
133
|
+
const token = new ERC20Token(tokenAddress, provider);
|
|
134
|
+
const txHash = await token.transferHybrid(
|
|
135
|
+
hybridWallet,
|
|
136
|
+
provider,
|
|
137
|
+
recipientAddress,
|
|
138
|
+
ethers.utils.parseEther('100'),
|
|
139
|
+
{ chainId: 1337, gasPrice: 0n, gasLimit: 100000n }
|
|
140
|
+
);
|
|
141
|
+
const receipt = await provider.waitForTransaction(txHash);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Zero-Knowledge Proof Transactions
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
import { ZKTransaction, ZK_PROOF_SYSTEM } from '@quorum/client';
|
|
148
|
+
|
|
149
|
+
const zkTx = new ZKTransaction({
|
|
150
|
+
to: contractAddress,
|
|
151
|
+
value: 0n,
|
|
152
|
+
data: encodedFunctionData,
|
|
153
|
+
gasPrice: 0n,
|
|
154
|
+
gasLimit: 100000n,
|
|
155
|
+
zkProofSystem: ZK_PROOF_SYSTEM.GROTH16,
|
|
156
|
+
zkProof: proofBytes,
|
|
157
|
+
zkPublicInputs: [publicInput1, publicInput2],
|
|
158
|
+
zkVerificationKeyHash: vkHash,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const txHash = await zkTx.send(provider, senderAddress);
|
|
162
|
+
const receipt = await provider.waitForTransaction(txHash);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## API Reference
|
|
166
|
+
|
|
167
|
+
### Providers
|
|
168
|
+
|
|
169
|
+
#### `QuorumProvider`
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
const provider = new QuorumProvider(rpcUrl, network);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Methods:**
|
|
176
|
+
- `sendRawTransaction(signedTx)`: Send raw transaction
|
|
177
|
+
- `getTransactionReceipt(txHash)`: Get transaction receipt
|
|
178
|
+
- `waitForTransaction(txHash, confirmations)`: Wait for transaction
|
|
179
|
+
- `getTransactionCount(address, blockTag)`: Get nonce
|
|
180
|
+
- `getBalance(address, blockTag)`: Get balance
|
|
181
|
+
- `estimateGas(transaction)`: Estimate gas
|
|
182
|
+
- `getGasPrice()`: Get current gas price
|
|
183
|
+
- `getBlockNumber()`: Get current block number
|
|
184
|
+
|
|
185
|
+
### Wallets
|
|
186
|
+
|
|
187
|
+
#### `ECDSAWallet`
|
|
188
|
+
|
|
189
|
+
Standard Ethereum wallet using ECDSA signatures.
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
const wallet = new ECDSAWallet(privateKey, provider);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### `PQCWallet`
|
|
196
|
+
|
|
197
|
+
Post-quantum wallet using Dilithium/ML-DSA-65 signatures.
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
const wallet = new PQCWallet(); // Generates new key pair
|
|
201
|
+
// or
|
|
202
|
+
const wallet = new PQCWallet(secretKey, publicKey);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Methods:**
|
|
206
|
+
- `sign(hash)`: Sign a message hash
|
|
207
|
+
- `verify(hash, signature)`: Verify a signature
|
|
208
|
+
- `getPublicKeyHex()`: Get public key as hex
|
|
209
|
+
- `getSecretKeyHex()`: Get secret key as hex (use with caution!)
|
|
210
|
+
|
|
211
|
+
#### `HybridWallet`
|
|
212
|
+
|
|
213
|
+
Hybrid wallet using both ECDSA and PQC signatures.
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
const wallet = new HybridWallet(ecdsaWallet, pqcWallet);
|
|
217
|
+
// or
|
|
218
|
+
const wallet = HybridWallet.fromKeys(ecdsaPrivateKey, pqcSecretKey, pqcPublicKey);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Transactions
|
|
222
|
+
|
|
223
|
+
#### Transaction Types
|
|
224
|
+
|
|
225
|
+
- `LegacyTransaction`: Type 0, ECDSA only
|
|
226
|
+
- `PQCLegacyTransaction`: Type 0, PQC only
|
|
227
|
+
- `HybridLegacyTransaction`: Type 0, ECDSA + PQC
|
|
228
|
+
- `AccessListTransaction`: Type 1, ECDSA only
|
|
229
|
+
- `PQCAccessListTransaction`: Type 1, PQC only
|
|
230
|
+
- `DynamicFeeTransaction`: Type 2, ECDSA only
|
|
231
|
+
- `PQCDynamicFeeTransaction`: Type 2, PQC only
|
|
232
|
+
|
|
233
|
+
#### Common Transaction Methods
|
|
234
|
+
|
|
235
|
+
- `sign(wallet)`: Sign transaction (for ECDSA)
|
|
236
|
+
- `sign(wallet)` or `sign(ecdsaWallet, pqcWallet)`: Sign transaction (for PQC/Hybrid)
|
|
237
|
+
- `getHex()`: Get serialized transaction as hex
|
|
238
|
+
- `verify()`: Verify PQC signature (for PQC transactions)
|
|
239
|
+
|
|
240
|
+
### Contracts
|
|
241
|
+
|
|
242
|
+
#### `Contract`
|
|
243
|
+
|
|
244
|
+
Generic contract interface.
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
const contract = new Contract(address, abi, provider, wallet);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### `ERC20Token`
|
|
251
|
+
|
|
252
|
+
ERC20 token interface with PQC and Hybrid support.
|
|
253
|
+
|
|
254
|
+
```javascript
|
|
255
|
+
const token = new ERC20Token(address, provider, wallet);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Methods:**
|
|
259
|
+
- `transfer(to, amount, txOptions)`: Transfer tokens (ECDSA)
|
|
260
|
+
- `transferPQC(wallet, provider, to, amount, txOptions)`: Transfer tokens (PQC)
|
|
261
|
+
- `transferHybrid(wallet, provider, to, amount, txOptions)`: Transfer tokens (Hybrid)
|
|
262
|
+
- `balanceOf(address)`: Get balance
|
|
263
|
+
- `name()`, `symbol()`, `decimals()`, `totalSupply()`: Token info
|
|
264
|
+
|
|
265
|
+
## Examples
|
|
266
|
+
|
|
267
|
+
See the `examples/` directory for more comprehensive examples:
|
|
268
|
+
|
|
269
|
+
- `send-coin.js`: Send native coin with different signature types
|
|
270
|
+
- `send-token.js`: Send ERC20 tokens with PQC/Hybrid signatures
|
|
271
|
+
- `zk-transaction.js`: Create and send ZK transactions
|
|
272
|
+
|
|
273
|
+
## Requirements
|
|
274
|
+
|
|
275
|
+
- Node.js 14+
|
|
276
|
+
- Quorum node with PQC and ZK support enabled
|
|
277
|
+
|
|
278
|
+
## Dependencies
|
|
279
|
+
|
|
280
|
+
- `ethers`: ^5.7.2
|
|
281
|
+
- `@noble/post-quantum`: ^1.0.0
|
|
282
|
+
|
|
283
|
+
## License
|
|
284
|
+
|
|
285
|
+
LGPL-3.0
|
|
286
|
+
|
|
287
|
+
## Contributing
|
|
288
|
+
|
|
289
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
290
|
+
|
|
291
|
+
## Support
|
|
292
|
+
|
|
293
|
+
For issues and questions, please open an issue on the repository.
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cheny56/node-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Client library for Quorum blockchain with Post-Quantum Cryptography (PQC) and Zero-Knowledge Proof (ZK) support",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"quorum",
|
|
12
|
+
"blockchain",
|
|
13
|
+
"ethereum",
|
|
14
|
+
"post-quantum",
|
|
15
|
+
"cryptography",
|
|
16
|
+
"zero-knowledge",
|
|
17
|
+
"zk-proof",
|
|
18
|
+
"dilithium",
|
|
19
|
+
"pqc"
|
|
20
|
+
],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "LGPL-3.0",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"ethers": "^5.7.2",
|
|
25
|
+
"@noble/post-quantum": "^1.0.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {},
|
|
28
|
+
"devDependencies": {},
|
|
29
|
+
"directories": {
|
|
30
|
+
"example": "examples"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transaction Type Constants
|
|
3
|
+
*/
|
|
4
|
+
export const TX_TYPE = {
|
|
5
|
+
LEGACY: 0,
|
|
6
|
+
ACCESS_LIST: 1,
|
|
7
|
+
DYNAMIC_FEE: 2,
|
|
8
|
+
ZK_PRIVATE: 4,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* PQC Signature Type Constants
|
|
13
|
+
*/
|
|
14
|
+
export const PQC_TYPE = {
|
|
15
|
+
NONE: 0,
|
|
16
|
+
DILITHIUM: 1,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* ZK Proof System Constants
|
|
21
|
+
*/
|
|
22
|
+
export const ZK_PROOF_SYSTEM = {
|
|
23
|
+
GROTH16: 1,
|
|
24
|
+
PLONK: 2,
|
|
25
|
+
STARK: 3,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Default Chain ID for Quorum
|
|
30
|
+
*/
|
|
31
|
+
export const DEFAULT_CHAIN_ID = 1337;
|
package/src/contract.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract Interaction
|
|
3
|
+
* Supports ERC20 token transfers and contract calls
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ethers } from 'ethers';
|
|
7
|
+
import { LegacyTransaction, PQCLegacyTransaction, HybridLegacyTransaction } from './transaction.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Contract class for interacting with smart contracts
|
|
11
|
+
*/
|
|
12
|
+
export class Contract {
|
|
13
|
+
constructor(address, abi, provider, wallet = null) {
|
|
14
|
+
this.address = address;
|
|
15
|
+
this.abi = abi;
|
|
16
|
+
this.provider = provider;
|
|
17
|
+
this.wallet = wallet;
|
|
18
|
+
this.contract = wallet
|
|
19
|
+
? new ethers.Contract(address, abi, wallet.wallet || wallet)
|
|
20
|
+
: new ethers.Contract(address, abi, provider);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Connect contract to a wallet
|
|
25
|
+
* @param {ECDSAWallet|PQCWallet|HybridWallet} wallet - Wallet instance
|
|
26
|
+
* @returns {Contract} New contract instance connected to wallet
|
|
27
|
+
*/
|
|
28
|
+
connect(wallet) {
|
|
29
|
+
return new Contract(this.address, this.abi, this.provider, wallet);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Encode function call data
|
|
34
|
+
* @param {string} functionName - Function name
|
|
35
|
+
* @param {Array} params - Function parameters
|
|
36
|
+
* @returns {string} Encoded data (hex)
|
|
37
|
+
*/
|
|
38
|
+
encodeFunctionData(functionName, params = []) {
|
|
39
|
+
const iface = new ethers.utils.Interface(this.abi);
|
|
40
|
+
return iface.encodeFunctionData(functionName, params);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Decode function result
|
|
45
|
+
* @param {string} functionName - Function name
|
|
46
|
+
* @param {string} data - Encoded data
|
|
47
|
+
* @returns {Array} Decoded parameters
|
|
48
|
+
*/
|
|
49
|
+
decodeFunctionResult(functionName, data) {
|
|
50
|
+
const iface = new ethers.utils.Interface(this.abi);
|
|
51
|
+
return iface.decodeFunctionResult(functionName, data);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Call a view/pure function
|
|
56
|
+
* @param {string} functionName - Function name
|
|
57
|
+
* @param {Array} params - Function parameters
|
|
58
|
+
* @returns {Promise<any>} Function result
|
|
59
|
+
*/
|
|
60
|
+
async call(functionName, ...params) {
|
|
61
|
+
return await this.contract[functionName](...params);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Send a transaction to a contract function (ECDSA)
|
|
66
|
+
* @param {string} functionName - Function name
|
|
67
|
+
* @param {Array} params - Function parameters
|
|
68
|
+
* @param {Object} txOptions - Transaction options (gasPrice, gasLimit, etc.)
|
|
69
|
+
* @returns {Promise<Object>} Transaction response
|
|
70
|
+
*/
|
|
71
|
+
async sendTransaction(functionName, params = [], txOptions = {}) {
|
|
72
|
+
if (!this.wallet) {
|
|
73
|
+
throw new Error('Wallet required for sending transactions');
|
|
74
|
+
}
|
|
75
|
+
const tx = await this.contract[functionName](...params, txOptions);
|
|
76
|
+
return tx;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* ERC20 Token Contract
|
|
82
|
+
* Simplified interface for ERC20 token operations
|
|
83
|
+
*/
|
|
84
|
+
export class ERC20Token extends Contract {
|
|
85
|
+
constructor(address, provider, wallet = null) {
|
|
86
|
+
const erc20Abi = [
|
|
87
|
+
'function name() view returns (string)',
|
|
88
|
+
'function symbol() view returns (string)',
|
|
89
|
+
'function decimals() view returns (uint8)',
|
|
90
|
+
'function totalSupply() view returns (uint256)',
|
|
91
|
+
'function balanceOf(address account) view returns (uint256)',
|
|
92
|
+
'function transfer(address to, uint256 amount) returns (bool)',
|
|
93
|
+
'function allowance(address owner, address spender) view returns (uint256)',
|
|
94
|
+
'function approve(address spender, uint256 amount) returns (bool)',
|
|
95
|
+
'function transferFrom(address from, address to, uint256 amount) returns (bool)',
|
|
96
|
+
];
|
|
97
|
+
super(address, erc20Abi, provider, wallet);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get token name
|
|
102
|
+
* @returns {Promise<string>} Token name
|
|
103
|
+
*/
|
|
104
|
+
async name() {
|
|
105
|
+
return await this.call('name');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get token symbol
|
|
110
|
+
* @returns {Promise<string>} Token symbol
|
|
111
|
+
*/
|
|
112
|
+
async symbol() {
|
|
113
|
+
return await this.call('symbol');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get token decimals
|
|
118
|
+
* @returns {Promise<number>} Token decimals
|
|
119
|
+
*/
|
|
120
|
+
async decimals() {
|
|
121
|
+
return await this.call('decimals');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get total supply
|
|
126
|
+
* @returns {Promise<ethers.BigNumber>} Total supply
|
|
127
|
+
*/
|
|
128
|
+
async totalSupply() {
|
|
129
|
+
return await this.call('totalSupply');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get balance of an address
|
|
134
|
+
* @param {string} address - Address to query
|
|
135
|
+
* @returns {Promise<ethers.BigNumber>} Balance
|
|
136
|
+
*/
|
|
137
|
+
async balanceOf(address) {
|
|
138
|
+
return await this.call('balanceOf', address);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Transfer tokens (ECDSA)
|
|
143
|
+
* @param {string} to - Recipient address
|
|
144
|
+
* @param {string|ethers.BigNumber} amount - Amount to transfer
|
|
145
|
+
* @param {Object} txOptions - Transaction options
|
|
146
|
+
* @returns {Promise<Object>} Transaction response
|
|
147
|
+
*/
|
|
148
|
+
async transfer(to, amount, txOptions = {}) {
|
|
149
|
+
return await this.sendTransaction('transfer', [to, amount], txOptions);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Transfer tokens using PQC transaction
|
|
154
|
+
* @param {PQCWallet} wallet - PQC wallet
|
|
155
|
+
* @param {QuorumProvider} provider - Provider instance
|
|
156
|
+
* @param {string} to - Recipient address
|
|
157
|
+
* @param {string|ethers.BigNumber} amount - Amount to transfer
|
|
158
|
+
* @param {Object} txOptions - Transaction options
|
|
159
|
+
* @returns {Promise<string>} Transaction hash
|
|
160
|
+
*/
|
|
161
|
+
async transferPQC(wallet, provider, to, amount, txOptions = {}) {
|
|
162
|
+
const data = this.encodeFunctionData('transfer', [to, amount]);
|
|
163
|
+
const nonce = await provider.getTransactionCount(wallet.address, 'pending');
|
|
164
|
+
|
|
165
|
+
const tx = new PQCLegacyTransaction({
|
|
166
|
+
chainId: txOptions.chainId || 1337,
|
|
167
|
+
nonce: nonce,
|
|
168
|
+
gasPrice: txOptions.gasPrice || 0n,
|
|
169
|
+
gasLimit: txOptions.gasLimit || 100000n,
|
|
170
|
+
to: this.address,
|
|
171
|
+
value: 0n,
|
|
172
|
+
data: data,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
tx.sign(wallet);
|
|
176
|
+
const serialized = tx.getHex();
|
|
177
|
+
return await provider.sendRawTransaction(serialized);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Transfer tokens using Hybrid transaction
|
|
182
|
+
* @param {HybridWallet} wallet - Hybrid wallet
|
|
183
|
+
* @param {QuorumProvider} provider - Provider instance
|
|
184
|
+
* @param {string} to - Recipient address
|
|
185
|
+
* @param {string|ethers.BigNumber} amount - Amount to transfer
|
|
186
|
+
* @param {Object} txOptions - Transaction options
|
|
187
|
+
* @returns {Promise<string>} Transaction hash
|
|
188
|
+
*/
|
|
189
|
+
async transferHybrid(wallet, provider, to, amount, txOptions = {}) {
|
|
190
|
+
const data = this.encodeFunctionData('transfer', [to, amount]);
|
|
191
|
+
const nonce = await provider.getTransactionCount(wallet.address, 'pending');
|
|
192
|
+
|
|
193
|
+
const tx = new HybridLegacyTransaction({
|
|
194
|
+
chainId: txOptions.chainId || 1337,
|
|
195
|
+
nonce: nonce,
|
|
196
|
+
gasPrice: txOptions.gasPrice || 0n,
|
|
197
|
+
gasLimit: txOptions.gasLimit || 100000n,
|
|
198
|
+
to: this.address,
|
|
199
|
+
value: 0n,
|
|
200
|
+
data: data,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
tx.sign(wallet.ecdsaWallet, wallet.pqcWallet);
|
|
204
|
+
const serialized = tx.getHex();
|
|
205
|
+
return await provider.sendRawTransaction(serialized);
|
|
206
|
+
}
|
|
207
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quorum Client Library
|
|
3
|
+
* Main entry point for the library
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Providers
|
|
7
|
+
export { QuorumProvider } from './provider.js';
|
|
8
|
+
|
|
9
|
+
// Wallets
|
|
10
|
+
export { ECDSAWallet, PQCWallet, HybridWallet } from './wallet.js';
|
|
11
|
+
|
|
12
|
+
// Transactions
|
|
13
|
+
export {
|
|
14
|
+
LegacyTransaction,
|
|
15
|
+
PQCLegacyTransaction,
|
|
16
|
+
HybridLegacyTransaction,
|
|
17
|
+
AccessListTransaction,
|
|
18
|
+
PQCAccessListTransaction,
|
|
19
|
+
DynamicFeeTransaction,
|
|
20
|
+
PQCDynamicFeeTransaction,
|
|
21
|
+
} from './transaction.js';
|
|
22
|
+
|
|
23
|
+
// ZK Transactions
|
|
24
|
+
export { ZKTransaction } from './zk-transaction.js';
|
|
25
|
+
|
|
26
|
+
// Contracts
|
|
27
|
+
export { Contract, ERC20Token } from './contract.js';
|
|
28
|
+
|
|
29
|
+
// Constants
|
|
30
|
+
export { TX_TYPE, PQC_TYPE, ZK_PROOF_SYSTEM, DEFAULT_CHAIN_ID } from './constants.js';
|
|
31
|
+
|
|
32
|
+
// Utilities
|
|
33
|
+
export { derivePQCAddress, deriveHybridAddress, isValidAddress } from './utils/address.js';
|
|
34
|
+
export { encodeUint64, encodeBigInt, encodeSignature } from './utils/rlp.js';
|
|
35
|
+
|
|
36
|
+
// Re-export ethers utilities for convenience
|
|
37
|
+
export { ethers } from 'ethers';
|
package/src/provider.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider for Quorum RPC connections
|
|
3
|
+
* Extends ethers.js JsonRpcProvider with Quorum-specific methods
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ethers } from 'ethers';
|
|
7
|
+
|
|
8
|
+
export class QuorumProvider extends ethers.providers.JsonRpcProvider {
|
|
9
|
+
constructor(url, network) {
|
|
10
|
+
super(url, network);
|
|
11
|
+
this.url = url;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Send a raw transaction (for PQC/Hybrid transactions)
|
|
16
|
+
* @param {string} signedTx - Hex-encoded signed transaction
|
|
17
|
+
* @returns {Promise<string>} Transaction hash
|
|
18
|
+
*/
|
|
19
|
+
async sendRawTransaction(signedTx) {
|
|
20
|
+
return await this.send('eth_sendRawTransaction', [signedTx]);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get transaction receipt
|
|
25
|
+
* @param {string} txHash - Transaction hash
|
|
26
|
+
* @returns {Promise<Object>} Transaction receipt
|
|
27
|
+
*/
|
|
28
|
+
async getTransactionReceipt(txHash) {
|
|
29
|
+
return await super.getTransactionReceipt(txHash);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Wait for transaction to be mined
|
|
34
|
+
* @param {string} txHash - Transaction hash
|
|
35
|
+
* @param {number} confirmations - Number of confirmations to wait for
|
|
36
|
+
* @returns {Promise<Object>} Transaction receipt
|
|
37
|
+
*/
|
|
38
|
+
async waitForTransaction(txHash, confirmations = 1) {
|
|
39
|
+
return await super.waitForTransaction(txHash, confirmations);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get transaction count (nonce) for an address
|
|
44
|
+
* @param {string} address - Address to query
|
|
45
|
+
* @param {string} blockTag - Block tag (default: 'pending')
|
|
46
|
+
* @returns {Promise<number>} Transaction count
|
|
47
|
+
*/
|
|
48
|
+
async getTransactionCount(address, blockTag = 'pending') {
|
|
49
|
+
return await super.getTransactionCount(address, blockTag);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get balance for an address
|
|
54
|
+
* @param {string} address - Address to query
|
|
55
|
+
* @param {string} blockTag - Block tag (default: 'latest')
|
|
56
|
+
* @returns {Promise<ethers.BigNumber>} Balance in Wei
|
|
57
|
+
*/
|
|
58
|
+
async getBalance(address, blockTag = 'latest') {
|
|
59
|
+
return await super.getBalance(address, blockTag);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Estimate gas for a transaction
|
|
64
|
+
* @param {Object} transaction - Transaction object
|
|
65
|
+
* @returns {Promise<ethers.BigNumber>} Estimated gas
|
|
66
|
+
*/
|
|
67
|
+
async estimateGas(transaction) {
|
|
68
|
+
return await super.estimateGas(transaction);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get gas price
|
|
73
|
+
* @returns {Promise<ethers.BigNumber>} Gas price in Wei
|
|
74
|
+
*/
|
|
75
|
+
async getGasPrice() {
|
|
76
|
+
return await super.getGasPrice();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get current block number
|
|
81
|
+
* @returns {Promise<number>} Block number
|
|
82
|
+
*/
|
|
83
|
+
async getBlockNumber() {
|
|
84
|
+
return await super.getBlockNumber();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get block by number
|
|
89
|
+
* @param {number|string} blockNumber - Block number or tag
|
|
90
|
+
* @returns {Promise<Object>} Block object
|
|
91
|
+
*/
|
|
92
|
+
async getBlock(blockNumber) {
|
|
93
|
+
return await super.getBlock(blockNumber);
|
|
94
|
+
}
|
|
95
|
+
}
|