@cfxdevkit/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/LICENSE +72 -0
  3. package/README.md +257 -0
  4. package/dist/clients/index.cjs +2053 -0
  5. package/dist/clients/index.cjs.map +1 -0
  6. package/dist/clients/index.d.cts +7 -0
  7. package/dist/clients/index.d.ts +7 -0
  8. package/dist/clients/index.js +2043 -0
  9. package/dist/clients/index.js.map +1 -0
  10. package/dist/config/index.cjs +423 -0
  11. package/dist/config/index.cjs.map +1 -0
  12. package/dist/config/index.d.cts +99 -0
  13. package/dist/config/index.d.ts +99 -0
  14. package/dist/config/index.js +380 -0
  15. package/dist/config/index.js.map +1 -0
  16. package/dist/config-BMtaWM0X.d.cts +165 -0
  17. package/dist/config-BMtaWM0X.d.ts +165 -0
  18. package/dist/core-C5qe16RS.d.ts +352 -0
  19. package/dist/core-RZA4aKwj.d.cts +352 -0
  20. package/dist/index-BhCpy6Fz.d.cts +165 -0
  21. package/dist/index-Qz84U9Oq.d.ts +165 -0
  22. package/dist/index.cjs +3773 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +945 -0
  25. package/dist/index.d.ts +945 -0
  26. package/dist/index.js +3730 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/types/index.cjs +44 -0
  29. package/dist/types/index.cjs.map +1 -0
  30. package/dist/types/index.d.cts +5 -0
  31. package/dist/types/index.d.ts +5 -0
  32. package/dist/types/index.js +17 -0
  33. package/dist/types/index.js.map +1 -0
  34. package/dist/utils/index.cjs +83 -0
  35. package/dist/utils/index.cjs.map +1 -0
  36. package/dist/utils/index.d.cts +11 -0
  37. package/dist/utils/index.d.ts +11 -0
  38. package/dist/utils/index.js +56 -0
  39. package/dist/utils/index.js.map +1 -0
  40. package/dist/wallet/index.cjs +852 -0
  41. package/dist/wallet/index.cjs.map +1 -0
  42. package/dist/wallet/index.d.cts +726 -0
  43. package/dist/wallet/index.d.ts +726 -0
  44. package/dist/wallet/index.js +815 -0
  45. package/dist/wallet/index.js.map +1 -0
  46. package/package.json +119 -0
