ethershell 0.1.1-alpha.15 → 0.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,55 +1,21 @@
1
- Business Source License 1.1
2
-
3
- Parameters
4
- -----------
5
- Licensor: Alireza Kiakojouri
6
- Licensed Work: EtherShell
7
- The Licensed Work is © 2025 Alireza Kiakojouri
8
- Additional Use Grant: You may make production use of the Licensed Work
9
- to develop, test, deploy, and maintain your own
10
- software and applications, provided you do not
11
- offer the Licensed Work itself or any derivative
12
- thereof as a product or service to third parties.
13
-
14
- Change Date: 2029-11-30
15
- Change License: Apache License, Version 2.0
16
-
17
- Terms
18
- -----
19
- The Licensor hereby grants you the right to copy, modify, create derivative
20
- works, redistribute, and make non-production use of the Licensed Work. The
21
- Licensor may make an Additional Use Grant, above, permitting limited production use.
22
-
23
- Effective on the Change Date, or the fourth anniversary of the first publicly
24
- available distribution of a specific version of the Licensed Work under this
25
- License, whichever comes first, the Licensor hereby grants you rights under
26
- the terms of the Change License, and the rights granted in the paragraph
27
- above terminate.
28
-
29
- If your use of the Licensed Work does not comply with the requirements
30
- currently in effect as described in this License, you must purchase a
31
- commercial license from the Licensor, its affiliated entities, or authorized
32
- resellers, or you must refrain from using the Licensed Work.
33
-
34
- All copies of the original and modified Licensed Work, and derivative works
35
- of the Licensed Work, are subject to this License. This License applies
36
- separately for each version of the Licensed Work and the Change Date may vary
37
- for each version of the Licensed Work released by Licensor.
38
-
39
- You must conspicuously display this License on each original or modified copy
40
- of the Licensed Work. If you receive the Licensed Work in original or
41
- modified form from a third party, the terms and conditions set forth in this
42
- License apply to your use of that work.
43
-
44
- Any use of the Licensed Work in violation of this License will automatically
45
- terminate your rights under this License for the current and all other
46
- versions of the Licensed Work.
47
-
48
- This License does not grant you any right in any trademark or logo of
49
- Licensor or its affiliates (provided that you may use a trademark or logo of
50
- Licensor as expressly required by this License).
51
-
52
- TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
53
- AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
54
- EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
55
- MERCHANTABILITY,
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Alireza Kiakojouri
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🔷 EtherShell - Interactive Ethereum Smart Contract Console
2
2
 
3
- **⚠️ WARNING: This package is in ALPHA testing. NOT production ready!**
3
+ **⚠️ WARNING: This package is in BETA testing. NOT production ready!**
4
4
 
5
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
6
 
@@ -13,16 +13,19 @@ An interactive Node.js console for Ethereum smart contract development. Write, c
13
13
 
14
14
  ## ✨ Features
15
15
 
16
- - **Interactive Shell** - Built-in async support for all commands
17
- - **Solidity Compilation** - Compile contracts with configurable optimization
16
+ - **Interactive REPL Shell** - Built-in async support for all commands with custom evaluation
17
+ - **Solidity Compilation** - Compile contracts with configurable optimization and viaIR mode
18
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
19
+ - **Wallet Management** - Create, import, and manage wallets (regular & HD wallets, node-managed accounts)
20
+ - **Multi-Network Support** - Switch between different blockchain networks with persistent configuration
21
+ - **Contract Proxy Wrapper** - Enhanced contract interaction with flexible transaction options (from, value, gasLimit, maxFeePerGas, etc.)
22
+ - **Contract Interactions** - Call contract methods with advanced options directly from the shell
23
+ - **ABI & Bytecode Generation** - Organized artifact output with metadata
23
24
  - **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
25
+ - **TypeScript Code Generation** - Auto-generate TypeScript types from contract ABIs
26
+ - **Gas Optimization** - Configure compiler optimization levels and viaIR code generation
27
+ - **Persistent Configuration** - Save and restore network, compiler, and wallet settings
28
+ - **Comprehensive JSDoc** - Full IDE autocomplete and type hints
26
29
 
27
30
  ## 🚀 Quick Start
