ethershell 0.1.2-beta.0 → 0.1.4-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/package.json +1 -1
- package/src/services/addContracts.js +28 -25
- package/src/services/build.js +5 -76
- package/src/services/config.js +163 -3
- package/src/services/contracts.js +1 -1
- package/src/services/files.js +3 -3
- package/src/services/network.js +12 -42
- package/src/services/wallet.js +28 -36
- package/src/utils/accounter.js +19 -5
- package/src/utils/configFileUpdate.js +4 -1
- package/src/utils/contractProxy.js +26 -1
- package/src/utils/event.js +22 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ethershell",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.4-beta.0",
|
|
5
5
|
"description": "Interactive JavaScript console for Ethereum smart contract management",
|
|
6
6
|
"author": "Alireza Kiakojouri (alirezaethdev@gmail.com)",
|
|
7
7
|
"repository": {
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
import { ethers } from 'ethers';
|
|
10
10
|
import fs from 'fs';
|
|
11
|
-
import { provider } from './
|
|
12
|
-
import { allAccounts
|
|
11
|
+
import { provider } from './config.js';
|
|
12
|
+
import { allAccounts } from './wallet.js';
|
|
13
13
|
import { LocalStorage } from 'node-localstorage';
|
|
14
14
|
import { r } from '../../bin/cli.js';
|
|
15
|
-
import { configFile } from './
|
|
15
|
+
import { configFile } from './config.js';
|
|
16
16
|
import { createContractProxy } from '../utils/contractProxy.js';
|
|
17
|
+
import { eventOf } from '../utils/event.js';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Local storage instance for persisting contract metadata
|
|
@@ -88,16 +89,6 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
|
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
allAccounts[accIndex].contracts.push(contSpec);
|
|
91
|
-
|
|
92
|
-
const accountsIndex = accounts.findIndex(wallet => wallet.index == accIndex);
|
|
93
|
-
if(accountsIndex >= 0) {
|
|
94
|
-
accounts[accountsIndex].contracts.push(contSpec);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const hdIndex = hdAccounts.findIndex(wallet => wallet.index == accIndex);
|
|
98
|
-
if(hdIndex >= 0) {
|
|
99
|
-
hdAccounts[hdIndex].contracts.push(contSpec);
|
|
100
|
-
}
|
|
101
92
|
|
|
102
93
|
// Extend contract object
|
|
103
94
|
deployTx.index = Array.from(contracts.values()).length;
|
|
@@ -117,6 +108,13 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
|
|
|
117
108
|
// Wrap the contract instace with proxy
|
|
118
109
|
const proxiedContract = createContractProxy(contractInstance, currentProvider, allAccounts);
|
|
119
110
|
|
|
111
|
+
proxiedContract.index = Array.from(contracts.values()).length;
|
|
112
|
+
proxiedContract.name = contractName;
|
|
113
|
+
proxiedContract.chain = connectedChain.name;
|
|
114
|
+
proxiedContract.chainId = connectedChain.chainId;
|
|
115
|
+
proxiedContract.deployType = 'ethershell-deployed';
|
|
116
|
+
proxiedContract.provider = currentProvider;
|
|
117
|
+
|
|
120
118
|
// Add to REPL context with proxy
|
|
121
119
|
r.context[contractName] = proxiedContract;
|
|
122
120
|
contracts.set(contractName, proxiedContract);
|
|
@@ -127,14 +125,22 @@ export async function deploy(contractName, args, accIndex, chain, abiLoc, byteco
|
|
|
127
125
|
const tx = await provider.getTransaction(deployHash);
|
|
128
126
|
delete tx.data;
|
|
129
127
|
|
|
128
|
+
// Get event values
|
|
129
|
+
const tx1 = await provider.getTransactionReceipt(deployHash);
|
|
130
|
+
const eventValues = eventOf(contractInstance, tx1);
|
|
131
|
+
|
|
130
132
|
// Extend transaction object
|
|
131
133
|
tx.ethershellIndex = deployTx.index;
|
|
132
134
|
tx.address = deployTx.target;
|
|
133
135
|
tx.name = deployTx.name;
|
|
134
136
|
tx.chain = deployTx.chain;
|
|
135
137
|
tx.deployType = deployTx.deployType;
|
|
138
|
+
|
|
139
|
+
if(eventValues) {
|
|
140
|
+
tx.eventValues = eventValues;
|
|
141
|
+
}
|
|
136
142
|
|
|
137
|
-
|
|
143
|
+
return tx;
|
|
138
144
|
} catch(err) {
|
|
139
145
|
console.error(err);
|
|
140
146
|
}
|
|
@@ -185,6 +191,13 @@ export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
|
|
|
185
191
|
// Wrap the contract instace with proxy
|
|
186
192
|
const proxiedContract = createContractProxy(newContract, currentProvider, allAccounts);
|
|
187
193
|
|
|
194
|
+
proxiedContract.index = Array.from(contracts.values()).length;
|
|
195
|
+
proxiedContract.name = contractName;
|
|
196
|
+
proxiedContract.chain = connectedChain.name;
|
|
197
|
+
proxiedContract.chainId = connectedChain.chainId;
|
|
198
|
+
proxiedContract.deployType = 'ethershell-deployed';
|
|
199
|
+
proxiedContract.provider = currentProvider;
|
|
200
|
+
|
|
188
201
|
// Add to REPL context with proxy
|
|
189
202
|
r.context[contractName] = proxiedContract;
|
|
190
203
|
contracts.set(contractName, proxiedContract);
|
|
@@ -197,16 +210,6 @@ export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
|
|
|
197
210
|
}
|
|
198
211
|
|
|
199
212
|
allAccounts[accIndex].contracts.push(contSpec);
|
|
200
|
-
|
|
201
|
-
const accountsIndex = accounts.findIndex(wallet => wallet.index == accIndex);
|
|
202
|
-
if(accountsIndex >= 0) {
|
|
203
|
-
accounts[accountsIndex].contracts.push(contSpec);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const hdIndex = hdAccounts.findIndex(wallet => wallet.index == accIndex);
|
|
207
|
-
if(hdIndex >= 0) {
|
|
208
|
-
hdAccounts[hdIndex].contracts.push(contSpec);
|
|
209
|
-
}
|
|
210
213
|
|
|
211
214
|
// Extend contract object
|
|
212
215
|
newContract.index = Array.from(contracts.values()).length;
|
|
@@ -227,7 +230,7 @@ export async function add(contractName, contractAddr, accIndex, abiLoc, chain) {
|
|
|
227
230
|
provider: newContract.provider
|
|
228
231
|
}
|
|
229
232
|
|
|
230
|
-
|
|
233
|
+
return result;
|
|
231
234
|
} catch(err) {
|
|
232
235
|
console.error(err);
|
|
233
236
|
}
|
package/src/services/build.js
CHANGED
|
@@ -6,92 +6,21 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import path from 'path';
|
|
9
|
-
import solc from 'solc';
|
|
10
9
|
import { check, collectSolFiles } from '../utils/dir.js';
|
|
11
10
|
import {
|
|
12
11
|
setVersion,
|
|
13
12
|
build,
|
|
14
|
-
loadSolcVersion,
|
|
15
13
|
extractLoadableVersion
|
|
16
14
|
} from '../utils/builder.js';
|
|
17
15
|
import fs from 'fs';
|
|
18
16
|
import {
|
|
19
17
|
generateAllTypes,
|
|
20
18
|
} from '../utils/typeGenerator.js';
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export const configPath = './ethershell/config.json';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Global compiler configuration state
|
|
30
|
-
* @type {Object}
|
|
31
|
-
* @property {Object} currentSolcInstance - Current Solidity compiler instance
|
|
32
|
-
* @property {boolean} optimizer - Whether gas optimizer is enabled
|
|
33
|
-
* @property {number} optimizerRuns - Number of optimizer runs
|
|
34
|
-
* @property {boolean} viaIR - Whether to use IR-based code generation
|
|
35
|
-
*/
|
|
36
|
-
let compConfig = {};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* JSON file fields of compiler configuration
|
|
40
|
-
* @type {Object}
|
|
41
|
-
* @property {string} version - Current Solidity compiler version
|
|
42
|
-
* @property {boolean} optimizer - Whether gas optimizer is enabled
|
|
43
|
-
* @property {number} optimizerRuns - Number of optimizer runs
|
|
44
|
-
* @property {boolean} viaIR - Whether to use IR-based code generation
|
|
45
|
-
*/
|
|
46
|
-
export let configFile = {
|
|
47
|
-
providerEndpoint: '',
|
|
48
|
-
defaultWallet: {},
|
|
49
|
-
compiler: {}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Global compiler configuration state
|
|
54
|
-
* @type {Object}
|
|
55
|
-
* @property {boolean} optimizer - Whether gas optimizer is enabled
|
|
56
|
-
* @property {number} optimizerRuns - Number of optimizer runs
|
|
57
|
-
* @property {boolean} viaIR - Whether to use IR-based code generation
|
|
58
|
-
*/
|
|
59
|
-
let storedCompConfig;
|
|
60
|
-
|
|
61
|
-
// Load config file
|
|
62
|
-
if(fs.existsSync(configPath)){
|
|
63
|
-
storedCompConfig = JSON.parse(fs.readFileSync(configPath));
|
|
64
|
-
} else {
|
|
65
|
-
storedCompConfig = null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Initialize global configuration of compiler
|
|
69
|
-
if(storedCompConfig){
|
|
70
|
-
configFile.compiler = storedCompConfig.compiler;
|
|
71
|
-
console.info(`Compiler is loading ...`);
|
|
72
|
-
compConfig.currentSolcInstance = await loadSolcVersion(configFile.compiler.version);
|
|
73
|
-
console.info(`Loading done!`);
|
|
74
|
-
compConfig.optimizer = configFile.compiler.optimizer;
|
|
75
|
-
compConfig.viaIR = configFile.compiler.viaIR;
|
|
76
|
-
compConfig.optimizerRuns = configFile.compiler.optimizerRuns;
|
|
77
|
-
compConfig.compilePath = configFile.compiler.compilePath;
|
|
78
|
-
} else {
|
|
79
|
-
compConfig = {
|
|
80
|
-
currentSolcInstance: solc, // default local compiler
|
|
81
|
-
optimizer: false,
|
|
82
|
-
viaIR: false,
|
|
83
|
-
optimizerRuns: 200,
|
|
84
|
-
compilePath: './build'
|
|
85
|
-
}
|
|
86
|
-
configFile.compiler.version = extractLoadableVersion(compConfig.currentSolcInstance.version());
|
|
87
|
-
configFile.compiler.optimizer = compConfig.optimizer;
|
|
88
|
-
configFile.compiler.viaIR = compConfig.viaIR;
|
|
89
|
-
configFile.compiler.optimizerRuns = compConfig.optimizerRuns;
|
|
90
|
-
configFile.compiler.compilePath = compConfig.compilePath;
|
|
91
|
-
|
|
92
|
-
// Update config file
|
|
93
|
-
fs.writeFileSync(configPath, JSON.stringify(configFile, null, 2));
|
|
94
|
-
}
|
|
19
|
+
import {
|
|
20
|
+
configPath,
|
|
21
|
+
configFile,
|
|
22
|
+
compConfig
|
|
23
|
+
} from './config.js';
|
|
95
24
|
|
|
96
25
|
/**
|
|
97
26
|
* Update the Solidity compiler to a specific version
|
package/src/services/config.js
CHANGED
|
@@ -1,15 +1,175 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
loadSolcVersion,
|
|
3
|
+
extractLoadableVersion
|
|
4
|
+
} from '../utils/builder.js';
|
|
5
|
+
import { allAccounts } from './wallet.js';
|
|
6
|
+
import { serializeBigInts } from '../utils/serialize.js';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import { ethers } from 'ethers';
|
|
9
|
+
|
|
10
|
+
// Sync Config Memory with Storage Config:
|
|
11
|
+
/**
|
|
12
|
+
* Default JSON-RPC URL for local Ethereum node
|
|
13
|
+
* @constant {string}
|
|
14
|
+
*/
|
|
15
|
+
export const defaultUrl = 'http://127.0.0.1:8545' ;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Currently active network URL
|
|
19
|
+
* @type {string}
|
|
20
|
+
*/
|
|
21
|
+
export let currentUrl;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Ethers.js JSON-RPC provider instance
|
|
25
|
+
* @type {ethers.JsonRpcProvider}
|
|
26
|
+
*/
|
|
27
|
+
export let provider
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Stored config path
|
|
31
|
+
* @type {string}
|
|
32
|
+
*/
|
|
33
|
+
export const configPath = './ethershell/config.json';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Global compiler configuration state
|
|
37
|
+
* @type {Object}
|
|
38
|
+
* @property {Object} currentSolcInstance - Current Solidity compiler instance
|
|
39
|
+
* @property {boolean} optimizer - Whether gas optimizer is enabled
|
|
40
|
+
* @property {number} optimizerRuns - Number of optimizer runs
|
|
41
|
+
* @property {boolean} viaIR - Whether to use IR-based code generation
|
|
42
|
+
*/
|
|
43
|
+
export let compConfig = {};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* JSON file fields of compiler configuration
|
|
47
|
+
* @type {Object}
|
|
48
|
+
* @property {string} version - Current Solidity compiler version
|
|
49
|
+
* @property {boolean} optimizer - Whether gas optimizer is enabled
|
|
50
|
+
* @property {number} optimizerRuns - Number of optimizer runs
|
|
51
|
+
* @property {boolean} viaIR - Whether to use IR-based code generation
|
|
52
|
+
*/
|
|
53
|
+
export let configFile = {
|
|
54
|
+
providerEndpoint: '',
|
|
55
|
+
defaultWallet: {},
|
|
56
|
+
compiler: {}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Global compiler configuration state
|
|
61
|
+
* @type {Object}
|
|
62
|
+
* @property {boolean} optimizer - Whether gas optimizer is enabled
|
|
63
|
+
* @property {number} optimizerRuns - Number of optimizer runs
|
|
64
|
+
* @property {boolean} viaIR - Whether to use IR-based code generation
|
|
65
|
+
*/
|
|
66
|
+
let storedCompConfig;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Object containing properties of config file
|
|
70
|
+
* @type {Object}
|
|
71
|
+
*/
|
|
72
|
+
let configObj;
|
|
73
|
+
|
|
74
|
+
// 1) Load config file
|
|
75
|
+
if(!fs.existsSync(configPath)){
|
|
76
|
+
storedCompConfig = null;
|
|
77
|
+
} else {
|
|
78
|
+
configObj = JSON.parse(fs.readFileSync(configPath));
|
|
79
|
+
storedCompConfig = configObj;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 2) Set Provider to Memory:
|
|
83
|
+
// Initialize provider with default URL
|
|
84
|
+
/**
|
|
85
|
+
* The specific RPC endpoint URL saved on storage before.
|
|
86
|
+
* @type {string}
|
|
87
|
+
*/
|
|
88
|
+
const storedUrl = configObj.providerEndpoint;
|
|
89
|
+
if(storedUrl) {
|
|
90
|
+
provider = new ethers.JsonRpcProvider(storedUrl);
|
|
91
|
+
currentUrl = storedUrl;
|
|
92
|
+
configFile.providerEndpoint = storedUrl;
|
|
93
|
+
} else {
|
|
94
|
+
provider = new ethers.JsonRpcProvider(defaultUrl);
|
|
95
|
+
currentUrl = defaultUrl;
|
|
96
|
+
configFile.providerEndpoint = defaultUrl;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 3) Set Compiler to Memeory:
|
|
100
|
+
// Initialize global configuration of compiler
|
|
101
|
+
if(storedCompConfig){
|
|
102
|
+
configFile.compiler = storedCompConfig.compiler;
|
|
103
|
+
console.info(`Compiler is loading ...`);
|
|
104
|
+
compConfig.currentSolcInstance = await loadSolcVersion(configFile.compiler.version);
|
|
105
|
+
console.info(`Loading done!`);
|
|
106
|
+
compConfig.optimizer = configFile.compiler.optimizer;
|
|
107
|
+
compConfig.viaIR = configFile.compiler.viaIR;
|
|
108
|
+
compConfig.optimizerRuns = configFile.compiler.optimizerRuns;
|
|
109
|
+
compConfig.compilePath = configFile.compiler.compilePath;
|
|
110
|
+
} else {
|
|
111
|
+
compConfig = {
|
|
112
|
+
currentSolcInstance: solc, // default local compiler
|
|
113
|
+
optimizer: false,
|
|
114
|
+
viaIR: false,
|
|
115
|
+
optimizerRuns: 200,
|
|
116
|
+
compilePath: './build'
|
|
117
|
+
}
|
|
118
|
+
configFile.compiler.version = extractLoadableVersion(compConfig.currentSolcInstance.version());
|
|
119
|
+
configFile.compiler.optimizer = compConfig.optimizer;
|
|
120
|
+
configFile.compiler.viaIR = compConfig.viaIR;
|
|
121
|
+
configFile.compiler.optimizerRuns = compConfig.optimizerRuns;
|
|
122
|
+
configFile.compiler.compilePath = compConfig.compilePath;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 4) Set Default Account:
|
|
126
|
+
// Set the default account from stored wallets
|
|
127
|
+
const defWallet = configObj.defaultWallet;
|
|
128
|
+
if(defWallet.address) {
|
|
129
|
+
configFile.defaultWallet = serializeBigInts(defWallet);
|
|
130
|
+
} else {
|
|
131
|
+
if(allAccounts && allAccounts.length > 0) {
|
|
132
|
+
configFile.defaultWallet = serializeBigInts(allAccounts[0]);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 5) Update config file
|
|
137
|
+
fs.writeFileSync(configPath, JSON.stringify(configFile, null, 2));
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Changes provider just in memory
|
|
141
|
+
* @param {Object} newProvider
|
|
142
|
+
*/
|
|
143
|
+
export function setProvider(newProvider) {
|
|
144
|
+
provider = new ethers.JsonRpcProvider(newProvider);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Changes provider just in memory
|
|
149
|
+
* @param {String} newUrl
|
|
150
|
+
*/
|
|
151
|
+
export function setCurrentUrl(newUrl) {
|
|
152
|
+
currentUrl = newUrl;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Changes configFile in memory
|
|
157
|
+
* @param {Object} newConfig
|
|
158
|
+
*/
|
|
159
|
+
export function setConfigFile(newConfig) {
|
|
160
|
+
configFile = newConfig;
|
|
161
|
+
}
|
|
2
162
|
|
|
3
163
|
/**
|
|
4
164
|
* Gets all fields of config file
|
|
5
165
|
*/
|
|
6
166
|
export function getConfigInfo() {
|
|
7
|
-
|
|
167
|
+
return configFile;
|
|
8
168
|
}
|
|
9
169
|
|
|
10
170
|
/**
|
|
11
171
|
* Gets just default account of config file
|
|
12
172
|
*/
|
|
13
173
|
export function getDefaultAccount() {
|
|
14
|
-
|
|
174
|
+
return configFile.defaultWallet;
|
|
15
175
|
}
|
package/src/services/files.js
CHANGED
|
@@ -23,17 +23,17 @@ export function deleteDirectory(dirPath){
|
|
|
23
23
|
}
|
|
24
24
|
// Check if the directory exists
|
|
25
25
|
if(!fs.existsSync(dirPath)){
|
|
26
|
-
console.
|
|
26
|
+
console.info('Path is not a directory');
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// For Node.js 14.14.0+ (recommended)
|
|
31
31
|
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
32
32
|
|
|
33
|
-
console.
|
|
33
|
+
console.info('Directory deleted successfully');
|
|
34
34
|
} catch (err) {
|
|
35
35
|
if (err.code === 'ENOENT') {
|
|
36
|
-
console.
|
|
36
|
+
console.info('Directory does not exist');
|
|
37
37
|
} else {
|
|
38
38
|
console.error('Error deleting directory:', err);
|
|
39
39
|
}
|
package/src/services/network.js
CHANGED
|
@@ -5,44 +5,14 @@
|
|
|
5
5
|
* @module network
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { ethers } from 'ethers';
|
|
9
|
-
import { configPath } from './build.js';
|
|
10
|
-
import fs from 'fs';
|
|
11
8
|
import { changeProvider } from '../utils/configFileUpdate.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Currently active network URL
|
|
21
|
-
* @type {string}
|
|
22
|
-
*/
|
|
23
|
-
export let currentUrl;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Ethers.js JSON-RPC provider instance
|
|
27
|
-
* @type {ethers.JsonRpcProvider}
|
|
28
|
-
*/
|
|
29
|
-
export let provider
|
|
30
|
-
|
|
31
|
-
// Initialize provider with default URL
|
|
32
|
-
/**
|
|
33
|
-
* The specific RPC endpoint URL saved on storage before.
|
|
34
|
-
* @type {string}
|
|
35
|
-
*/
|
|
36
|
-
const storedUrl = JSON.parse(fs.readFileSync(configPath)).providerEndpoint;
|
|
37
|
-
if(storedUrl) {
|
|
38
|
-
provider = new ethers.JsonRpcProvider(storedUrl);
|
|
39
|
-
currentUrl = storedUrl;
|
|
40
|
-
} else {
|
|
41
|
-
provider = new ethers.JsonRpcProvider(defaultUrl);
|
|
42
|
-
currentUrl = defaultUrl;
|
|
43
|
-
changeProvider(currentUrl);
|
|
44
|
-
}
|
|
45
|
-
|
|
9
|
+
import {
|
|
10
|
+
currentUrl,
|
|
11
|
+
setCurrentUrl,
|
|
12
|
+
provider,
|
|
13
|
+
setProvider,
|
|
14
|
+
defaultUrl
|
|
15
|
+
} from './config.js';
|
|
46
16
|
|
|
47
17
|
/**
|
|
48
18
|
* Set a new network provider
|
|
@@ -55,8 +25,8 @@ if(storedUrl) {
|
|
|
55
25
|
*/
|
|
56
26
|
export async function set(url){
|
|
57
27
|
try{
|
|
58
|
-
|
|
59
|
-
|
|
28
|
+
setProvider(url);
|
|
29
|
+
setCurrentUrl(url);
|
|
60
30
|
const result = await provider.getNetwork();
|
|
61
31
|
const network = {
|
|
62
32
|
URL: currentUrl,
|
|
@@ -64,7 +34,7 @@ export async function set(url){
|
|
|
64
34
|
chainId: result.chainId
|
|
65
35
|
}
|
|
66
36
|
changeProvider(currentUrl);
|
|
67
|
-
|
|
37
|
+
return network;
|
|
68
38
|
}catch(err){
|
|
69
39
|
console.error(err);
|
|
70
40
|
}
|
|
@@ -86,7 +56,7 @@ export async function get(){
|
|
|
86
56
|
name: result.name,
|
|
87
57
|
chainId: result.chainId
|
|
88
58
|
}
|
|
89
|
-
|
|
59
|
+
return network;
|
|
90
60
|
}catch(err){
|
|
91
61
|
console.error(err);
|
|
92
62
|
}
|
|
@@ -103,7 +73,7 @@ export function getDefault(){
|
|
|
103
73
|
const result = {
|
|
104
74
|
URL: defaultUrl
|
|
105
75
|
}
|
|
106
|
-
|
|
76
|
+
return result;
|
|
107
77
|
}catch(err){
|
|
108
78
|
console.error(err);
|
|
109
79
|
}
|
package/src/services/wallet.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { ethers } from 'ethers';
|
|
10
|
-
import { provider } from './
|
|
10
|
+
import { provider } from './config.js';
|
|
11
11
|
import {
|
|
12
12
|
deleteByIndex,
|
|
13
13
|
deleteByIndexArr,
|
|
@@ -18,8 +18,6 @@ import {
|
|
|
18
18
|
updateAccountMemory,
|
|
19
19
|
setDefaultAccount
|
|
20
20
|
} from '../utils/accounter.js';
|
|
21
|
-
import { configPath } from './build.js';
|
|
22
|
-
import fs from 'fs';
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
23
|
* Array containing all accounts (imported, generated, HD, and node-managed)
|
|
@@ -27,17 +25,6 @@ import {
|
|
|
27
25
|
*/
|
|
28
26
|
export let allAccounts = getWalletJSON();
|
|
29
27
|
|
|
30
|
-
// Set the default account from stored wallets
|
|
31
|
-
const defWallet = JSON.parse(fs.readFileSync(configPath)).defaultWallet;
|
|
32
|
-
if(defWallet.address) {
|
|
33
|
-
setDefaultAccount(defWallet);
|
|
34
|
-
} else {
|
|
35
|
-
if(allAccounts && allAccounts.length > 0) {
|
|
36
|
-
setDefaultAccount(allAccounts[0]);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
28
|
/**
|
|
42
29
|
* Array containing only regular accounts (imported and generated)
|
|
43
30
|
* @type {Array<Object>}
|
|
@@ -94,7 +81,7 @@ export function addAccounts(privKeyArr) {
|
|
|
94
81
|
updateWalletJSON(allAccounts);
|
|
95
82
|
newAccObj.index = allAccounts.length - 1;
|
|
96
83
|
accounts.push(newAccObj);
|
|
97
|
-
|
|
84
|
+
return allAccounts[newFrom];
|
|
98
85
|
}
|
|
99
86
|
|
|
100
87
|
if(Array.isArray(privKeyArr)){
|
|
@@ -112,7 +99,7 @@ export function addAccounts(privKeyArr) {
|
|
|
112
99
|
accounts.push(newAccObj);
|
|
113
100
|
});
|
|
114
101
|
|
|
115
|
-
|
|
102
|
+
return allAccounts.slice(newFrom);
|
|
116
103
|
}
|
|
117
104
|
setDefaultAccount(allAccounts[0]);
|
|
118
105
|
}
|
|
@@ -157,8 +144,8 @@ export function addHD(phrase, count = 10) {
|
|
|
157
144
|
}
|
|
158
145
|
updateWalletJSON(allAccounts);
|
|
159
146
|
setDefaultAccount(allAccounts[0]);
|
|
160
|
-
console.
|
|
161
|
-
|
|
147
|
+
console.info(`!WARNING!\n The generated accounts are NOT safe. Do NOT use them on main net!`);
|
|
148
|
+
return allAccounts.slice(newFrom);
|
|
162
149
|
}
|
|
163
150
|
|
|
164
151
|
/**
|
|
@@ -187,8 +174,8 @@ export function createAccounts(count = 1) {
|
|
|
187
174
|
}
|
|
188
175
|
updateWalletJSON(allAccounts);
|
|
189
176
|
setDefaultAccount(allAccounts[0]);
|
|
190
|
-
console.
|
|
191
|
-
|
|
177
|
+
console.info(`!WARNING!\n The generated accounts are NOT safe. Do NOT use them on main net!`);
|
|
178
|
+
return allAccounts.slice(newFrom);
|
|
192
179
|
}
|
|
193
180
|
|
|
194
181
|
/**
|
|
@@ -222,8 +209,8 @@ export function createHD(count = 10) {
|
|
|
222
209
|
}
|
|
223
210
|
updateWalletJSON(allAccounts);
|
|
224
211
|
setDefaultAccount(allAccounts[0]);
|
|
225
|
-
console.
|
|
226
|
-
|
|
212
|
+
console.info(`!WARNING!\n The generated accounts are NOT safe. Do NOT use them on main net!`);
|
|
213
|
+
return allAccounts.slice(newFrom);
|
|
227
214
|
}
|
|
228
215
|
|
|
229
216
|
/**
|
|
@@ -232,8 +219,8 @@ export function createHD(count = 10) {
|
|
|
232
219
|
* getAllAccounts();
|
|
233
220
|
*/
|
|
234
221
|
export function getAllAccounts() {
|
|
235
|
-
console.
|
|
236
|
-
|
|
222
|
+
console.info(`!WARNING!\n The generated accounts are NOT safe. Do NOT use them on main net!`);
|
|
223
|
+
return allAccounts;
|
|
237
224
|
}
|
|
238
225
|
|
|
239
226
|
/**
|
|
@@ -242,8 +229,8 @@ export function getAllAccounts() {
|
|
|
242
229
|
* getAccounts();
|
|
243
230
|
*/
|
|
244
231
|
export function getAccounts() {
|
|
245
|
-
console.
|
|
246
|
-
|
|
232
|
+
console.info(`!WARNING!\n The generated accounts are NOT safe. Do NOT use them on main net!`);
|
|
233
|
+
return accounts;
|
|
247
234
|
}
|
|
248
235
|
|
|
249
236
|
/**
|
|
@@ -252,8 +239,8 @@ export function getAccounts() {
|
|
|
252
239
|
* getHDAccounts();
|
|
253
240
|
*/
|
|
254
241
|
export function getHDAccounts() {
|
|
255
|
-
console.
|
|
256
|
-
|
|
242
|
+
console.info(`!WARNING!\n The generated accounts are NOT safe. Do NOT use them on main net!`);
|
|
243
|
+
return hdAccounts;
|
|
257
244
|
}
|
|
258
245
|
|
|
259
246
|
/**
|
|
@@ -267,14 +254,14 @@ export function getHDAccounts() {
|
|
|
267
254
|
* deleteAccount(); // Delete all accounts
|
|
268
255
|
*/
|
|
269
256
|
export function deleteAccount(accPointer) {
|
|
270
|
-
if(!accPointer) {
|
|
257
|
+
if(!accPointer && accPointer !== 0) {
|
|
271
258
|
deleteByIndex(null);
|
|
272
|
-
|
|
259
|
+
return allAccounts;
|
|
273
260
|
}
|
|
274
261
|
|
|
275
262
|
if(typeof accPointer === 'number') {
|
|
276
263
|
deleteByIndex(accPointer);
|
|
277
|
-
|
|
264
|
+
return allAccounts;
|
|
278
265
|
}
|
|
279
266
|
|
|
280
267
|
if(ethers.isAddress(accPointer)) {
|
|
@@ -283,11 +270,12 @@ export function deleteAccount(accPointer) {
|
|
|
283
270
|
if(index !== -1) {
|
|
284
271
|
deleteByIndex(index);
|
|
285
272
|
}
|
|
286
|
-
|
|
273
|
+
return allAccounts;
|
|
287
274
|
}
|
|
288
275
|
|
|
289
276
|
if(Array.isArray(accPointer)) {
|
|
290
277
|
deleteByIndexArr(accPointer);
|
|
278
|
+
return allAccounts;
|
|
291
279
|
}
|
|
292
280
|
|
|
293
281
|
if(ethers.Mnemonic.isValidMnemonic(accPointer)) {
|
|
@@ -309,7 +297,7 @@ export function deleteAccount(accPointer) {
|
|
|
309
297
|
deleteByIndex(indicesToDelete[i]);
|
|
310
298
|
}
|
|
311
299
|
|
|
312
|
-
|
|
300
|
+
return allAccounts;
|
|
313
301
|
return;
|
|
314
302
|
}
|
|
315
303
|
}
|
|
@@ -363,16 +351,16 @@ export async function getWalletInfo(accPointer) {
|
|
|
363
351
|
|
|
364
352
|
if(typeof accPointer === 'number') {
|
|
365
353
|
const index = allAccounts.findIndex(wallet => wallet.index == accPointer);
|
|
366
|
-
await getAccountInfo(index);
|
|
354
|
+
return await getAccountInfo(index);
|
|
367
355
|
}
|
|
368
356
|
|
|
369
357
|
if(ethers.isAddress(accPointer)) {
|
|
370
358
|
const index = allAccounts.findIndex(wallet => wallet.address == accPointer);
|
|
371
|
-
await getAccountInfo(index);
|
|
359
|
+
return await getAccountInfo(index);
|
|
372
360
|
}
|
|
373
361
|
|
|
374
362
|
if(Array.isArray(accPointer)) {
|
|
375
|
-
await getAccountInfo(accPointer);
|
|
363
|
+
return await getAccountInfo(accPointer);
|
|
376
364
|
}
|
|
377
365
|
|
|
378
366
|
} catch(err) {
|
|
@@ -402,6 +390,10 @@ export function changeDefaultAccount(accPointer) {
|
|
|
402
390
|
}
|
|
403
391
|
|
|
404
392
|
if(ethers.isHexString(accPointer, 32)) {
|
|
393
|
+
const dupWallet = detectDupWallet(accPointer);
|
|
394
|
+
if(dupWallet.status) {
|
|
395
|
+
throw `Wallets may NOT be duplicated! You are adding wallet index ${dupWallet.index} again!`
|
|
396
|
+
}
|
|
405
397
|
const newAccount = new ethers.Wallet(accPointer, provider);
|
|
406
398
|
const newAccObj = {
|
|
407
399
|
index: allAccounts.length,
|
package/src/utils/accounter.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { allAccounts, accounts, hdAccounts } from '../services/wallet.js';
|
|
9
|
-
import { provider } from '../services/
|
|
9
|
+
import { provider } from '../services/config.js';
|
|
10
10
|
import fs from 'fs';
|
|
11
|
-
import { configFile, configPath } from '../services/
|
|
11
|
+
import { configFile, configPath } from '../services/config.js';
|
|
12
12
|
import { serializeBigInts } from './serialize.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -69,9 +69,9 @@ export function deleteByIndexArr(indices) {
|
|
|
69
69
|
*/
|
|
70
70
|
export async function getAccountInfo(index) {
|
|
71
71
|
if (Array.isArray(index)) {
|
|
72
|
-
await _getAccArrInfo(index);
|
|
72
|
+
return await _getAccArrInfo(index);
|
|
73
73
|
} else if (typeof index === 'number') {
|
|
74
|
-
await _getAccountInfo(index);
|
|
74
|
+
return await _getAccountInfo(index);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -182,7 +182,7 @@ async function _getAccountInfo(_index) {
|
|
|
182
182
|
accInfo.nonce = await provider.getTransactionCount(accInfo.address);
|
|
183
183
|
accInfo.balance = await provider.getBalance(accInfo.address);
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
return accInfo;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
/**
|
|
@@ -227,6 +227,11 @@ function _deleteBySingIndex(_index) {
|
|
|
227
227
|
_index++;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
+
|
|
231
|
+
// Remove from config file if it is default wallet
|
|
232
|
+
if(accountIndex == configFile.defaultWallet.index) {
|
|
233
|
+
deleteDefaultAccount();
|
|
234
|
+
}
|
|
230
235
|
}
|
|
231
236
|
}
|
|
232
237
|
|
|
@@ -282,6 +287,7 @@ function _deleteAll() {
|
|
|
282
287
|
allAccounts.splice(0);
|
|
283
288
|
accounts.splice(0);
|
|
284
289
|
hdAccounts.splice(0);
|
|
290
|
+
deleteDefaultAccount();
|
|
285
291
|
fs.writeFileSync(walletJSONPath, JSON.stringify([], null, 2));
|
|
286
292
|
return;
|
|
287
293
|
}
|
|
@@ -294,3 +300,11 @@ export function setDefaultAccount(account) {
|
|
|
294
300
|
configFile.defaultWallet = serializeBigInts(account);
|
|
295
301
|
fs.writeFileSync(configPath, JSON.stringify(configFile, null, 2));
|
|
296
302
|
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Deletes default account from config file
|
|
306
|
+
*/
|
|
307
|
+
export function deleteDefaultAccount() {
|
|
308
|
+
configFile.defaultWallet = {};
|
|
309
|
+
fs.writeFileSync(configPath, JSON.stringify(configFile, null, 2));
|
|
310
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/utils/contractProxy.js
|
|
2
2
|
import { ethers } from 'ethers';
|
|
3
|
+
import { eventOf } from './event.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Creates a proxy wrapper for ethers.js Contract objects
|
|
@@ -25,6 +26,10 @@ import { ethers } from 'ethers';
|
|
|
25
26
|
export function createContractProxy(contract, provider, allAccounts) {
|
|
26
27
|
return new Proxy(contract, {
|
|
27
28
|
get(target, prop) {
|
|
29
|
+
if (prop === 'provider') {
|
|
30
|
+
return provider;
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
// Pass through non-function properties
|
|
29
34
|
if (typeof target[prop] !== 'function') {
|
|
30
35
|
return target[prop];
|
|
@@ -155,7 +160,27 @@ export function createContractProxy(contract, provider, allAccounts) {
|
|
|
155
160
|
}
|
|
156
161
|
|
|
157
162
|
// Call the method with remaining args and tx options
|
|
158
|
-
|
|
163
|
+
const result = await method.apply(method, args);
|
|
164
|
+
|
|
165
|
+
// Check if result is a transaction response (has wait method)
|
|
166
|
+
if (result && typeof result.wait === 'function') {
|
|
167
|
+
// This is a transaction - wait for mining
|
|
168
|
+
const receipt = await result.wait();
|
|
169
|
+
|
|
170
|
+
// Get event values
|
|
171
|
+
const tx = await provider.getTransactionReceipt(receipt.hash);
|
|
172
|
+
const eventValues = eventOf(contract, tx);
|
|
173
|
+
|
|
174
|
+
// Extend transaction receipt with event values
|
|
175
|
+
if(eventValues) {
|
|
176
|
+
receipt.eventValues = eventValues;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return receipt;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// This is a view/pure function result - return as-is
|
|
183
|
+
return result;
|
|
159
184
|
};
|
|
160
185
|
}
|
|
161
186
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns event values
|
|
3
|
+
* @param {Object} contract
|
|
4
|
+
* @param {Object} tx
|
|
5
|
+
* @returns {Array<Object>}
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function eventOf(contract, tx){
|
|
9
|
+
const events = tx.logs.map(log => {
|
|
10
|
+
try {
|
|
11
|
+
return contract.interface.parseLog(log);
|
|
12
|
+
} catch (e) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}).filter(log => log !== null);
|
|
16
|
+
|
|
17
|
+
const parsedEvents = events.map(e => ({
|
|
18
|
+
name: e.name,
|
|
19
|
+
values: e.args,
|
|
20
|
+
}));
|
|
21
|
+
return parsedEvents;
|
|
22
|
+
}
|