mirror of https://github.com/embarklabs/embark.git
feat(@embark/embark-rpc-manager): Add support for `eth_signTypedData_v3`
This PR adds support for EIP-712 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md), by allowing the signing of typed data transactions using the `eth_signTypeData_v3` or `eth_signTypedData` request. Add a module called `embark-rpc-manager` to handle all RPC transaction modifications. The internal events management module extracted to `embark-core`. This allows other modules (ie plugins) to use a private instance of Embark’s event API. Remove transaction modifications in `embark-accounts-manager` and leave only the functionality in this module that handle account management (ie funding of accounts). Other functionality was moved to `embark-rpc-manager`. - Transactions should now reflect when a new node account is added via `personal_newAccount` or via the node itself (and once `eth_accounts` is requested). - In the proxy, errors are handled for all cases and are now JSON-RPC spec-compliant. - Always register `eth_signTypedData` RPC response and display error message if account cannot be found. NOTE: Updated yarn.lock due to conflict after rebase. Avoid race condition with rpc modifications Refactor proxy to make request handling asynchronous, and to allow circumvention of forwarding requests to the node in cases where it is not needed. Move loading of plugins to after core and stack components (in cmd_controller). We should load custom plugins LAST (ie after all core and stack components, and after all Embark plugins). To do this, we disable automatic loading of plugins in the config, and allow them to be loading explicitly in cmd_controller. Create a system that allows registration of custom plugins. Each plugin is generated in EmbarkJS by instantiating the registered class. For example, we can register a Plasma plugin and it will be generated in to EmbarkJS.Plasma with an instantiation of `embarkjs-plasma`. The DApp itself can then do what it wants with `EmbarkJS.Plasma` (ie call `EmbarkJS.Plasma.init()`. NOTE: loading of custom plugins needs to be applied to all other commands in `cmd_controller`. This PR only loads custom plugins for the `run` command. NOTE: This PR is based on branch fix/ws-eth-subscribe (#1850). I will rebase this PR when (and if) #1850 is merged.
This commit is contained in:
parent
5dc4b2134e
commit
c7ec49a38f
|
@ -66,7 +66,9 @@
|
||||||
"eth_getTransactionReceipt": "eth_getTransactionReceipt",
|
"eth_getTransactionReceipt": "eth_getTransactionReceipt",
|
||||||
"eth_call": "eth_call",
|
"eth_call": "eth_call",
|
||||||
"eth_accounts": "eth_accounts",
|
"eth_accounts": "eth_accounts",
|
||||||
"personal_listAccounts": "personal_listAccounts"
|
"eth_signTypedData": "eth_signTypedData",
|
||||||
|
"personal_listAccounts": "personal_listAccounts",
|
||||||
|
"personal_newAccount": "personal_newAccount"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
declare module "embark-core" {
|
|
||||||
export class IPC {
|
|
||||||
constructor(options: {ipcRole: string});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -132,8 +132,8 @@ export class Config {
|
||||||
|
|
||||||
// TODO: refactor this so reading the file can be done with a normal resolver or something that takes advantage of the plugin api
|
// TODO: refactor this so reading the file can be done with a normal resolver or something that takes advantage of the plugin api
|
||||||
this.events.setCommandHandler("config:contractsFiles:add", (filename, resolver) => {
|
this.events.setCommandHandler("config:contractsFiles:add", (filename, resolver) => {
|
||||||
resolver = resolver || function(callback) { callback(fs.readFileSync(filename).toString()); };
|
resolver = resolver || function (callback) { callback(fs.readFileSync(filename).toString()); };
|
||||||
this.contractsFiles.push(new File({path: filename, originalPath: filename, type: Types.custom, resolver}));
|
this.contractsFiles.push(new File({ path: filename, originalPath: filename, type: Types.custom, resolver }));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.events.setCommandHandler("config:contractsFiles:reset", (cb) => {
|
this.events.setCommandHandler("config:contractsFiles:reset", (cb) => {
|
||||||
|
@ -179,7 +179,6 @@ export class Config {
|
||||||
env: this.env,
|
env: this.env,
|
||||||
version: this.version
|
version: this.version
|
||||||
});
|
});
|
||||||
this.plugins.loadPlugins();
|
|
||||||
|
|
||||||
this.loadEmbarkConfigFile();
|
this.loadEmbarkConfigFile();
|
||||||
this.loadBlockchainConfigFile();
|
this.loadBlockchainConfigFile();
|
||||||
|
@ -208,6 +207,7 @@ export class Config {
|
||||||
this.loadAssetFiles();
|
this.loadAssetFiles();
|
||||||
this.loadContractsConfigFile();
|
this.loadContractsConfigFile();
|
||||||
this.loadExternalContractsFiles();
|
this.loadExternalContractsFiles();
|
||||||
|
this.loadPluginContractFiles();
|
||||||
|
|
||||||
this._updateBlockchainCors();
|
this._updateBlockchainCors();
|
||||||
}
|
}
|
||||||
|
@ -302,7 +302,7 @@ export class Config {
|
||||||
if (env) {
|
if (env) {
|
||||||
if (env === 'test' && !configObject[env]) {
|
if (env === 'test' && !configObject[env]) {
|
||||||
// Disabled all configs in tests as they are opt in
|
// Disabled all configs in tests as they are opt in
|
||||||
return Object.assign({}, defaultConfig.default, {enabled: false});
|
return Object.assign({}, defaultConfig.default, { enabled: false });
|
||||||
}
|
}
|
||||||
return recursiveMerge(configObject.default || {}, configObject[env]);
|
return recursiveMerge(configObject.default || {}, configObject[env]);
|
||||||
} else if (env !== false) {
|
} else if (env !== false) {
|
||||||
|
@ -448,7 +448,7 @@ export class Config {
|
||||||
let configObject = getContractDefaults(this.embarkConfig.versions);
|
let configObject = getContractDefaults(this.embarkConfig.versions);
|
||||||
|
|
||||||
const contractsConfigs = this.plugins.getPluginsProperty('contractsConfig', 'contractsConfigs');
|
const contractsConfigs = this.plugins.getPluginsProperty('contractsConfig', 'contractsConfigs');
|
||||||
contractsConfigs.forEach(function(pluginConfig) {
|
contractsConfigs.forEach(function (pluginConfig) {
|
||||||
configObject = recursiveMerge(configObject, pluginConfig);
|
configObject = recursiveMerge(configObject, pluginConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -534,11 +534,11 @@ export class Config {
|
||||||
upload: {
|
upload: {
|
||||||
provider: "ipfs",
|
provider: "ipfs",
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
host : defaultHost,
|
host: defaultHost,
|
||||||
port: 5001,
|
port: 5001,
|
||||||
getUrl: "http://localhost:8080/ipfs/"
|
getUrl: "http://localhost:8080/ipfs/"
|
||||||
},
|
},
|
||||||
dappConnection: [{provider: "ipfs", host: "localhost", port: 5001, getUrl: "http://localhost:8080/ipfs/"}]
|
dappConnection: [{ provider: "ipfs", host: "localhost", port: 5001, getUrl: "http://localhost:8080/ipfs/" }]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -610,7 +610,7 @@ export class Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (configFilePath === false) {
|
if (configFilePath === false) {
|
||||||
this.webServerConfig = {enabled: false};
|
this.webServerConfig = { enabled: false };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.webServerConfig) {
|
if (this.webServerConfig) {
|
||||||
|
@ -698,11 +698,11 @@ export class Config {
|
||||||
const readFiles: File[] = [];
|
const readFiles: File[] = [];
|
||||||
const storageConfig = self.storageConfig;
|
const storageConfig = self.storageConfig;
|
||||||
|
|
||||||
originalFiles.filter(function(file) {
|
originalFiles.filter(function (file) {
|
||||||
return (file[0] === '$' || file.indexOf('.') >= 0);
|
return (file[0] === '$' || file.indexOf('.') >= 0);
|
||||||
}).filter(function(file) {
|
}).filter(function (file) {
|
||||||
const basedir = findMatchingExpression(file, files);
|
const basedir = findMatchingExpression(file, files);
|
||||||
readFiles.push(new File({path: file, originalPath: file, type: Types.dappFile, basedir, storageConfig}));
|
readFiles.push(new File({ path: file, originalPath: file, type: Types.dappFile, basedir, storageConfig }));
|
||||||
});
|
});
|
||||||
|
|
||||||
const filesFromPlugins: File[] = [];
|
const filesFromPlugins: File[] = [];
|
||||||
|
@ -718,7 +718,7 @@ export class Config {
|
||||||
self.logger.error(err.message);
|
self.logger.error(err.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
filesFromPlugins.filter(function(file) {
|
filesFromPlugins.filter(function (file) {
|
||||||
if ((file.intendedPath && fileMatchesPattern(files, file.intendedPath)) || fileMatchesPattern(files, file.file)) {
|
if ((file.intendedPath && fileMatchesPattern(files, file.intendedPath)) || fileMatchesPattern(files, file.file)) {
|
||||||
readFiles.push(file);
|
readFiles.push(file);
|
||||||
}
|
}
|
||||||
|
@ -735,7 +735,8 @@ export class Config {
|
||||||
contractsPlugins.forEach((plugin: Plugin) => {
|
contractsPlugins.forEach((plugin: Plugin) => {
|
||||||
plugin.contractsFiles.forEach(file => {
|
plugin.contractsFiles.forEach(file => {
|
||||||
const filename = file.replace('./', '');
|
const filename = file.replace('./', '');
|
||||||
self.contractsFiles.push(new File({ path: filename, originalPath: path.join(plugin.pluginPath, filename), pluginPath: plugin.pluginPath, type: Types.custom, storageConfig,
|
self.contractsFiles.push(new File({
|
||||||
|
path: filename, originalPath: path.join(plugin.pluginPath, filename), pluginPath: plugin.pluginPath, type: Types.custom, storageConfig,
|
||||||
resolver(callback) {
|
resolver(callback) {
|
||||||
callback(plugin.loadPluginFile(file));
|
callback(plugin.loadPluginFile(file));
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,13 +78,13 @@ export class Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_options, callback) {
|
init(_options, callback) {
|
||||||
callback = callback || function() {};
|
callback = callback || function () { };
|
||||||
|
|
||||||
const options = _options || {};
|
const options = _options || {};
|
||||||
this.events = options.events || this.events || new Events();
|
this.events = options.events || this.events || new Events();
|
||||||
this.logger = options.logger || new Logger({context: this.context, logLevel: options.logLevel || this.logLevel || 'info', events: this.events, logFile: this.logFile});
|
this.logger = options.logger || new Logger({ context: this.context, logLevel: options.logLevel || this.logLevel || 'info', events: this.events, logFile: this.logFile });
|
||||||
this.config = new Config({env: this.env, logger: this.logger, events: this.events, context: this.context, webServerConfig: this.webServerConfig, version: this.version, package: this.package});
|
this.config = new Config({ env: this.env, logger: this.logger, events: this.events, context: this.context, webServerConfig: this.webServerConfig, version: this.version, package: this.package });
|
||||||
this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs});
|
this.config.loadConfigFiles({ embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs });
|
||||||
this.plugins = this.config.plugins;
|
this.plugins = this.config.plugins;
|
||||||
this.isDev = this.config && this.config.blockchainConfig && (this.config.blockchainConfig.isDev || this.config.blockchainConfig.default);
|
this.isDev = this.config && this.config.blockchainConfig && (this.config.blockchainConfig.isDev || this.config.blockchainConfig.default);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ export class Engine {
|
||||||
interceptLogs(console, this.logger);
|
interceptLogs(console, this.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ipc = new IPC({logger: this.logger, ipcRole: this.ipcRole});
|
this.ipc = new IPC({ logger: this.logger, ipcRole: this.ipcRole });
|
||||||
if (this.ipc.isClient()) {
|
if (this.ipc.isClient()) {
|
||||||
return this.ipc.connect((_err) => {
|
return this.ipc.connect((_err) => {
|
||||||
callback();
|
callback();
|
||||||
|
@ -105,6 +105,13 @@ export class Engine {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadDappPlugins() {
|
||||||
|
if (this.config) {
|
||||||
|
this.config.plugins.loadPlugins();
|
||||||
|
this.config.reloadConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
startEngine(cb) {
|
startEngine(cb) {
|
||||||
if (this.plugins) {
|
if (this.plugins) {
|
||||||
this.plugins.emitAndRunActionsForEvent("embark:engine:started", {}, (err) => {
|
this.plugins.emitAndRunActionsForEvent("embark:engine:started", {}, (err) => {
|
||||||
|
@ -189,26 +196,26 @@ export class Engine {
|
||||||
plugins: this.plugins
|
plugins: this.plugins
|
||||||
});
|
});
|
||||||
|
|
||||||
this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger, plugins: this.plugins});
|
this.servicesMonitor = new ServicesMonitor({ events: this.events, logger: this.logger, plugins: this.plugins });
|
||||||
|
|
||||||
if (this.servicesMonitor) {
|
if (this.servicesMonitor) {
|
||||||
this.servicesMonitor.addCheck('Embark', (cb) => {
|
this.servicesMonitor.addCheck('Embark', (cb) => {
|
||||||
return cb({name: 'Embark ' + this.version, status: 'on'});
|
return cb({ name: 'Embark ' + this.version, status: 'on' });
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
if (this.plugins) {
|
if (this.plugins) {
|
||||||
const plugin = this.plugins.createPlugin('coreservicesplugin', {});
|
const plugin = this.plugins.createPlugin('coreservicesplugin', {});
|
||||||
plugin.registerActionForEvent("embark:engine:started", (_params, cb) => {
|
plugin.registerActionForEvent("embark:engine:started", undefined, (_params, cb) => {
|
||||||
this.servicesMonitor && this.servicesMonitor.startMonitor();
|
this.servicesMonitor && this.servicesMonitor.startMonitor();
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.registerModulePackage('embark-code-runner', {ipc: this.ipc});
|
this.registerModulePackage('embark-code-runner', { ipc: this.ipc });
|
||||||
|
|
||||||
// TODO: we shouldn't need useDashboard
|
// TODO: we shouldn't need useDashboard
|
||||||
this.registerModulePackage('embark-library-manager', {useDashboard: this.useDashboard});
|
this.registerModulePackage('embark-library-manager', { useDashboard: this.useDashboard });
|
||||||
}
|
}
|
||||||
|
|
||||||
consoleComponents() {
|
consoleComponents() {
|
||||||
|
@ -233,18 +240,18 @@ export class Engine {
|
||||||
stackComponents(options) {
|
stackComponents(options) {
|
||||||
this.registerModulePackage('embark-pipeline', { plugins: this.plugins });
|
this.registerModulePackage('embark-pipeline', { plugins: this.plugins });
|
||||||
this.registerModulePackage('embark-blockchain', { plugins: this.plugins });
|
this.registerModulePackage('embark-blockchain', { plugins: this.plugins });
|
||||||
this.registerModulePackage('embark-proxy', {plugins: this.plugins});
|
this.registerModulePackage('embark-proxy', { plugins: this.plugins });
|
||||||
// TODO: coverage param should be part of the request compilation command, not an option here
|
// TODO: coverage param should be part of the request compilation command, not an option here
|
||||||
// some other params in the options might not longer be relevant, in fact we probably don't need options anymore
|
// some other params in the options might not longer be relevant, in fact we probably don't need options anymore
|
||||||
this.registerModulePackage('embark-compiler', {plugins: this.plugins, isCoverage: options.isCoverage});
|
this.registerModulePackage('embark-compiler', { plugins: this.plugins, isCoverage: options.isCoverage });
|
||||||
this.registerModulePackage('embark-contracts-manager', {plugins: this.plugins, compileOnceOnly: options.compileOnceOnly});
|
this.registerModulePackage('embark-contracts-manager', { plugins: this.plugins, compileOnceOnly: options.compileOnceOnly });
|
||||||
this.registerModulePackage('embark-deployment', {plugins: this.plugins, onlyCompile: options.onlyCompile});
|
this.registerModulePackage('embark-deployment', { plugins: this.plugins, onlyCompile: options.onlyCompile });
|
||||||
this.registerModulePackage('embark-blockchain-client');
|
this.registerModulePackage('embark-blockchain-client');
|
||||||
this.registerModulePackage('embark-storage');
|
this.registerModulePackage('embark-storage');
|
||||||
this.registerModulePackage('embark-communication');
|
this.registerModulePackage('embark-communication');
|
||||||
this.registerModulePackage('embark-namesystem');
|
this.registerModulePackage('embark-namesystem');
|
||||||
this.registerModulePackage('embark-process-logs-api-manager');
|
this.registerModulePackage('embark-process-logs-api-manager');
|
||||||
this.registerModulePackage('embark-embarkjs', {plugins: this.plugins});
|
this.registerModulePackage('embark-embarkjs', { plugins: this.plugins });
|
||||||
}
|
}
|
||||||
|
|
||||||
blockchainComponents() {
|
blockchainComponents() {
|
||||||
|
@ -266,15 +273,15 @@ export class Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
testComponents(options) {
|
testComponents(options) {
|
||||||
this.registerModulePackage('embark-test-runner', {plugins: this.plugins});
|
this.registerModulePackage('embark-test-runner', { plugins: this.plugins });
|
||||||
this.registerModulePackage('embark-coverage', {plugins: this.plugins, coverage: options.coverage});
|
this.registerModulePackage('embark-coverage', { plugins: this.plugins, coverage: options.coverage });
|
||||||
this.registerModulePackage('embark-solidity-tests', {plugins: this.plugins, coverage: options.coverage});
|
this.registerModulePackage('embark-solidity-tests', { plugins: this.plugins, coverage: options.coverage });
|
||||||
this.registerModulePackage('embark-mocha-tests', {plugins: this.plugins, coverage: options.coverage});
|
this.registerModulePackage('embark-mocha-tests', { plugins: this.plugins, coverage: options.coverage });
|
||||||
}
|
}
|
||||||
|
|
||||||
compilerComponents(_options) {
|
compilerComponents(_options) {
|
||||||
// TODO: should be moved (they are plugins)
|
// TODO: should be moved (they are plugins)
|
||||||
this.registerModulePackage('embark-solidity', {ipc: this.ipc, useDashboard: this.useDashboard});
|
this.registerModulePackage('embark-solidity', { ipc: this.ipc, useDashboard: this.useDashboard });
|
||||||
this.registerModulePackage('embark-vyper');
|
this.registerModulePackage('embark-vyper');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +290,8 @@ export class Engine {
|
||||||
this.registerModulePackage('embark-ethereum-blockchain-client');
|
this.registerModulePackage('embark-ethereum-blockchain-client');
|
||||||
this.registerModulePackage('embark-web3');
|
this.registerModulePackage('embark-web3');
|
||||||
this.registerModulePackage('embark-accounts-manager');
|
this.registerModulePackage('embark-accounts-manager');
|
||||||
this.registerModulePackage('embark-specialconfigs', {plugins: this.plugins});
|
this.registerModulePackage('embark-rpc-manager');
|
||||||
|
this.registerModulePackage('embark-specialconfigs', { plugins: this.plugins });
|
||||||
this.registerModulePackage('embark-transaction-logger');
|
this.registerModulePackage('embark-transaction-logger');
|
||||||
this.registerModulePackage('embark-transaction-tracker');
|
this.registerModulePackage('embark-transaction-tracker');
|
||||||
this.registerModulePackage('embark-profiler');
|
this.registerModulePackage('embark-profiler');
|
||||||
|
@ -303,10 +311,10 @@ export class Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
cockpitModules() {
|
cockpitModules() {
|
||||||
this.registerModulePackage('embark-authenticator', {singleUseAuthToken: this.singleUseAuthToken});
|
this.registerModulePackage('embark-authenticator', { singleUseAuthToken: this.singleUseAuthToken });
|
||||||
this.registerModulePackage('embark-api', {plugins: this.plugins});
|
this.registerModulePackage('embark-api', { plugins: this.plugins });
|
||||||
// Register logs for the cockpit console
|
// Register logs for the cockpit console
|
||||||
this.events.request('process:logs:register', {processName: EMBARK_PROCESS_NAME, eventName: "log", silent: false, alwaysAlreadyLogged: true});
|
this.events.request('process:logs:register', { processName: EMBARK_PROCESS_NAME, eventName: "log", silent: false, alwaysAlreadyLogged: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,23 +322,23 @@ function interceptLogs(consoleContext, logger) {
|
||||||
const context: any = {};
|
const context: any = {};
|
||||||
context.console = consoleContext;
|
context.console = consoleContext;
|
||||||
|
|
||||||
context.console.log = function() {
|
context.console.log = function () {
|
||||||
logger.info(normalizeInput(arguments));
|
logger.info(normalizeInput(arguments));
|
||||||
};
|
};
|
||||||
context.console.warn = function() {
|
context.console.warn = function () {
|
||||||
logger.warn(normalizeInput(arguments));
|
logger.warn(normalizeInput(arguments));
|
||||||
};
|
};
|
||||||
context.console.info = function() {
|
context.console.info = function () {
|
||||||
logger.info(normalizeInput(arguments));
|
logger.info(normalizeInput(arguments));
|
||||||
};
|
};
|
||||||
context.console.debug = function() {
|
context.console.debug = function () {
|
||||||
// TODO: ue JSON.stringify
|
// TODO: ue JSON.stringify
|
||||||
logger.debug(normalizeInput(arguments));
|
logger.debug(normalizeInput(arguments));
|
||||||
};
|
};
|
||||||
context.console.trace = function() {
|
context.console.trace = function () {
|
||||||
logger.trace(normalizeInput(arguments));
|
logger.trace(normalizeInput(arguments));
|
||||||
};
|
};
|
||||||
context.console.dir = function() {
|
context.console.dir = function () {
|
||||||
logger.dir(normalizeInput(arguments));
|
logger.dir(normalizeInput(arguments));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,10 @@ export class Plugin {
|
||||||
if (!Array.isArray(this.acceptedContext)) {
|
if (!Array.isArray(this.acceptedContext)) {
|
||||||
this.acceptedContext = [this.acceptedContext];
|
this.acceptedContext = [this.acceptedContext];
|
||||||
}
|
}
|
||||||
|
this.registerActionForEvent("tests:config:updated", { priority: 30 }, async ({ accounts }, cb) => {
|
||||||
|
this.config.blockchainConfig.accounts = accounts;
|
||||||
|
cb(null, null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_log(type) {
|
_log(type) {
|
||||||
|
@ -158,7 +162,7 @@ export class Plugin {
|
||||||
|
|
||||||
loadPlugin() {
|
loadPlugin() {
|
||||||
if (!this.isContextValid()) {
|
if (!this.isContextValid()) {
|
||||||
this.logger.warn(__('Plugin {{name}} can only be loaded in the context of "{{contexts}}"', {name: this.name, contexts: this.acceptedContext.join(', ')}));
|
this.logger.warn(__('Plugin {{name}} can only be loaded in the context of "{{contexts}}"', { name: this.name, contexts: this.acceptedContext.join(', ') }));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
|
@ -217,12 +221,12 @@ export class Plugin {
|
||||||
|
|
||||||
registerPipeline(matcthingFiles, cb) {
|
registerPipeline(matcthingFiles, cb) {
|
||||||
// TODO: generate error for more than one pipeline per plugin
|
// TODO: generate error for more than one pipeline per plugin
|
||||||
this.pipeline.push({matcthingFiles, cb});
|
this.pipeline.push({ matcthingFiles, cb });
|
||||||
this.addPluginType('pipeline');
|
this.addPluginType('pipeline');
|
||||||
}
|
}
|
||||||
|
|
||||||
registerDappGenerator(framework, cb) {
|
registerDappGenerator(framework, cb) {
|
||||||
this.dappGenerators.push({framework, cb});
|
this.dappGenerators.push({ framework, cb });
|
||||||
this.pluginTypes.push('dappGenerator');
|
this.pluginTypes.push('dappGenerator');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +235,7 @@ export class Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
addFileToPipeline(file, intendedPath, options) {
|
addFileToPipeline(file, intendedPath, options) {
|
||||||
this.pipelineFiles.push({file, intendedPath, options});
|
this.pipelineFiles.push({ file, intendedPath, options });
|
||||||
this.addPluginType('pipelineFiles');
|
this.addPluginType('pipelineFiles');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +258,7 @@ export class Plugin {
|
||||||
|
|
||||||
// TODO: this only works for services done on startup
|
// TODO: this only works for services done on startup
|
||||||
registerServiceCheck(checkName, checkFn, time) {
|
registerServiceCheck(checkName, checkFn, time) {
|
||||||
this.serviceChecks.push({checkName, checkFn, time});
|
this.serviceChecks.push({ checkName, checkFn, time });
|
||||||
this.addPluginType('serviceChecks');
|
this.addPluginType('serviceChecks');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,13 +272,13 @@ export class Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
generateProvider(args) {
|
generateProvider(args) {
|
||||||
return this.clientWeb3Providers.map(function(cb) {
|
return this.clientWeb3Providers.map(function (cb) {
|
||||||
return cb.call(this, args);
|
return cb.call(this, args);
|
||||||
}).join("\n");
|
}).join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
generateContracts(args) {
|
generateContracts(args) {
|
||||||
return this.contractsGenerators.map(function(cb) {
|
return this.contractsGenerators.map(function (cb) {
|
||||||
return cb.call(this, args);
|
return cb.call(this, args);
|
||||||
}).join("\n");
|
}).join("\n");
|
||||||
}
|
}
|
||||||
|
@ -285,12 +289,12 @@ export class Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
registerCompiler(extension, cb) {
|
registerCompiler(extension, cb) {
|
||||||
this.compilers.push({extension, cb});
|
this.compilers.push({ extension, cb });
|
||||||
this.addPluginType('compilers');
|
this.addPluginType('compilers');
|
||||||
}
|
}
|
||||||
|
|
||||||
registerUploadCommand(cmd, cb) {
|
registerUploadCommand(cmd, cb) {
|
||||||
this.uploadCmds.push({cmd, cb});
|
this.uploadCmds.push({ cmd, cb });
|
||||||
this.addPluginType('uploadCmds');
|
this.addPluginType('uploadCmds');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,14 +339,14 @@ export class Plugin {
|
||||||
if (!this.eventActions[eventName]) {
|
if (!this.eventActions[eventName]) {
|
||||||
this.eventActions[eventName] = [];
|
this.eventActions[eventName] = [];
|
||||||
}
|
}
|
||||||
this.eventActions[eventName].push({action: cb, options: Object.assign({priority: DEFAULT_ACTION_PRIORITY}, options)});
|
this.eventActions[eventName].push({ action: cb, options: Object.assign({ priority: DEFAULT_ACTION_PRIORITY }, options) });
|
||||||
this.addPluginType('eventActions');
|
this.addPluginType('eventActions');
|
||||||
}
|
}
|
||||||
|
|
||||||
registerAPICall(method, endpoint, cb) {
|
registerAPICall(method, endpoint, cb) {
|
||||||
this.apiCalls.push({method, endpoint, cb});
|
this.apiCalls.push({ method, endpoint, cb });
|
||||||
this.addPluginType('apiCalls');
|
this.addPluginType('apiCalls');
|
||||||
this.events.emit('plugins:register:api', {method, endpoint, cb});
|
this.events.emit('plugins:register:api', { method, endpoint, cb });
|
||||||
}
|
}
|
||||||
|
|
||||||
runFilePipeline() {
|
runFilePipeline() {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import './src/omg-js-util';
|
||||||
import './src/prettier-plugin-solidity';
|
import './src/prettier-plugin-solidity';
|
||||||
import './src/remix-debug-debugtest';
|
import './src/remix-debug-debugtest';
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
declare module '@omisego/omg-js-util';
|
|
@ -12,6 +12,9 @@ const ERROR_ACCOUNT = 'ERROR_ACCOUNT';
|
||||||
export default class AccountParser {
|
export default class AccountParser {
|
||||||
static parseAccountsConfig(accountsConfig, web3, dappPath, logger, nodeAccounts) {
|
static parseAccountsConfig(accountsConfig, web3, dappPath, logger, nodeAccounts) {
|
||||||
let accounts = [];
|
let accounts = [];
|
||||||
|
if (!(accountsConfig && accountsConfig.length)) {
|
||||||
|
return nodeAccounts;
|
||||||
|
}
|
||||||
if (accountsConfig && accountsConfig.length) {
|
if (accountsConfig && accountsConfig.length) {
|
||||||
accountsConfig.forEach(accountConfig => {
|
accountsConfig.forEach(accountConfig => {
|
||||||
let account = AccountParser.getAccount(accountConfig, web3, dappPath, logger, nodeAccounts);
|
let account = AccountParser.getAccount(accountConfig, web3, dappPath, logger, nodeAccounts);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { dappPath, embarkPath, joinPath, setUpEnv } from 'embark-utils';
|
||||||
import { Logger } from 'embark-logger';
|
import { Logger } from 'embark-logger';
|
||||||
let async = require('async');
|
let async = require('async');
|
||||||
const constants = require('embark-core/constants');
|
const constants = require('embark-core/constants');
|
||||||
const {reset: embarkReset, paths: defaultResetPaths} = require('embark-reset');
|
const { reset: embarkReset, paths: defaultResetPaths } = require('embark-reset');
|
||||||
const cloneDeep = require('clone-deep');
|
const cloneDeep = require('clone-deep');
|
||||||
|
|
||||||
setUpEnv(joinPath(__dirname, '../../'));
|
setUpEnv(joinPath(__dirname, '../../'));
|
||||||
|
@ -26,10 +26,10 @@ class EmbarkController {
|
||||||
|
|
||||||
initConfig(env, options) {
|
initConfig(env, options) {
|
||||||
this.events = new Events();
|
this.events = new Events();
|
||||||
this.logger = new Logger({logLevel: Logger.logLevels.debug, events: this.events, context: this.context});
|
this.logger = new Logger({ logLevel: Logger.logLevels.debug, events: this.events, context: this.context });
|
||||||
|
|
||||||
this.logger.info('foo');
|
this.logger.info('foo');
|
||||||
this.config = new Config({env: env, logger: this.logger, events: this.events, context: this.context, version: this.version});
|
this.config = new Config({ env: env, logger: this.logger, events: this.events, context: this.context, version: this.version });
|
||||||
this.config.loadConfigFiles(options);
|
this.config.loadConfigFiles(options);
|
||||||
this.plugins = this.config.plugins;
|
this.plugins = this.config.plugins;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ class EmbarkController {
|
||||||
|
|
||||||
engine.startEngine(async () => {
|
engine.startEngine(async () => {
|
||||||
try {
|
try {
|
||||||
const alreadyStarted = await engine.events.request2("blockchain:node:start", Object.assign(engine.config.blockchainConfig, {isStandalone: true}));
|
const alreadyStarted = await engine.events.request2("blockchain:node:start", Object.assign(engine.config.blockchainConfig, { isStandalone: true }));
|
||||||
if (alreadyStarted) {
|
if (alreadyStarted) {
|
||||||
engine.logger.warn(__('Blockchain process already started. No need to run `embark blockchain`'));
|
engine.logger.warn(__('Blockchain process already started. No need to run `embark blockchain`'));
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
@ -147,10 +147,6 @@ class EmbarkController {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function (callback) {
|
function (callback) {
|
||||||
const pluginList = engine.plugins.listPlugins();
|
|
||||||
if (pluginList.length > 0) {
|
|
||||||
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
|
||||||
}
|
|
||||||
|
|
||||||
engine.registerModuleGroup("coreComponents");
|
engine.registerModuleGroup("coreComponents");
|
||||||
engine.registerModuleGroup("stackComponents");
|
engine.registerModuleGroup("stackComponents");
|
||||||
|
@ -167,7 +163,14 @@ class EmbarkController {
|
||||||
engine.registerModuleGroup("filewatcher");
|
engine.registerModuleGroup("filewatcher");
|
||||||
engine.registerModuleGroup("storage");
|
engine.registerModuleGroup("storage");
|
||||||
engine.registerModuleGroup("cockpit");
|
engine.registerModuleGroup("cockpit");
|
||||||
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins});
|
engine.registerModulePackage('embark-deploy-tracker', { plugins: engine.plugins });
|
||||||
|
|
||||||
|
// load custom plugins
|
||||||
|
engine.loadDappPlugins();
|
||||||
|
let pluginList = engine.plugins.listPlugins();
|
||||||
|
if (pluginList.length > 0) {
|
||||||
|
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
||||||
|
}
|
||||||
|
|
||||||
const plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {});
|
const plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {});
|
||||||
plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => {
|
plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => {
|
||||||
|
@ -274,7 +277,7 @@ class EmbarkController {
|
||||||
engine.registerModuleGroup("pipeline");
|
engine.registerModuleGroup("pipeline");
|
||||||
engine.registerModuleGroup("communication");
|
engine.registerModuleGroup("communication");
|
||||||
engine.registerModuleGroup("namesystem");
|
engine.registerModuleGroup("namesystem");
|
||||||
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins});
|
engine.registerModulePackage('embark-deploy-tracker', { plugins: engine.plugins });
|
||||||
|
|
||||||
engine.registerModuleGroup("blockchain");
|
engine.registerModuleGroup("blockchain");
|
||||||
|
|
||||||
|
@ -353,7 +356,7 @@ class EmbarkController {
|
||||||
package: pkg
|
package: pkg
|
||||||
});
|
});
|
||||||
|
|
||||||
const isSecondaryProcess = (engine) => {return engine.ipc.connected && engine.ipc.isClient();};
|
const isSecondaryProcess = (engine) => { return engine.ipc.connected && engine.ipc.isClient(); };
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
callback => {
|
callback => {
|
||||||
|
@ -382,7 +385,7 @@ class EmbarkController {
|
||||||
if (!isSecondaryProcess(engine)) {
|
if (!isSecondaryProcess(engine)) {
|
||||||
engine.registerModuleGroup("cockpit");
|
engine.registerModuleGroup("cockpit");
|
||||||
}
|
}
|
||||||
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins});
|
engine.registerModulePackage('embark-deploy-tracker', { plugins: engine.plugins });
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
|
@ -525,7 +528,7 @@ class EmbarkController {
|
||||||
return path.charAt(path.length - 1) === '/' ? path.substr(0, path.length - 1) : path;
|
return path.charAt(path.length - 1) === '/' ? path.substr(0, path.length - 1) : path;
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
await embarkReset({removePaths});
|
await embarkReset({ removePaths });
|
||||||
}
|
}
|
||||||
|
|
||||||
ejectWebpack() {
|
ejectWebpack() {
|
||||||
|
@ -587,7 +590,7 @@ class EmbarkController {
|
||||||
engine.startService("web3");
|
engine.startService("web3");
|
||||||
engine.startService("processManager");
|
engine.startService("processManager");
|
||||||
engine.startService("codeRunner");
|
engine.startService("codeRunner");
|
||||||
engine.startService("deployment", {onlyCompile: true});
|
engine.startService("deployment", { onlyCompile: true });
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
|
@ -607,7 +610,7 @@ class EmbarkController {
|
||||||
engine.logger.error(err.message || err);
|
engine.logger.error(err.message || err);
|
||||||
}
|
}
|
||||||
engine.logger.info(__("finished generating the UI").underline);
|
engine.logger.info(__("finished generating the UI").underline);
|
||||||
engine.logger.info(__("To see the result, execute {{cmd}} and go to /{{contract}}.html", {cmd: 'embark run'.underline, contract: options.contract}));
|
engine.logger.info(__("To see the result, execute {{cmd}} and go to /{{contract}}.html", { cmd: 'embark run'.underline, contract: options.contract }));
|
||||||
|
|
||||||
process.exit(err ? 1 : 0);
|
process.exit(err ? 1 : 0);
|
||||||
});
|
});
|
||||||
|
@ -668,7 +671,7 @@ class EmbarkController {
|
||||||
engine.registerModuleGroup("webserver");
|
engine.registerModuleGroup("webserver");
|
||||||
engine.registerModuleGroup("filewatcher");
|
engine.registerModuleGroup("filewatcher");
|
||||||
engine.registerModuleGroup("storage");
|
engine.registerModuleGroup("storage");
|
||||||
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins});
|
engine.registerModulePackage('embark-deploy-tracker', { plugins: engine.plugins });
|
||||||
|
|
||||||
const plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {});
|
const plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {});
|
||||||
plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => {
|
plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => {
|
||||||
|
@ -733,12 +736,7 @@ class EmbarkController {
|
||||||
function initEngine(next) {
|
function initEngine(next) {
|
||||||
engine.init({}, next);
|
engine.init({}, next);
|
||||||
},
|
},
|
||||||
function loadPlugins(next) {
|
function loadModules(next) {
|
||||||
let pluginList = engine.plugins.listPlugins();
|
|
||||||
if (pluginList.length > 0) {
|
|
||||||
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
|
||||||
}
|
|
||||||
|
|
||||||
engine.registerModuleGroup("coreComponents");
|
engine.registerModuleGroup("coreComponents");
|
||||||
engine.registerModuleGroup("stackComponents");
|
engine.registerModuleGroup("stackComponents");
|
||||||
|
|
||||||
|
@ -747,11 +745,23 @@ class EmbarkController {
|
||||||
engine.registerModuleGroup("contracts");
|
engine.registerModuleGroup("contracts");
|
||||||
engine.registerModuleGroup("pipeline");
|
engine.registerModuleGroup("pipeline");
|
||||||
engine.registerModuleGroup("tests", options);
|
engine.registerModuleGroup("tests", options);
|
||||||
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins, trackContracts: false});
|
engine.registerModulePackage('embark-deploy-tracker', { plugins: engine.plugins, trackContracts: false });
|
||||||
engine.registerModuleGroup("namesystem");
|
engine.registerModuleGroup("namesystem");
|
||||||
engine.registerModuleGroup("storage");
|
engine.registerModuleGroup("storage");
|
||||||
engine.registerModuleGroup("communication");
|
engine.registerModuleGroup("communication");
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
function loadDappPlugins(next) {
|
||||||
|
// load custom plugins
|
||||||
|
engine.loadDappPlugins();
|
||||||
|
|
||||||
|
let pluginList = engine.plugins.listPlugins();
|
||||||
|
if (pluginList.length > 0) {
|
||||||
|
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
function startEngine(next) {
|
||||||
engine.startEngine(next);
|
engine.startEngine(next);
|
||||||
},
|
},
|
||||||
function startNodes(next) {
|
function startNodes(next) {
|
||||||
|
@ -767,7 +777,7 @@ class EmbarkController {
|
||||||
engine.events.request2('tests:run', options, next);
|
engine.events.request2('tests:run', options, next);
|
||||||
}
|
}
|
||||||
], (err, passes, fails) => {
|
], (err, passes, fails) => {
|
||||||
if(err) {
|
if (err) {
|
||||||
engine.logger.error(`Error occurred while running tests: ${err.message || err}`);
|
engine.logger.error(`Error occurred while running tests: ${err.message || err}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,7 +819,7 @@ async function setupCargoAndWatcher(engine) {
|
||||||
});
|
});
|
||||||
|
|
||||||
let fileTimeout;
|
let fileTimeout;
|
||||||
engine.events.on('file-event', ({fileType, _path}) => {
|
engine.events.on('file-event', ({ fileType, _path }) => {
|
||||||
clearTimeout(fileTimeout);
|
clearTimeout(fileTimeout);
|
||||||
// Throttle file changes so we re-write only once for all files
|
// Throttle file changes so we re-write only once for all files
|
||||||
fileTimeout = setTimeout(async () => {
|
fileTimeout = setTimeout(async () => {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Web3 from "web3";
|
||||||
|
|
||||||
const TARGET = 0x7FFFFFFFFFFFFFFF;
|
const TARGET = 0x7FFFFFFFFFFFFFFF;
|
||||||
|
|
||||||
export default async function fundAccount(web3: Web3, accountAddress: string, coinbaseAddress: string, hexBalance: string | number | undefined) {
|
export default async function fundAccount(web3: Web3, accountAddress: string, coinbaseAddress: string, hexBalance?: string | number) {
|
||||||
if (!hexBalance) {
|
if (!hexBalance) {
|
||||||
hexBalance = TARGET;
|
hexBalance = TARGET;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,66 +1,36 @@
|
||||||
import async from "async";
|
import async from "async";
|
||||||
import { Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
import { Callback, Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
import { __ } from "embark-i18n";
|
import { __ } from "embark-i18n";
|
||||||
import { AccountParser, dappPath } from "embark-utils";
|
import { AccountParser, dappPath } from "embark-utils";
|
||||||
import { Logger } from 'embark-logger';
|
import { Logger } from 'embark-logger';
|
||||||
import Web3 from "web3";
|
import Web3 from "web3";
|
||||||
const { blockchain: blockchainConstants } = require("embark-core/constants");
|
|
||||||
|
|
||||||
import fundAccount from "./fundAccount";
|
import fundAccount from "./fundAccount";
|
||||||
|
|
||||||
function arrayEqual(arrayA: string[], arrayB: string[]) {
|
|
||||||
if (arrayA.length !== arrayB.length) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return arrayA.every((address, index) => Web3.utils.toChecksumAddress(address) === Web3.utils.toChecksumAddress(arrayB[index]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class AccountsManager {
|
export default class AccountsManager {
|
||||||
private readonly logger: Logger;
|
private readonly logger: Logger;
|
||||||
private readonly events: Events;
|
private readonly events: Events;
|
||||||
private accounts: any[] = [];
|
|
||||||
private nodeAccounts: string[] = [];
|
|
||||||
private _web3: Web3 | null = null;
|
private _web3: Web3 | null = null;
|
||||||
private ready = false;
|
private _accounts: any[] | null = null;
|
||||||
private signTransactionQueue: any;
|
|
||||||
private nonceCache: any = {};
|
|
||||||
|
|
||||||
constructor(private readonly embark: Embark, _options: any) {
|
constructor(private readonly embark: Embark, _options: any) {
|
||||||
this.logger = embark.logger;
|
this.logger = embark.logger;
|
||||||
this.events = embark.events;
|
this.events = embark.events;
|
||||||
|
|
||||||
this.embark.registerActionForEvent("blockchain:proxy:request", this.checkBlockchainRequest.bind(this));
|
this.parseAndFundAccounts();
|
||||||
this.embark.registerActionForEvent("blockchain:proxy:response", this.checkBlockchainResponse.bind(this));
|
|
||||||
|
|
||||||
this.events.on("blockchain:started", () => {
|
this.events.on("blockchain:started", () => {
|
||||||
this._web3 = null;
|
this._web3 = null;
|
||||||
this.parseAndFundAccounts(null);
|
|
||||||
});
|
|
||||||
this.embark.registerActionForEvent("accounts:reseted", async (params, cb) => {
|
|
||||||
this.ready = false;
|
|
||||||
await this.parseAndFundAccounts(params.accounts);
|
|
||||||
cb(null, null);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Allow to run transaction in parallel by resolving the nonce manually.
|
this.embark.registerActionForEvent("tests:config:updated", undefined, async (params, cb) => {
|
||||||
// For each transaction, resolve the nonce by taking the max of current transaction count and the cache we keep locally.
|
// reset accounts backing variable as the accounts in config may have changed and
|
||||||
// Update the nonce and sign it
|
// web.eth.getAccounts may return a different value now
|
||||||
this.signTransactionQueue = async.queue(({ payload, account }, callback: (error: any, result: any) => void) => {
|
this._accounts = null;
|
||||||
this.getNonce(payload.from, async (err: any, newNonce: number) => {
|
|
||||||
if (err) {
|
// as the accounts may have changed, we need to fund the accounts again
|
||||||
return callback(err, null);
|
await this.parseAndFundAccounts();
|
||||||
}
|
cb(null, null);
|
||||||
payload.nonce = newNonce;
|
|
||||||
const web3 = await this.web3;
|
|
||||||
web3.eth.accounts.signTransaction(payload, account.privateKey, (signingError: any, result: any) => {
|
|
||||||
if (signingError) {
|
|
||||||
return callback(signingError, null);
|
|
||||||
}
|
|
||||||
callback(null, result.rawTransaction);
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get web3() {
|
get web3() {
|
||||||
|
@ -73,86 +43,35 @@ export default class AccountsManager {
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getNonce(address: string, callback: (error: any, result: any) => void) {
|
get accounts() {
|
||||||
|
return (async () => {
|
||||||
|
if (!this._accounts) {
|
||||||
const web3 = await this.web3;
|
const web3 = await this.web3;
|
||||||
web3.eth.getTransactionCount(address, undefined, (error: any, transactionCount: number) => {
|
this._accounts = await web3.eth.getAccounts();
|
||||||
if (error) {
|
|
||||||
return callback(error, null);
|
|
||||||
}
|
}
|
||||||
if (this.nonceCache[address] === undefined) {
|
return this._accounts || [];
|
||||||
this.nonceCache[address] = -1;
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transactionCount > this.nonceCache[address]) {
|
private async parseAndFundAccounts() {
|
||||||
this.nonceCache[address] = transactionCount;
|
|
||||||
return callback(null, this.nonceCache[address]);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.nonceCache[address]++;
|
|
||||||
callback(null, this.nonceCache[address]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkBlockchainRequest(params: any, callback: (error: any, result: any) => void) {
|
|
||||||
if (!this.ready) {
|
|
||||||
return callback(null, params);
|
|
||||||
}
|
|
||||||
if (params.reqData.method === blockchainConstants.transactionMethods.eth_sendTransaction && this.accounts.length) {
|
|
||||||
// Check if we have that account in our wallet
|
|
||||||
const account = this.accounts.find((acc) => Web3.utils.toChecksumAddress(acc.address) === Web3.utils.toChecksumAddress(params.reqData.params[0].from));
|
|
||||||
if (account && account.privateKey) {
|
|
||||||
return this.signTransactionQueue.push({ payload: params.reqData.params[0], account }, (err: any, newPayload: any) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err, null);
|
|
||||||
}
|
|
||||||
params.reqData.method = blockchainConstants.transactionMethods.eth_sendRawTransaction;
|
|
||||||
params.reqData.params = [newPayload];
|
|
||||||
callback(err, params);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(null, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkBlockchainResponse(params: any, callback: (error: any, result: any) => void) {
|
|
||||||
if (!this.ready) {
|
|
||||||
return callback(null, params);
|
|
||||||
}
|
|
||||||
if ((params.reqData.method === blockchainConstants.transactionMethods.eth_accounts ||
|
|
||||||
params.reqData.method === blockchainConstants.transactionMethods.personal_listAccounts) && this.accounts.length) {
|
|
||||||
if (!arrayEqual(params.respData.result, this.nodeAccounts)) {
|
|
||||||
this.nodeAccounts = params.respData.result;
|
|
||||||
const web3 = await this.web3;
|
const web3 = await this.web3;
|
||||||
this.accounts = AccountParser.parseAccountsConfig(this.embark.config.blockchainConfig.accounts, web3, dappPath(), this.logger, this.nodeAccounts);
|
const accounts = await this.accounts;
|
||||||
}
|
|
||||||
params.respData.result = this.accounts.map((acc) => {
|
|
||||||
if (acc.address) {
|
|
||||||
return acc.address;
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
});
|
|
||||||
return callback(null, params);
|
|
||||||
}
|
|
||||||
callback(null, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async parseAndFundAccounts(accounts: any[] | null) {
|
if (!accounts.length || !this.embark.config.blockchainConfig.isDev) {
|
||||||
const web3 = await this.web3;
|
|
||||||
|
|
||||||
const nodeAccounts = await web3.eth.getAccounts();
|
|
||||||
this.nodeAccounts = nodeAccounts;
|
|
||||||
this.accounts = AccountParser.parseAccountsConfig(accounts || this.embark.config.blockchainConfig.accounts, web3, dappPath(), this.logger, nodeAccounts);
|
|
||||||
|
|
||||||
if (!this.accounts.length || !this.embark.config.blockchainConfig.isDev) {
|
|
||||||
this.ready = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const coinbase = await web3.eth.getCoinbase();
|
const coinbase = await web3.eth.getCoinbase();
|
||||||
const accts = this.accounts
|
const acctsFromConfig = AccountParser.parseAccountsConfig(this.embark.config.blockchainConfig.accounts, web3, dappPath(), this.logger, accounts);
|
||||||
.filter((account) => account.address);
|
const accountsWithBalance = accounts.map((address) => {
|
||||||
|
const acctFromConfig = acctsFromConfig.find((acctCfg) => acctCfg.address === address);
|
||||||
|
return {
|
||||||
|
address,
|
||||||
|
hexBalance: acctFromConfig ? acctFromConfig.hexBalance : undefined
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
async.eachLimit(accts, 1, (acct, eachCb) => {
|
async.eachLimit(accountsWithBalance, 1, (acct, eachCb) => {
|
||||||
fundAccount(web3, acct.address, coinbase, acct.hexBalance)
|
fundAccount(web3, acct.address, coinbase, acct.hexBalance)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
eachCb();
|
eachCb();
|
||||||
|
@ -162,6 +81,5 @@ export default class AccountsManager {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logger.error(__("Error funding accounts"), err.message || err);
|
this.logger.error(__("Error funding accounts"), err.message || err);
|
||||||
}
|
}
|
||||||
this.ready = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ export default class Coverage {
|
||||||
this.fs.ensureDirSync(path.join(dappPath(), ".embark"));
|
this.fs.ensureDirSync(path.join(dappPath(), ".embark"));
|
||||||
const coveragePath = path.join(dappPath(), ".embark", "coverage.json");
|
const coveragePath = path.join(dappPath(), ".embark", "coverage.json");
|
||||||
|
|
||||||
const coverageReport = this.contracts.reduce((acc: {[name: string]: ICoverage}, contract) => {
|
const coverageReport = this.contracts.reduce((acc: { [name: string]: ICoverage }, contract) => {
|
||||||
if (contract.source) {
|
if (contract.source) {
|
||||||
acc[contract.filepath] = contract.coverage;
|
acc[contract.filepath] = contract.coverage;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ export default class Coverage {
|
||||||
|
|
||||||
private collectEvents(web3Contracts: Web3Contract[]) {
|
private collectEvents(web3Contracts: Web3Contract[]) {
|
||||||
return web3Contracts.map(async (web3Contract) => {
|
return web3Contracts.map(async (web3Contract) => {
|
||||||
const events = await web3Contract.getPastEvents("allEvents", {fromBlock: 0});
|
const events = await web3Contract.getPastEvents("allEvents", { fromBlock: 0 });
|
||||||
this.contracts.forEach((contract) => contract.updateCoverage(events));
|
this.contracts.forEach((contract) => contract.updateCoverage(events));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ export default class Coverage {
|
||||||
return new Promise<Web3Contract>((resolve) => {
|
return new Promise<Web3Contract>((resolve) => {
|
||||||
const address = deployedContract.deployedAddress;
|
const address = deployedContract.deployedAddress;
|
||||||
const abi = deployedContract.abiDefinition;
|
const abi = deployedContract.abiDefinition;
|
||||||
this.embark.events.request("blockchain:contract:create", {address, abi}, (web3Contract: Web3Contract) => {
|
this.embark.events.request("blockchain:contract:create", { address, abi }, (web3Contract: Web3Contract) => {
|
||||||
resolve(web3Contract);
|
resolve(web3Contract);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -107,7 +107,7 @@ export default class Coverage {
|
||||||
|
|
||||||
private getDeployedContracts() {
|
private getDeployedContracts() {
|
||||||
return new Promise<Contract[]>((resolve, reject) => {
|
return new Promise<Contract[]>((resolve, reject) => {
|
||||||
this.embark.events.request("contracts:all", (error: Error, contracts: {[name: string]: Contract}) => {
|
this.embark.events.request("contracts:all", (error: Error, contracts: { [name: string]: Contract }) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
return reject(error);
|
return reject(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
const WebSocket = require("ws");
|
const WebSocket = require("ws");
|
||||||
const http = require("http");
|
const http = require("http");
|
||||||
|
|
||||||
const LIVENESS_CHECK=`{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":42}`;
|
const LIVENESS_CHECK = `{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":42}`;
|
||||||
|
|
||||||
const parseAndRespond = (data, cb) => {
|
const parseAndRespond = (data, cb) => {
|
||||||
let resp;
|
let resp;
|
||||||
try {
|
try {
|
||||||
resp = JSON.parse(data);
|
resp = JSON.parse(data);
|
||||||
|
if (resp.error) {
|
||||||
|
return cb(resp.error);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return cb('Version data is not valid JSON');
|
return cb('Version data is not valid JSON');
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
engine-strict = true
|
||||||
|
package-lock = false
|
||||||
|
save-exact = true
|
||||||
|
scripts-prepend-node-path = true
|
|
@ -0,0 +1,9 @@
|
||||||
|
embark-rpc-manager
|
||||||
|
==========================
|
||||||
|
|
||||||
|
> Embark RPC Manager
|
||||||
|
|
||||||
|
Modifies RPC calls to/from Embark (to/from `embark-proxy`).
|
||||||
|
|
||||||
|
Visit [embark.status.im](https://embark.status.im/) to get started with
|
||||||
|
[Embark](https://github.com/embark-framework/embark).
|
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"name": "embark-rpc-manager",
|
||||||
|
"version": "5.0.0-alpha.1",
|
||||||
|
"description": "Embark RPC Manager",
|
||||||
|
"main": "./dist/lib/index.js",
|
||||||
|
"repository": {
|
||||||
|
"directory": "packages/plugins/embark-rpc-manager",
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/embark-framework/embark/"
|
||||||
|
},
|
||||||
|
"author": "Iuri Matias <iuri.matias@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": "https://github.com/embark-framework/embark/issues",
|
||||||
|
"keywords": [
|
||||||
|
"blockchain",
|
||||||
|
"dapps",
|
||||||
|
"ethereum",
|
||||||
|
"ipfs",
|
||||||
|
"serverless",
|
||||||
|
"solc",
|
||||||
|
"solidity"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"dist/"
|
||||||
|
],
|
||||||
|
"embark-collective": {
|
||||||
|
"build:node": true
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"_build": "npm run solo -- build",
|
||||||
|
"ci": "npm run qa",
|
||||||
|
"clean": "npm run reset",
|
||||||
|
"lint": "npm-run-all lint:*",
|
||||||
|
"lint:js": "eslint src/",
|
||||||
|
"lint:ts": "tslint -c tslint.json \"src/**/*.ts\"",
|
||||||
|
"qa": "npm-run-all lint typecheck _build test",
|
||||||
|
"reset": "npx rimraf .nyc_output coverage dist embark-*.tgz package",
|
||||||
|
"solo": "embark-solo",
|
||||||
|
"test": "nyc --reporter=html --reporter=json mocha \"dist/test/**/*.js\" --exit --no-timeouts --require source-map-support/register",
|
||||||
|
"typecheck": "tsc"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": "../../../.eslintrc.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime-corejs3": "7.6.3",
|
||||||
|
"@omisego/omg-js-util": "2.0.0-v0.2",
|
||||||
|
"async": "2.6.1",
|
||||||
|
"embark-core": "^5.0.0-alpha.1",
|
||||||
|
"embark-i18n": "^5.0.0-alpha.1",
|
||||||
|
"embark-utils": "^5.0.0-alpha.1",
|
||||||
|
"web3": "1.2.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/async": "2.0.50",
|
||||||
|
"cross-env": "5.2.0",
|
||||||
|
"eslint": "5.7.0",
|
||||||
|
"mocha": "6.2.0",
|
||||||
|
"npm-run-all": "4.1.5",
|
||||||
|
"rimraf": "3.0.0",
|
||||||
|
"tslint": "5.16.0",
|
||||||
|
"typescript": "3.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.17.0 <12.0.0",
|
||||||
|
"npm": ">=6.11.3",
|
||||||
|
"yarn": ">=1.19.1"
|
||||||
|
},
|
||||||
|
"nyc": {
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**",
|
||||||
|
"coverage/**",
|
||||||
|
"dist/test/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { Callback, Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
|
import Web3 from "web3";
|
||||||
|
const { blockchain: blockchainConstants } = require("embark-core/constants");
|
||||||
|
import { __ } from "embark-i18n";
|
||||||
|
import RpcModifier from "./rpcModifier";
|
||||||
|
|
||||||
|
const METHODS_TO_MODIFY = [
|
||||||
|
blockchainConstants.transactionMethods.eth_accounts,
|
||||||
|
blockchainConstants.transactionMethods.personal_listAccounts,
|
||||||
|
];
|
||||||
|
|
||||||
|
function arrayEqual(arrayA: string[], arrayB: string[]) {
|
||||||
|
if (!(arrayA && arrayB) || arrayA.length !== arrayB.length) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return arrayA.every((address, index) => Web3.utils.toChecksumAddress(address) === Web3.utils.toChecksumAddress(arrayB[index]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class EthAccounts extends RpcModifier {
|
||||||
|
constructor(embark: Embark, rpcModifierEvents: Events) {
|
||||||
|
super(embark, rpcModifierEvents);
|
||||||
|
|
||||||
|
this.embark.registerActionForEvent("blockchain:proxy:response", undefined, this.checkResponseFor_eth_accounts.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkResponseFor_eth_accounts(params: any, callback: Callback<any>) {
|
||||||
|
|
||||||
|
if (!(METHODS_TO_MODIFY.includes(params.reqData.method))) {
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.trace(__(`Modifying blockchain '${params.reqData.method}' response:`));
|
||||||
|
this.logger.trace(__(`Original request/response data: ${JSON.stringify(params)}`));
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!arrayEqual(params.respData.result, this._nodeAccounts || [])) {
|
||||||
|
// reset backing variables so accounts is recalculated
|
||||||
|
await this.rpcModifierEvents.request2("nodeAccounts:updated", params.respData.result);
|
||||||
|
}
|
||||||
|
const accounts = await this.accounts;
|
||||||
|
if (!(accounts && accounts.length)) {
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
params.respData.result = accounts.map((acc) => acc.address || acc);
|
||||||
|
this.logger.trace(__(`Modified request/response data: ${JSON.stringify(params)}`));
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
import async from "async";
|
||||||
|
import { Callback, Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
|
import { __ } from "embark-i18n";
|
||||||
|
import Web3 from "web3";
|
||||||
|
const { blockchain: blockchainConstants } = require("embark-core/constants");
|
||||||
|
import RpcModifier from "./rpcModifier";
|
||||||
|
|
||||||
|
export default class EthSendTransaction extends RpcModifier {
|
||||||
|
private signTransactionQueue: any;
|
||||||
|
private nonceCache: any = {};
|
||||||
|
constructor(embark: Embark, rpcModifierEvents: Events) {
|
||||||
|
super(embark, rpcModifierEvents);
|
||||||
|
|
||||||
|
embark.registerActionForEvent("blockchain:proxy:request", undefined, this.checkRequestFor_eth_sendTransaction.bind(this));
|
||||||
|
|
||||||
|
// Allow to run transaction in parallel by resolving the nonce manually.
|
||||||
|
// For each transaction, resolve the nonce by taking the max of current transaction count and the cache we keep locally.
|
||||||
|
// Update the nonce and sign it
|
||||||
|
this.signTransactionQueue = async.queue(({ payload, account }, callback: Callback<any>) => {
|
||||||
|
this.getNonce(payload.from, async (err: any, newNonce: number) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err, null);
|
||||||
|
}
|
||||||
|
payload.nonce = newNonce;
|
||||||
|
const web3 = await this.web3;
|
||||||
|
web3.eth.accounts.signTransaction(payload, account.privateKey, (signingError: any, result: any) => {
|
||||||
|
if (signingError) {
|
||||||
|
return callback(signingError, null);
|
||||||
|
}
|
||||||
|
callback(null, result.rawTransaction);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getNonce(address: string, callback: Callback<any>) {
|
||||||
|
const web3 = await this.web3;
|
||||||
|
web3.eth.getTransactionCount(address, undefined, (error: any, transactionCount: number) => {
|
||||||
|
if (error) {
|
||||||
|
return callback(error, null);
|
||||||
|
}
|
||||||
|
if (this.nonceCache[address] === undefined) {
|
||||||
|
this.nonceCache[address] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionCount > this.nonceCache[address]) {
|
||||||
|
this.nonceCache[address] = transactionCount;
|
||||||
|
return callback(null, this.nonceCache[address]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nonceCache[address]++;
|
||||||
|
callback(null, this.nonceCache[address]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private async checkRequestFor_eth_sendTransaction(params: any, callback: Callback<any>) {
|
||||||
|
if (!(params.reqData.method === blockchainConstants.transactionMethods.eth_sendTransaction)) {
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
const accounts = await this.accounts;
|
||||||
|
if (!(accounts && accounts.length)) {
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.trace(__(`Modifying blockchain '${params.reqData.method}' request:`));
|
||||||
|
this.logger.trace(__(`Original request data: ${JSON.stringify(params)}`));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if we have that account in our wallet
|
||||||
|
const account = accounts.find((acc) => Web3.utils.toChecksumAddress(acc.address) === Web3.utils.toChecksumAddress(params.reqData.params[0].from));
|
||||||
|
if (account && account.privateKey) {
|
||||||
|
return this.signTransactionQueue.push({ payload: params.reqData.params[0], account }, (err: any, newPayload: any) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err, null);
|
||||||
|
}
|
||||||
|
params.reqData.method = blockchainConstants.transactionMethods.eth_sendRawTransaction;
|
||||||
|
params.reqData.params = [newPayload];
|
||||||
|
callback(err, params);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
this.logger.trace(__(`Modified request/response data: ${JSON.stringify(params)}`));
|
||||||
|
callback(null, params);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { sign, transaction } from "@omisego/omg-js-util";
|
||||||
|
import { Callback, Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
|
import { __ } from "embark-i18n";
|
||||||
|
import Web3 from "web3";
|
||||||
|
import RpcModifier from "./rpcModifier";
|
||||||
|
|
||||||
|
export default class EthSignTypedData extends RpcModifier {
|
||||||
|
constructor(embark: Embark, rpcModifierEvents: Events) {
|
||||||
|
super(embark, rpcModifierEvents);
|
||||||
|
|
||||||
|
this.embark.registerActionForEvent("blockchain:proxy:request", undefined, this.checkRequestFor_eth_signTypedData.bind(this));
|
||||||
|
this.embark.registerActionForEvent("blockchain:proxy:response", undefined, this.checkResponseFor_eth_signTypedData.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkRequestFor_eth_signTypedData(params: any, callback: Callback<any>) {
|
||||||
|
// check for:
|
||||||
|
// - eth_signTypedData
|
||||||
|
// - eth_signTypedData_v3
|
||||||
|
// - eth_signTypedData_v4
|
||||||
|
// - personal_signTypedData (parity)
|
||||||
|
if (params.reqData.method.includes("signTypedData")) {
|
||||||
|
// indicate that we do not want this call to go to the node
|
||||||
|
params.sendToNode = false;
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
callback(null, params);
|
||||||
|
}
|
||||||
|
private async checkResponseFor_eth_signTypedData(params: any, callback: Callback<any>) {
|
||||||
|
|
||||||
|
// check for:
|
||||||
|
// - eth_signTypedData
|
||||||
|
// - eth_signTypedData_v3
|
||||||
|
// - eth_signTypedData_v4
|
||||||
|
// - personal_signTypedData (parity)
|
||||||
|
if (!params.reqData.method.includes("signTypedData")) {
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.trace(__(`Modifying blockchain '${params.reqData.method}' response:`));
|
||||||
|
this.logger.trace(__(`Original request/response data: ${JSON.stringify(params)}`));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accounts = await this.accounts;
|
||||||
|
const [fromAddr, typedData] = params.reqData.params;
|
||||||
|
const account = accounts.find((acc) => Web3.utils.toChecksumAddress(acc.address) === Web3.utils.toChecksumAddress(fromAddr));
|
||||||
|
if (!(account && account.privateKey)) {
|
||||||
|
return callback(
|
||||||
|
new Error(__("Could not sign transaction because Embark does not have a private key associated with '%s'. " +
|
||||||
|
"Please ensure you have configured your account(s) to use a mnemonic, privateKey, or privateKeyFile.", fromAddr)));
|
||||||
|
}
|
||||||
|
const toSign = transaction.getToSignHash(typeof typedData === "string" ? JSON.parse(typedData) : typedData);
|
||||||
|
const signature = sign(toSign, [account.privateKey]);
|
||||||
|
|
||||||
|
params.respData.result = signature[0];
|
||||||
|
this.logger.trace(__(`Modified request/response data: ${JSON.stringify(params)}`));
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
callback(null, params);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { Callback, Embark, Events } from "embark-core";
|
||||||
|
import { Logger } from 'embark-logger';
|
||||||
|
import Web3 from "web3";
|
||||||
|
import EthAccounts from "./eth_accounts";
|
||||||
|
import EthSendTransaction from "./eth_sendTransaction";
|
||||||
|
import EthSignTypedData from "./eth_signTypedData";
|
||||||
|
import PersonalNewAccount from "./personal_newAccount";
|
||||||
|
import RpcModifier from "./rpcModifier";
|
||||||
|
|
||||||
|
export default class RpcManager {
|
||||||
|
|
||||||
|
private modifiers: RpcModifier[] = [];
|
||||||
|
private _web3: Web3 | null = null;
|
||||||
|
private rpcModifierEvents: Events;
|
||||||
|
private logger: Logger;
|
||||||
|
private events: Events;
|
||||||
|
public _accounts: any[] | null = null;
|
||||||
|
public _nodeAccounts: any[] | null = null;
|
||||||
|
constructor(private readonly embark: Embark) {
|
||||||
|
this.events = embark.events;
|
||||||
|
this.logger = embark.logger;
|
||||||
|
this.rpcModifierEvents = new Events();
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async init() {
|
||||||
|
|
||||||
|
this.rpcModifierEvents.setCommandHandler("nodeAccounts:updated", this.updateAccounts.bind(this));
|
||||||
|
this.rpcModifierEvents.setCommandHandler("nodeAccounts:added", async (addedNodeAccount: any, cb: Callback<null>) => {
|
||||||
|
if (!this._nodeAccounts) {
|
||||||
|
this._nodeAccounts = [addedNodeAccount];
|
||||||
|
} else {
|
||||||
|
this._nodeAccounts.push(addedNodeAccount);
|
||||||
|
}
|
||||||
|
return this.updateAccounts(this._nodeAccounts, cb);
|
||||||
|
});
|
||||||
|
this.modifiers = [PersonalNewAccount, EthAccounts, EthSendTransaction, EthSignTypedData].map((rpcModifier) => new rpcModifier(this.embark, this.rpcModifierEvents));
|
||||||
|
}
|
||||||
|
private async updateAccounts(updatedNodeAccounts: any[], cb: Callback<null>) {
|
||||||
|
for (const modifier of this.modifiers) {
|
||||||
|
await (modifier.nodeAccounts = Promise.resolve(updatedNodeAccounts));
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { Callback, Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
|
import Web3 from "web3";
|
||||||
|
const { blockchain: blockchainConstants } = require("embark-core/constants");
|
||||||
|
import { __ } from "embark-i18n";
|
||||||
|
import RpcModifier from "./rpcModifier";
|
||||||
|
export default class PersonalNewAccount extends RpcModifier {
|
||||||
|
constructor(embark: Embark, rpcModifierEvents: Events) {
|
||||||
|
super(embark, rpcModifierEvents);
|
||||||
|
|
||||||
|
embark.registerActionForEvent("blockchain:proxy:response", undefined, this.checkResponseFor_personal_newAccount.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkResponseFor_personal_newAccount(params: any, callback: Callback<any>) {
|
||||||
|
if (params.reqData.method !== blockchainConstants.transactionMethods.personal_newAccount) {
|
||||||
|
return callback(null, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit event so tx modifiers can refresh accounts
|
||||||
|
await this.rpcModifierEvents.request2("nodeAccounts:added", params.respData.result);
|
||||||
|
|
||||||
|
callback(null, params);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { Embark, Events, Logger } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
|
import { AccountParser, dappPath } from "embark-utils";
|
||||||
|
import Web3 from "web3";
|
||||||
|
|
||||||
|
export default class RpcModifier {
|
||||||
|
public events: Events;
|
||||||
|
public logger: Logger;
|
||||||
|
private _web3: Web3 | null = null;
|
||||||
|
private _accounts: any[] | null = null;
|
||||||
|
protected _nodeAccounts: any[] | null = null;
|
||||||
|
constructor(readonly embark: Embark, readonly rpcModifierEvents: Events) {
|
||||||
|
this.events = embark.events;
|
||||||
|
this.logger = embark.logger;
|
||||||
|
|
||||||
|
this.embark.registerActionForEvent("tests:config:updated", { priority: 40 }, async (_params, cb) => {
|
||||||
|
// reset accounts backing variable as the accounts in config may have changed and
|
||||||
|
// web.eth.getAccounts may return a different value now
|
||||||
|
this._accounts = null;
|
||||||
|
this._nodeAccounts = null;
|
||||||
|
cb(null, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get web3() {
|
||||||
|
return (async () => {
|
||||||
|
if (!this._web3) {
|
||||||
|
const provider = await this.events.request2("blockchain:client:provider", "ethereum");
|
||||||
|
this._web3 = new Web3(provider);
|
||||||
|
}
|
||||||
|
return this._web3;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get nodeAccounts() {
|
||||||
|
return (async () => {
|
||||||
|
if (!this._nodeAccounts) {
|
||||||
|
const web3 = await this.web3;
|
||||||
|
this._nodeAccounts = await web3.eth.getAccounts();
|
||||||
|
}
|
||||||
|
return this._nodeAccounts || [];
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
public set nodeAccounts(nodeAccounts: Promise<any[]>) {
|
||||||
|
(async () => {
|
||||||
|
this._nodeAccounts = await nodeAccounts;
|
||||||
|
// reset accounts backing variable as it neesd to be recalculated
|
||||||
|
this._accounts = null;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get accounts() {
|
||||||
|
return (async () => {
|
||||||
|
if (!this._accounts) {
|
||||||
|
const web3 = await this.web3;
|
||||||
|
const nodeAccounts = await this.nodeAccounts;
|
||||||
|
this._accounts = AccountParser.parseAccountsConfig(this.embark.config.blockchainConfig.accounts, web3, dappPath(), this.logger, nodeAccounts);
|
||||||
|
}
|
||||||
|
return this._accounts || [];
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected set accounts(accounts) {
|
||||||
|
(async () => {
|
||||||
|
this._accounts = await accounts;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"include": ["src/**/*"]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tslint.json"
|
||||||
|
}
|
|
@ -52,4 +52,13 @@ if (typeof WebSocket !== 'undefined') {
|
||||||
}
|
}
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
<% for (let stackName in (customPlugins || [])) { %>
|
||||||
|
<% for (let pluginName in (customPlugins[stackName] || [])) { %>
|
||||||
|
let __embark<%- pluginName %> = require('<%- customPlugins[stackName][pluginName] %>');
|
||||||
|
__embark<%- pluginName %> = __embark<%- pluginName %>.default || __embark<%- pluginName %>;
|
||||||
|
const customPluginConfig = require('./config/<%- stackName %>.json');
|
||||||
|
EmbarkJS.<%- stackName %> = new __embark<%- pluginName %>({pluginConfig: customPluginConfig});
|
||||||
|
<% }; %>
|
||||||
|
<% }; %>
|
||||||
|
|
||||||
export default EmbarkJS;
|
export default EmbarkJS;
|
|
@ -21,16 +21,26 @@ class EmbarkJS {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.embarkJSPlugins = {};
|
this.embarkJSPlugins = {};
|
||||||
|
this.customEmbarkJSPlugins = {};
|
||||||
this.events.setCommandHandler("embarkjs:plugin:register", (stackName, pluginName, packageName) => {
|
this.events.setCommandHandler("embarkjs:plugin:register", (stackName, pluginName, packageName) => {
|
||||||
this.embarkJSPlugins[stackName] = this.embarkJSPlugins[stackName] || {};
|
this.embarkJSPlugins[stackName] = this.embarkJSPlugins[stackName] || {};
|
||||||
this.embarkJSPlugins[stackName][pluginName] = packageName;
|
this.embarkJSPlugins[stackName][pluginName] = packageName;
|
||||||
});
|
});
|
||||||
|
this.events.setCommandHandler("embarkjs:plugin:register:custom", (stackName, pluginName, packageName) => {
|
||||||
|
this.customEmbarkJSPlugins[stackName] = this.customEmbarkJSPlugins[stackName] || {};
|
||||||
|
this.customEmbarkJSPlugins[stackName][pluginName] = packageName;
|
||||||
|
});
|
||||||
|
|
||||||
this.events.setCommandHandler("embarkjs:console:register", (stackName, pluginName, packageName, cb) => {
|
this.events.setCommandHandler("embarkjs:console:register", (stackName, pluginName, packageName, cb) => {
|
||||||
this.events.request("runcode:whitelist", packageName, () => { });
|
this.events.request("runcode:whitelist", packageName, () => {});
|
||||||
this.registerEmbarkJSPlugin(stackName, pluginName, packageName, cb || (() => {}));
|
this.registerEmbarkJSPlugin(stackName, pluginName, packageName, cb || (() => {}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.events.setCommandHandler("embarkjs:console:regsiter:custom", (stackName, pluginName, packageName, options, cb) => {
|
||||||
|
this.events.request("runcode:whitelist", packageName, () => {});
|
||||||
|
this.registerCustomEmbarkJSPluginInVm(stackName, pluginName, packageName, options, cb || (() => {}));
|
||||||
|
});
|
||||||
|
|
||||||
this.events.setCommandHandler("embarkjs:console:setProvider", this.setProvider.bind(this));
|
this.events.setCommandHandler("embarkjs:console:setProvider", this.setProvider.bind(this));
|
||||||
this.events.setCommandHandler("embarkjs:contract:generate", this.addContractArtifact.bind(this));
|
this.events.setCommandHandler("embarkjs:contract:generate", this.addContractArtifact.bind(this));
|
||||||
this.events.setCommandHandler("embarkjs:contract:runInVm", this.runInVm.bind(this));
|
this.events.setCommandHandler("embarkjs:contract:runInVm", this.runInVm.bind(this));
|
||||||
|
@ -65,8 +75,27 @@ class EmbarkJS {
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async registerCustomEmbarkJSPluginInVm(stackName, pluginName, packageName, options, cb) {
|
||||||
|
await this.registerEmbarkJS();
|
||||||
|
|
||||||
|
const customPluginCode = `
|
||||||
|
let __embark${pluginName} = require('${packageName}');
|
||||||
|
__embark${pluginName} = __embark${pluginName}.default || __embark${pluginName};
|
||||||
|
const customPluginOptions = ${JSON.stringify(options)};
|
||||||
|
EmbarkJS.${stackName} = new __embark${pluginName}({pluginConfig: customPluginOptions});
|
||||||
|
EmbarkJS.${stackName}.init();
|
||||||
|
`;
|
||||||
|
|
||||||
|
await this.events.request2('runcode:eval', customPluginCode);
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
addEmbarkJSArtifact(_params, cb) {
|
addEmbarkJSArtifact(_params, cb) {
|
||||||
const embarkjsCode = Templates.embarkjs_artifact({ plugins: this.embarkJSPlugins, hasWebserver: this.embark.config.webServerConfig.enabled });
|
const embarkjsCode = Templates.embarkjs_artifact({
|
||||||
|
plugins: this.embarkJSPlugins,
|
||||||
|
hasWebserver: this.embark.config.webServerConfig.enabled,
|
||||||
|
customPlugins: this.customEmbarkJSPlugins
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: generate a .node file
|
// TODO: generate a .node file
|
||||||
this.events.request("pipeline:register", {
|
this.events.request("pipeline:register", {
|
||||||
|
@ -142,10 +171,10 @@ class EmbarkJS {
|
||||||
const result = await this.events.request2('runcode:eval', contract.className);
|
const result = await this.events.request2('runcode:eval', contract.className);
|
||||||
result.currentProvider = provider;
|
result.currentProvider = provider;
|
||||||
await this.events.request2("runcode:register", contract.className, result);
|
await this.events.request2("runcode:register", contract.className, result);
|
||||||
cb();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ const constants = require("embark-core/constants");
|
||||||
export default class ProxyManager {
|
export default class ProxyManager {
|
||||||
private readonly logger: Logger;
|
private readonly logger: Logger;
|
||||||
private readonly events: Events;
|
private readonly events: Events;
|
||||||
private proxy: any;
|
private wsProxy: any;
|
||||||
|
private httpProxy: any;
|
||||||
private plugins: any;
|
private plugins: any;
|
||||||
private readonly host: string;
|
private readonly host: string;
|
||||||
private rpcPort = 0;
|
private rpcPort = 0;
|
||||||
|
@ -79,7 +80,7 @@ export default class ProxyManager {
|
||||||
if (!this.embark.config.blockchainConfig.proxy) {
|
if (!this.embark.config.blockchainConfig.proxy) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.proxy) {
|
if (this.httpProxy || this.wsProxy) {
|
||||||
throw new Error("Proxy is already started");
|
throw new Error("Proxy is already started");
|
||||||
}
|
}
|
||||||
const port = await findNextPort(this.embark.config.blockchainConfig.rpcPort + constants.blockchain.servicePortOnProxy);
|
const port = await findNextPort(this.embark.config.blockchainConfig.rpcPort + constants.blockchain.servicePortOnProxy);
|
||||||
|
@ -88,23 +89,47 @@ export default class ProxyManager {
|
||||||
this.wsPort = port + 1;
|
this.wsPort = port + 1;
|
||||||
this.isWs = clientName === constants.blockchain.vm || (/wss?/).test(this.embark.config.blockchainConfig.endpoint);
|
this.isWs = clientName === constants.blockchain.vm || (/wss?/).test(this.embark.config.blockchainConfig.endpoint);
|
||||||
|
|
||||||
this.proxy = await new Proxy({
|
// HTTP
|
||||||
endpoint: clientName === constants.blockchain.vm ? constants.blockchain.vm : this.embark.config.blockchainConfig.endpoint,
|
if (clientName !== constants.blockchain.vm) {
|
||||||
|
this.httpProxy = await new Proxy({
|
||||||
|
endpoint: this.embark.config.blockchainConfig.endpoint,
|
||||||
events: this.events,
|
events: this.events,
|
||||||
isWs: this.isWs,
|
isWs: false,
|
||||||
logger: this.logger,
|
logger: this.logger,
|
||||||
plugins: this.plugins,
|
plugins: this.plugins,
|
||||||
vms: this.vms,
|
vms: this.vms,
|
||||||
});
|
})
|
||||||
|
.serve(
|
||||||
await this.proxy.serve(
|
|
||||||
this.host,
|
this.host,
|
||||||
this.isWs ? this.wsPort : this.rpcPort,
|
this.rpcPort,
|
||||||
);
|
);
|
||||||
|
this.logger.info(`HTTP Proxy for node endpoint ${this.embark.config.blockchainConfig.endpoint} listening on ${buildUrl("http", this.host, this.rpcPort, "rpc")}`);
|
||||||
|
}
|
||||||
|
if (this.isWs) {
|
||||||
|
const endpoint = clientName === constants.blockchain.vm ? constants.blockchain.vm : this.embark.config.blockchainConfig.endpoint;
|
||||||
|
this.wsProxy = await new Proxy({
|
||||||
|
endpoint,
|
||||||
|
events: this.events,
|
||||||
|
isWs: true,
|
||||||
|
logger: this.logger,
|
||||||
|
plugins: this.plugins,
|
||||||
|
vms: this.vms,
|
||||||
|
})
|
||||||
|
.serve(
|
||||||
|
this.host,
|
||||||
|
this.wsPort,
|
||||||
|
);
|
||||||
|
this.logger.info(`WS Proxy for node endpoint ${endpoint} listening on ${buildUrl("ws", this.host, this.wsPort, "ws")}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private stopProxy() {
|
private stopProxy() {
|
||||||
this.proxy.stop();
|
if (this.wsProxy) {
|
||||||
this.proxy = null;
|
this.wsProxy.stop();
|
||||||
|
this.wsProxy = null;
|
||||||
|
}
|
||||||
|
if (this.httpProxy) {
|
||||||
|
this.httpProxy.stop();
|
||||||
|
this.httpProxy = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,7 @@ export class Proxy {
|
||||||
// stripped out by modifying the response (via actions for blockchain:proxy:response)
|
// stripped out by modifying the response (via actions for blockchain:proxy:response)
|
||||||
respData.error = fwdReqErr.message || fwdReqErr;
|
respData.error = fwdReqErr.message || fwdReqErr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const modifiedResp = await this.emitActionsForResponse(modifiedRequest.reqData, respData);
|
const modifiedResp = await this.emitActionsForResponse(modifiedRequest.reqData, respData);
|
||||||
|
@ -193,7 +194,7 @@ export class Proxy {
|
||||||
const rpcErrorObj = { "jsonrpc": "2.0", "error": { "code": -32603, "message": error }, "id": modifiedRequest.reqData.id };
|
const rpcErrorObj = { "jsonrpc": "2.0", "error": { "code": -32603, "message": error }, "id": modifiedRequest.reqData.id };
|
||||||
return this.respondError(transport, rpcErrorObj);
|
return this.respondError(transport, rpcErrorObj);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,7 +225,7 @@ class TestRunner {
|
||||||
Object.assign(this.simOptions, {host, port, type, protocol, accounts, client: config.blockchain && config.blockchain.client});
|
Object.assign(this.simOptions, {host, port, type, protocol, accounts, client: config.blockchain && config.blockchain.client});
|
||||||
|
|
||||||
if (!resetServices && !deepEqual(accounts, ogAccounts)) {
|
if (!resetServices && !deepEqual(accounts, ogAccounts)) {
|
||||||
return this.plugins.emitAndRunActionsForEvent("accounts:reseted", {accounts}, cb);
|
return this.plugins.emitAndRunActionsForEvent("tests:config:updated", {accounts}, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resetServices) {
|
if (!resetServices) {
|
||||||
|
|
51
yarn.lock
51
yarn.lock
|
@ -2598,6 +2598,17 @@
|
||||||
universal-user-agent "^3.0.0"
|
universal-user-agent "^3.0.0"
|
||||||
url-template "^2.0.8"
|
url-template "^2.0.8"
|
||||||
|
|
||||||
|
"@omisego/omg-js-util@2.0.0-v0.2":
|
||||||
|
version "2.0.0-v0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@omisego/omg-js-util/-/omg-js-util-2.0.0-v0.2.tgz#30b5882cc8a45446e7206576240caade614c8590"
|
||||||
|
integrity sha512-J5J5Q2XC7ZkpfQJiXJxii/66Tn3x4rhnhky3BmL++XEBoK6I34wgWMs/7dzsejWNHmmhGv/M/OZb+QBI+HlvlA==
|
||||||
|
dependencies:
|
||||||
|
eth-sig-util "^2.1.1"
|
||||||
|
ethereumjs-util "^6.0.0"
|
||||||
|
js-sha3 "^0.8.0"
|
||||||
|
number-to-bn "^1.7.0"
|
||||||
|
rlp "^2.2.2"
|
||||||
|
|
||||||
"@reach/router@^1.2.1":
|
"@reach/router@^1.2.1":
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.2.1.tgz#34ae3541a5ac44fa7796e5506a5d7274a162be4e"
|
resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.2.1.tgz#34ae3541a5ac44fa7796e5506a5d7274a162be4e"
|
||||||
|
@ -3146,6 +3157,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect "^1.0.1"
|
defer-to-connect "^1.0.1"
|
||||||
|
|
||||||
|
"@types/async@2.0.50":
|
||||||
|
version "2.0.50"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.50.tgz#117540e026d64e1846093abbd5adc7e27fda7bcb"
|
||||||
|
integrity sha512-VMhZMMQgV1zsR+lX/0IBfAk+8Eb7dPVMWiQGFAt3qjo5x7Ml6b77jUo0e1C3ToD+XRDXqtrfw+6AB0uUsPEr3Q==
|
||||||
|
|
||||||
"@types/async@3.0.3":
|
"@types/async@3.0.3":
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/async/-/async-3.0.3.tgz#ea3694128c757580e4f9328cd941b81d9c3e9bf6"
|
resolved "https://registry.yarnpkg.com/@types/async/-/async-3.0.3.tgz#ea3694128c757580e4f9328cd941b81d9c3e9bf6"
|
||||||
|
@ -5096,7 +5112,7 @@ bn.js@4.11.6:
|
||||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
|
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
|
||||||
integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU=
|
integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU=
|
||||||
|
|
||||||
bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0:
|
bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0:
|
||||||
version "4.11.8"
|
version "4.11.8"
|
||||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
|
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
|
||||||
integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
|
integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
|
||||||
|
@ -8543,6 +8559,18 @@ eth-lib@0.2.7:
|
||||||
elliptic "^6.4.0"
|
elliptic "^6.4.0"
|
||||||
xhr-request-promise "^0.1.2"
|
xhr-request-promise "^0.1.2"
|
||||||
|
|
||||||
|
eth-sig-util@^2.1.1:
|
||||||
|
version "2.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.4.4.tgz#8804ead83de8648bcf81eadbfac1e3ccdd360aea"
|
||||||
|
integrity sha512-iWGqEJwsUMgtk8AqQQqIDTjMz+pW8s2Sq8gN640dh9U9HoEFQJO3m6ro96DgV6hMB2LYu8F5812LQyynOgCbEw==
|
||||||
|
dependencies:
|
||||||
|
buffer "^5.2.1"
|
||||||
|
elliptic "^6.4.0"
|
||||||
|
ethereumjs-abi "0.6.5"
|
||||||
|
ethereumjs-util "^5.1.1"
|
||||||
|
tweetnacl "^1.0.0"
|
||||||
|
tweetnacl-util "^0.15.0"
|
||||||
|
|
||||||
ethashjs@~0.0.7:
|
ethashjs@~0.0.7:
|
||||||
version "0.0.7"
|
version "0.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.7.tgz#30bfe4196726690a0c59d3b8272e70d4d0c34bae"
|
resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.7.tgz#30bfe4196726690a0c59d3b8272e70d4d0c34bae"
|
||||||
|
@ -8570,6 +8598,14 @@ ethereum-common@^0.0.18:
|
||||||
resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f"
|
resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f"
|
||||||
integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=
|
integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=
|
||||||
|
|
||||||
|
ethereumjs-abi@0.6.5:
|
||||||
|
version "0.6.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241"
|
||||||
|
integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=
|
||||||
|
dependencies:
|
||||||
|
bn.js "^4.10.0"
|
||||||
|
ethereumjs-util "^4.3.0"
|
||||||
|
|
||||||
ethereumjs-account@^2.0.3:
|
ethereumjs-account@^2.0.3:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84"
|
resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84"
|
||||||
|
@ -8668,7 +8704,7 @@ ethereumjs-util@6.0.0, ethereumjs-util@~6.0.0:
|
||||||
safe-buffer "^5.1.1"
|
safe-buffer "^5.1.1"
|
||||||
secp256k1 "^3.0.1"
|
secp256k1 "^3.0.1"
|
||||||
|
|
||||||
ethereumjs-util@^4.0.1, ethereumjs-util@^4.5.0:
|
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
|
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
|
||||||
integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=
|
integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=
|
||||||
|
@ -8679,7 +8715,7 @@ ethereumjs-util@^4.0.1, ethereumjs-util@^4.5.0:
|
||||||
rlp "^2.0.0"
|
rlp "^2.0.0"
|
||||||
secp256k1 "^3.0.1"
|
secp256k1 "^3.0.1"
|
||||||
|
|
||||||
ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.2, ethereumjs-util@^5.2.0:
|
ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.2.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642"
|
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642"
|
||||||
integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==
|
integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==
|
||||||
|
@ -14562,7 +14598,7 @@ number-is-nan@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||||
|
|
||||||
number-to-bn@1.7.0:
|
number-to-bn@1.7.0, number-to-bn@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0"
|
resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0"
|
||||||
integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=
|
integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=
|
||||||
|
@ -18058,7 +18094,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
|
||||||
hash-base "^3.0.0"
|
hash-base "^3.0.0"
|
||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
|
|
||||||
rlp@^2.0.0:
|
rlp@^2.0.0, rlp@^2.2.2:
|
||||||
version "2.2.3"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.3.tgz#7f94aef86cec412df87d5ea1d8cb116a47d45f0e"
|
resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.3.tgz#7f94aef86cec412df87d5ea1d8cb116a47d45f0e"
|
||||||
integrity sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==
|
integrity sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==
|
||||||
|
@ -20179,6 +20215,11 @@ tunnel-agent@^0.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
tweetnacl-util@^0.15.0:
|
||||||
|
version "0.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz#4576c1cee5e2d63d207fee52f1ba02819480bc75"
|
||||||
|
integrity sha1-RXbBzuXi1j0gf+5S8boCgZSAvHU=
|
||||||
|
|
||||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||||
version "0.14.5"
|
version "0.14.5"
|
||||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||||
|
|
Loading…
Reference in New Issue