28
31
 
@@ -32,7 +35,7 @@ An interactive Node.js console for Ethereum smart contract development. Write, c
32
35
  # Install globally:
33
36
  npm i -g ethershell
34
37
 
35
- # Start EtherShell:
38
+ # Start EtherShell in the root directory of your project:
36
39
  ethershell
37
40
 
38
41
  #or
@@ -43,7 +46,7 @@ npx ethershell
43
46
  ### Basic Usage
44
47
 
45
48
  ```bash
46
- # Start the console
49
+ # Start the console in the root directory of your project:
47
50
  ethershell
48
51
 
49
52
  # You should see:
@@ -164,6 +167,13 @@ EtherShell> walletInfo(0)
164
167
  EtherShell> walletInfo('0x1234...5678')
165
168
  // or multiple
166
169
  EtherShell> walletInfo([0, 1, 2])
170
+
171
+ // Change default account
172
+ EtherShell> changeDefWallet(0)
173
+ // or by address
174
+ EtherShell> changeDefWallet('0x1234...5678')
175
+ // or import and set as default in one command
176
+ EtherShell> changeDefWallet('0xPrivateKeyHere')
167
177
  ```
168
178
 
169
179
  #### Delete Wallets
@@ -198,7 +208,7 @@ EtherShell> compiler()
198
208
  EtherShell> compUpdate('v0.8.19+commit.7dd6d404')
199
209
  Loaded solc version: 0.8.19+commit.7dd6d404.Emscripten.clang
200
210
 
201
- // Configure compilation options
211
+ // Configure compilation options (gasOptimizer, viaIR, optimizerRuns)
202
212
  EtherShell> compOpts(true, false, 1000)
203
213
  ✓ Compiler options updated:
204
214
  Gas Optimizer: Enabled
@@ -208,6 +218,27 @@ EtherShell> compOpts(true, false, 1000)
208
218
  // Get current options
209
219
  EtherShell> compInfo()
210
220
  { optimizer: true, optimizerRuns: 1000, viaIR: false }
221
+
222
+ // Get current config info
223
+ EtherShell> configInfo()
224
+ {
225
+ providerEndpoint: '...',
226
+ defaultWallet: { ... },
227
+ compiler: {
228
+ version: 'v0.8.29+commit.ab55807c',
229
+ optimizer: false,
230
+ viaIR: false,
231
+ optimizerRuns: 200,
232
+ compilePath: './build'
233
+ }
234
+ }
235
+
236
+ // Get default wallet
237
+ EtherShell> defWallet()
238
+ { address: '0x...', ... }
239
+
240
+ // Change build output path
241
+ EtherShell> compPath('./custom-build')
211
242
  ```
212
243
 
213
244
  #### Compile Contracts
@@ -216,6 +247,7 @@ EtherShell> compInfo()
216
247
  // Compile all .sol files in ./contracts directory
217
248
  EtherShell> build()
218
249
  Contracts compiled into /path/to/build
250
+ TypeScript types generated in /path/to/build/types
219
251
 
220
252
  // Compile a specific contract file
221
253
  EtherShell> build('./contracts/MyToken.sol')
@@ -236,7 +268,8 @@ build/
236
268
  ├── artifacts/ # Complete contract data with metadata
237
269
  ├── abis/ # Contract ABIs (.abi.json files)
238
270
  ├── bytecode/ # Contract bytecode (.bin files)
239
- └── metadata/ # Contract metadata (.metadata.json files)
271
+ ├── metadata/ # Contract metadata (.metadata.json files)
272
+ └── types/ # Auto-generated TypeScript types
240
273
  ```
241
274
 
242
275
  ### 4. Smart Contract Deployment
@@ -244,7 +277,35 @@ build/
244
277
  #### Deploy New Contracts
245
278
 
