ethershell 0.1.0-alpha.0 → 0.1.0-alpha.10
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 +49 -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 +383 -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
|
@@ -1,221 +1,221 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Smart contract deployment and management
|
|
3
|
-
* @description Provides functions to deploy new smart contracts and add existing
|
|
4
|
-
* contracts to the EtherShell environment. Manages contract instances and integrates
|
|
5
|
-
* them with the REPL context.
|
|
6
|
-
* @module addContracts
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { ethers } from 'ethers';
|
|
10
|
-
import fs from 'fs';
|
|
11
|
-
import { provider } from './network.js';
|
|
12
|
-
import { allAccounts, accounts, hdAccounts } from './wallet.js';
|
|
13
|
-
import { LocalStorage } from 'node-localstorage';
|
|
14
|
-
import { r } from '../../bin/cli.js';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Local storage instance for persisting contract metadata
|
|
18
|
-
* @type {LocalStorage}
|
|
19
|
-
*/
|
|
20
|
-
const localStorage = new LocalStorage('./localStorage');
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Map of all deployed and added contracts
|
|
24
|
-
* @type {Map<string, ethers.Contract>}
|
|
25
|
-
*/
|
|
26
|
-
export const contracts = new Map();
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Deploy a new smart contract to the blockchain
|
|
30
|
-
* @async
|
|
31
|
-
* @param {string} contractName - Name of the contract to deploy
|
|
32
|
-
* @param {Array} [args=[]] - Constructor arguments for the contract
|
|
33
|
-
* @param {number} [accIndex=0] - Index of the account to deploy from
|
|
34
|
-
* @param {string} [chain] - Optional custom chain URL
|
|
35
|
-
* @param {string} [abiLoc] - Optional custom ABI file location
|
|
36
|
-
* @param {string} [bytecodeLoc] - Optional custom bytecode file location
|
|
37
|
-
* @returns {Promise<void>}
|
|
38
|
-
* @throws {Error} If contract name is empty, account index is out of range, or deployment fails
|
|
39
|
-
* @example
|
|
40
|
-
* deploy('MyToken', [1000000], 0);
|
|
41
|
-
*/
|
|
42
|
-
export async function deploy(contractName, args, accIndex, chain, abiLoc, bytecodeLoc) {
|
|
43
|
-
try {
|
|
44
|
-
let currentProvider;
|
|
45
|
-
let connectedChain;
|
|
46
|
-
|
|
47
|
-
if(!contractName) {
|
|
48
|
-
throw new Error('Contract name is empty');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const contractArgs = args || [];
|
|
52
|
-
|
|
53
|
-
if(accIndex > allAccounts.length - 1) {
|
|
54
|
-
throw new Error('Wallet index is out of range');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if(!accIndex) {
|
|
58
|
-
accIndex = 0;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if(chain) {
|
|
62
|
-
currentProvider = new ethers.JsonRpcProvider(chain);
|
|
63
|
-
} else {
|
|
64
|
-
currentProvider = provider;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
let wallet = new ethers.Wallet(allAccounts[accIndex].privateKey, currentProvider);
|
|
68
|
-
connectedChain = await currentProvider.getNetwork();
|
|
69
|
-
|
|
70
|
-
const abiPath = abiLoc || localStorage.getItem(`${contractName}_abi`);
|
|
71
|
-
const bytecodePath = bytecodeLoc || localStorage.getItem(`${contractName}_bytecode`);
|
|
72
|
-
|
|
73
|
-
const abi = JSON.parse(fs.readFileSync(abiPath, 'utf8'));
|
|
74
|
-
const bytecode = JSON.parse(fs.readFileSync(bytecodePath, 'utf8'));
|
|
75
|
-
|
|
76
|
-
const factory = new ethers.ContractFactory(abi, bytecode, wallet);
|
|
77
|
-
const deployTx = await factory.deploy(...contractArgs);
|
|
78
|
-
await deployTx.waitForDeployment();
|
|
79
|
-
|
|
80
|
-
// Update deployer contract list
|
|
81
|
-
const contSpec = {
|
|
82
|
-
address: deployTx.target,
|
|
83
|
-
deployedOn: connectedChain.name,
|
|
84
|
-
chainId: connectedChain.chainId
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
allAccounts[accIndex].contracts.push(contSpec);
|
|
88
|
-
|
|
89
|
-
const accountsIndex = accounts.findIndex(wallet => wallet.index == accIndex);
|
|
90
|
-
if(accountsIndex >= 0) {
|
|
91
|
-
accounts[accountsIndex].contracts.push(contSpec);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const hdIndex = hdAccounts.findIndex(wallet => wallet.index == accIndex);
|
|
95
|
-
if(hdIndex >= 0) {
|
|
96
|
-
hdAccounts[hdIndex].contracts.push(contSpec);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Extend contract object
|
|
100
|
-
deployTx.index = Array.from(contracts.values()).length;
|
|
101
|
-
deployTx.name = contractName;
|
|
102
|
-
deployTx.chain = connectedChain.name;
|
|
103
|
-
deployTx.chainId = connectedChain.chainId;
|
|
104
|
-
deployTx.deployType = 'ethershell-deployed',
|
|
105
|
-
deployTx.provider = currentProvider;
|
|
106
|
-
|
|
107
|
-
// Add to contract list
|
|
108
|
-
contracts.set(contractName, deployTx);
|
|
109
|
-
|
|
110
|
-
// Add to REPL context
|
|
111
|
-
r.context[contractName] = deployTx;
|
|
112
|
-
|
|
113
|
-
const deployHash = deployTx.deploymentTransaction().hash;
|
|
114
|
-
const tx = await provider.getTransaction(deployHash);
|
|
115
|
-
delete tx.data;
|
|
116
|
-
|
|
117
|
-
// Extend transaction object
|
|
118
|
-
tx.ethershellIndex = deployTx.index;
|
|
119
|
-
tx.address = deployTx.target;
|
|
120
|
-
tx.name = deployTx.name;
|
|
121
|
-
tx.chain = deployTx.chain;
|
|
122
|
-
tx.deployType = deployTx.deployType;
|
|
123
|
-
|
|
124
|
-
console.log(tx);
|
|
125
|
-
} catch(err) {
|
|
126
|
-
console.error(err);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Add an existing deployed contract to EtherShell
|
|
132
|
-
* @async
|
|
133
|
-
* @param {string} contractName - Name to assign to the contract
|
|
134
|
-
* @param {string} contractAddr - Address of the deployed contract
|
|
135
|
-
* @param {number} [accIndex=0] - Index of the account to interact with the contract
|
|
136
|
-
* @param {string} abiLoc - Path to the contract ABI file
|
|
137
|
-
* @param {string} [chain] - Optional custom chain URL
|
|
138
|
-
* @returns {Promise<void>}
|
|
139
|
-
* @throws {Error} If contract address or ABI location is null/undefined
|
|
140
|
-
* @example
|
|
141
|
-
* add('USDT', '0xdac17f958d2ee523a2206206994597c13d831ec7', 0, './abis/USDT.json');
|
|
142
|
-
*/
|
|
143
|
-
export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
|
|
144
|
-
try {
|
|
145
|
-
let currentProvider;
|
|
146
|
-
let connectedChain;
|
|
147
|
-
|
|
148
|
-
if(!contractAddr) {
|
|
149
|
-
throw new Error('Contract address may not be null or undefined!');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if(!accIndex) {
|
|
153
|
-
accIndex = 0;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if(chain) {
|
|
157
|
-
currentProvider = new ethers.JsonRpcProvider(chain);
|
|
158
|
-
} else {
|
|
159
|
-
currentProvider = provider;
|
|
160
|
-
}
|
|
161
|
-
|
|
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!');
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const abi = JSON.parse(fs.readFileSync(abiLoc, 'utf8'));
|
|
170
|
-
|
|
171
|
-
const newContract = new ethers.Contract(contractAddr, abi, wallet);
|
|
172
|
-
|
|
173
|
-
// Update deployer contract list
|
|
174
|
-
const contSpec = {
|
|
175
|
-
address: newContract.target,
|
|
176
|
-
deployedOn: connectedChain.name,
|
|
177
|
-
chainId: connectedChain.chainId
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
allAccounts[accIndex].contracts.push(contSpec);
|
|
181
|
-
|
|
182
|
-
const accountsIndex = accounts.findIndex(wallet => wallet.index == accIndex);
|
|
183
|
-
if(accountsIndex >= 0) {
|
|
184
|
-
accounts[accountsIndex].contracts.push(contSpec);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const hdIndex = hdAccounts.findIndex(wallet => wallet.index == accIndex);
|
|
188
|
-
if(hdIndex >= 0) {
|
|
189
|
-
hdAccounts[hdIndex].contracts.push(contSpec);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Extend contract object
|
|
193
|
-
newContract.index = Array.from(contracts.values()).length;
|
|
194
|
-
newContract.name = contractName;
|
|
195
|
-
newContract.chain = connectedChain.name;
|
|
196
|
-
newContract.chainId = connectedChain.chainId;
|
|
197
|
-
newContract.deployType = 'pre-deployed',
|
|
198
|
-
newContract.provider = currentProvider;
|
|
199
|
-
|
|
200
|
-
// Add to contract list
|
|
201
|
-
contracts.set(contractName, newContract);
|
|
202
|
-
|
|
203
|
-
// Add to REPL context
|
|
204
|
-
r.context[contractName] = newContract;
|
|
205
|
-
|
|
206
|
-
// Add result
|
|
207
|
-
const result = {
|
|
208
|
-
index: newContract.index,
|
|
209
|
-
name: newContract.name,
|
|
210
|
-
address: newContract.target,
|
|
211
|
-
chain: newContract.chain,
|
|
212
|
-
chainId: newContract.chainId,
|
|
213
|
-
deployType: newContract.deployType,
|
|
214
|
-
provider: newContract.provider
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
console.log(result);
|
|
218
|
-
} catch(err) {
|
|
219
|
-
console.error(err);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Smart contract deployment and management
|
|
3
|
+
* @description Provides functions to deploy new smart contracts and add existing
|
|
4
|
+
* contracts to the EtherShell environment. Manages contract instances and integrates
|
|
5
|
+
* them with the REPL context.
|
|
6
|
+
* @module addContracts
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { ethers } from 'ethers';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import { provider } from './network.js';
|
|
12
|
+
import { allAccounts, accounts, hdAccounts } from './wallet.js';
|
|
13
|
+
import { LocalStorage } from 'node-localstorage';
|
|
14
|
+
import { r } from '../../bin/cli.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Local storage instance for persisting contract metadata
|
|
18
|
+
* @type {LocalStorage}
|
|
19
|
+
*/
|
|
20
|
+
const localStorage = new LocalStorage('./localStorage');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Map of all deployed and added contracts
|
|
24
|
+
* @type {Map<string, ethers.Contract>}
|
|
25
|
+
*/
|
|
26
|
+
export const contracts = new Map();
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Deploy a new smart contract to the blockchain
|
|
30
|
+
* @async
|
|
31
|
+
* @param {string} contractName - Name of the contract to deploy
|
|
32
|
+
* @param {Array} [args=[]] - Constructor arguments for the contract
|
|
33
|
+
* @param {number} [accIndex=0] - Index of the account to deploy from
|
|
34
|
+
* @param {string} [chain] - Optional custom chain URL
|
|
35
|
+
* @param {string} [abiLoc] - Optional custom ABI file location
|
|
36
|
+
* @param {string} [bytecodeLoc] - Optional custom bytecode file location
|
|
37
|
+
* @returns {Promise<void>}
|
|
38
|
+
* @throws {Error} If contract name is empty, account index is out of range, or deployment fails
|
|
39
|
+
* @example
|
|
40
|
+
* deploy('MyToken', [1000000], 0);
|
|
41
|
+
*/
|
|
42
|
+
export async function deploy(contractName, args, accIndex, chain, abiLoc, bytecodeLoc) {
|
|
43
|
+
try {
|
|
44
|
+
let currentProvider;
|
|
45
|
+
let connectedChain;
|
|
46
|
+
|
|
47
|
+
if(!contractName) {
|
|
48
|
+
throw new Error('Contract name is empty');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const contractArgs = args || [];
|
|
52
|
+
|
|
53
|
+
if(accIndex > allAccounts.length - 1) {
|
|
54
|
+
throw new Error('Wallet index is out of range');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if(!accIndex) {
|
|
58
|
+
accIndex = 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if(chain) {
|
|
62
|
+
currentProvider = new ethers.JsonRpcProvider(chain);
|
|
63
|
+
} else {
|
|
64
|
+
currentProvider = provider;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let wallet = new ethers.Wallet(allAccounts[accIndex].privateKey, currentProvider);
|
|
68
|
+
connectedChain = await currentProvider.getNetwork();
|
|
69
|
+
|
|
70
|
+
const abiPath = abiLoc || localStorage.getItem(`${contractName}_abi`);
|
|
71
|
+
const bytecodePath = bytecodeLoc || localStorage.getItem(`${contractName}_bytecode`);
|
|
72
|
+
|
|
73
|
+
const abi = JSON.parse(fs.readFileSync(abiPath, 'utf8'));
|
|
74
|
+
const bytecode = JSON.parse(fs.readFileSync(bytecodePath, 'utf8'));
|
|
75
|
+
|
|
76
|
+
const factory = new ethers.ContractFactory(abi, bytecode, wallet);
|
|
77
|
+
const deployTx = await factory.deploy(...contractArgs);
|
|
78
|
+
await deployTx.waitForDeployment();
|
|
79
|
+
|
|
80
|
+
// Update deployer contract list
|
|
81
|
+
const contSpec = {
|
|
82
|
+
address: deployTx.target,
|
|
83
|
+
deployedOn: connectedChain.name,
|
|
84
|
+
chainId: connectedChain.chainId
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
allAccounts[accIndex].contracts.push(contSpec);
|
|
88
|
+
|
|
89
|
+
const accountsIndex = accounts.findIndex(wallet => wallet.index == accIndex);
|
|
90
|
+
if(accountsIndex >= 0) {
|
|
91
|
+
accounts[accountsIndex].contracts.push(contSpec);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const hdIndex = hdAccounts.findIndex(wallet => wallet.index == accIndex);
|
|
95
|
+
if(hdIndex >= 0) {
|
|
96
|
+
hdAccounts[hdIndex].contracts.push(contSpec);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Extend contract object
|
|
100
|
+
deployTx.index = Array.from(contracts.values()).length;
|
|
101
|
+
deployTx.name = contractName;
|
|
102
|
+
deployTx.chain = connectedChain.name;
|
|
103
|
+
deployTx.chainId = connectedChain.chainId;
|
|
104
|
+
deployTx.deployType = 'ethershell-deployed',
|
|
105
|
+
deployTx.provider = currentProvider;
|
|
106
|
+
|
|
107
|
+
// Add to contract list
|
|
108
|
+
contracts.set(contractName, deployTx);
|
|
109
|
+
|
|
110
|
+
// Add to REPL context
|
|
111
|
+
r.context[contractName] = deployTx;
|
|
112
|
+
|
|
113
|
+
const deployHash = deployTx.deploymentTransaction().hash;
|
|
114
|
+
const tx = await provider.getTransaction(deployHash);
|
|
115
|
+
delete tx.data;
|
|
116
|
+
|
|
117
|
+
// Extend transaction object
|
|
118
|
+
tx.ethershellIndex = deployTx.index;
|
|
119
|
+
tx.address = deployTx.target;
|
|
120
|
+
tx.name = deployTx.name;
|
|
121
|
+
tx.chain = deployTx.chain;
|
|
122
|
+
tx.deployType = deployTx.deployType;
|
|
123
|
+
|
|
124
|
+
console.log(tx);
|
|
125
|
+
} catch(err) {
|
|
126
|
+
console.error(err);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Add an existing deployed contract to EtherShell
|
|
132
|
+
* @async
|
|
133
|
+
* @param {string} contractName - Name to assign to the contract
|
|
134
|
+
* @param {string} contractAddr - Address of the deployed contract
|
|
135
|
+
* @param {number} [accIndex=0] - Index of the account to interact with the contract
|
|
136
|
+
* @param {string} abiLoc - Path to the contract ABI file
|
|
137
|
+
* @param {string} [chain] - Optional custom chain URL
|
|
138
|
+
* @returns {Promise<void>}
|
|
139
|
+
* @throws {Error} If contract address or ABI location is null/undefined
|
|
140
|
+
* @example
|
|
141
|
+
* add('USDT', '0xdac17f958d2ee523a2206206994597c13d831ec7', 0, './abis/USDT.json');
|
|
142
|
+
*/
|
|
143
|
+
export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
|
|
144
|
+
try {
|
|
145
|
+
let currentProvider;
|
|
146
|
+
let connectedChain;
|
|
147
|
+
|
|
148
|
+
if(!contractAddr) {
|
|
149
|
+
throw new Error('Contract address may not be null or undefined!');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if(!accIndex) {
|
|
153
|
+
accIndex = 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if(chain) {
|
|
157
|
+
currentProvider = new ethers.JsonRpcProvider(chain);
|
|
158
|
+
} else {
|
|
159
|
+
currentProvider = provider;
|
|
160
|
+
}
|
|
161
|
+
|
|
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!');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const abi = JSON.parse(fs.readFileSync(abiLoc, 'utf8'));
|
|
170
|
+
|
|
171
|
+
const newContract = new ethers.Contract(contractAddr, abi, wallet);
|
|
172
|
+
|
|
173
|
+
// Update deployer contract list
|
|
174
|
+
const contSpec = {
|
|
175
|
+
address: newContract.target,
|
|
176
|
+
deployedOn: connectedChain.name,
|
|
177
|
+
chainId: connectedChain.chainId
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
allAccounts[accIndex].contracts.push(contSpec);
|
|
181
|
+
|
|
182
|
+
const accountsIndex = accounts.findIndex(wallet => wallet.index == accIndex);
|
|
183
|
+
if(accountsIndex >= 0) {
|
|
184
|
+
accounts[accountsIndex].contracts.push(contSpec);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const hdIndex = hdAccounts.findIndex(wallet => wallet.index == accIndex);
|
|
188
|
+
if(hdIndex >= 0) {
|
|
189
|
+
hdAccounts[hdIndex].contracts.push(contSpec);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Extend contract object
|
|
193
|
+
newContract.index = Array.from(contracts.values()).length;
|
|
194
|
+
newContract.name = contractName;
|
|
195
|
+
newContract.chain = connectedChain.name;
|
|
196
|
+
newContract.chainId = connectedChain.chainId;
|
|
197
|
+
newContract.deployType = 'pre-deployed',
|
|
198
|
+
newContract.provider = currentProvider;
|
|
199
|
+
|
|
200
|
+
// Add to contract list
|
|
201
|
+
contracts.set(contractName, newContract);
|
|
202
|
+
|
|
203
|
+
// Add to REPL context
|
|
204
|
+
r.context[contractName] = newContract;
|
|
205
|
+
|
|
206
|
+
// Add result
|
|
207
|
+
const result = {
|
|
208
|
+
index: newContract.index,
|
|
209
|
+
name: newContract.name,
|
|
210
|
+
address: newContract.target,
|
|
211
|
+
chain: newContract.chain,
|
|
212
|
+
chainId: newContract.chainId,
|
|
213
|
+
deployType: newContract.deployType,
|
|
214
|
+
provider: newContract.provider
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log(result);
|
|
218
|
+
} catch(err) {
|
|
219
|
+
console.error(err);
|
|
220
|
+
}
|
|
221
|
+
}
|