@@ -0,0 +1,2043 @@
1
+ // src/clients/core.ts
2
+ import {
3
+ createPublicClient,
4
+ createTestClient,
5
+ createWalletClient,
6
+ formatCFX,
7
+ http,
8
+ parseCFX
9
+ } from "cive";
10
+ import { privateKeyToAccount } from "cive/accounts";
11
+ import {
12
+ defineChain as defineChain2,
13
+ encodeFunctionData,
14
+ formatUnits,
15
+ hexAddressToBase32,
16
+ isAddress as isCoreAddress
17
+ } from "cive/utils";
18
+ import { isAddress as isEspaceAddress } from "viem";
19
+
20
+ // src/config/chains.ts
21
+ import { defineChain } from "cive/utils";
22
+ import { defineChain as defineEvmChain } from "viem";
23
+ var CORE_MAINNET = {
24
+ id: 1029,
25
+ name: "conflux-core",
26
+ type: "core",
27
+ testnet: false,
28
+ nativeCurrency: {
29
+ name: "Conflux",
30
+ symbol: "CFX",
31
+ decimals: 18
32
+ },
33
+ rpcUrls: {
34
+ default: {
35
+ http: ["https://main.confluxrpc.com"],
36
+ webSocket: ["wss://main.confluxrpc.com/ws"]
37
+ }
38
+ },
39
+ blockExplorers: {
40
+ default: {
41
+ name: "ConfluxScan",
42
+ url: "https://confluxscan.io"
43
+ }
44
+ }
45
+ };
46
+ var CORE_TESTNET = {
47
+ id: 1,
48
+ name: "conflux-core-testnet",
49
+ type: "core",
50
+ testnet: true,
51
+ nativeCurrency: {
52
+ name: "Conflux",
53
+ symbol: "CFX",
54
+ decimals: 18
55
+ },
56
+ rpcUrls: {
57
+ default: {
58
+ http: ["https://test.confluxrpc.com"],
59
+ webSocket: ["wss://test.confluxrpc.com/ws"]
60
+ }
61
+ },
62
+ blockExplorers: {
63
+ default: {
64
+ name: "ConfluxScan Testnet",
65
+ url: "https://testnet.confluxscan.io"
66
+ }
67
+ }
68
+ };
69
+ var CORE_LOCAL = {
70
+ id: 2029,
71
+ name: "conflux-core-local",
72
+ type: "core",
73
+ testnet: true,
74
+ nativeCurrency: {
75
+ name: "Conflux",
76
+ symbol: "CFX",
77
+ decimals: 18
78
+ },
79
+ rpcUrls: {
80
+ default: {
81
+ http: ["http://localhost:12537"],
82
+ webSocket: ["ws://localhost:12536"]
83
+ }
84
+ }
85
+ };
86
+ var EVM_MAINNET = {
87
+ id: 1030,
88
+ name: "conflux-espace",
89
+ type: "evm",
90
+ testnet: false,
91
+ nativeCurrency: {
92
+ name: "Conflux",
93
+ symbol: "CFX",
94
+ decimals: 18
95
+ },
96
+ rpcUrls: {
97
+ default: {
98
+ http: ["https://evm.confluxrpc.com"]
99
+ }
100
+ },
101
+ blockExplorers: {
102
+ default: {
103
+ name: "ConfluxScan eSpace",
104
+ url: "https://evm.confluxscan.net"
105
+ }
106
+ },
107
+ contracts: {
108
+ multicall3: {
109
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
110
+ blockCreated: 62512243
111
+ }
112
+ }
113
+ };
114
+ var EVM_TESTNET = {
115
+ id: 71,
116
+ name: "conflux-espace-testnet",
117
+ type: "evm",
118
+ testnet: true,
119
+ nativeCurrency: {
120
+ name: "Conflux",
121
+ symbol: "CFX",
122
+ decimals: 18
123
+ },
124
+ rpcUrls: {
125
+ default: {
126
+ http: ["https://evmtestnet.confluxrpc.com"]
127
+ }
128
+ },
129
+ blockExplorers: {
130
+ default: {
131
+ name: "ConfluxScan eSpace Testnet",
132
+ url: "https://evmtestnet.confluxscan.net"
133
+ }
134
+ },
135
+ contracts: {
136
+ multicall3: {
137
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
138
+ blockCreated: 117499050
139
+ }
140
+ }
141
+ };
142
+ var EVM_LOCAL = {
143
+ id: 2030,
144
+ name: "conflux-espace-local",
145
+ type: "evm",
146
+ testnet: true,
147
+ nativeCurrency: {
148
+ name: "Conflux",
149
+ symbol: "CFX",
150
+ decimals: 18
151
+ },
152
+ rpcUrls: {
153
+ default: {
154
+ http: ["http://localhost:8545"]
155
+ }
156
+ }
157
+ };
158
+ var SUPPORTED_CHAINS = {
159
+ 1029: CORE_MAINNET,
160
+ 1: CORE_TESTNET,
161
+ 2029: CORE_LOCAL,
162
+ 1030: EVM_MAINNET,
163
+ 71: EVM_TESTNET,
164
+ 2030: EVM_LOCAL
165
+ };
166
+ function getChainConfig(chainId) {
167
+ const config = SUPPORTED_CHAINS[chainId];
168
+ if (!config) {
169
+ throw new Error(`Unsupported chain ID: ${chainId}`);
170
+ }
171
+ return config;
172
+ }
173
+ function isValidChainId(chainId) {
174
+ return chainId in SUPPORTED_CHAINS;
175
+ }
176
+ var NetworkSelector = class {
177
+ currentChainId;
178
+ previousChainId = null;
179
+ listeners = /* @__PURE__ */ new Set();
180
+ nodeRunningListeners = /* @__PURE__ */ new Set();
181
+ isNodeRunning = false;
182
+ lockedToLocal = false;
183
+ constructor(initialChainId = 1) {
184
+ this.currentChainId = initialChainId;
185
+ }
186
+ getCurrentChain() {
187
+ return getChainConfig(this.currentChainId);
188
+ }
189
+ getCurrentChainId() {
190
+ return this.currentChainId;
191
+ }
192
+ /**
193
+ * Switch to a specific chain
194
+ * @param chainId - Chain ID to switch to
195
+ * @param force - Force switch even if node is running (for wallet operations)
196
+ */
197
+ switchChain(chainId, force = false) {
198
+ if (!isValidChainId(chainId)) {
199
+ throw new Error(`Invalid chain ID: ${chainId}`);
200
+ }
201
+ if (this.isNodeRunning && !this.isLocalChain(chainId) && !force) {
202
+ console.warn(
203
+ `Cannot switch to chain ${chainId} while local node is running. Use force=true for wallet operations.`
204
+ );
205
+ return;
206
+ }
207
+ if (this.currentChainId !== chainId) {
208
+ this.currentChainId = chainId;
209
+ this.notifyListeners();
210
+ }
211
+ }
212
+ /**
213
+ * Called when local node starts - automatically switches to local chains
214
+ */
215
+ onNodeStart(coreChainId = 2029, evmChainId = 2030) {
216
+ if (!this.isNodeRunning) {
217
+ if (!this.isLocal()) {
218
+ this.previousChainId = this.currentChainId;
219
+ }
220
+ this.isNodeRunning = true;
221
+ this.lockedToLocal = true;
222
+ const targetLocalChain = this.isEvm() ? evmChainId : coreChainId;
223
+ this.switchChain(targetLocalChain, true);
224
+ this.notifyNodeRunningListeners();
225
+ }
226
+ }
227
+ /**
228
+ * Called when local node stops - can restore previous chain
229
+ */
230
+ onNodeStop(restorePrevious = true) {
231
+ if (this.isNodeRunning) {
232
+ this.isNodeRunning = false;
233
+ this.lockedToLocal = false;
234
+ if (restorePrevious && this.previousChainId) {
235
+ this.switchChain(this.previousChainId, true);
236
+ this.previousChainId = null;
237
+ }
238
+ this.notifyNodeRunningListeners();
239
+ }
240
+ }
241
+ /**
242
+ * Check if node is currently running
243
+ */
244
+ getNodeRunningStatus() {
245
+ return this.isNodeRunning;
246
+ }
247
+ /**
248
+ * Check if selector is locked to local chains
249
+ */
250
+ isLockedToLocal() {
251
+ return this.lockedToLocal;
252
+ }
253
+ onChainChange(listener) {
254
+ this.listeners.add(listener);
255
+ return () => this.listeners.delete(listener);
256
+ }
257
+ onNodeRunningChange(listener) {
258
+ this.nodeRunningListeners.add(listener);
259
+ return () => this.nodeRunningListeners.delete(listener);
260
+ }
261
+ notifyListeners() {
262
+ for (const listener of this.listeners) {
263
+ try {
264
+ listener(this.currentChainId);
265
+ } catch (error) {
266
+ console.error("Error in chain change listener:", error);
267
+ }
268
+ }
269
+ }
270
+ notifyNodeRunningListeners() {
271
+ for (const listener of this.nodeRunningListeners) {
272
+ try {
273
+ listener(this.isNodeRunning);
274
+ } catch (error) {
275
+ console.error("Error in node running listener:", error);
276
+ }
277
+ }
278
+ }
279
+ isLocalChain(chainId) {
280
+ return chainId === 2029 || chainId === 2030;
281
+ }
282
+ // Helper methods for chain type detection
283
+ isCore() {
284
+ return this.getCurrentChain().type === "core";
285
+ }
286
+ isEvm() {
287
+ return this.getCurrentChain().type === "evm";
288
+ }
289
+ isTestnet() {
290
+ return this.getCurrentChain().testnet;
291
+ }
292
+ isLocal() {
293
+ return this.currentChainId === 2029 || this.currentChainId === 2030;
294
+ }
295
+ // Get corresponding chain IDs
296
+ getCorrespondingChainId() {
297
+ switch (this.currentChainId) {
298
+ case 1029:
299
+ return 1030;
300
+ // Core mainnet -> eSpace mainnet
301
+ case 1030:
302
+ return 1029;
303
+ // eSpace mainnet -> Core mainnet
304
+ case 1:
305
+ return 71;
306
+ // Core testnet -> eSpace testnet
307
+ case 71:
308
+ return 1;
309
+ // eSpace testnet -> Core testnet
310
+ case 2029:
311
+ return 2030;
312
+ // Core local -> eSpace local
313
+ case 2030:
314
+ return 2029;
315
+ // eSpace local -> Core local
316
+ default:
317
+ return null;
318
+ }
319
+ }
320
+ /**
321
+ * Update local chain configurations with actual node URLs
322
+ * Called when ServerManager starts with specific ports
323
+ */
324
+ updateLocalChainUrls(coreRpcPort, evmRpcPort, wsPort) {
325
+ const coreLocal = SUPPORTED_CHAINS[2029];
326
+ if (coreLocal) {
327
+ coreLocal.rpcUrls.default.http = [`http://localhost:${coreRpcPort}`];
328
+ if (wsPort) {
329
+ coreLocal.rpcUrls.default.webSocket = [`ws://localhost:${wsPort}`];
330
+ }
331
+ }
332
+ const evmLocal = SUPPORTED_CHAINS[2030];
333
+ if (evmLocal) {
334
+ evmLocal.rpcUrls.default.http = [`http://localhost:${evmRpcPort}`];
335
+ }
336
+ }
337
+ };
338
+ var defaultNetworkSelector = new NetworkSelector();
339
+
340
+ // src/types/config.ts
341
+ var NodeError = class extends Error {
342
+ code;
343
+ chain;
344
+ context;
345
+ constructor(message, code, chain, context) {
346
+ super(message);
347
+ this.name = "NodeError";
348
+ this.code = code;
349
+ this.chain = chain;
350
+ this.context = context;
351
+ }
352
+ };
353
+
354
+ // src/clients/core.ts
355
+ var conflux = defineChain2({
356
+ id: 1029,
357
+ name: "Conflux Core",
358
+ nativeCurrency: { name: "Conflux", symbol: "CFX", decimals: 18 },
359
+ rpcUrls: { default: { http: ["https://main.confluxrpc.com"] } }
360
+ });
361
+ var confluxTestnet = defineChain2({
362
+ id: 1,
363
+ name: "Conflux Core Testnet",
364
+ nativeCurrency: { name: "Conflux", symbol: "CFX", decimals: 18 },
365
+ rpcUrls: { default: { http: ["https://test.confluxrpc.com"] } }
366
+ });
367
+ var CoreClient = class {
368
+ chainType = "core";
369
+ chainId;
370
+ address;
371
+ publicClient;
372
+ chain;
373
+ constructor(config) {
374
+ this.chainId = config.chainId;
375
+ this.chain = defineChain2({
376
+ id: this.chainId,
377
+ name: `ConfluxCore-${this.chainId}`,
378
+ nativeCurrency: {
379
+ decimals: 18,
380
+ name: "Conflux",
381
+ symbol: "CFX"
382
+ },
383
+ rpcUrls: {
384
+ default: {
385
+ http: [config.rpcUrl],
386
+ webSocket: config.wsUrl ? [config.wsUrl] : void 0
387
+ }
388
+ }
389
+ });
390
+ this.publicClient = createPublicClient({
391
+ chain: this.chain,
392
+ transport: http(config.rpcUrl),
393
+ pollingInterval: config.pollingInterval || 1e3
394
+ });
395
+ this.address = "";
396
+ }
397
+ async getBlockNumber() {
398
+ try {
399
+ const epochNumber = await this.publicClient.getEpochNumber();
400
+ return BigInt(epochNumber.toString());
401
+ } catch (error) {
402
+ throw new NodeError(
403
+ `Failed to get block number: ${error instanceof Error ? error.message : String(error)}`,
404
+ "BLOCK_NUMBER_ERROR",
405
+ "core",
406
+ { originalError: error }
407
+ );
408
+ }
409
+ }
410
+ async getBalance(address) {
411
+ if (!isCoreAddress(address)) {
412
+ throw new NodeError(
413
+ "Invalid Core address format",
414
+ "INVALID_ADDRESS",
415
+ "core"
416
+ );
417
+ }
418
+ try {
419
+ const balance = await this.publicClient.getBalance({ address });
420
+ return formatCFX(balance);
421
+ } catch (error) {
422
+ throw new NodeError(
423
+ `Failed to get balance: ${error instanceof Error ? error.message : String(error)}`,
424
+ "BALANCE_ERROR",
425
+ "core",
426
+ { address, originalError: error }
427
+ );
428
+ }
429
+ }
430
+ async getGasPrice() {
431
+ try {
432
+ const gasPrice = await this.publicClient.getGasPrice();
433
+ return gasPrice;
434
+ } catch (error) {
435
+ throw new NodeError(
436
+ `Failed to get gas price: ${error instanceof Error ? error.message : String(error)}`,
437
+ "GAS_PRICE_ERROR",
438
+ "core",
439
+ { originalError: error }
440
+ );
441
+ }
442
+ }
443
+ async estimateGas(tx) {
444
+ try {
445
+ const estimate = await this.publicClient.request({
446
+ method: "cfx_estimateGasAndCollateral",
447
+ params: [
448
+ {
449
+ to: tx.to,
450
+ value: tx.value ? `0x${tx.value.toString(16)}` : void 0,
451
+ data: tx.data
452
+ }
453
+ ]
454
+ });
455
+ return BigInt(estimate.gasLimit);
456
+ } catch (error) {
457
+ throw new NodeError(
458
+ `Failed to estimate gas: ${error instanceof Error ? error.message : String(error)}`,
459
+ "GAS_ESTIMATE_ERROR",
460
+ "core",
461
+ { transaction: tx, originalError: error }
462
+ );
463
+ }
464
+ }
465
+ async sendTransaction(_tx) {
466
+ throw new NodeError(
467
+ "Cannot send transaction from public client. Use wallet client instead.",
468
+ "WALLET_REQUIRED",
469
+ "core"
470
+ );
471
+ }
472
+ async waitForTransaction(hash) {
473
+ try {
474
+ const receipt = await this.publicClient.waitForTransactionReceipt({
475
+ hash
476
+ });
477
+ return {
478
+ hash: receipt.transactionHash,
479
+ blockNumber: BigInt(receipt.epochNumber?.toString() || "0"),
480
+ blockHash: receipt.blockHash || "",
481
+ transactionIndex: Number(receipt.index || 0),
482
+ status: receipt.outcomeStatus === "success" ? "success" : "reverted",
483
+ gasUsed: receipt.gasUsed || 0n,
484
+ contractAddress: receipt.contractCreated || void 0,
485
+ logs: receipt.log?.map((log) => ({
486
+ address: log.address || "",
487
+ topics: log.topics || [],
488
+ data: log.data || "0x",
489
+ blockNumber: BigInt(log.epochNumber?.toString() || "0"),
490
+ transactionHash: log.transactionHash || "",
491
+ logIndex: Number(log.logIndex || 0)
492
+ })) || []
493
+ };
494
+ } catch (error) {
495
+ throw new NodeError(
496
+ `Failed to wait for transaction: ${error instanceof Error ? error.message : String(error)}`,
497
+ "TRANSACTION_WAIT_ERROR",
498
+ "core",
499
+ { hash, originalError: error }
500
+ );
501
+ }
502
+ }
503
+ async getTokenBalance(tokenAddress, holderAddress) {
504
+ const holder = holderAddress || this.address;
505
+ if (!this.isValidAddress(tokenAddress)) {
506
+ throw new NodeError(
507
+ "Invalid token address format",
508
+ "INVALID_ADDRESS",
509
+ "core",
510
+ { tokenAddress }
511
+ );
512
+ }
513
+ if (!this.isValidAddress(holder)) {
514
+ throw new NodeError(
515
+ "Invalid holder address format",
516
+ "INVALID_ADDRESS",
517
+ "core",
518
+ { holder }
519
+ );
520
+ }
521
+ try {
522
+ const [balance, decimals] = await Promise.all([
523
+ this.publicClient.readContract({
524
+ address: tokenAddress,
525
+ abi: [
526
+ {
527
+ name: "balanceOf",
528
+ type: "function",
529
+ inputs: [{ name: "account", type: "address" }],
530
+ outputs: [{ name: "", type: "uint256" }],
531
+ stateMutability: "view"
532
+ }
533
+ ],
534
+ functionName: "balanceOf",
535
+ args: [holder]
536
+ }),
537
+ this.publicClient.readContract({
538
+ address: tokenAddress,
539
+ abi: [
540
+ {
541
+ name: "decimals",
542
+ type: "function",
543
+ inputs: [],
544
+ outputs: [{ name: "", type: "uint8" }],
545
+ stateMutability: "view"
546
+ }
547
+ ],
548
+ functionName: "decimals"
549
+ })
550
+ ]);
551
+ return this.formatTokenAmount(balance, Number(decimals));
552
+ } catch (error) {
553
+ throw new NodeError(
554
+ `Failed to get token balance: ${error instanceof Error ? error.message : String(error)}`,
555
+ "TOKEN_BALANCE_ERROR",
556
+ "core",
557
+ { tokenAddress, holder, originalError: error }
558
+ );
559
+ }
560
+ }
561
+ watchBlocks(callback) {
562
+ return this.publicClient.watchEpochNumber({
563
+ emitMissed: false,
564
+ epochTag: "latest_mined",
565
+ onEpochNumber: async (epochNumber) => {
566
+ try {
567
+ const blockHashes = await this.publicClient.getBlocksByEpoch({
568
+ epochNumber
569
+ });
570
+ for (const hash of blockHashes) {
571
+ try {
572
+ const block = await this.publicClient.getBlock({
573
+ blockHash: hash
574
+ });
575
+ const blockEvent = {
576
+ chainType: "core",
577
+ blockNumber: BigInt(block.epochNumber?.toString() || "0"),
578
+ blockHash: block.hash || "",
579
+ timestamp: Number(block.timestamp || 0),
580
+ transactionCount: block.transactions?.length || 0
581
+ };
582
+ callback(blockEvent);
583
+ } catch (error) {
584
+ console.error(`Failed to process block ${hash}:`, error);
585
+ }
586
+ }
587
+ } catch (error) {
588
+ console.error(
589
+ `Failed to get blocks for epoch ${epochNumber}:`,
590
+ error
591
+ );
592
+ }
593
+ }
594
+ });
595
+ }
596
+ watchTransactions(callback) {
597
+ return this.publicClient.watchEpochNumber({
598
+ emitMissed: false,
599
+ epochTag: "latest_mined",
600
+ onEpochNumber: async (epochNumber) => {
601
+ try {
602
+ const blockHashes = await this.publicClient.getBlocksByEpoch({
603
+ epochNumber
604
+ });
605
+ for (const hash of blockHashes) {
606
+ try {
607
+ const block = await this.publicClient.getBlock({
608
+ blockHash: hash
609
+ });
610
+ await Promise.all(
611
+ (block.transactions || []).map(
612
+ async (txHash) => {
613
+ try {
614
+ const tx = await this.publicClient.getTransaction({
615
+ hash: txHash
616
+ });
617
+ const txEvent = {
618
+ chainType: "core",
619
+ hash: tx.hash,
620
+ from: tx.from,
621
+ to: tx.to || void 0,
622
+ value: tx.value || 0n,
623
+ blockNumber: BigInt(
624
+ block.epochNumber?.toString() || "0"
625
+ )
626
+ };
627
+ callback(txEvent);
628
+ } catch (error) {
629
+ console.error(
630
+ `Failed to get transaction ${txHash}:`,
631
+ error
632
+ );
633
+ }
634
+ }
635
+ )
636
+ );
637
+ } catch (error) {
638
+ console.error(`Failed to process block ${hash}:`, error);
639
+ }
640
+ }
641
+ } catch (error) {
642
+ console.error(
643
+ `Failed to get blocks for epoch ${epochNumber}:`,
644
+ error
645
+ );
646
+ }
647
+ }
648
+ });
649
+ }
650
+ isValidAddress(address) {
651
+ return isCoreAddress(address);
652
+ }
653
+ formatAmount(amount) {
654
+ return formatCFX(amount);
655
+ }
656
+ parseAmount(amount) {
657
+ return parseCFX(amount);
658
+ }
659
+ getInternalClient() {
660
+ return this.publicClient;
661
+ }
662
+ formatTokenAmount(amount, decimals) {
663
+ const formatted = formatUnits(amount, decimals);
664
+ return Number(formatted).toFixed(4);
665
+ }
666
+ };
667
+ var CoreWalletClient = class {
668
+ chainType = "core";
669
+ address;
670
+ chainId;
671
+ walletClient;
672
+ publicClient;
673
+ account;
674
+ chain;
675
+ constructor(config) {
676
+ this.chainId = config.chainId;
677
+ this.chain = defineChain2({
678
+ id: config.chainId,
679
+ name: `ConfluxCore-${config.chainId}`,
680
+ nativeCurrency: {
681
+ decimals: 18,
682
+ name: "Conflux",
683
+ symbol: "CFX"
684
+ },
685
+ rpcUrls: {
686
+ default: {
687
+ http: [config.rpcUrl],
688
+ webSocket: config.wsUrl ? [config.wsUrl] : void 0
689
+ }
690
+ }
691
+ });
692
+ this.account = privateKeyToAccount(config.privateKey, {
693
+ networkId: config.chainId
694
+ });
695
+ this.address = this.account.address;
696
+ this.walletClient = createWalletClient({
697
+ account: this.account,
698
+ chain: this.chain,
699
+ transport: http(config.rpcUrl),
700
+ pollingInterval: config.pollingInterval || 1e3
701
+ });
702
+ this.publicClient = createPublicClient({
703
+ chain: this.chain,
704
+ transport: http(config.rpcUrl),
705
+ pollingInterval: config.pollingInterval || 1e3
706
+ });
707
+ }
708
+ async sendTransaction(tx) {
709
+ try {
710
+ return await this.walletClient.sendTransaction({
711
+ to: tx.to,
712
+ value: tx.value,
713
+ data: tx.data,
714
+ gas: tx.gasLimit,
715
+ gasPrice: tx.gasPrice,
716
+ nonce: tx.nonce,
717
+ account: this.account,
718
+ chain: this.chain
719
+ });
720
+ } catch (error) {
721
+ throw new NodeError(
722
+ `Failed to send transaction: ${error instanceof Error ? error.message : String(error)}`,
723
+ "TRANSACTION_SEND_ERROR",
724
+ "core",
725
+ { transaction: tx, originalError: error }
726
+ );
727
+ }
728
+ }
729
+ async signMessage(message) {
730
+ try {
731
+ return await this.walletClient.signMessage({
732
+ account: this.account,
733
+ message
734
+ });
735
+ } catch (error) {
736
+ throw new NodeError(
737
+ `Failed to sign message: ${error instanceof Error ? error.message : String(error)}`,
738
+ "MESSAGE_SIGN_ERROR",
739
+ "core",
740
+ { message, originalError: error }
741
+ );
742
+ }
743
+ }
744
+ getInternalClient() {
745
+ return this.walletClient;
746
+ }
747
+ async waitForTransaction(hash) {
748
+ try {
749
+ const receipt = await this.publicClient.waitForTransactionReceipt({
750
+ hash,
751
+ timeout: 5e3
752
+ // 5 second timeout for faster response
753
+ });
754
+ return {
755
+ hash: receipt.transactionHash,
756
+ blockNumber: BigInt(receipt.epochNumber?.toString() || "0"),
757
+ blockHash: receipt.blockHash || "",
758
+ transactionIndex: Number(receipt.index || 0),
759
+ status: receipt.outcomeStatus === "success" ? "success" : "reverted",
760
+ gasUsed: receipt.gasUsed || 0n,
761
+ contractAddress: receipt.contractCreated || void 0,
762
+ logs: receipt.log?.map((log) => ({
763
+ address: log.address || "",
764
+ topics: log.topics || [],
765
+ data: log.data || "0x",
766
+ blockNumber: BigInt(log.epochNumber?.toString() || "0"),
767
+ transactionHash: log.transactionHash || "",
768
+ logIndex: Number(log.logIndex || 0)
769
+ })) || []
770
+ };
771
+ } catch (error) {
772
+ throw new NodeError(
773
+ `Failed to wait for transaction: ${error instanceof Error ? error.message : String(error)}`,
774
+ "TRANSACTION_WAIT_ERROR",
775
+ "core",
776
+ { hash, originalError: error }
777
+ );
778
+ }
779
+ }
780
+ /**
781
+ * Unified faucet functionality
782
+ * Automatically detects address type and sends CFX accordingly:
783
+ * - Core address: Direct transfer
784
+ * - eSpace address: Cross-chain transfer via internal contract
785
+ */
786
+ async faucet(address, amount) {
787
+ const isCoreAddr = isCoreAddress(address);
788
+ const isEspaceAddr = isEspaceAddress(address);
789
+ if (!isCoreAddr && !isEspaceAddr) {
790
+ throw new NodeError(
791
+ "Invalid address format (must be Core or eSpace address)",
792
+ "INVALID_ADDRESS",
793
+ "core",
794
+ { address }
795
+ );
796
+ }
797
+ try {
798
+ if (isCoreAddr) {
799
+ return await this.walletClient.sendTransaction({
800
+ chain: this.chain,
801
+ account: this.account,
802
+ to: address,
803
+ value: parseCFX(amount)
804
+ });
805
+ } else {
806
+ return await this.walletClient.sendTransaction({
807
+ chain: this.chain,
808
+ account: this.account,
809
+ to: hexAddressToBase32({
810
+ hexAddress: "0x0888000000000000000000000000000000000006",
811
+ networkId: this.chain.id
812
+ }),
813
+ value: parseCFX(amount),
814
+ data: encodeFunctionData({
815
+ abi: [
816
+ {
817
+ type: "function",
818
+ name: "transferEVM",
819
+ inputs: [{ name: "to", type: "bytes20" }],
820
+ outputs: [{ name: "output", type: "bytes" }],
821
+ stateMutability: "payable"
822
+ }
823
+ ],
824
+ functionName: "transferEVM",
825
+ args: [address]
826
+ })
827
+ });
828
+ }
829
+ } catch (error) {
830
+ throw new NodeError(
831
+ `Failed to send faucet transaction: ${error instanceof Error ? error.message : String(error)}`,
832
+ "FAUCET_ERROR",
833
+ "core",
834
+ { address, amount, originalError: error }
835
+ );
836
+ }
837
+ }
838
+ /**
839
+ * Cross-chain faucet functionality (Core → eSpace)
840
+ * Sends CFX from Core space to eSpace address via internal contract
841
+ * @deprecated Use faucet() instead which auto-detects address type
842
+ */
843
+ async faucetToEspace(espaceAddress, amount) {
844
+ if (!isEspaceAddress(espaceAddress)) {
845
+ throw new NodeError(
846
+ "Invalid eSpace address format",
847
+ "INVALID_ADDRESS",
848
+ "core",
849
+ { espaceAddress }
850
+ );
851
+ }
852
+ try {
853
+ return await this.walletClient.sendTransaction({
854
+ chain: this.chain,
855
+ account: this.account,
856
+ to: hexAddressToBase32({
857
+ hexAddress: "0x0888000000000000000000000000000000000006",
858
+ networkId: this.chain.id
859
+ }),
860
+ value: parseCFX(amount),
861
+ data: encodeFunctionData({
862
+ abi: [
863
+ {
864
+ type: "function",
865
+ name: "transferEVM",
866
+ inputs: [{ name: "to", type: "bytes20" }],
867
+ outputs: [{ name: "output", type: "bytes" }],
868
+ stateMutability: "payable"
869
+ }
870
+ ],
871
+ functionName: "transferEVM",
872
+ args: [espaceAddress]
873
+ })
874
+ });
875
+ } catch (error) {
876
+ throw new NodeError(
877
+ `Failed to send faucet transaction to eSpace: ${error instanceof Error ? error.message : String(error)}`,
878
+ "FAUCET_ERROR",
879
+ "core",
880
+ { espaceAddress, amount, originalError: error }
881
+ );
882
+ }
883
+ }
884
+ /**
885
+ * Deploy a contract to Core Space
886
+ */
887
+ async deployContract(abi, bytecode, constructorArgs = []) {
888
+ try {
889
+ const hash = await this.walletClient.deployContract({
890
+ account: this.account,
891
+ chain: this.chain,
892
+ abi,
893
+ bytecode,
894
+ args: constructorArgs
895
+ });
896
+ const receipt = await this.waitForTransaction(hash);
897
+ if (!receipt.contractAddress) {
898
+ throw new Error("Contract address not found in transaction receipt");
899
+ }
900
+ return receipt.contractAddress;
901
+ } catch (error) {
902
+ throw new NodeError(
903
+ `Failed to deploy contract: ${error instanceof Error ? error.message : String(error)}`,
904
+ "DEPLOYMENT_ERROR",
905
+ "core",
906
+ { abi, bytecode, constructorArgs, originalError: error }
907
+ );
908
+ }
909
+ }
910
+ /**
911
+ * Call a contract method (read-only)
912
+ */
913
+ async callContract(address, abi, functionName, args = []) {
914
+ try {
915
+ const result = await this.publicClient.readContract({
916
+ address,
917
+ abi,
918
+ functionName,
919
+ args
920
+ });
921
+ return result;
922
+ } catch (error) {
923
+ throw new NodeError(
924
+ `Failed to call contract: ${error instanceof Error ? error.message : String(error)}`,
925
+ "CONTRACT_CALL_ERROR",
926
+ "core",
927
+ { address, functionName, args, originalError: error }
928
+ );
929
+ }
930
+ }
931
+ /**
932
+ * Write to a contract (transaction)
933
+ */
934
+ async writeContract(address, abi, functionName, args = [], value) {
935
+ try {
936
+ const hash = await this.walletClient.writeContract({
937
+ account: this.account,
938
+ chain: this.chain,
939
+ address,
940
+ abi,
941
+ functionName,
942
+ args,
943
+ value
944
+ });
945
+ return hash;
946
+ } catch (error) {
947
+ throw new NodeError(
948
+ `Failed to write to contract: ${error instanceof Error ? error.message : String(error)}`,
949
+ "CONTRACT_WRITE_ERROR",
950
+ "core",
951
+ { address, functionName, args, value, originalError: error }
952
+ );
953
+ }
954
+ }
955
+ };
956
+ var CoreTestClient = class extends CoreClient {
957
+ testClient;
958
+ constructor(config) {
959
+ super(config);
960
+ this.testClient = createTestClient({
961
+ chain: this.chainId === 1029 ? conflux : confluxTestnet,
962
+ transport: http(config.rpcUrl),
963
+ pollingInterval: config.pollingInterval || 1e3
964
+ });
965
+ }
966
+ async mine(blocks = 1) {
967
+ try {
968
+ await this.testClient.mine({ blocks });
969
+ } catch (error) {
970
+ throw new NodeError(
971
+ `Failed to mine blocks: ${error instanceof Error ? error.message : String(error)}`,
972
+ "MINE_ERROR",
973
+ "core",
974
+ { blocks, originalError: error }
975
+ );
976
+ }
977
+ }
978
+ async setNextBlockTimestamp(_timestamp) {
979
+ throw new NodeError(
980
+ "setNextBlockTimestamp not implemented for Core client",
981
+ "NOT_IMPLEMENTED",
982
+ "core"
983
+ );
984
+ }
985
+ async increaseTime(_seconds) {
986
+ throw new NodeError(
987
+ "increaseTime not implemented for Core client",
988
+ "NOT_IMPLEMENTED",
989
+ "core"
990
+ );
991
+ }
992
+ async impersonateAccount(_address) {
993
+ throw new NodeError(
994
+ "impersonateAccount not implemented for Core client",
995
+ "NOT_IMPLEMENTED",
996
+ "core"
997
+ );
998
+ }
999
+ async stopImpersonatingAccount(_address) {
1000
+ throw new NodeError(
1001
+ "stopImpersonatingAccount not implemented for Core client",
1002
+ "NOT_IMPLEMENTED",
1003
+ "core"
1004
+ );
1005
+ }
1006
+ async setBalance(_address, _balance) {
1007
+ throw new NodeError(
1008
+ "setBalance not implemented for Core client",
1009
+ "NOT_IMPLEMENTED",
1010
+ "core"
1011
+ );
1012
+ }
1013
+ async getStorageAt(_address, _slot) {
1014
+ throw new NodeError(
1015
+ "getStorageAt not implemented for Core client",
1016
+ "NOT_IMPLEMENTED",
1017
+ "core"
1018
+ );
1019
+ }
1020
+ async setStorageAt(_address, _slot, _value) {
1021
+ throw new NodeError(
1022
+ "setStorageAt not implemented for Core client",
1023
+ "NOT_IMPLEMENTED",
1024
+ "core"
1025
+ );
1026
+ }
1027
+ getInternalTestClient() {
1028
+ return this.testClient;
1029
+ }
1030
+ };
1031
+ async function createCoreClient(config) {
1032
+ const chainConfig = getChainConfig(config.chainId);
1033
+ if (chainConfig.type !== "core") {
1034
+ throw new NodeError(
1035
+ `Invalid chain type for Core client: ${chainConfig.type}`,
1036
+ "INVALID_CHAIN_TYPE",
1037
+ "core"
1038
+ );
1039
+ }
1040
+ const clientConfig = {
1041
+ ...config,
1042
+ rpcUrl: config.rpcUrl || chainConfig.rpcUrls.default.http[0] || "http://localhost:12537",
1043
+ wsUrl: config.wsUrl || chainConfig.rpcUrls.default.webSocket?.[0]
1044
+ };
1045
+ const publicClient = new CoreClient(clientConfig);
1046
+ let walletClient;
1047
+ let testClient;
1048
+ if (config.account) {
1049
+ let privateKey;
1050
+ if (typeof config.account === "string") {
1051
+ privateKey = config.account;
1052
+ } else {
1053
+ privateKey = config.account.privateKey;
1054
+ }
1055
+ const walletConfig = {
1056
+ ...clientConfig,
1057
+ privateKey,
1058
+ accountIndex: typeof config.account === "object" ? config.account.accountIndex : 0
1059
+ };
1060
+ walletClient = new CoreWalletClient(walletConfig);
1061
+ }
1062
+ if (config.testMode) {
1063
+ const testConfig = {
1064
+ ...clientConfig,
1065
+ enableTestMode: true
1066
+ };
1067
+ testClient = new CoreTestClient(testConfig);
1068
+ }
1069
+ return {
1070
+ publicClient,
1071
+ walletClient,
1072
+ testClient
1073
+ };
1074
+ }
1075
+
1076
+ // src/clients/evm.ts
1077
+ import {
1078
+ createPublicClient as createPublicClient2,
1079
+ createTestClient as createTestClient2,
1080
+ createWalletClient as createWalletClient2,
1081
+ defineChain as defineChain3,
1082
+ encodeFunctionData as encodeFunctionData2,
1083
+ formatEther,
1084
+ http as http2,
1085
+ isAddress as isEvmAddress,
1086
+ parseEther
1087
+ } from "viem";
1088
+ import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
1089
+ var espaceMainnet = defineChain3({
1090
+ id: 1030,
1091
+ name: "Conflux eSpace",
1092
+ nativeCurrency: { name: "Conflux", symbol: "CFX", decimals: 18 },
1093
+ rpcUrls: { default: { http: ["https://evm.confluxrpc.com"] } },
1094
+ blockExplorers: {
1095
+ default: { name: "ConfluxScan", url: "https://evm.confluxscan.net" }
1096
+ }
1097
+ });
1098
+ var espaceTestnet = defineChain3({
1099
+ id: 71,
1100
+ name: "Conflux eSpace Testnet",
1101
+ nativeCurrency: { name: "Conflux", symbol: "CFX", decimals: 18 },
1102
+ rpcUrls: { default: { http: ["https://evmtestnet.confluxrpc.com"] } },
1103
+ blockExplorers: {
1104
+ default: { name: "ConfluxScan", url: "https://evmtestnet.confluxscan.net" }
1105
+ }
1106
+ });
1107
+ var EspaceClient = class {
1108
+ chainId;
1109
+ chainType = "evm";
1110
+ publicClient;
1111
+ chain;
1112
+ address;
1113
+ constructor(config) {
1114
+ this.chainId = config.chainId;
1115
+ if (config.chainId === 1030) {
1116
+ this.chain = espaceMainnet;
1117
+ } else if (config.chainId === 71) {
1118
+ this.chain = espaceTestnet;
1119
+ } else {
1120
+ this.chain = defineChain3({
1121
+ id: config.chainId,
1122
+ name: `Conflux eSpace (${config.chainId})`,
1123
+ nativeCurrency: { name: "Conflux", symbol: "CFX", decimals: 18 },
1124
+ rpcUrls: { default: { http: [config.rpcUrl] } }
1125
+ });
1126
+ }
1127
+ this.publicClient = createPublicClient2({
1128
+ chain: this.chain,
1129
+ transport: http2(config.rpcUrl),
1130
+ pollingInterval: config.pollingInterval || 1e3
1131
+ });
1132
+ this.address = "";
1133
+ }
1134
+ async getBlockNumber() {
1135
+ try {
1136
+ const blockNumber = await this.publicClient.getBlockNumber();
1137
+ return blockNumber;
1138
+ } catch (error) {
1139
+ throw new NodeError(
1140
+ `Failed to get block number: ${error instanceof Error ? error.message : String(error)}`,
1141
+ "BLOCK_NUMBER_ERROR",
1142
+ "evm",
1143
+ { originalError: error }
1144
+ );
1145
+ }
1146
+ }
1147
+ async getBalance(address) {
1148
+ if (!isEvmAddress(address)) {
1149
+ throw new NodeError(
1150
+ "Invalid EVM address format",
1151
+ "INVALID_ADDRESS",
1152
+ "evm"
1153
+ );
1154
+ }
1155
+ try {
1156
+ const balance = await this.publicClient.getBalance({ address });
1157
+ return formatEther(balance);
1158
+ } catch (error) {
1159
+ throw new NodeError(
1160
+ `Failed to get balance: ${error instanceof Error ? error.message : String(error)}`,
1161
+ "BALANCE_ERROR",
1162
+ "evm",
1163
+ { address, originalError: error }
1164
+ );
1165
+ }
1166
+ }
1167
+ async estimateGas(tx) {
1168
+ try {
1169
+ const gas = await this.publicClient.estimateGas({
1170
+ to: tx.to,
1171
+ value: tx.value,
1172
+ data: tx.data
1173
+ });
1174
+ return gas;
1175
+ } catch (error) {
1176
+ throw new NodeError(
1177
+ `Failed to estimate gas: ${error instanceof Error ? error.message : String(error)}`,
1178
+ "GAS_ESTIMATE_ERROR",
1179
+ "evm",
1180
+ { transaction: tx, originalError: error }
1181
+ );
1182
+ }
1183
+ }
1184
+ async waitForTransaction(hash) {
1185
+ try {
1186
+ const receipt = await this.publicClient.waitForTransactionReceipt({
1187
+ hash,
1188
+ timeout: 5e3
1189
+ // 5 second timeout for faster response
1190
+ });
1191
+ return {
1192
+ hash: receipt.transactionHash,
1193
+ blockNumber: receipt.blockNumber,
1194
+ blockHash: receipt.blockHash,
1195
+ transactionIndex: receipt.transactionIndex,
1196
+ status: receipt.status === "success" ? "success" : "reverted",
1197
+ gasUsed: receipt.gasUsed,
1198
+ contractAddress: receipt.contractAddress || void 0,
1199
+ logs: receipt.logs.map((log) => ({
1200
+ address: log.address,
1201
+ topics: log.topics,
1202
+ data: log.data,
1203
+ blockNumber: log.blockNumber || 0n,
1204
+ transactionHash: log.transactionHash || "",
1205
+ logIndex: log.logIndex || 0
1206
+ }))
1207
+ };
1208
+ } catch (error) {
1209
+ throw new NodeError(
1210
+ `Failed to wait for transaction: ${error instanceof Error ? error.message : String(error)}`,
1211
+ "TRANSACTION_WAIT_ERROR",
1212
+ "evm",
1213
+ { hash, originalError: error }
1214
+ );
1215
+ }
1216
+ }
1217
+ async getGasPrice() {
1218
+ try {
1219
+ const gasPrice = await this.publicClient.getGasPrice();
1220
+ return gasPrice;
1221
+ } catch (error) {
1222
+ throw new NodeError(
1223
+ `Failed to get gas price: ${error instanceof Error ? error.message : String(error)}`,
1224
+ "GAS_PRICE_ERROR",
1225
+ "evm",
1226
+ { originalError: error }
1227
+ );
1228
+ }
1229
+ }
1230
+ /**
1231
+ * Get the current chain ID from the network
1232
+ */
1233
+ async getChainId() {
1234
+ try {
1235
+ const chainId = await this.publicClient.getChainId();
1236
+ return chainId;
1237
+ } catch (error) {
1238
+ throw new NodeError(
1239
+ `Failed to get chain ID: ${error instanceof Error ? error.message : String(error)}`,
1240
+ "CHAIN_ID_ERROR",
1241
+ "evm",
1242
+ { originalError: error }
1243
+ );
1244
+ }
1245
+ }
1246
+ /**
1247
+ * Check if the client is connected to the network
1248
+ */
1249
+ async isConnected() {
1250
+ try {
1251
+ await this.publicClient.getBlockNumber();
1252
+ return true;
1253
+ } catch {
1254
+ return false;
1255
+ }
1256
+ }
1257
+ // Base implementation - should be overridden by WalletClient
1258
+ async sendTransaction(_tx) {
1259
+ throw new NodeError(
1260
+ "sendTransaction not available on public client",
1261
+ "METHOD_NOT_AVAILABLE",
1262
+ "evm"
1263
+ );
1264
+ }
1265
+ async getTokenBalance(_address, _tokenAddress) {
1266
+ try {
1267
+ const balance = await this.publicClient.readContract({
1268
+ address: _tokenAddress,
1269
+ abi: [
1270
+ {
1271
+ type: "function",
1272
+ name: "balanceOf",
1273
+ inputs: [{ name: "account", type: "address" }],
1274
+ outputs: [{ name: "balance", type: "uint256" }],
1275
+ stateMutability: "view"
1276
+ }
1277
+ ],
1278
+ functionName: "balanceOf",
1279
+ args: [_address]
1280
+ });
1281
+ return balance.toString();
1282
+ } catch (error) {
1283
+ throw new NodeError(
1284
+ `Failed to get token balance: ${error instanceof Error ? error.message : String(error)}`,
1285
+ "TOKEN_BALANCE_ERROR",
1286
+ "evm",
1287
+ { address: _address, tokenAddress: _tokenAddress, originalError: error }
1288
+ );
1289
+ }
1290
+ }
1291
+ watchBlocks(callback) {
1292
+ const unwatch = this.publicClient.watchBlocks({
1293
+ onBlock: (block) => callback({
1294
+ chainType: "evm",
1295
+ blockNumber: block.number || 0n,
1296
+ blockHash: block.hash || "",
1297
+ timestamp: Number(block.timestamp || 0),
1298
+ transactionCount: block.transactions?.length || 0
1299
+ })
1300
+ });
1301
+ return unwatch;
1302
+ }
1303
+ async watchTransaction(_hash, _callback) {
1304
+ const pollTransaction = async () => {
1305
+ try {
1306
+ const receipt = await this.waitForTransaction(_hash);
1307
+ _callback(receipt);
1308
+ } catch {
1309
+ setTimeout(pollTransaction, 1e3);
1310
+ }
1311
+ };
1312
+ setTimeout(pollTransaction, 1e3);
1313
+ return () => {
1314
+ };
1315
+ }
1316
+ getInternalClient() {
1317
+ return this.publicClient;
1318
+ }
1319
+ // Base implementation - should be overridden by TestClient
1320
+ watchTransactions(_callback) {
1321
+ throw new NodeError(
1322
+ "watchTransactions not available on public client",
1323
+ "METHOD_NOT_AVAILABLE",
1324
+ "evm"
1325
+ );
1326
+ }
1327
+ isValidAddress(address) {
1328
+ return isEvmAddress(address);
1329
+ }
1330
+ formatAmount(amount) {
1331
+ return formatEther(amount);
1332
+ }
1333
+ parseAmount(amount) {
1334
+ return parseEther(amount);
1335
+ }
1336
+ };
1337
+ var EspaceWalletClient = class extends EspaceClient {
1338
+ walletClient;
1339
+ account;
1340
+ constructor(config) {
1341
+ super(config);
1342
+ this.account = privateKeyToAccount2(config.privateKey);
1343
+ this.address = this.account.address;
1344
+ this.walletClient = createWalletClient2({
1345
+ account: this.account,
1346
+ chain: this.chain,
1347
+ transport: http2(config.rpcUrl)
1348
+ });
1349
+ }
1350
+ getAddress() {
1351
+ return this.address;
1352
+ }
1353
+ async sendTransaction(tx) {
1354
+ try {
1355
+ const hash = await this.walletClient.sendTransaction({
1356
+ account: this.account,
1357
+ chain: this.chain,
1358
+ to: tx.to,
1359
+ value: tx.value,
1360
+ data: tx.data,
1361
+ gas: tx.gasLimit,
1362
+ gasPrice: tx.gasPrice,
1363
+ nonce: tx.nonce
1364
+ });
1365
+ return hash;
1366
+ } catch (error) {
1367
+ throw new NodeError(
1368
+ `Failed to send transaction: ${error instanceof Error ? error.message : String(error)}`,
1369
+ "TRANSACTION_ERROR",
1370
+ "evm",
1371
+ { transaction: tx, originalError: error }
1372
+ );
1373
+ }
1374
+ }
1375
+ async signMessage(message) {
1376
+ try {
1377
+ const signature = await this.walletClient.signMessage({
1378
+ account: this.account,
1379
+ message
1380
+ });
1381
+ return signature;
1382
+ } catch (error) {
1383
+ throw new NodeError(
1384
+ `Failed to sign message: ${error instanceof Error ? error.message : String(error)}`,
1385
+ "SIGNING_ERROR",
1386
+ "evm",
1387
+ { message, originalError: error }
1388
+ );
1389
+ }
1390
+ }
1391
+ async deployContract(abi, bytecode, constructorArgs = []) {
1392
+ try {
1393
+ const hash = await this.walletClient.deployContract({
1394
+ account: this.account,
1395
+ chain: this.chain,
1396
+ abi,
1397
+ bytecode,
1398
+ args: constructorArgs
1399
+ });
1400
+ const receipt = await this.waitForTransaction(hash);
1401
+ if (!receipt.contractAddress) {
1402
+ throw new Error("Contract address not found in transaction receipt");
1403
+ }
1404
+ return receipt.contractAddress;
1405
+ } catch (error) {
1406
+ throw new NodeError(
1407
+ `Failed to deploy contract: ${error instanceof Error ? error.message : String(error)}`,
1408
+ "DEPLOYMENT_ERROR",
1409
+ "evm",
1410
+ { bytecode, constructorArgs, originalError: error }
1411
+ );
1412
+ }
1413
+ }
1414
+ async callContract(address, abi, functionName, args = []) {
1415
+ try {
1416
+ const result = await this.publicClient.readContract({
1417
+ address,
1418
+ abi,
1419
+ functionName,
1420
+ args
1421
+ });
1422
+ return result;
1423
+ } catch (error) {
1424
+ throw new NodeError(
1425
+ `Failed to call contract: ${error instanceof Error ? error.message : String(error)}`,
1426
+ "CONTRACT_CALL_ERROR",
1427
+ "evm",
1428
+ { address, functionName, args, originalError: error }
1429
+ );
1430
+ }
1431
+ }
1432
+ async writeContract(address, abi, functionName, args = [], value) {
1433
+ try {
1434
+ const hash = await this.walletClient.writeContract({
1435
+ account: this.account,
1436
+ chain: this.chain,
1437
+ address,
1438
+ abi,
1439
+ functionName,
1440
+ args,
1441
+ value
1442
+ });
1443
+ return hash;
1444
+ } catch (error) {
1445
+ throw new NodeError(
1446
+ `Failed to write contract: ${error instanceof Error ? error.message : String(error)}`,
1447
+ "CONTRACT_WRITE_ERROR",
1448
+ "evm",
1449
+ { address, functionName, args, value, originalError: error }
1450
+ );
1451
+ }
1452
+ }
1453
+ /**
1454
+ * Transfer CFX from eSpace to Core Space
1455
+ * Uses the built-in withdrawal mechanism
1456
+ */
1457
+ async faucetToCore(coreAddress, amount) {
1458
+ if (!coreAddress.startsWith("cfx:") || coreAddress.length < 30) {
1459
+ throw new NodeError(
1460
+ "Invalid Core address format",
1461
+ "INVALID_ADDRESS",
1462
+ "evm",
1463
+ { coreAddress }
1464
+ );
1465
+ }
1466
+ try {
1467
+ const hash = await this.walletClient.sendTransaction({
1468
+ account: this.account,
1469
+ chain: this.chain,
1470
+ to: "0x0888000000000000000000000000000000000006",
1471
+ // CrossSpaceCall precompiled address
1472
+ value: parseEther(amount),
1473
+ data: encodeFunctionData2({
1474
+ abi: [
1475
+ {
1476
+ type: "function",
1477
+ name: "withdrawFromMapped",
1478
+ inputs: [{ name: "value", type: "uint256" }],
1479
+ outputs: [],
1480
+ stateMutability: "payable"
1481
+ }
1482
+ ],
1483
+ functionName: "withdrawFromMapped",
1484
+ args: [parseEther(amount)]
1485
+ })
1486
+ });
1487
+ return hash;
1488
+ } catch (error) {
1489
+ throw new NodeError(
1490
+ `Failed to send faucet transaction to Core: ${error instanceof Error ? error.message : String(error)}`,
1491
+ "FAUCET_ERROR",
1492
+ "evm",
1493
+ { coreAddress, amount, originalError: error }
1494
+ );
1495
+ }
1496
+ }
1497
+ getInternalClient() {
1498
+ return this.walletClient;
1499
+ }
1500
+ };
1501
+ var EspaceTestClient = class extends EspaceWalletClient {
1502
+ testClient;
1503
+ constructor(config) {
1504
+ super(config);
1505
+ this.testClient = createTestClient2({
1506
+ mode: "anvil",
1507
+ chain: this.chainId === 1030 ? espaceMainnet : espaceTestnet,
1508
+ transport: http2(config.rpcUrl),
1509
+ pollingInterval: config.pollingInterval || 1e3
1510
+ });
1511
+ }
1512
+ async mine(blocks = 1) {
1513
+ try {
1514
+ await this.testClient.mine({ blocks });
1515
+ } catch (error) {
1516
+ throw new NodeError(
1517
+ `Failed to mine blocks: ${error instanceof Error ? error.message : String(error)}`,
1518
+ "MINING_ERROR",
1519
+ "evm",
1520
+ { blocks, originalError: error }
1521
+ );
1522
+ }
1523
+ }
1524
+ async setNextBlockTimestamp(timestamp) {
1525
+ try {
1526
+ await this.testClient.setNextBlockTimestamp({
1527
+ timestamp: BigInt(timestamp)
1528
+ });
1529
+ } catch (error) {
1530
+ throw new NodeError(
1531
+ `Failed to set next block timestamp: ${error instanceof Error ? error.message : String(error)}`,
1532
+ "TIMESTAMP_ERROR",
1533
+ "evm",
1534
+ { timestamp, originalError: error }
1535
+ );
1536
+ }
1537
+ }
1538
+ async increaseTime(seconds) {
1539
+ try {
1540
+ await this.testClient.increaseTime({ seconds });
1541
+ } catch (error) {
1542
+ throw new NodeError(
1543
+ `Failed to increase time: ${error instanceof Error ? error.message : String(error)}`,
1544
+ "TIME_INCREASE_ERROR",
1545
+ "evm",
1546
+ { seconds, originalError: error }
1547
+ );
1548
+ }
1549
+ }
1550
+ async impersonateAccount(address) {
1551
+ try {
1552
+ await this.testClient.impersonateAccount({ address });
1553
+ } catch (error) {
1554
+ throw new NodeError(
1555
+ `Failed to impersonate account: ${error instanceof Error ? error.message : String(error)}`,
1556
+ "IMPERSONATION_ERROR",
1557
+ "evm",
1558
+ { address, originalError: error }
1559
+ );
1560
+ }
1561
+ }
1562
+ async stopImpersonatingAccount(address) {
1563
+ try {
1564
+ await this.testClient.stopImpersonatingAccount({
1565
+ address
1566
+ });
1567
+ } catch (error) {
1568
+ throw new NodeError(
1569
+ `Failed to stop impersonating account: ${error instanceof Error ? error.message : String(error)}`,
1570
+ "IMPERSONATION_STOP_ERROR",
1571
+ "evm",
1572
+ { address, originalError: error }
1573
+ );
1574
+ }
1575
+ }
1576
+ async setBalance(address, balance) {
1577
+ try {
1578
+ await this.testClient.setBalance({
1579
+ address,
1580
+ value: balance
1581
+ });
1582
+ } catch (error) {
1583
+ throw new NodeError(
1584
+ `Failed to set balance: ${error instanceof Error ? error.message : String(error)}`,
1585
+ "BALANCE_SET_ERROR",
1586
+ "evm",
1587
+ { address, balance, originalError: error }
1588
+ );
1589
+ }
1590
+ }
1591
+ async snapshot() {
1592
+ try {
1593
+ const snapshotId = await this.testClient.snapshot();
1594
+ return snapshotId;
1595
+ } catch (error) {
1596
+ throw new NodeError(
1597
+ `Failed to create snapshot: ${error instanceof Error ? error.message : String(error)}`,
1598
+ "SNAPSHOT_ERROR",
1599
+ "evm",
1600
+ { originalError: error }
1601
+ );
1602
+ }
1603
+ }
1604
+ async revert(snapshotId) {
1605
+ try {
1606
+ await this.testClient.revert({ id: snapshotId });
1607
+ } catch (error) {
1608
+ throw new NodeError(
1609
+ `Failed to revert to snapshot: ${error instanceof Error ? error.message : String(error)}`,
1610
+ "REVERT_ERROR",
1611
+ "evm",
1612
+ { snapshotId, originalError: error }
1613
+ );
1614
+ }
1615
+ }
1616
+ async getStorageAt(address, slot) {
1617
+ try {
1618
+ const value = await this.publicClient.getStorageAt({
1619
+ address,
1620
+ slot
1621
+ });
1622
+ return value || "0x";
1623
+ } catch (error) {
1624
+ throw new NodeError(
1625
+ `Failed to get storage: ${error instanceof Error ? error.message : String(error)}`,
1626
+ "STORAGE_GET_ERROR",
1627
+ "evm",
1628
+ { address, slot, originalError: error }
1629
+ );
1630
+ }
1631
+ }
1632
+ async setStorageAt(address, slot, value) {
1633
+ try {
1634
+ await this.testClient.setStorageAt({
1635
+ address,
1636
+ index: slot,
1637
+ value
1638
+ });
1639
+ } catch (error) {
1640
+ throw new NodeError(
1641
+ `Failed to set storage: ${error instanceof Error ? error.message : String(error)}`,
1642
+ "STORAGE_SET_ERROR",
1643
+ "evm",
1644
+ { address, slot, value, originalError: error }
1645
+ );
1646
+ }
1647
+ }
1648
+ watchTransactions(callback) {
1649
+ const unwatch = this.publicClient.watchPendingTransactions({
1650
+ onTransactions: (hashes) => {
1651
+ for (const hash of hashes) {
1652
+ callback({
1653
+ chainType: "evm",
1654
+ hash,
1655
+ from: "",
1656
+ // Would need to fetch transaction details
1657
+ to: "",
1658
+ // Would need to fetch transaction details
1659
+ value: 0n,
1660
+ // Would need to fetch transaction details
1661
+ blockNumber: 0n
1662
+ // Would need to fetch transaction details
1663
+ });
1664
+ }
1665
+ }
1666
+ });
1667
+ return unwatch;
1668
+ }
1669
+ isValidAddress(address) {
1670
+ return isEvmAddress(address);
1671
+ }
1672
+ async getCurrentEpoch() {
1673
+ return await this.getBlockNumber();
1674
+ }
1675
+ async generateAccounts(count) {
1676
+ const accounts = [];
1677
+ for (let i = 0; i < count; i++) {
1678
+ const privateKey = `0x${"0".repeat(64 - 2)}${i.toString(16).padStart(2, "0")}${"0".repeat(60)}`;
1679
+ const account = privateKeyToAccount2(privateKey);
1680
+ accounts.push(account.address);
1681
+ }
1682
+ return accounts;
1683
+ }
1684
+ };
1685
+ async function createEspaceClient(config) {
1686
+ const chainConfig = getChainConfig(config.chainId);
1687
+ if (chainConfig.type !== "evm") {
1688
+ throw new NodeError(
1689
+ `Invalid chain type for eSpace client: ${chainConfig.type}`,
1690
+ "INVALID_CHAIN_TYPE",
1691
+ "evm"
1692
+ );
1693
+ }
1694
+ const clientConfig = {
1695
+ ...config,
1696
+ rpcUrl: config.rpcUrl || chainConfig.rpcUrls.default.http[0] || "http://localhost:8545"
1697
+ };
1698
+ const publicClient = new EspaceClient(clientConfig);
1699
+ let walletClient;
1700
+ let testClient;
1701
+ if (config.account) {
1702
+ let privateKey;
1703
+ if (typeof config.account === "string") {
1704
+ privateKey = config.account;
1705
+ } else {
1706
+ privateKey = config.account.privateKey;
1707
+ }
1708
+ const walletConfig = {
1709
+ ...clientConfig,
1710
+ privateKey,
1711
+ accountIndex: typeof config.account === "object" ? config.account.accountIndex : 0
1712
+ };
1713
+ walletClient = new EspaceWalletClient(walletConfig);
1714
+ }
1715
+ if (config.testMode) {
1716
+ let privateKey;
1717
+ if (config.account) {
1718
+ if (typeof config.account === "string") {
1719
+ privateKey = config.account;
1720
+ } else {
1721
+ privateKey = config.account.privateKey;
1722
+ }
1723
+ } else {
1724
+ privateKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
1725
+ }
1726
+ const testConfig = {
1727
+ ...clientConfig,
1728
+ enableTestMode: true,
1729
+ privateKey
1730
+ };
1731
+ testClient = new EspaceTestClient(testConfig);
1732
+ }
1733
+ return {
1734
+ publicClient,
1735
+ walletClient,
1736
+ testClient
1737
+ };
1738
+ }
1739
+
1740
+ // src/clients/manager.ts
1741
+ import { EventEmitter } from "events";
1742
+ var HEALTH_CHECK_INTERVAL = 3e4;
1743
+ var HEALTH_CHECK_TIMEOUT = 5e3;
1744
+ var ClientManager = class extends EventEmitter {
1745
+ config;
1746
+ coreClient = null;
1747
+ evmClient = null;
1748
+ healthCheckInterval = null;
1749
+ networkSelectorUnsubscribe = null;
1750
+ nodeRunningUnsubscribe = null;
1751
+ initialized = false;
1752
+ constructor(config) {
1753
+ super();
1754
+ this.config = {
1755
+ enableHealthMonitoring: true,
1756
+ healthCheckInterval: HEALTH_CHECK_INTERVAL,
1757
+ healthCheckTimeout: HEALTH_CHECK_TIMEOUT,
1758
+ ...config
1759
+ };
1760
+ }
1761
+ /**
1762
+ * Initialize the Client Manager
1763
+ * Sets up clients, server, and monitoring
1764
+ */
1765
+ async initialize() {
1766
+ if (this.initialized) {
1767
+ return;
1768
+ }
1769
+ try {
1770
+ this.setupNetworkListeners();
1771
+ await this.initializeClients();
1772
+ if (this.config.enableHealthMonitoring) {
1773
+ this.startHealthMonitoring();
1774
+ }
1775
+ this.initialized = true;
1776
+ this.emit("manager:ready");
1777
+ } catch (error) {
1778
+ const managerError = error instanceof Error ? error : new Error(String(error));
1779
+ this.emit("manager:error", { error: managerError });
1780
+ throw managerError;
1781
+ }
1782
+ }
1783
+ /**
1784
+ * Gracefully shutdown the Client Manager
1785
+ */
1786
+ async shutdown() {
1787
+ if (!this.initialized) {
1788
+ return;
1789
+ }
1790
+ try {
1791
+ this.stopHealthMonitoring();
1792
+ if (this.networkSelectorUnsubscribe) {
1793
+ this.networkSelectorUnsubscribe();
1794
+ this.networkSelectorUnsubscribe = null;
1795
+ }
1796
+ if (this.nodeRunningUnsubscribe) {
1797
+ this.nodeRunningUnsubscribe();
1798
+ this.nodeRunningUnsubscribe = null;
1799
+ }
1800
+ this.coreClient = null;
1801
+ this.evmClient = null;
1802
+ this.initialized = false;
1803
+ this.removeAllListeners();
1804
+ } catch (error) {
1805
+ const shutdownError = error instanceof Error ? error : new Error(String(error));
1806
+ this.emit("manager:error", { error: shutdownError });
1807
+ throw shutdownError;
1808
+ }
1809
+ }
1810
+ /**
1811
+ * Get current Core Space client
1812
+ */
1813
+ getCoreClient() {
1814
+ return this.coreClient;
1815
+ }
1816
+ /**
1817
+ * Get current eSpace client
1818
+ */
1819
+ getEvmClient() {
1820
+ return this.evmClient;
1821
+ }
1822
+ /**
1823
+ * Get comprehensive status
1824
+ */
1825
+ getStatus() {
1826
+ const currentChainId = defaultNetworkSelector.getCurrentChainId();
1827
+ const currentChain = getChainConfig(currentChainId);
1828
+ return {
1829
+ initialized: this.initialized,
1830
+ coreClient: {
1831
+ connected: !!this.coreClient,
1832
+ chainId: currentChain.type === "core" ? currentChainId : defaultNetworkSelector.getCorrespondingChainId() || 1,
1833
+ health: "unknown",
1834
+ // TODO: Implement health status tracking
1835
+ lastHealthCheck: void 0
1836
+ },
1837
+ evmClient: {
1838
+ connected: !!this.evmClient,
1839
+ chainId: currentChain.type === "evm" ? currentChainId : defaultNetworkSelector.getCorrespondingChainId() || 71,
1840
+ health: "unknown",
1841
+ // TODO: Implement health status tracking
1842
+ lastHealthCheck: void 0
1843
+ },
1844
+ networkSelector: {
1845
+ currentChain: currentChainId,
1846
+ isLocalNode: defaultNetworkSelector.getNodeRunningStatus(),
1847
+ lockedToLocal: defaultNetworkSelector.isLockedToLocal()
1848
+ }
1849
+ };
1850
+ }
1851
+ /**
1852
+ * Switch to a specific network
1853
+ * @param chainId - Target chain ID
1854
+ * @param force - Force switch even if node is running (for wallet operations)
1855
+ */
1856
+ async switchNetwork(chainId, force = false) {
1857
+ if (!isValidChainId(chainId)) {
1858
+ throw new Error(`Invalid chain ID: ${chainId}`);
1859
+ }
1860
+ const previousChainId = defaultNetworkSelector.getCurrentChainId();
1861
+ if (previousChainId === chainId) {
1862
+ return;
1863
+ }
1864
+ defaultNetworkSelector.switchChain(chainId, force);
1865
+ if (defaultNetworkSelector.getCurrentChainId() === chainId) {
1866
+ await this.initializeClients();
1867
+ this.emit("network:switched", { from: previousChainId, to: chainId });
1868
+ }
1869
+ }
1870
+ /**
1871
+ * Initialize or reinitialize client instances based on current network
1872
+ */
1873
+ async initializeClients() {
1874
+ const currentChainId = defaultNetworkSelector.getCurrentChainId();
1875
+ const currentChain = getChainConfig(currentChainId);
1876
+ try {
1877
+ if (currentChain.type === "core") {
1878
+ const evmChainId = defaultNetworkSelector.getCorrespondingChainId() || 71;
1879
+ this.coreClient = await createCoreClient({
1880
+ ...this.config.core,
1881
+ chainId: currentChainId
1882
+ });
1883
+ this.evmClient = await createEspaceClient({
1884
+ ...this.config.evm,
1885
+ chainId: evmChainId
1886
+ });
1887
+ } else {
1888
+ const coreChainId = defaultNetworkSelector.getCorrespondingChainId() || 1;
1889
+ this.coreClient = await createCoreClient({
1890
+ ...this.config.core,
1891
+ chainId: coreChainId
1892
+ });
1893
+ this.evmClient = await createEspaceClient({
1894
+ ...this.config.evm,
1895
+ chainId: currentChainId
1896
+ });
1897
+ }
1898
+ this.emit("client:ready", {
1899
+ type: "core",
1900
+ chainId: this.coreClient.publicClient.chainId
1901
+ });
1902
+ this.emit("client:ready", {
1903
+ type: "evm",
1904
+ chainId: this.evmClient.publicClient.chainId
1905
+ });
1906
+ } catch (error) {
1907
+ const clientError = error instanceof Error ? error : new Error(String(error));
1908
+ this.emit("manager:error", { error: clientError });
1909
+ throw clientError;
1910
+ }
1911
+ }
1912
+ /**
1913
+ * Set up network selector event listeners
1914
+ */
1915
+ setupNetworkListeners() {
1916
+ this.networkSelectorUnsubscribe = defaultNetworkSelector.onChainChange(
1917
+ async (_chainId) => {
1918
+ try {
1919
+ await this.initializeClients();
1920
+ } catch (error) {
1921
+ const networkError = error instanceof Error ? error : new Error(String(error));
1922
+ this.emit("manager:error", { error: networkError });
1923
+ }
1924
+ }
1925
+ );
1926
+ this.nodeRunningUnsubscribe = defaultNetworkSelector.onNodeRunningChange(
1927
+ async (isRunning) => {
1928
+ if (isRunning) {
1929
+ } else {
1930
+ }
1931
+ }
1932
+ );
1933
+ }
1934
+ /**
1935
+ * Start health monitoring for all clients
1936
+ */
1937
+ startHealthMonitoring() {
1938
+ if (this.healthCheckInterval) {
1939
+ return;
1940
+ }
1941
+ this.healthCheckInterval = setInterval(async () => {
1942
+ await this.performHealthChecks();
1943
+ }, this.config.healthCheckInterval || HEALTH_CHECK_INTERVAL);
1944
+ setTimeout(() => this.performHealthChecks(), 1e3);
1945
+ }
1946
+ /**
1947
+ * Stop health monitoring
1948
+ */
1949
+ stopHealthMonitoring() {
1950
+ if (this.healthCheckInterval) {
1951
+ clearInterval(this.healthCheckInterval);
1952
+ this.healthCheckInterval = null;
1953
+ }
1954
+ }
1955
+ /**
1956
+ * Perform health checks on all clients
1957
+ */
1958
+ async performHealthChecks() {
1959
+ const timeout = this.config.healthCheckTimeout || HEALTH_CHECK_TIMEOUT;
1960
+ if (this.coreClient) {
1961
+ try {
1962
+ const healthPromise = this.checkCoreClientHealth();
1963
+ const result = await Promise.race([
1964
+ healthPromise,
1965
+ new Promise(
1966
+ (_, reject) => setTimeout(() => reject(new Error("Health check timeout")), timeout)
1967
+ )
1968
+ ]);
1969
+ this.emit("client:health", {
1970
+ type: "core",
1971
+ chainId: this.coreClient.publicClient.chainId,
1972
+ status: result
1973
+ });
1974
+ } catch (error) {
1975
+ this.emit("client:error", {
1976
+ type: "core",
1977
+ chainId: this.coreClient.publicClient.chainId,
1978
+ error: error instanceof Error ? error : new Error(String(error))
1979
+ });
1980
+ }
1981
+ }
1982
+ if (this.evmClient) {
1983
+ try {
1984
+ const healthPromise = this.checkEvmClientHealth();
1985
+ const result = await Promise.race([
1986
+ healthPromise,
1987
+ new Promise(
1988
+ (_, reject) => setTimeout(() => reject(new Error("Health check timeout")), timeout)
1989
+ )
1990
+ ]);
1991
+ this.emit("client:health", {
1992
+ type: "evm",
1993
+ chainId: this.evmClient.publicClient.chainId,
1994
+ status: result
1995
+ });
1996
+ } catch (error) {
1997
+ this.emit("client:error", {
1998
+ type: "evm",
1999
+ chainId: this.evmClient.publicClient.chainId,
2000
+ error: error instanceof Error ? error : new Error(String(error))
2001
+ });
2002
+ }
2003
+ }
2004
+ }
2005
+ /**
2006
+ * Check Core client health
2007
+ */
2008
+ async checkCoreClientHealth() {
2009
+ if (!this.coreClient) {
2010
+ return "disconnected";
2011
+ }
2012
+ try {
2013
+ await this.coreClient.publicClient.getBlockNumber();
2014
+ return "healthy";
2015
+ } catch (_error) {
2016
+ return "unhealthy";
2017
+ }
2018
+ }
2019
+ /**
2020
+ * Check eSpace client health
2021
+ */
2022
+ async checkEvmClientHealth() {
2023
+ if (!this.evmClient) {
2024
+ return "disconnected";
2025
+ }
2026
+ try {
2027
+ await this.evmClient.publicClient.getBlockNumber();
2028
+ return "healthy";
2029
+ } catch (_error) {
2030
+ return "unhealthy";
2031
+ }
2032
+ }
2033
+ };
2034
+ export {
2035
+ ClientManager,
2036
+ CoreClient,
2037
+ CoreTestClient,
2038
+ CoreWalletClient,
2039
+ EspaceClient,
2040
+ EspaceTestClient,
2041
+ EspaceWalletClient
2042
+ };
2043
+ //# sourceMappingURL=index.js.map