246
279
  ```javascript
247
- // Deploy MyToken contract with constructor args
280
+ // Deploy contract without constructor args and with default wallet
281
+ // Arguments: contractName
282
+ EtherShell> deploy('contractName')
283
+ {
284
+ hash: '0x123abc...',
285
+ from: '0x1234...5678',
286
+ to: null,
287
+ address: '0xabcd...ef01',
288
+ name: 'contractName',
289
+ chain: 'sepolia',
290
+ chainId: 11155111n,
291
+ deployType: 'ethershell-deployed'
292
+ }
293
+
294
+ // Deploy MyToken contract with constructor args and default wallet
295
+ // Arguments: contractName, args[], walletIndex, [chainURL], [abiLocation], [bytecodeLocation]
296
+ EtherShell> deploy('MyToken', ['MyTokenName', 'MTK', 1000000])
297
+ {
298
+ hash: '0x123abc...',
299
+ from: '0x1234...5678',
300
+ to: null,
301
+ address: '0xabcd...ef01',
302
+ name: 'MyToken',
303
+ chain: 'sepolia',
304
+ chainId: 11155111n,
305
+ deployType: 'ethershell-deployed'
306
+ }
307
+
308
+ // Deploy MyToken contract with constructor args and a non-default wallet
248
309
  // Arguments: contractName, args[], walletIndex, [chainURL], [abiLocation], [bytecodeLocation]
249
310
  EtherShell> deploy('MyToken', ['MyTokenName', 'MTK', 1000000], 0)
250
311
  {
@@ -254,13 +315,14 @@ EtherShell> deploy('MyToken', ['MyTokenName', 'MTK', 1000000], 0)
254
315
  address: '0xabcd...ef01',
255
316
  name: 'MyToken',
256
317
  chain: 'sepolia',
318
+ chainId: 11155111n,
257
319
  deployType: 'ethershell-deployed'
258
320
  }
259
321
 
260
322
  // Deploy with custom chain
261
323
  EtherShell> deploy('MyContract', ['arg1', 'arg2'], 0, 'https://custom-rpc.url')
262
324
 
263
- // The deployed contract is automatically added to console context
325
+ // The deployed contract is automatically added to console context as a proxy
264
326
  EtherShell> MyToken
265
327
  Contract {
266
328
  target: '0xabcd...ef01',
@@ -304,16 +366,14 @@ EtherShell> contracts()
304
366
  address: '0xabcd...ef01',
305
367
  chain: 'sepolia',
306
368
  chainId: 11155111n,
307
- deployType: 'ethershell-deployed',
308
- balance: 0n
369
+ deployType: 'ethershell-deployed'
309
370
  },
310
371
  {
311
372
  index: 1,
312
373
  name: 'USDT',
313
374
  address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
314
375
  chain: 'mainnet',
315
- deployType: 'pre-deployed',
316
- balance: 0n
376
+ deployType: 'pre-deployed'
317
377
  }
318
378
  ]
319
379
 
@@ -345,11 +405,36 @@ EtherShell> MyToken.totalSupply()
345
405
  EtherShell> MyToken.transfer('0xRecipientAddress', 100)
346
406
  ContractTransactionResponse { ... }
347
407
 
408
+ // Call with advanced transaction options
409
+ EtherShell> MyToken.transfer('0xRecipientAddress', 100, {
410
+ from: '0xSenderAddress', // Switch signer
411
+ value: 10000000000000n, // Send ETH (for payable functions)
412
+ gasLimit: 500000, // Custom gas limit
413
+ maxFeePerGas: 100000000000n, // EIP-1559
414
+ maxPriorityFeePerGas: 2000000000n,
415
+ nonce: 42,
416
+ chainId: 1
417
+ })
418
+
348
419
  // Check balance
349
420
  EtherShell> MyToken.balanceOf('0x1234...5678')
350
421
  100n
351
422
  ```
352
423
 
424
+ **Contract Proxy Options:**
425
+ The contract proxy wrapper supports these transaction options:
426
+ - `from`: Change the signer/sender for the transaction
427
+ - `value`: ETH amount to send (for payable functions)
428
+ - `gasLimit` / `gas`: Maximum gas to use
429
+ - `gasPrice`: Legacy transaction gas price
430
+ - `maxFeePerGas`: EIP-1559 max fee per gas
431
+ - `maxPriorityFeePerGas`: EIP-1559 priority fee per gas
432
+ - `nonce`: Transaction nonce for ordering
433
+ - `chainId`: Network chain ID
434
+ - `accessList`: EIP-2930 access list
435
+ - `type`: Transaction type (0, 1, 2, or 3)
436
+ - `customData`: Custom data for special networks (zkSync)
437
+
353
438
  ## 🎯 Complete Usage Example
