Skip to content

Commit

Permalink
feat(@embark/nethermind): add Nethermind blockchain client plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jrainville authored and iurimatias committed Jan 16, 2020
1 parent 4190d5e commit 6db8d87
Show file tree
Hide file tree
Showing 23 changed files with 1,022 additions and 14 deletions.
3 changes: 3 additions & 0 deletions packages/core/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export class Config {

version: string;

locale: string;

shownNoAccountConfigMsg = false; // flag to ensure "no account config" message is only displayed once to the user

corsParts: string[] = [];
Expand All @@ -95,6 +97,7 @@ export class Config {
this.configDir = options.configDir || DEFAULT_CONFIG_PATH;
this.chainsFile = options.chainsFile;
this.plugins = options.plugins;
this.locale = options.locale || 'en';
this.logger = options.logger;
this.package = options.package;
this.events = options.events;
Expand Down
7 changes: 0 additions & 7 deletions packages/core/core/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,6 @@ export class Plugin {
this._loggerObject[type](this.name + ':', ...[].slice.call(arguments, 1));
}

setUpLogger() {
this.logger = new Logger({});
}

isContextValid() {
if (this.currentContext.includes(constants.contexts.any) || this.acceptedContext.includes(constants.contexts.any)) {
return true;
Expand All @@ -161,9 +157,6 @@ export class Plugin {
return false;
}
this.loaded = true;
if (this.shouldInterceptLogs) {
this.setUpLogger();
}
if (isEs6Module(this.pluginModule)) {
if (this.pluginModule.default) {
this.pluginModule = this.pluginModule.default;
Expand Down
11 changes: 10 additions & 1 deletion packages/core/engine/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,16 @@ export class Engine {
const options = _options || {};
this.events = options.events || this.events || new Events();
this.logger = this.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,
locale: this.locale
});
this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs});
this.plugins = this.config.plugins;
this.isDev = this.config && this.config.blockchainConfig && (this.config.blockchainConfig.isDev || this.config.blockchainConfig.default);
Expand Down
62 changes: 62 additions & 0 deletions packages/core/utils/src/check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const WebSocket = require("ws");
const http = require("http");
const https = require("https");

const LIVENESS_CHECK=`{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":42}`;

const parseAndRespond = (data, cb) => {
let resp;
try {
resp = JSON.parse(data);
if (resp.error) {
return cb(resp.error);
}
} catch (e) {
return cb('Version data is not valid JSON');
}
if (!resp || !resp.result) {
return cb('No version returned');
}
const [_, version, __] = resp.result.split('/');
cb(null, version);
};

const testRpcWithEndpoint = (endpoint, cb) => {
const options = {
method: "POST",
timeout: 1000,
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(LIVENESS_CHECK)
}
};

let obj = http;
if (endpoint.startsWith('https')) {
obj = https;
}

const req = obj.request(endpoint, options, (res) => {
let data = "";
res.on("data", chunk => { data += chunk; });
res.on("end", () => parseAndRespond(data, cb));
});
req.on("error", (e) => cb(e));
req.write(LIVENESS_CHECK);
req.end();
};

const testWsEndpoint = (endpoint, cb) => {
const conn = new WebSocket(endpoint);
conn.on("message", (data) => {
parseAndRespond(data, cb);
conn.close();
});
conn.on("open", () => conn.send(LIVENESS_CHECK));
conn.on("error", (e) => cb(e));
};

module.exports = {
testWsEndpoint,
testRpcWithEndpoint
};
1 change: 1 addition & 0 deletions packages/core/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const clipboardy = require('clipboardy');
import { canonicalHost } from './host';
export { canonicalHost, defaultCorsHost, defaultHost, dockerHostSwap, isDocker } from './host';
export { downloadFile, findNextPort, getJson, httpGet, httpsGet, httpGetJson, httpsGetJson, pingEndpoint } from './network';
export { testRpcWithEndpoint, testWsEndpoint } from './check';
const logUtils = require('./log-utils');
export const escapeHtml = logUtils.escapeHtml;
export const normalizeInput = logUtils.normalizeInput;
Expand Down
11 changes: 10 additions & 1 deletion packages/embark/src/cmd/cmd_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,22 @@ class EmbarkController {
});

engine.init({}, () => {
Object.assign(engine.config.blockchainConfig, { isStandalone: true });

engine.registerModuleGroup("coreComponents");
engine.registerModuleGroup("blockchainStackComponents");
engine.registerModuleGroup("blockchain");

// load custom plugins
engine.loadDappPlugins();
let pluginList = engine.plugins.listPlugins();
if (pluginList.length > 0) {
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
}

engine.startEngine(async () => {
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", engine.config.blockchainConfig);
if (alreadyStarted) {
engine.logger.warn(__('Blockchain process already started. No need to run `embark blockchain`'));
process.exit(0);
Expand Down
2 changes: 1 addition & 1 deletion packages/embark/src/test/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ describe('embark.Config', function () {
},
"datadir": ".embark/extNetwork/datadir",
"rpcHost": "mynetwork.com",
"rpcPort": undefined,
"rpcPort": false,
"rpcCorsDomain": {
"auto": true,
"additionalCors": []
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/ethereum-blockchain-client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class EthereumBlockchainClient {
const code = contract.code.substring(0, 2) === '0x' ? contract.code : "0x" + contract.code;
const contractObject = contractObj.deploy({arguments: (contract.args || []), data: code});
if (contract.gas === 'auto' || !contract.gas) {
const gasValue = await contractObject.estimateGas();
const gasValue = await contractObject.estimateGas({value: 0, from: account});
const increase_per = 1 + (Math.random() / 10.0);
contract.gas = Math.floor(gasValue * increase_per);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/geth/src/blockchain.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Blockchain {
this.config = {
silent: this.userConfig.silent,
client: this.userConfig.client,
ethereumClientBin: this.userConfig.ethereumClientBin || this.userConfig.client,
ethereumClientBin: this.userConfig.ethereumClientBin,
networkType: this.userConfig.networkType || clientClass.DEFAULTS.NETWORK_TYPE,
networkId: this.userConfig.networkId || clientClass.DEFAULTS.NETWORK_ID,
genesisBlock: this.userConfig.genesisBlock || false,
Expand Down
1 change: 1 addition & 0 deletions packages/plugins/geth/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Geth {
this.embarkConfig = embark.config.embarkConfig;
this.blockchainConfig = embark.config.blockchainConfig;
this.communicationConfig = embark.config.communicationConfig;
// TODO get options from config instead of options
this.locale = options.locale;
this.logger = embark.logger;
this.client = options.client;
Expand Down
4 changes: 4 additions & 0 deletions packages/plugins/nethermind/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
engine-strict = true
package-lock = false
save-exact = true
scripts-prepend-node-path = true
20 changes: 20 additions & 0 deletions packages/plugins/nethermind/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# `embark-nethermind`

> Nethermind blockchain client plugin for Embark

## Quick docs

To configure the Netherminds client, you can use the Embark configs as always, or for more control, use the Nethermind config files.
To change them, go in your Netherminds directory, then in `configs/`. There, you will see all the configuration files for the different networks.
If you ever need to run a different network than dev, testnet or mainnet, you can change it in the Embark blockchain configuration by changing the `networkType` to the name of the config file, without the `.cfg`.
Eg: For the Goerli network, just put `networkType: 'goerli`
Note: The dev mode of Netherminds is called `ndm` and the config file is `ndm_consumer_local.cfg`. Using `miningMode: 'dev'` automatically translates to using that config file.

## Websocket support

Even though Nethermind supports Websocket connections, it does not support `eth_subscribe`, so you will not be able to use contract events.
Also, please note that you will need to change the `endpoint` in the blockchain configuration to `ws://localhost:8545/ws/json-rpc` when working in local. Do change the port or the host to whatever you need.

Visit [embark.status.im](https://embark.status.im/) to get started with
[Embark](https://github.com/embark-framework/embark).
67 changes: 67 additions & 0 deletions packages/plugins/nethermind/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"name": "embark-nethermind",
"version": "5.0.0-alpha.9",
"author": "Iuri Matias <iuri.matias@gmail.com>",
"contributors": [],
"description": "Nethermind blockchain client plugin for Embark",
"homepage": "https://github.com/embark-framework/embark/tree/master/packages/plugins/nethermind#readme",
"bugs": "https://github.com/embark-framework/embark/issues",
"keywords": [
"blockchain",
"dapps",
"ethereum",
"serverless",
"nethermind"
],
"files": [
"dist"
],
"license": "MIT",
"repository": {
"directory": "packages/plugins/nethermind",
"type": "git",
"url": "https://github.com/embark-framework/embark.git"
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"embark-collective": {
"build:node": true,
"typecheck": true
},
"scripts": {
"_build": "npm run solo -- build",
"_typecheck": "npm run solo -- typecheck",
"ci": "npm run qa",
"clean": "npm run reset",
"lint": "eslint src/",
"qa": "npm-run-all lint _typecheck _build",
"reset": "npx rimraf dist embark-*.tgz package",
"solo": "embark-solo"
},
"eslintConfig": {
"extends": "../../../.eslintrc.json"
},
"dependencies": {
"@babel/runtime-corejs3": "7.7.4",
"async": "2.6.1",
"core-js": "3.4.3",
"embark-core": "^5.0.0-alpha.9",
"embark-i18n": "^5.0.0-alpha.5",
"embark-utils": "^5.0.0-alpha.9",
"fs-extra": "8.1.0",
"netcat": "1.3.5",
"semver": "5.6.0",
"ws": "7.1.2"
},
"devDependencies": {
"embark-solo": "^5.0.0-alpha.5",
"eslint": "5.7.0",
"npm-run-all": "4.1.5",
"rimraf": "3.0.0"
},
"engines": {
"node": ">=10.17.0 <12.0.0",
"npm": ">=6.11.3",
"yarn": ">=1.19.1"
}
}
Loading

0 comments on commit 6db8d87

Please sign in to comment.