ethershell 0.1.0-alpha.0 → 0.1.0-alpha.4
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/LICENSE +55 -55
- package/README.md +643 -647
- package/bin/cli.js +88 -88
- package/package.json +48 -49
- package/src/services/addContracts.js +221 -221
- package/src/services/build.js +156 -156
- package/src/services/contracts.js +43 -43
- package/src/services/files.js +39 -39
- package/src/services/network.js +112 -112
- package/src/services/wallet.js +375 -375
- package/src/utils/accounter.js +212 -212
- package/src/utils/builder.js +169 -169
- package/src/utils/contractLister.js +36 -36
- package/src/utils/dir.js +80 -80
- package/src/utils/replHelper.js +45 -45
package/README.md
CHANGED
|
@@ -1,647 +1,643 @@
|
|
|
1
|
-
# 🔷 EtherShell - Interactive Ethereum Smart Contract Console
|
|
2
|
-
|
|
3
|
-
**⚠️ WARNING: This package is in ALPHA testing. NOT production ready!**
|
|
4
|
-
|
|
5
|
-
An interactive Node.js console for Ethereum smart contract development. Write, compile, deploy, and manage smart contracts directly from the shell with an intuitive, Solidity-focused developer experience.
|
|
6
|
-
|
|
7
|
-
**Perfect for:**
|
|
8
|
-
- Smart contract developers who want a fast, interactive workflow
|
|
9
|
-
- Rapid prototyping and testing of Solidity contracts
|
|
10
|
-
- Learning Ethereum development
|
|
11
|
-
- DeFi protocol development and testing
|
|
12
|
-
- Quick contract interactions and deployments
|
|
13
|
-
|
|
14
|
-
## ✨ Features
|
|
15
|
-
|
|
16
|
-
- **Interactive Shell** - Built-in async support for all commands
|
|
17
|
-
- **Solidity Compilation** - Compile contracts with configurable optimization
|
|
18
|
-
- **Smart Contract Deployment** - Deploy contracts to any EVM network
|
|
19
|
-
- **Wallet Management** - Create, import, and manage wallets (regular & HD wallets)
|
|
20
|
-
- **Multi-Network Support** - Switch between different blockchain networks
|
|
21
|
-
- **Contract Interactions** - Call contract methods directly from the shell
|
|
22
|
-
- **ABI & Bytecode Generation** - Organized artifact output
|
|
23
|
-
- **Node Signer Integration** - Connect to node-managed accounts (Ganache, Hardhat)
|
|
24
|
-
- **TypeScript JSDoc** - Full IDE autocomplete and type hints
|
|
25
|
-
- **Gas Optimization** - Configure compiler optimization levels
|
|
26
|
-
|
|
27
|
-
## 🚀 Quick Start
|
|
28
|
-
|
|
29
|
-
### Installation
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
#
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
//
|
|
61
|
-
EtherShell> chain()
|
|
62
|
-
{ URL: '
|
|
63
|
-
|
|
64
|
-
//
|
|
65
|
-
EtherShell>
|
|
66
|
-
{ URL: '
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
//
|
|
162
|
-
EtherShell> walletInfo(0)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
//
|
|
194
|
-
EtherShell>
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
//
|
|
198
|
-
EtherShell>
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// Compile
|
|
217
|
-
EtherShell> build()
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
// Compile
|
|
221
|
-
EtherShell> build('./contracts/MyToken.sol')
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
//
|
|
225
|
-
EtherShell>
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
//
|
|
334
|
-
EtherShell> MyToken
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
EtherShell> MyToken.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
//
|
|
345
|
-
EtherShell> MyToken.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
|
403
|
-
|
|
404
|
-
| `
|
|
405
|
-
| `
|
|
406
|
-
| `
|
|
407
|
-
| `
|
|
408
|
-
| `
|
|
409
|
-
| `
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
|
417
|
-
|
|
418
|
-
| `
|
|
419
|
-
| `
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
├──
|
|
457
|
-
│
|
|
458
|
-
├──
|
|
459
|
-
│ ├──
|
|
460
|
-
│ │
|
|
461
|
-
│
|
|
462
|
-
│
|
|
463
|
-
│
|
|
464
|
-
│
|
|
465
|
-
│
|
|
466
|
-
│
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
//
|
|
518
|
-
EtherShell> MyToken.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
- @
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
##
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
- [
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
**Made with ❤️ for Ethereum developers**
|
|
646
|
-
|
|
647
|
-
Happy coding! 🚀
|
|
1
|
+
# 🔷 EtherShell - Interactive Ethereum Smart Contract Console
|
|
2
|
+
|
|
3
|
+
**⚠️ WARNING: This package is in ALPHA testing. NOT production ready!**
|
|
4
|
+
|
|
5
|
+
An interactive Node.js console for Ethereum smart contract development. Write, compile, deploy, and manage smart contracts directly from the shell with an intuitive, Solidity-focused developer experience.
|
|
6
|
+
|
|
7
|
+
**Perfect for:**
|
|
8
|
+
- Smart contract developers who want a fast, interactive workflow
|
|
9
|
+
- Rapid prototyping and testing of Solidity contracts
|
|
10
|
+
- Learning Ethereum development
|
|
11
|
+
- DeFi protocol development and testing
|
|
12
|
+
- Quick contract interactions and deployments
|
|
13
|
+
|
|
14
|
+
## ✨ Features
|
|
15
|
+
|
|
16
|
+
- **Interactive Shell** - Built-in async support for all commands
|
|
17
|
+
- **Solidity Compilation** - Compile contracts with configurable optimization
|
|
18
|
+
- **Smart Contract Deployment** - Deploy contracts to any EVM network
|
|
19
|
+
- **Wallet Management** - Create, import, and manage wallets (regular & HD wallets)
|
|
20
|
+
- **Multi-Network Support** - Switch between different blockchain networks
|
|
21
|
+
- **Contract Interactions** - Call contract methods directly from the shell
|
|
22
|
+
- **ABI & Bytecode Generation** - Organized artifact output
|
|
23
|
+
- **Node Signer Integration** - Connect to node-managed accounts (Ganache, Hardhat)
|
|
24
|
+
- **TypeScript JSDoc** - Full IDE autocomplete and type hints
|
|
25
|
+
- **Gas Optimization** - Configure compiler optimization levels
|
|
26
|
+
|
|
27
|
+
## 🚀 Quick Start
|
|
28
|
+
|
|
29
|
+
### Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Install globally
|
|
33
|
+
npm i -g ethershell
|
|
34
|
+
|
|
35
|
+
# Start EtherShell
|
|
36
|
+
npm start
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Basic Usage
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Start the console
|
|
43
|
+
npm start
|
|
44
|
+
|
|
45
|
+
# You should see:
|
|
46
|
+
# EtherShell>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 📖 Step-by-Step Guide
|
|
50
|
+
|
|
51
|
+
### 1. Network Configuration
|
|
52
|
+
|
|
53
|
+
First, connect to a blockchain network:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
// View current network
|
|
57
|
+
EtherShell> chain()
|
|
58
|
+
{ URL: 'http://127.0.0.1:8545', name: 'unknown', chainId: 1337n }
|
|
59
|
+
|
|
60
|
+
// Switch to a different network
|
|
61
|
+
EtherShell> chain('https://sepolia.infura.io/v3/YOUR-PROJECT-ID')
|
|
62
|
+
{ URL: 'https://sepolia.infura.io/v3/...', name: 'sepolia', chainId: 11155111n }
|
|
63
|
+
|
|
64
|
+
// Get default network info
|
|
65
|
+
EtherShell> defaultChain()
|
|
66
|
+
{ URL: 'http://127.0.0.1:8545' }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Wallet Management
|
|
70
|
+
|
|
71
|
+
#### Create New Wallets
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// Create a single random wallet
|
|
75
|
+
EtherShell> newWallet()
|
|
76
|
+
!WARNING!
|
|
77
|
+
The generated accounts are NOT safe. Do NOT use them on main net!
|
|
78
|
+
[
|
|
79
|
+
{
|
|
80
|
+
index: 0,
|
|
81
|
+
address: '0x1234...5678',
|
|
82
|
+
privateKey: '0xabcd...ef01',
|
|
83
|
+
type: 'user-generated',
|
|
84
|
+
contracts: []
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
// Create 5 new wallets at once
|
|
89
|
+
EtherShell> newWallet(5)
|
|
90
|
+
!WARNING!
|
|
91
|
+
The generated accounts are NOT safe. Do NOT use them on main net!
|
|
92
|
+
[
|
|
93
|
+
{ index: 0, address: '0x...', ... },
|
|
94
|
+
{ index: 1, address: '0x...', ... },
|
|
95
|
+
// ... 5 wallets total
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Import Existing Wallets
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
// Import a single private key
|
|
103
|
+
EtherShell> addWallet('0xYourPrivateKeyHere')
|
|
104
|
+
|
|
105
|
+
// Import multiple private keys
|
|
106
|
+
EtherShell> addWallet([
|
|
107
|
+
'0xPrivateKey1...',
|
|
108
|
+
'0xPrivateKey2...',
|
|
109
|
+
'0xPrivateKey3...'
|
|
110
|
+
])
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### HD Wallet Management
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
// Create new HD wallet (10 derived accounts)
|
|
117
|
+
EtherShell> newHDWallet()
|
|
118
|
+
!WARNING!
|
|
119
|
+
The generated accounts are NOT safe. Do NOT use them on main net!
|
|
120
|
+
[
|
|
121
|
+
{ index: 0, address: '0x...', phrase: '...', path: "m/0", ... },
|
|
122
|
+
{ index: 1, address: '0x...', phrase: '...', path: "m/1", ... },
|
|
123
|
+
// ... 10 accounts
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
// Create 5 derived accounts from new random mnemonic
|
|
127
|
+
EtherShell> newHDWallet(5)
|
|
128
|
+
|
|
129
|
+
// Import HD wallet from known mnemonic
|
|
130
|
+
EtherShell> addHDWallet('word word word ... (12 or 24 words)', 10)
|
|
131
|
+
|
|
132
|
+
// View all HD wallets
|
|
133
|
+
EtherShell> hdWallets()
|
|
134
|
+
!WARNING!
|
|
135
|
+
The generated accounts are NOT safe. Do NOT use them on main net!
|
|
136
|
+
[...]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### Connect to Node-Managed Accounts
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// For Ganache, Hardhat, or other nodes with unlocked accounts
|
|
143
|
+
EtherShell> connectWallet()
|
|
144
|
+
|
|
145
|
+
// This adds accounts managed by the node (e.g., Ganache default accounts)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### View Wallets
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
// View regular (imported/generated) accounts
|
|
152
|
+
EtherShell> wallets()
|
|
153
|
+
|
|
154
|
+
// View all accounts (regular + HD + node-managed)
|
|
155
|
+
EtherShell> allWallets()
|
|
156
|
+
|
|
157
|
+
// View wallet details with balance and nonce
|
|
158
|
+
EtherShell> walletInfo(0)
|
|
159
|
+
// or by address
|
|
160
|
+
EtherShell> walletInfo('0x1234...5678')
|
|
161
|
+
// or multiple
|
|
162
|
+
EtherShell> walletInfo([0, 1, 2])
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Delete Wallets
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
// Delete by index
|
|
169
|
+
EtherShell> removeWallet(0)
|
|
170
|
+
|
|
171
|
+
// Delete by address
|
|
172
|
+
EtherShell> removeWallet('0x1234...5678')
|
|
173
|
+
|
|
174
|
+
// Delete by mnemonic (all derived accounts from this phrase)
|
|
175
|
+
EtherShell> removeWallet('word word word ...')
|
|
176
|
+
|
|
177
|
+
// Delete multiple by indices
|
|
178
|
+
EtherShell> removeWallet([0, 2, 4])
|
|
179
|
+
|
|
180
|
+
// Delete all wallets
|
|
181
|
+
EtherShell> removeWallet()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 3. Solidity Compilation
|
|
185
|
+
|
|
186
|
+
#### Configure Compiler
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
// View current compiler version
|
|
190
|
+
EtherShell> compiler()
|
|
191
|
+
"0.8.20+commit.a1b79de6.Emscripten.clang"
|
|
192
|
+
|
|
193
|
+
// Switch to a different Solidity version
|
|
194
|
+
EtherShell> compUpdate('v0.8.19+commit.7dd6d404')
|
|
195
|
+
Loaded solc version: 0.8.19+commit.7dd6d404.Emscripten.clang
|
|
196
|
+
|
|
197
|
+
// Configure compilation options
|
|
198
|
+
EtherShell> compOpts(true, false, 1000)
|
|
199
|
+
✓ Compiler options updated:
|
|
200
|
+
Gas Optimizer: Enabled
|
|
201
|
+
Optimizer Runs: 1000
|
|
202
|
+
ViaIR: Disabled
|
|
203
|
+
|
|
204
|
+
// Get current options
|
|
205
|
+
EtherShell> compInfo()
|
|
206
|
+
{ optimizer: true, optimizerRuns: 1000, viaIR: false }
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### Compile Contracts
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
// Compile all .sol files in ./contracts directory
|
|
213
|
+
EtherShell> build()
|
|
214
|
+
Contracts compiled into /path/to/build
|
|
215
|
+
|
|
216
|
+
// Compile a specific contract file
|
|
217
|
+
EtherShell> build('./contracts/MyToken.sol')
|
|
218
|
+
Contract compiled into /path/to/build
|
|
219
|
+
|
|
220
|
+
// Compile specific contracts from a file
|
|
221
|
+
EtherShell> build('./contracts/MyToken.sol', ['MyToken', 'OtherContract'], './custom-build')
|
|
222
|
+
Contracts compiled into /path/to/custom-build
|
|
223
|
+
|
|
224
|
+
// Clean build directory
|
|
225
|
+
EtherShell> clean()
|
|
226
|
+
Directory deleted successfully
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Compiler Output Structure:**
|
|
230
|
+
```
|
|
231
|
+
build/
|
|
232
|
+
├── artifacts/ # Complete contract data with metadata
|
|
233
|
+
├── abis/ # Contract ABIs (.abi.json files)
|
|
234
|
+
├── bytecode/ # Contract bytecode (.bin files)
|
|
235
|
+
└── metadata/ # Contract metadata (.metadata.json files)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 4. Smart Contract Deployment
|
|
239
|
+
|
|
240
|
+
#### Deploy New Contracts
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// Deploy MyToken contract with constructor args
|
|
244
|
+
// Arguments: contractName, args[], walletIndex, [chainURL], [abiLocation], [bytecodeLocation]
|
|
245
|
+
EtherShell> deploy('MyToken', ['MyTokenName', 'MTK', 1000000], 0)
|
|
246
|
+
{
|
|
247
|
+
hash: '0x123abc...',
|
|
248
|
+
from: '0x1234...5678',
|
|
249
|
+
to: null,
|
|
250
|
+
address: '0xabcd...ef01',
|
|
251
|
+
name: 'MyToken',
|
|
252
|
+
chain: 'sepolia',
|
|
253
|
+
deployType: 'ethershell-deployed'
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Deploy with custom chain
|
|
257
|
+
EtherShell> deploy('MyContract', ['arg1', 'arg2'], 0, 'https://custom-rpc.url')
|
|
258
|
+
|
|
259
|
+
// The deployed contract is automatically added to console context
|
|
260
|
+
EtherShell> MyToken
|
|
261
|
+
Contract {
|
|
262
|
+
target: '0xabcd...ef01',
|
|
263
|
+
interface: Interface { ... },
|
|
264
|
+
runner: Signer { ... },
|
|
265
|
+
// ... contract methods available
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Add Existing Contracts
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
// Add an already-deployed contract
|
|
273
|
+
// Arguments: contractName, contractAddress, walletIndex, abiPath, [chainURL]
|
|
274
|
+
EtherShell> addContract('USDT', '0xdAC17F958D2ee523a2206206994597C13D831ec7', 0, './abis/USDT.json')
|
|
275
|
+
{
|
|
276
|
+
index: 1,
|
|
277
|
+
name: 'USDT',
|
|
278
|
+
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
279
|
+
chain: 'mainnet',
|
|
280
|
+
chainId: 1n,
|
|
281
|
+
deployType: 'pre-deployed'
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Now you can interact with it
|
|
285
|
+
EtherShell> USDT.balanceOf('0x1234...5678')
|
|
286
|
+
n
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### 5. Contract Interaction
|
|
290
|
+
|
|
291
|
+
#### View Contracts
|
|
292
|
+
|
|
293
|
+
```javascript
|
|
294
|
+
// Get all deployed/added contracts
|
|
295
|
+
EtherShell> contracts()
|
|
296
|
+
[
|
|
297
|
+
{
|
|
298
|
+
index: 0,
|
|
299
|
+
name: 'MyToken',
|
|
300
|
+
address: '0xabcd...ef01',
|
|
301
|
+
chain: 'sepolia',
|
|
302
|
+
chainId: 11155111n,
|
|
303
|
+
deployType: 'ethershell-deployed',
|
|
304
|
+
balance: 0n
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
index: 1,
|
|
308
|
+
name: 'USDT',
|
|
309
|
+
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
310
|
+
chain: 'mainnet',
|
|
311
|
+
deployType: 'pre-deployed',
|
|
312
|
+
balance: 0n
|
|
313
|
+
}
|
|
314
|
+
]
|
|
315
|
+
|
|
316
|
+
// Get contract by index
|
|
317
|
+
EtherShell> contracts(0)
|
|
318
|
+
|
|
319
|
+
// Get contract by address
|
|
320
|
+
EtherShell> contracts('0xabcd...ef01')
|
|
321
|
+
|
|
322
|
+
// Get contract by name
|
|
323
|
+
EtherShell> contracts('MyToken')
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
#### Call Contract Functions
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
// Your deployed contracts are available as variables
|
|
330
|
+
EtherShell> MyToken
|
|
331
|
+
Contract { ... }
|
|
332
|
+
|
|
333
|
+
// Read-only functions (no gas cost)
|
|
334
|
+
EtherShell> MyToken.name()
|
|
335
|
+
"MyTokenName"
|
|
336
|
+
|
|
337
|
+
EtherShell> MyToken.totalSupply()
|
|
338
|
+
1000000n
|
|
339
|
+
|
|
340
|
+
// State-changing functions (costs gas, requires signer)
|
|
341
|
+
EtherShell> MyToken.transfer('0xRecipientAddress', 100)
|
|
342
|
+
ContractTransactionResponse { ... }
|
|
343
|
+
|
|
344
|
+
// Check balance
|
|
345
|
+
EtherShell> MyToken.balanceOf('0x1234...5678')
|
|
346
|
+
100n
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## 🎯 Complete Usage Example
|
|
350
|
+
|
|
351
|
+
Here's a full workflow example:
|
|
352
|
+
|
|
353
|
+
```javascript
|
|
354
|
+
// 1. Connect to network
|
|
355
|
+
EtherShell> chain('http://127.0.0.1:8545')
|
|
356
|
+
|
|
357
|
+
// 2. Create wallets
|
|
358
|
+
EtherShell> newWallet(2)
|
|
359
|
+
|
|
360
|
+
// 3. View wallets
|
|
361
|
+
EtherShell> wallets()
|
|
362
|
+
|
|
363
|
+
// 4. Configure compiler
|
|
364
|
+
EtherShell> compOpts(true, false, 1000)
|
|
365
|
+
|
|
366
|
+
// 5. Compile contracts
|
|
367
|
+
EtherShell> build()
|
|
368
|
+
|
|
369
|
+
// 6. Deploy contract
|
|
370
|
+
EtherShell> deploy('MyToken', ['TestToken', 'TEST', 1000000], 0)
|
|
371
|
+
|
|
372
|
+
// 7. Interact with contract
|
|
373
|
+
EtherShell> MyToken.balanceOf('0x...')
|
|
374
|
+
|
|
375
|
+
// 8. Transfer tokens
|
|
376
|
+
EtherShell> tx = MyToken.transfer('0x...', 100)
|
|
377
|
+
|
|
378
|
+
// 9. Wait for transaction
|
|
379
|
+
EtherShell> receipt = tx.wait()
|
|
380
|
+
|
|
381
|
+
// 10. Check balance again
|
|
382
|
+
EtherShell> MyToken.balanceOf('0x...')
|
|
383
|
+
|
|
384
|
+
// 11. View all contracts
|
|
385
|
+
EtherShell> contracts()
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## 📋 Command Reference
|
|
389
|
+
|
|
390
|
+
### Network Commands
|
|
391
|
+
| Command | Description |
|
|
392
|
+
|---------|-------------|
|
|
393
|
+
| `chain(url)` | Connect to blockchain network |
|
|
394
|
+
| `chain()` | Get current network info |
|
|
395
|
+
| `defaultChain()` | Get default network URL |
|
|
396
|
+
|
|
397
|
+
### Wallet Commands
|
|
398
|
+
| Command | Description |
|
|
399
|
+
|---------|-------------|
|
|
400
|
+
| `newWallet([count])` | Create random wallets |
|
|
401
|
+
| `addWallet(privKey\|keys)` | Import wallets from private keys |
|
|
402
|
+
| `newHDWallet([count])` | Create HD wallet with random mnemonic |
|
|
403
|
+
| `addHDWallet(phrase, count)` | Import HD wallet from mnemonic |
|
|
404
|
+
| `connectWallet()` | Connect to node-managed accounts |
|
|
405
|
+
| `wallets()` | View regular accounts |
|
|
406
|
+
| `hdWallets()` | View HD accounts |
|
|
407
|
+
| `allWallets()` | View all accounts |
|
|
408
|
+
| `walletInfo(index\|address\|[indices])` | Get wallet details (balance, nonce) |
|
|
409
|
+
| `removeWallet(pointer)` | Delete account(s) |
|
|
410
|
+
|
|
411
|
+
### Compiler Commands
|
|
412
|
+
| Command | Description |
|
|
413
|
+
|---------|-------------|
|
|
414
|
+
| `compiler()` | Get current Solidity version |
|
|
415
|
+
| `compUpdate(version)` | Load specific Solidity version |
|
|
416
|
+
| `compOpts(gasOpt, viaIR, runs)` | Configure optimization |
|
|
417
|
+
| `compInfo()` | Get current compiler options |
|
|
418
|
+
| `build([path], [contracts], [output])` | Compile contracts |
|
|
419
|
+
| `clean([path])` | Delete build directory |
|
|
420
|
+
|
|
421
|
+
### Contract Commands
|
|
422
|
+
| Command | Description |
|
|
423
|
+
|---------|-------------|
|
|
424
|
+
| `deploy(name, args, index)` | Deploy new contract |
|
|
425
|
+
| `addContract(name, address, index, abiPath)` | Add existing contract |
|
|
426
|
+
| `contracts([pointer])` | List contracts or get specific one |
|
|
427
|
+
|
|
428
|
+
## 🛠️ Setup for Development
|
|
429
|
+
|
|
430
|
+
### Prerequisites
|
|
431
|
+
- Node.js 16+
|
|
432
|
+
- npm or yarn
|
|
433
|
+
- Basic Solidity knowledge
|
|
434
|
+
|
|
435
|
+
### Development Setup
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
# Install dev dependencies
|
|
439
|
+
npm install --save-dev @types/node typescript
|
|
440
|
+
|
|
441
|
+
# Run in development mode
|
|
442
|
+
npm run dev
|
|
443
|
+
|
|
444
|
+
# Run tests (if available)
|
|
445
|
+
npm test
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Project Structure
|
|
449
|
+
|
|
450
|
+
```
|
|
451
|
+
ethershell/
|
|
452
|
+
├── bin/
|
|
453
|
+
│ └── cli.js # Entry point
|
|
454
|
+
├── src/
|
|
455
|
+
│ ├── services/
|
|
456
|
+
│ │ ├── build.js # Compiler management
|
|
457
|
+
│ │ ├── wallet.js # Wallet management
|
|
458
|
+
│ │ ├── network.js # Network provider
|
|
459
|
+
│ │ ├── addContracts.js # Contract deployment
|
|
460
|
+
│ │ └── contracts.js # Contract retrieval
|
|
461
|
+
│ └── utils/
|
|
462
|
+
│ ├── builder.js # Compilation engine
|
|
463
|
+
│ ├── dir.js # Directory utilities
|
|
464
|
+
│ ├── accounter.js # Account utilities
|
|
465
|
+
│ ├── contractLister.js # Contract formatting
|
|
466
|
+
│ └── replHelper.js # REPL customization
|
|
467
|
+
├── contracts/ # Your Solidity contracts
|
|
468
|
+
├── build/ # Compiled artifacts
|
|
469
|
+
└── package.json
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
## 📚 Example Contracts
|
|
473
|
+
|
|
474
|
+
### Simple ERC20 Token
|
|
475
|
+
|
|
476
|
+
```solidity
|
|
477
|
+
// contracts/MyToken.sol
|
|
478
|
+
pragma solidity ^0.8.20;
|
|
479
|
+
|
|
480
|
+
contract MyToken {
|
|
481
|
+
string public name = "My Token";
|
|
482
|
+
string public symbol = "MTK";
|
|
483
|
+
uint8 public decimals = 18;
|
|
484
|
+
uint256 public totalSupply = 1000000 * 10 ** uint256(decimals);
|
|
485
|
+
|
|
486
|
+
mapping(address => uint256) public balanceOf;
|
|
487
|
+
event Transfer(address indexed from, address indexed to, uint256 value);
|
|
488
|
+
|
|
489
|
+
constructor() {
|
|
490
|
+
balanceOf[msg.sender] = totalSupply;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function transfer(address to, uint256 value) public returns (bool) {
|
|
494
|
+
require(to != address(0));
|
|
495
|
+
require(balanceOf[msg.sender] >= value);
|
|
496
|
+
balanceOf[msg.sender] -= value;
|
|
497
|
+
balanceOf[to] += value;
|
|
498
|
+
emit Transfer(msg.sender, to, value);
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Deployment Example
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
// 1. Compile
|
|
508
|
+
EtherShell> build('./contracts/MyToken.sol')
|
|
509
|
+
|
|
510
|
+
// 2. Deploy
|
|
511
|
+
EtherShell> deploy('MyToken', [], 0)
|
|
512
|
+
|
|
513
|
+
// 3. Interact
|
|
514
|
+
EtherShell> MyToken.balanceOf('0x...')
|
|
515
|
+
1000000000000000000000000n
|
|
516
|
+
|
|
517
|
+
// 4. Transfer
|
|
518
|
+
EtherShell> MyToken.transfer('0x...', 100)
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
## ⚙️ Configuration
|
|
522
|
+
|
|
523
|
+
### Environment Variables
|
|
524
|
+
|
|
525
|
+
Create a `.env` file (optional):
|
|
526
|
+
|
|
527
|
+
```env
|
|
528
|
+
# Network
|
|
529
|
+
RPC_URL=http://127.0.0.1:8545
|
|
530
|
+
|
|
531
|
+
# Build
|
|
532
|
+
BUILD_PATH=./build
|
|
533
|
+
|
|
534
|
+
# Contracts
|
|
535
|
+
CONTRACTS_PATH=./contracts
|
|
536
|
+
|
|
537
|
+
# Compiler
|
|
538
|
+
COMPILER_VERSION=0.8.20+commit.a1b79de6
|
|
539
|
+
OPTIMIZER_ENABLED=true
|
|
540
|
+
OPTIMIZER_RUNS=200
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
## 🔒 Security Warnings
|
|
544
|
+
|
|
545
|
+
⚠️ **IMPORTANT SECURITY NOTES:**
|
|
546
|
+
|
|
547
|
+
1. **Never use generated accounts on mainnet** - They are only for testing
|
|
548
|
+
2. **Keep private keys safe** - Don't commit `.env` files or private keys to git
|
|
549
|
+
3. **Use read-only RPCs** - For production, use read-only endpoints
|
|
550
|
+
4. **Test on testnet first** - Always test contracts on Sepolia before mainnet
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
# Add to .gitignore
|
|
554
|
+
.env
|
|
555
|
+
.env.local
|
|
556
|
+
node_modules/
|
|
557
|
+
build/
|
|
558
|
+
localStorage/
|
|
559
|
+
*.log
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## 🐛 Troubleshooting
|
|
563
|
+
|
|
564
|
+
### Common Issues
|
|
565
|
+
|
|
566
|
+
**Issue: `Error: Cannot find module 'ethers'`**
|
|
567
|
+
```bash
|
|
568
|
+
Solution: npm install
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
**Issue: `Cannot connect to network`**
|
|
572
|
+
```bash
|
|
573
|
+
- Check RPC URL is correct
|
|
574
|
+
- Verify network is running (Hardhat, Ganache, etc.)
|
|
575
|
+
- Check internet connection for public RPCs
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**Issue: `Insufficient balance for gas`**
|
|
579
|
+
```bash
|
|
580
|
+
- Ensure wallet has enough ETH for gas
|
|
581
|
+
- Use testnet faucet for test ETH
|
|
582
|
+
- Check gas prices (sepolia is usually cheap)
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
**Issue: `Contract not found in build artifacts`**
|
|
586
|
+
```bash
|
|
587
|
+
- Run build() first
|
|
588
|
+
- Check contract names match exactly
|
|
589
|
+
- Verify .sol file exists in ./contracts
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
## 📖 API Documentation
|
|
593
|
+
|
|
594
|
+
Full JSDoc documentation is available in the source files. Each file includes:
|
|
595
|
+
- @fileoverview - File purpose
|
|
596
|
+
- @param - Parameter types and descriptions
|
|
597
|
+
- @returns - Return type information
|
|
598
|
+
- @throws - Error documentation
|
|
599
|
+
- @example - Usage examples
|
|
600
|
+
|
|
601
|
+
Generate HTML docs:
|
|
602
|
+
```bash
|
|
603
|
+
npm install -g jsdoc
|
|
604
|
+
jsdoc src/ -r -d docs/
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
## 🤝 Contributing
|
|
608
|
+
|
|
609
|
+
Contributions are welcome! Please:
|
|
610
|
+
|
|
611
|
+
1. Fork the repository
|
|
612
|
+
2. Create a feature branch (`git checkout -b feature/AmazingFeature`)
|
|
613
|
+
3. Commit changes (`git commit -m 'Add AmazingFeature'`)
|
|
614
|
+
4. Push to branch (`git push origin feature/AmazingFeature`)
|
|
615
|
+
5. Open a Pull Request
|
|
616
|
+
|
|
617
|
+
## 📄 License
|
|
618
|
+
|
|
619
|
+
This project is licensed under the BUSL-1.1 License - see LICENSE file for details.
|
|
620
|
+
|
|
621
|
+
## 💬 Support & Community
|
|
622
|
+
|
|
623
|
+
- **Issues**: Report bugs on GitHub Issues
|
|
624
|
+
- **Discussions**: Ask questions on GitHub Discussions
|
|
625
|
+
- **Documentation**: Check the docs/ folder
|
|
626
|
+
|
|
627
|
+
## 🎓 Learning Resources
|
|
628
|
+
|
|
629
|
+
- [Solidity Documentation](https://docs.soliditylang.org/)
|
|
630
|
+
- [Ethers.js Documentation](https://docs.ethers.org/)
|
|
631
|
+
- [Ethereum Development Guide](https://ethereum.org/en/developers/docs/)
|
|
632
|
+
- [Hardhat Documentation](https://hardhat.org/docs)
|
|
633
|
+
|
|
634
|
+
## 📞 Contact
|
|
635
|
+
|
|
636
|
+
- GitHub: [@yourusername](https://github.com/yourusername)
|
|
637
|
+
- Email: your.email@example.com
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
**Made with ❤️ for Ethereum developers**
|
|
642
|
+
|
|
643
|
+
Happy coding! 🚀
|