354
439
 
355
440
  Here's a full workflow example:
@@ -371,21 +456,22 @@ EtherShell> compOpts(true, false, 1000)
371
456
  EtherShell> build()
372
457
 
373
458
  // 6. Deploy contract
374
- EtherShell> deploy('MyToken', ['TestToken', 'TEST', 1000000], 0)
459
+ EtherShell> deploy('MyToken', ['TestToken', 'TEST', 1000000])
375
460
 
376
461
  // 7. Interact with contract
377
462
  EtherShell> MyToken.balanceOf('0x...')
463
+ 1000000000000000000000000n
378
464
 
379
- // 8. Transfer tokens
380
- EtherShell> tx = MyToken.transfer('0x...', 100)
381
-
382
- // 9. Wait for transaction
383
- EtherShell> receipt = tx.wait()
465
+ // 8. Transfer tokens with custom options
466
+ EtherShell> tx = MyToken.transfer('0x...', 100, {
467
+ gasLimit: 100000,
468
+ maxFeePerGas: 50000000000n
469
+ })
384
470
 
385
- // 10. Check balance again
471
+ // 9. Check balance again
386
472
  EtherShell> MyToken.balanceOf('0x...')
387
473
 
388
- // 11. View all contracts
474
+ // 10. View all contracts
389
475
  EtherShell> contracts()
390
476
  ```
391
477
 
@@ -395,7 +481,7 @@ EtherShell> contracts()
395
481
  | Command | Description |
396
482
  |---------|-------------|
397
483
  | `chain(url)` | Connect to blockchain network |
398
- | `chain()` | Get current network info |
484
+ | `chainInfo()` | Get current network info |
399
485
  | `defaultChain()` | Get default network URL |
400
486
 
401
487
  ### Wallet Commands
@@ -410,6 +496,7 @@ EtherShell> contracts()
410
496
  | `hdWallets()` | View HD accounts |
411
497
  | `allWallets()` | View all accounts |
412
498
  | `walletInfo(index\|address\|[indices])` | Get wallet details (balance, nonce) |
499
+ | `changeDefWallet(pointer)` | Set default account |
413
500
  | `removeWallet(pointer)` | Delete account(s) |
414
501
 
415
502
  ### Compiler Commands
@@ -419,13 +506,16 @@ EtherShell> contracts()
419
506
  | `compUpdate(version)` | Load specific Solidity version |
420
507
  | `compOpts(gasOpt, viaIR, runs)` | Configure optimization |
421
508
  | `compInfo()` | Get current compiler options |
509
+ | `configInfo()` | Get all configuration info |
510
+ | `defWallet()` | Get default account |
511
+ | `compPath(newPath)` | Change build output path |
422
512
  | `build([path], [contracts], [output])` | Compile contracts |
423
513
  | `clean([path])` | Delete build directory |
424
514
 
425
515
  ### Contract Commands
426
516
  | Command | Description |
427
517
  |---------|-------------|
428
- | `deploy(name, args, index)` | Deploy new contract |
518
+ | `deploy(name, [args], [index], [chainURL], [abiLocation], [bytecodeLocation])` | Deploy new contract |
429
519
  | `addContract(name, address, index, abiPath)` | Add existing contract |
430
520
  | `contracts([pointer])` | List contracts or get specific one |
431
521
 
@@ -461,15 +551,22 @@ ethershell/
461
551
  │ │ ├── wallet.js # Wallet management
462
552
  │ │ ├── network.js # Network provider
463
553
  │ │ ├── addContracts.js # Contract deployment
464
- │ │ └── contracts.js # Contract retrieval
554
+ │ │ ├── contracts.js # Contract retrieval
555
+ │ │ ├── config.js # Configuration
556
+ │ │ └── files.js # File utilities
465
557
  │ └── utils/
466
558
  │ ├── builder.js # Compilation engine
467
559
  │ ├── dir.js # Directory utilities
468
560
  │ ├── accounter.js # Account utilities
561
+ │ ├── contractProxy.js # Contract proxy wrapper
469
562
  │ ├── contractLister.js # Contract formatting
470
- └── replHelper.js # REPL customization
563
+ ├── typeGenerator.js # TypeScript type generation
564
+ │ ├── replHelper.js # REPL customization
565
+ │ ├── serialize.js # BigInt serialization
566
+ │ └── configFileUpdate.js # Config utilities
471
567
  ├── contracts/ # Your Solidity contracts
472
568
  ├── build/ # Compiled artifacts
569
+ ├── localStorage/ # Persistent config and wallet storage
473
570
  └── package.json
474
571
  ```
