ethershell 0.1.6-beta.0 → 0.2.0-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/bin/cli.js +2 -1
- package/package.json +1 -1
- package/src/services/addContracts.js +159 -83
- package/src/services/configSync.js +4 -2
- package/src/utils/contractLister.js +50 -6
package/bin/cli.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
changeDefaultAccount
|
|
37
37
|
} from '../src/services/wallet.js';
|
|
38
38
|
|
|
39
|
-
import { deploy, add } from '../src/services/addContracts.js';
|
|
39
|
+
import { deploy, add, restore } from '../src/services/addContracts.js';
|
|
40
40
|
import { getContracts } from '../src/services/contracts.js';
|
|
41
41
|
import { getConfigInfo, getDefaultAccount } from '../src/services/configSync.js';
|
|
42
42
|
|
|
@@ -97,3 +97,4 @@ r.context.addContract = add;
|
|
|
97
97
|
|
|
98
98
|
// Contract
|
|
99
99
|
r.context.contracts = getContracts;
|
|
100
|
+
r.context.restoreContract = restore;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ethershell",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-beta.0",
|
|
5
5
|
"description": "Interactive JavaScript console for Ethereum smart contract management",
|
|
6
6
|
"author": "Alireza Kiakojouri (alirezaethdev@gmail.com)",
|
|
7
7
|
"repository": {
|
|
@@ -17,6 +17,10 @@ import { LocalStorage } from 'node-localstorage';
|
|
|
17
17
|
import { r } from '../../bin/cli.js';
|
|
18
18
|
import { createContractProxy } from '../utils/contractProxy.js';
|
|
19
19
|
import { eventOf } from '../utils/event.js';
|
|
20
|
+
import {
|
|
21
|
+
updateContractJSON,
|
|
22
|
+
getContractJSON
|
|
23
|
+
} from '../utils/contractLister.js';
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* Local storage instance for persisting contract metadata
|
|
@@ -28,7 +32,29 @@ const localStorage = new LocalStorage('./ethershell');
|
|
|
28
32
|
* Map of all deployed and added contracts
|
|
29
33
|
* @type {Map<string, ethers.Contract>}
|
|
30
34
|
*/
|
|
31
|
-
export const contracts =
|
|
35
|
+
export const contracts = getContractJSON();
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Instantiate stored contracts to interact with the shell
|
|
39
|
+
*/
|
|
40
|
+
export async function restore() {
|
|
41
|
+
if(contracts) {
|
|
42
|
+
console.info(`Stored contracts instantiating ...`);
|
|
43
|
+
const contractsLength = contracts.length;
|
|
44
|
+
for(let i = 0; i < contractsLength; i++) {
|
|
45
|
+
await _add(
|
|
46
|
+
contracts[i].name,
|
|
47
|
+
contracts[i].address,
|
|
48
|
+
configFile.defaultWallet.index,
|
|
49
|
+
contracts[i].abiPath
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
console.info(`All stored contracts instantiated!`);
|
|
53
|
+
} else {
|
|
54
|
+
return `The storage is empty!`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
32
58
|
|
|
33
59
|
/**
|
|
34
60
|
* Deploy a new smart contract to the blockchain
|
|
@@ -92,13 +118,13 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
|
|
|
92
118
|
|
|
93
119
|
allAccounts[accIndex].contracts.push(contSpec);
|
|
94
120
|
|
|
95
|
-
//
|
|
96
|
-
deployTx.
|
|
97
|
-
deployTx.
|
|
98
|
-
deployTx.
|
|
99
|
-
deployTx.
|
|
100
|
-
deployTx.
|
|
101
|
-
deployTx.
|
|
121
|
+
// Decorate contract instance with metadata
|
|
122
|
+
deployTx._contractIndex = contracts.length;
|
|
123
|
+
deployTx._contractName = contractName;
|
|
124
|
+
deployTx._contractChain = connectedChain.name;
|
|
125
|
+
deployTx._contractChainId = connectedChain.chainId;
|
|
126
|
+
deployTx._contractDeployType = 'ethershell-deployed',
|
|
127
|
+
deployTx._contractProvider = currentProvider;
|
|
102
128
|
|
|
103
129
|
//////////////////////////////////
|
|
104
130
|
|
|
@@ -110,16 +136,31 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
|
|
|
110
136
|
// Wrap the contract instace with proxy
|
|
111
137
|
const proxiedContract = createContractProxy(contractInstance, currentProvider, allAccounts);
|
|
112
138
|
|
|
113
|
-
proxiedContract.
|
|
114
|
-
proxiedContract.
|
|
115
|
-
proxiedContract.
|
|
116
|
-
proxiedContract.
|
|
117
|
-
proxiedContract.
|
|
118
|
-
proxiedContract.
|
|
139
|
+
proxiedContract._contractIndex = contracts.length;
|
|
140
|
+
proxiedContract._contractName = contractName;
|
|
141
|
+
proxiedContract._contractChain = connectedChain.name;
|
|
142
|
+
proxiedContract._contractChainId = connectedChain.chainId;
|
|
143
|
+
proxiedContract._contractDeployType = 'ethershell-deployed';
|
|
144
|
+
proxiedContract._contractProvider = currentProvider;
|
|
145
|
+
proxiedContract._contractABIPath = abiPath;
|
|
119
146
|
|
|
120
147
|
// Add to REPL context with proxy
|
|
121
148
|
r.context[contractName] = proxiedContract;
|
|
122
|
-
|
|
149
|
+
|
|
150
|
+
const contracToStore = {
|
|
151
|
+
index: proxiedContract._contractIndex,
|
|
152
|
+
name: proxiedContract._contractName,
|
|
153
|
+
address: proxiedContract.target,
|
|
154
|
+
chain: proxiedContract._contractChain,
|
|
155
|
+
chainId: proxiedContract._contractChainId,
|
|
156
|
+
deployType: proxiedContract._contractDeployType,
|
|
157
|
+
balance: await proxiedContract.provider.getBalance(proxiedContract.target),
|
|
158
|
+
abiPath: proxiedContract._contractABIPath
|
|
159
|
+
}
|
|
160
|
+
contracts.push(contracToStore);
|
|
161
|
+
|
|
162
|
+
// Update contracts.json
|
|
163
|
+
updateContractJSON(contracts);
|
|
123
164
|
|
|
124
165
|
////////////////////////////////////////////
|
|
125
166
|
|
|
@@ -131,12 +172,12 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
|
|
|
131
172
|
const tx1 = await provider.getTransactionReceipt(deployHash);
|
|
132
173
|
const eventValues = eventOf(contractInstance, tx1);
|
|
133
174
|
|
|
134
|
-
//
|
|
135
|
-
tx.ethershellIndex = deployTx.
|
|
175
|
+
// Decorate transaction object with metadata
|
|
176
|
+
tx.ethershellIndex = deployTx._contractIndex;
|
|
136
177
|
tx.address = deployTx.target;
|
|
137
|
-
tx.name = deployTx.
|
|
138
|
-
tx.chain = deployTx.
|
|
139
|
-
tx.deployType = deployTx.
|
|
178
|
+
tx.name = deployTx._contractName;
|
|
179
|
+
tx.chain = deployTx._contractChain;
|
|
180
|
+
tx.deployType = deployTx._contractDeployType;
|
|
140
181
|
|
|
141
182
|
if(eventValues) {
|
|
142
183
|
tx.eventValues = eventValues;
|
|
@@ -163,77 +204,112 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
|
|
|
163
204
|
*/
|
|
164
205
|
export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
|
|
165
206
|
try {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if(!accIndex && accIndex !== 0) {
|
|
181
|
-
accIndex = configFile.defaultWallet.index;
|
|
207
|
+
const result = await _add(contractName, contractAddr, accIndex, abiLoc, chain);
|
|
208
|
+
|
|
209
|
+
// Decorate contract object
|
|
210
|
+
const contracToStore = {
|
|
211
|
+
index: result.index,
|
|
212
|
+
name: result.name,
|
|
213
|
+
address: result.address,
|
|
214
|
+
chain: result.chain,
|
|
215
|
+
chainId: result.chainId,
|
|
216
|
+
deployType: result.deployType,
|
|
217
|
+
balance: await result.provider.getBalance(result.address),
|
|
218
|
+
abiPath: abiLoc
|
|
182
219
|
}
|
|
220
|
+
// Update contracts array
|
|
221
|
+
contracts.push(contracToStore);
|
|
183
222
|
|
|
184
|
-
|
|
185
|
-
|
|
223
|
+
// Update contracts.json
|
|
224
|
+
updateContractJSON(contracts);
|
|
186
225
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Create contract proxy
|
|
193
|
-
// Wrap the contract instace with proxy
|
|
194
|
-
const proxiedContract = createContractProxy(newContract, currentProvider, allAccounts);
|
|
226
|
+
return result;
|
|
227
|
+
} catch(err) {
|
|
228
|
+
console.error(err);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
195
231
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
proxiedContract.deployType = 'ethershell-deployed';
|
|
201
|
-
proxiedContract.provider = currentProvider;
|
|
232
|
+
async function _add(contractName, contractAddr, accIndex, abiLoc, chain) {
|
|
233
|
+
let currentProvider;
|
|
234
|
+
let connectedChain;
|
|
235
|
+
let wallet;
|
|
202
236
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
237
|
+
if(!contractAddr) {
|
|
238
|
+
throw new Error('Contract address may not be null or undefined!');
|
|
239
|
+
}
|
|
206
240
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
241
|
+
if(chain) {
|
|
242
|
+
currentProvider = new ethers.JsonRpcProvider(chain);
|
|
243
|
+
} else {
|
|
244
|
+
currentProvider = provider;
|
|
245
|
+
}
|
|
213
246
|
|
|
214
|
-
|
|
247
|
+
if(!accIndex && accIndex !== 0) {
|
|
248
|
+
accIndex = configFile.defaultWallet.index;
|
|
249
|
+
}
|
|
215
250
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
251
|
+
wallet = new ethers.Wallet(allAccounts[accIndex].privateKey, currentProvider);
|
|
252
|
+
connectedChain = await currentProvider.getNetwork();
|
|
253
|
+
|
|
254
|
+
const abiPath = abiLoc || localStorage.getItem(`${contractName}_abi`);
|
|
255
|
+
const abi = JSON.parse(fs.readFileSync(abiPath, 'utf8'));
|
|
256
|
+
|
|
257
|
+
const newContract = new ethers.Contract(contractAddr, abi, wallet);
|
|
258
|
+
|
|
259
|
+
// Create contract proxy
|
|
260
|
+
// Wrap the contract instace with proxy
|
|
261
|
+
const proxiedContract = createContractProxy(newContract, currentProvider, allAccounts);
|
|
262
|
+
|
|
263
|
+
proxiedContract._contractIndex = contracts.length;
|
|
264
|
+
proxiedContract._contractName = contractName;
|
|
265
|
+
proxiedContract._contractChain = connectedChain.name;
|
|
266
|
+
proxiedContract._contractChainId = connectedChain.chainId;
|
|
267
|
+
proxiedContract._contractDeployType = 'ethershell-deployed';
|
|
268
|
+
proxiedContract._contractProvider = currentProvider;
|
|
269
|
+
proxiedContract._contractABIPath = abiPath;
|
|
270
|
+
|
|
271
|
+
// Add to REPL context with proxy
|
|
272
|
+
r.context[contractName] = proxiedContract;
|
|
273
|
+
|
|
274
|
+
// const contracToStore = {
|
|
275
|
+
// index: proxiedContract._contractIndex,
|
|
276
|
+
// name: proxiedContract._contractName,
|
|
277
|
+
// address: proxiedContract.target,
|
|
278
|
+
// chain: proxiedContract._contractChain,
|
|
279
|
+
// chainId: proxiedContract._contractChainId,
|
|
280
|
+
// deployType: proxiedContract._contractDeployType,
|
|
281
|
+
// balance: await proxiedContract.provider.getBalance(proxiedContract.target),
|
|
282
|
+
// abiPath: proxiedContract._contractABIPath
|
|
283
|
+
// }
|
|
284
|
+
// contracts.push(contracToStore);
|
|
285
|
+
|
|
286
|
+
// Update deployer contract list
|
|
287
|
+
const contSpec = {
|
|
288
|
+
address: newContract.target,
|
|
289
|
+
deployedOn: connectedChain.name,
|
|
290
|
+
chainId: connectedChain.chainId
|
|
291
|
+
}
|
|
234
292
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
293
|
+
allAccounts[accIndex].contracts.push(contSpec);
|
|
294
|
+
|
|
295
|
+
// Decorate contract instance with metadata
|
|
296
|
+
newContract._contractIndex = contracts.length + 1;
|
|
297
|
+
newContract._contractName = contractName;
|
|
298
|
+
newContract._contractChain = connectedChain.name;
|
|
299
|
+
newContract._contractChainId = connectedChain.chainId;
|
|
300
|
+
newContract._contractDeployType = 'pre-deployed',
|
|
301
|
+
newContract._contractProvider = currentProvider;
|
|
302
|
+
|
|
303
|
+
// Add result
|
|
304
|
+
const result = {
|
|
305
|
+
index: newContract._contractIndex,
|
|
306
|
+
name: newContract._contractName,
|
|
307
|
+
address: newContract.target,
|
|
308
|
+
chain: newContract._contractChain,
|
|
309
|
+
chainId: newContract._contractChainId,
|
|
310
|
+
deployType: newContract._contractDeployType,
|
|
311
|
+
provider: newContract._contractProvider
|
|
238
312
|
}
|
|
313
|
+
|
|
314
|
+
return result;
|
|
239
315
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadSolcVersion,
|
|
3
|
-
extractLoadableVersion
|
|
3
|
+
extractLoadableVersion
|
|
4
4
|
} from '../utils/builder.js';
|
|
5
5
|
import { allAccounts } from './wallet.js';
|
|
6
6
|
import { serializeBigInts } from '../utils/serialize.js';
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
import { ethers } from 'ethers';
|
|
9
|
+
import solc from 'solc';
|
|
9
10
|
|
|
10
11
|
// Sync Config Memory with Storage Config:
|
|
11
12
|
/**
|
|
@@ -98,7 +99,8 @@ if(storedUrl) {
|
|
|
98
99
|
|
|
99
100
|
// 3) Set Compiler to Memory:
|
|
100
101
|
// Initialize global configuration of compiler
|
|
101
|
-
if(storedCompConfig){
|
|
102
|
+
// if(storedCompConfig){
|
|
103
|
+
if(false){
|
|
102
104
|
configFile.compiler = storedCompConfig.compiler;
|
|
103
105
|
console.info(`Compiler is loading ...`);
|
|
104
106
|
compConfig.currentSolcInstance = await loadSolcVersion(configFile.compiler.version);
|
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { contracts } from '../services/addContracts.js';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import { serializeBigInts } from './serialize.js'
|
|
11
|
+
import { provider } from '../services/configSync.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
const contractJSONPath = './ethershell/contracts.json';
|
|
9
17
|
|
|
10
18
|
/**
|
|
11
19
|
* Get array of all contracts with their information
|
|
@@ -20,18 +28,54 @@ import { contracts } from '../services/addContracts.js';
|
|
|
20
28
|
export async function getContArr() {
|
|
21
29
|
let contractsArray = [];
|
|
22
30
|
|
|
23
|
-
for (const x of contracts
|
|
24
|
-
|
|
31
|
+
for (const x of contracts) {
|
|
32
|
+
const balance = await provider.getBalance(x.address);
|
|
33
|
+
|
|
34
|
+
contractsArray.push({
|
|
25
35
|
index: x.index,
|
|
26
36
|
name: x.name,
|
|
27
|
-
address: x.
|
|
37
|
+
address: x.address,
|
|
28
38
|
chain: x.chain,
|
|
29
39
|
chainId: x.chainId,
|
|
30
40
|
deployType: x.deployType,
|
|
31
|
-
balance
|
|
32
|
-
|
|
33
|
-
|
|
41
|
+
balance,
|
|
42
|
+
abiPath: x.abiPath
|
|
43
|
+
});
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
return contractsArray;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Writes/Updates contracts json file
|
|
51
|
+
* @param {Array<string>} contractArr - Contract array
|
|
52
|
+
* @example
|
|
53
|
+
* updateContractJSON([{
|
|
54
|
+
...
|
|
55
|
+
}]);
|
|
56
|
+
*/
|
|
57
|
+
export function updateContractJSON(contractArr) {
|
|
58
|
+
const contractObj = serializeBigInts(contractArr);
|
|
59
|
+
fs.writeFileSync(contractJSONPath, JSON.stringify(contractObj, null, 2));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Returns pre-added/deployed contracts' objects from saved json file
|
|
64
|
+
* @returns {Object}
|
|
65
|
+
*/
|
|
66
|
+
export function getContractJSON(){
|
|
67
|
+
if(fs.existsSync(contractJSONPath)){
|
|
68
|
+
const contractJSON = fs.readFileSync(contractJSONPath, 'utf8');
|
|
69
|
+
// Return empty array if contratcs.json is empty
|
|
70
|
+
if(contractJSON.length === 0) {
|
|
71
|
+
return [];
|
|
72
|
+
} else {
|
|
73
|
+
return JSON.parse(fs.readFileSync(contractJSONPath));
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
// Generate empty contracts.json if it doesn't exist
|
|
77
|
+
const fd = fs.openSync(contractJSONPath, 'w');
|
|
78
|
+
fs.closeSync(fd);
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
37
81
|
}
|