475
572
 
@@ -512,7 +609,7 @@ contract MyToken {
512
609
  EtherShell> build('./contracts/MyToken.sol')
513
610
 
514
611
  // 2. Deploy
515
- EtherShell> deploy('MyToken', [], 0)
612
+ EtherShell> deploy('MyToken')
516
613
 
517
614
  // 3. Interact
518
615
  EtherShell> MyToken.balanceOf('0x...')
@@ -524,7 +621,39 @@ EtherShell> MyToken.transfer('0x...', 100)
524
621
 
525
622
  ## ⚙️ Configuration
526
623
 
527
- ### Environment Variables
624
+ ### Persistent Storage
625
+
626
+ EtherShell stores configuration in the `localStorage` directory:
627
+
628
+ ```
629
+ localStorage/
630
+ ├── config.json # Compiler and network settings
631
+ ├── wallets.json # Imported/generated wallets
632
+ ```
633
+
634
+ ### Configuration File
635
+
636
+ The `config.json` file contains:
637
+
638
+ ```json
639
+ {
640
+ "providerEndpoint": "http://127.0.0.1:8545",
641
+ "defaultWallet": {
642
+ "index": 0,
643
+ "address": "0x...",
644
+ "type": "user-generated"
645
+ },
646
+ "compiler": {
647
+ "version": "v0.8.20+commit.a1b79de6",
648
+ "optimizer": false,
649
+ "viaIR": false,
650
+ "optimizerRuns": 200,
651
+ "compilePath": "./build"
652
+ }
653
+ }
654
+ ```
655
+
656
+ ### Environment Variables (Optional)
528
657
 
529
658
  Create a `.env` file (optional):
530
659
 
@@ -542,6 +671,7 @@ CONTRACTS_PATH=./contracts
542
671
  COMPILER_VERSION=0.8.20+commit.a1b79de6
543
672
  OPTIMIZER_ENABLED=true
544
673
  OPTIMIZER_RUNS=200
674
+ VIAIR_ENABLED=false
545
675
  ```
546
676
 
547
677
  ## 🔒 Security Warnings
@@ -552,6 +682,7 @@ OPTIMIZER_RUNS=200
552
682
  2. **Keep private keys safe** - Don't commit `.env` files or private keys to git
553
683
  3. **Use read-only RPCs** - For production, use read-only endpoints
554
684
  4. **Test on testnet first** - Always test contracts on Sepolia before mainnet
685
+ 5. **Verify contracts on Etherscan** - Always verify production contracts
555
686
 
556
687
  ```bash
557
688
  # Add to .gitignore
@@ -593,6 +724,20 @@ Solution: npm install
593
724
  - Verify .sol file exists in ./contracts
594
725
  ```
595
726
 
727
+ **Issue: `Cannot use 'from' option with node-managed account`**
728
+ ```bash
729
+ - Node-managed accounts cannot be used with the 'from' option
730
+ - Only imported/generated wallets with private keys support 'from'
731
+ - Use .connect() method for node-managed accounts
732
+ ```
733
+
734
+ **Issue: `TypeScript types not generated`**
735
+ ```bash
736
+ - Ensure contracts compiled successfully with build()
737
+ - Check ABIs exist in build/abis/ directory
738
+ - Look for error messages in the build() output
739
+ ```
740
+
596
741
  ## 📖 API Documentation
597
742
 
598
743
  Full JSDoc documentation is available in the source files. Each file includes:
@@ -644,4 +789,4 @@ This project is licensed under the BUSL-1.1 License - see LICENSE file for detai
644
789
 
645
790
  **Made with ❤️ for Ethereum developers**
646
791
 
647
- Happy coding! 🚀
792
+ Happy coding! 🚀
package/bin/cli.js CHANGED
@@ -16,7 +16,8 @@ import {
16
16
  currentCompiler,
17
17
  compilerOptions,
18
18
  getCompilerOptions,
19
- compile
19
+ compile,
20
+ changeCompPath
20
21
  } from '../src/services/build.js';
21
22
  import { set, get, getDefault } from '../src/services/network.js';
22
23
  import { deleteDirectory } from '../src/services/files.js';
@@ -30,12 +31,13 @@ import {
30
31
  addHD,
31
32
  getAllAccounts,
32
33
  connectWallet,
33
- getWalletInfo
34
+ getWalletInfo,
35
+ changeDefaultAccount
34
36
  } from '../src/services/wallet.js';
35
37
 
36
38
  import { deploy, add } from '../src/services/addContracts.js';
37
39
  import { getContracts } from '../src/services/contracts.js';
38
- import { getConfigInfo } from '../src/services/config.js';
40
+ import { getConfigInfo, getDefaultAccount } from '../src/services/config.js';
39
41
 
40
42
  /**
41
43
  * REPL instance for EtherShell interactive environment
@@ -62,10 +64,13 @@ r.context.compiler = currentCompiler;
62
64
  r.context.compUpdate = updateCompiler;
63
65
  r.context.compInfo = getCompilerOptions;
64
66
  r.context.compOpts = compilerOptions;
67
+ r.context.compPath = changeCompPath;
65
68
  r.context.build = compile;
66
69
 
67
70
  // Config commands
68
71
  r.context.configInfo = getConfigInfo;
72
+ r.context.changeDefWallet = changeDefaultAccount;
73
+ r.context.defWallet = getDefaultAccount;
69
74
 
70
75
  // Clean build folder
71
76
  r.context.clean = deleteDirectory;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "ethershell",
3
- "version": "0.1.1-alpha.15",
3
+ "license": "MIT",
4
+ "version": "0.1.2-beta.0",
4
5
  "description": "Interactive JavaScript console for Ethereum smart contract management",
5
- "license": "BUSL-1.1",
6
6
  "author": "Alireza Kiakojouri (alirezaethdev@gmail.com)",
7
7
  "repository": {
8
8
  "type": "git",
@@ -45,5 +45,11 @@
45
45
  "src/",
46
46
  "LICENSE",
47
47
  "README.md"
48
- ]
48
+ ],
49
+ "devDependencies": {
50
+ "@typechain/ethers-v6": "^0.5.1",
51
+ "@types/node": "^24.10.2",
52
+ "typechain": "^8.3.2",
53
+ "typescript": "^5.9.3"
54
+ }
49
55
  }
@@ -12,12 +12,14 @@ import { provider } from './network.js';
12
12
  import { allAccounts, accounts, hdAccounts } from './wallet.js';
13
13
  import { LocalStorage } from 'node-localstorage';
14
14
  import { r } from '../../bin/cli.js';
15
+ import { configFile } from './build.js';
16
+ import { createContractProxy } from '../utils/contractProxy.js';
15
17
 
16
18
  /**
17
19
  * Local storage instance for persisting contract metadata
18
20
  * @type {LocalStorage}
19
21
  */
20
- const localStorage = new LocalStorage('./localStorage');
22
+ const localStorage = new LocalStorage('./ethershell');
21
23
 
22
24
  /**
23
25
  * Map of all deployed and added contracts
@@ -43,6 +45,7 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
43
45
  try {
44
46
  let currentProvider;
45
47
  let connectedChain;
48
+ let wallet;
46
49
 
47
50
  if(!contractName) {
48
51
  throw new Error('Contract name is empty');
@@ -54,17 +57,17 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
54
57
  throw new Error('Wallet index is out of range');
55
58
  }
56
59
 
57
- if(!accIndex) {
58
- accIndex = 0;
59
- }
60
-
61
60
  if(chain) {
62
61
  currentProvider = new ethers.JsonRpcProvider(chain);
63
62
  } else {
64
63
  currentProvider = provider;
65
64
  }
66
65
 
67
- let wallet = new ethers.Wallet(allAccounts[accIndex].privateKey, currentProvider);
66
+ if(!accIndex && accIndex !== 0) {
67
+ accIndex = configFile.defaultWallet.index;
68
+ }
69
+
70
+ wallet = new ethers.Wallet(allAccounts[accIndex].privateKey, currentProvider);
68
71
  connectedChain = await currentProvider.getNetwork();
69
72
 
70
73
  const abiPath = abiLoc || localStorage.getItem(`${contractName}_abi`);
@@ -104,11 +107,21 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
104
107
  deployTx.deployType = 'ethershell-deployed',
105
108
  deployTx.provider = currentProvider;
106
109
 
107
- // Add to contract list
108
- contracts.set(contractName, deployTx);
110
+ //////////////////////////////////
111
+
112
+ // Create contract proxy
113
+ // Get the contract instance from ethers
114
+ const contractAbi = JSON.parse(fs.readFileSync(abiPath, 'utf8'));
115
+ const contractInstance = new ethers.Contract(deployTx.target, contractAbi, wallet);
109
116
 
110
- // Add to REPL context
111
- r.context[contractName] = deployTx;
117
+ // Wrap the contract instace with proxy
118
+ const proxiedContract = createContractProxy(contractInstance, currentProvider, allAccounts);
119
+
120
+ // Add to REPL context with proxy
121
+ r.context[contractName] = proxiedContract;
122
+ contracts.set(contractName, proxiedContract);
123
+
124
+ ////////////////////////////////////////////
112
125
 
113
126
  const deployHash = deployTx.deploymentTransaction().hash;
114
127
  const tx = await provider.getTransaction(deployHash);
@@ -144,32 +157,38 @@ export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
144
157
  try {
145
158
  let currentProvider;
146
159
  let connectedChain;
160
+ let wallet;
147
161
 
148
162
  if(!contractAddr) {
149
163
  throw new Error('Contract address may not be null or undefined!');
150
164
  }
151
165
 
152
- if(!accIndex) {
153
- accIndex = 0;
154
- }
155
-
156
166
  if(chain) {
157
167
  currentProvider = new ethers.JsonRpcProvider(chain);
158
168
  } else {
159
169
  currentProvider = provider;
160
170
  }
161
171
 
162
- let wallet = new ethers.Wallet(allAccounts[accIndex].privateKey, currentProvider);
163
- connectedChain = await currentProvider.getNetwork();
164
-
165
- if(!abiLoc) {
166
- throw new Error('ABI path may not be null or undefined!');
172
+ if(!accIndex && accIndex !== 0) {
173
+ accIndex = configFile.defaultWallet.index;
167
174
  }
168
175
 
169
- const abi = JSON.parse(fs.readFileSync(abiLoc, 'utf8'));
176
+ wallet = new ethers.Wallet(allAccounts[accIndex].privateKey, currentProvider);
177
+ connectedChain = await currentProvider.getNetwork();
178
+
179
+ const abiPath = abiLoc || localStorage.getItem(`${contractName}_abi`);
180
+ const abi = JSON.parse(fs.readFileSync(abiPath, 'utf8'));
170
181
 
171
182
  const newContract = new ethers.Contract(contractAddr, abi, wallet);
172
183
 
184
+ // Create contract proxy
185
+ // Wrap the contract instace with proxy
186
+ const proxiedContract = createContractProxy(newContract, currentProvider, allAccounts);
187
+
188
+ // Add to REPL context with proxy
189
+ r.context[contractName] = proxiedContract;
190
+ contracts.set(contractName, proxiedContract);
191
+
173
192
  // Update deployer contract list
174
193
  const contSpec = {
175
194
  address: newContract.target,
@@ -197,12 +216,6 @@ export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
197
216
  newContract.deployType = 'pre-deployed',
198
217
  newContract.provider = currentProvider;
199
218
 
200
- // Add to contract list
201
- contracts.set(contractName, newContract);
202
-
203
- // Add to REPL context
204
- r.context[contractName] = newContract;
205
-
206
219
  // Add result
207
220
  const result = {
208
221
  index: newContract.index,