fix: alleviate races re: embarkjs by introducing Plugin#addGeneratedCode and related refactors

This commit is contained in:
Iuri Matias 2019-06-20 19:39:31 -04:00 committed by Michael Bradley
parent d684b9af0f
commit fc4faa8ba9
22 changed files with 258 additions and 564 deletions

View File

@ -80,6 +80,10 @@ class CodeGenerator {
cb(this.getEmbarkJsProviderCode());
});
this.events.setCommandHandler('code-generator:embarkjs:set-provider-code', (cb) => {
cb(this.getSetProviderCode());
});
this.events.setCommandHandler('code-generator:embarkjs:init-provider-code', (cb) => {
cb(this.getInitProviderCode());
});
@ -100,6 +104,14 @@ class CodeGenerator {
});
}
getSetProviderCode() {
let code = "\n";
code += this.generateCommunicationInitialization(true);
code += this.generateStorageInitialization(true);
code += this.generateNamesInitialization(true);
return code;
}
generateContracts(contractsList, useEmbarkJS, isDeployment, useLoader) {
let self = this;
let result = "\n";
@ -313,7 +325,6 @@ class CodeGenerator {
const self = this;
let embarkjsCode = '';
let code = "/* eslint-disable */";
const deps = ['web3', 'ens', 'ipfs', 'swarm', 'whisper'];
async.waterfall([
// TODO: here due to a race condition when running embark build
@ -342,30 +353,36 @@ class CodeGenerator {
embarkjsCode += `\nconst EmbarkJS = require("${symlinkDest}").default || require("${symlinkDest}");`;
embarkjsCode += `\nEmbarkJS.environment = '${self.env}';`;
embarkjsCode += "\nglobal.EmbarkJS = EmbarkJS;";
code += "\n" + embarkjsCode + "\n";
next();
});
},
...deps.map((dep) => {
return function(next) {
self.events.request('version:downloadIfNeeded', `embarkjs-${dep}`, (err, location) => {
if (err) {
self.logger.error(__(`Error downloading embarkjs-${dep}`));
return next(err);
}
self.generateSymlink(location, `embarkjs-${dep}`, (err, _symlinkDest) => {
if (err) {
self.logger.error(__(`Error creating a symlink to embarkjs-${dep}`));
return next(err);
}
return next();
});
});
};
}),
function addCodeFromDependencies(next) {
async.eachSeries(
self.plugins.getPluginsFor('generatedCode'),
(plugin, callback) => {
async.eachSeries(
plugin.generated_code,
(codeCall, callback) => {
codeCall((err, generatedCode, packageName, location) => {
if (err) return callback(err);
self.generateSymlink(location, packageName, (err, _symlinkDest) => {
if (err) {
self.logger.error(__(`Error creating a symlink to ${packageName}`));
return callback(err);
}
code += generatedCode;
callback();
});
});
},
(err) => { callback(err); }
);
},
(err) => { next(err); }
);
},
function getJSCode(next) {
code += "\n" + embarkjsCode + "\n";
code += self.getEmbarkJsProviderCode();
code += self.generateCommunicationInitialization(true);
code += self.generateStorageInitialization(true);

View File

@ -37,8 +37,6 @@ export default class CodeRunner {
this.registerEvents();
this.registerCommands();
this.events.emit("runcode:ready");
this.ready = true;
}
private generateListener(provider: string, eventType: ProviderEventType) {
@ -52,101 +50,64 @@ export default class CodeRunner {
});
}
private fireEmbarkJSEvents(code: string) {
const regexRegister = /EmbarkJS\.(.*)\.registerProvider/gm;
const regexSet = /EmbarkJS\.(.*)\.setProvider/gm;
let matches = regexRegister.exec(code);
if (matches) {
let [, provider] = matches;
provider = provider.toLowerCase();
this.providerStates[`${provider}:${ProviderEventType.ProviderRegistered}`] = true;
this.events.emit(`runcode:${provider}:${ProviderEventType.ProviderRegistered}`);
}
matches = regexSet.exec(code);
if (matches) {
let [, provider] = matches;
provider = provider.toLowerCase();
this.providerStates[`${provider}:${ProviderEventType.ProviderSet}`] = true;
this.events.emit(`runcode:${provider}:${ProviderEventType.ProviderSet}`);
}
private registerEvents() {
this.events.on("runcode:register", this.registerVar.bind(this));
}
private registerEvents() {
this.events.on("runcode:register", this.registerVar.bind(this));
this.events.on("runcode:init-console-code:updated", (code: string, cb: Callback<null>) => {
this.evalCode(code, (err, _result) => {
if (err) {
this.logger.error("Error running init console code: ", err.message || err);
}
this.fireEmbarkJSEvents(code);
cb();
private registerCommands() {
this.events.setCommandHandler("runcode:getContext", (cb) => {
cb(this.vm.options.sandbox);
});
});
this.events.on("runcode:embarkjs-code:updated", (code: string, cb: Callback<any>) => {
this.evalCode(code, (err, _result) => {
if (err) {
this.logger.error("Error running embarkjs code: ", err.message || err);
}
this.fireEmbarkJSEvents(code);
cb();
this.events.setCommandHandler("runcode:eval", this.evalCode.bind(this));
this.events.setCommandHandler("runcode:embarkjs:reset", (cb) => {
this.resetEmbarkJS(cb);
});
});
}
private registerCommands() {
this.events.setCommandHandler("runcode:getContext", (cb) => {
cb(this.vm.options.sandbox);
});
this.events.setCommandHandler("runcode:eval", this.evalCode.bind(this));
this.events.setCommandHandler("runcode:ready", (cb) => {
if (this.ready) {
return cb();
}
this.events.once("runcode:ready", cb);
});
this.events.setCommandHandler("runcode:embarkjs:reset", this.resetEmbarkJS.bind(this));
// register listeners for when EmbarkJS runs registerProvider through the console.
// For example, when `EmbarkJS.Storage.registerProvider(...)` is run through the console,
// emit the `runcode:storage:providerRegistered` event, and fire any requests attached to it
Object.keys(EmbarkJS)
.filter((propName) => EmbarkJS[propName].hasOwnProperty("registerProvider"))
.forEach((providerName) => {
this.generateListener(providerName.toLowerCase(), ProviderEventType.ProviderRegistered);
});
// register listeners for when EmbarkJS runs setProvider through the console.
// For example, when `EmbarkJS.Storage.setProvider(...)` is run through the console,
// emit the `runcode:storage:providerSet` event, and fire any requests attached to it
Object.keys(EmbarkJS)
.filter((propName) => EmbarkJS[propName].hasOwnProperty("setProvider"))
.forEach((providerName) => {
this.generateListener(providerName.toLowerCase(), ProviderEventType.ProviderSet);
});
}
private resetEmbarkJS(cb: Callback<null>) {
this.events.request("code-generator:embarkjs:provider-code", (code: string) => {
this.evalCode(code, (err) => {
if (err) {
return cb(err);
}
this.events.request("code-generator:embarkjs:init-provider-code", (providerCode: string) => {
this.evalCode(providerCode, (errInitProvider, _result) => {
cb(errInitProvider);
}, true);
this.events.on("contractsDeployed", () => {
this.events.on("code-generator-ready", (_modifiedAssets: any) => {
this.resetEmbarkJS();
});
}, true);
});
}
});
// register listeners for when EmbarkJS runs registerProvider through the console.
// For example, when `EmbarkJS.Storage.registerProvider(...)` is run through the console,
// emit the `runcode:storage:providerRegistered` event, and fire any requests attached to it
Object.keys(EmbarkJS)
.filter((propName) => EmbarkJS[propName].hasOwnProperty("registerProvider"))
.forEach((providerName) => {
this.generateListener(providerName.toLowerCase(), ProviderEventType.ProviderRegistered);
});
// register listeners for when EmbarkJS runs setProvider through the console.
// For example, when `EmbarkJS.Storage.setProvider(...)` is run through the console,
// emit the `runcode:storage:providerSet` event, and fire any requests attached to it
Object.keys(EmbarkJS)
.filter((propName) => EmbarkJS[propName].hasOwnProperty("setProvider"))
.forEach((providerName) => {
this.generateListener(providerName.toLowerCase(), ProviderEventType.ProviderSet);
});
}
private resetEmbarkJS(cb?: Callback<null>) {
this.events.request("code-generator:embarkjs:init-provider-code", (code: string) => {
this.evalCode(code, (err) => {
if (err) {
console.dir(err);
return;
}
this.events.request("code-generator:embarkjs:set-provider-code", (providerCode: string) => {
this.evalCode(providerCode, (errInitProvider, _result) => {
if (cb) { cb(errInitProvider); }
}, false);
});
}, false);
});
}
private registerVar(varName: string, code: any, cb = () => { }) {
this.vm.registerVar(varName, code, cb);
}
private evalCode(code: string, cb: Callback < any >, tolerateError = false) {
private evalCode(code: string, cb: Callback<any>, tolerateError = false) {
cb = cb || (() => { });
if (!code) {

View File

@ -27,7 +27,6 @@ class Console {
private history: string[];
private cmdHistoryFile: string;
private suggestions?: Suggestions;
private providerReady: boolean;
constructor(embark: Embark, options: any) {
this.embark = embark;
@ -40,7 +39,6 @@ class Console {
this.config = options.config;
this.history = [];
this.cmdHistoryFile = options.cmdHistoryFile || dappPath(".embark", "cmd_history");
this.providerReady = false;
this.loadHistory();
if (this.ipc.isServer()) {
@ -60,24 +58,11 @@ class Console {
}
this.events.setCommandHandler("console:executeCmd", this.executeCmd.bind(this));
this.events.setCommandHandler("console:history", (cb: any) => this.getHistory(this.cmdHistorySize(), cb));
this.events.setCommandHandler("console:provider:ready", (cb: any) => {
if (this.providerReady || this.isEmbarkConsole) {
return cb();
}
this.events.once("console:provider:done", cb);
});
this.registerConsoleCommands();
if (this.isEmbarkConsole) {
return;
}
this.registerEmbarkJs((err?: Error | null) => {
if (err) {
return this.logger.error(err);
}
this.providerReady = true;
this.events.emit("console:provider:done");
});
this.registerApi();
this.suggestions = new Suggestions(embark, options);
@ -202,43 +187,6 @@ class Console {
}, true);
}
private registerEmbarkJs(cb: Callback<null>) {
waterfall([
// wait for the VM to be setup
(next: any) => {
this.events.request("runcode:ready", next);
},
(next: any) => {
const waitingForReady = setTimeout(() => {
this.logger.warn(__("Waiting for the blockchain connector to be ready..."));
// TODO add docs link to how to install one
this.logger.warn(__("If you did not install a blockchain connector, stop this process and install one"));
}, 5000);
this.events.request("blockchain:connector:ready", () => {
clearTimeout(waitingForReady);
next();
});
},
(next: any) => {
if (this.isEmbarkConsole) {
return next();
}
this.events.request("runcode:blockchain:providerSet", next);
},
(next: any) => {
if (this.isEmbarkConsole) {
return next();
}
const connectCode = `EmbarkJS.Blockchain.connectConsole((err) => {
if(err) throw new Error("[VM]: Error connecting to blockchain. " + err);
});`;
this.events.request("runcode:eval", connectCode, (err: Error, _result: any) => {
cb(err);
});
},
], cb);
}
private registerConsoleCommands() {
this.embark.registerConsoleCommand({
description: __("display console commands history"),

View File

@ -384,18 +384,31 @@ class ENS {
return this.logger.error(err.message || err);
}
this.events.emit('runcode:register', 'namehash', require('eth-ens-namehash'), () => {
let linkedModulePath = path.join(this.modulesPath, 'embarkjs-ens');
if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\');
const code = `
const __embarkENS = require('${linkedModulePath}');
EmbarkJS.Names.registerProvider('ens', __embarkENS.default || __embarkENS);
`;
this.embark.addCodeToEmbarkJS(code);
});
});
});
let linkedModulePath = path.join(this.modulesPath, 'embarkjs-ens');
if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\');
const code = `
const __embarkENS = require('${linkedModulePath}');
EmbarkJS.Names.registerProvider('ens', __embarkENS.default || __embarkENS);
`;
this.events.request('version:downloadIfNeeded', 'embarkjs-ens', (err, location) => {
if (err) {
this.logger.error(__('Error downloading embarkjs-ens'));
throw err;
}
this.embark.addProviderInit("names", code, () => { return true; });
this.embark.addConsoleProviderInit("names", code, () => { return true; });
this.embark.addGeneratedCode((cb) => {
return cb(null, code, `embarkjs-ens`, location);
});
});
});
}
@ -406,6 +419,7 @@ class ENS {
return (namesConfig.provider === 'ens' && namesConfig.enabled === true);
};
// TODO This stacks the setProviders making it so that we call it multiple times
this.embark.addProviderInit('names', code, shouldInit);
this.embark.addConsoleProviderInit('names', code, shouldInit);
}

View File

@ -35,9 +35,6 @@ class Test {
init(callback) {
async.waterfall([
(next) => {
this.events.request('runcode:ready', next);
},
(next) => {
this.gasLimit = GAS_LIMIT;
this.events.request('deploy:setGasLimit', this.gasLimit);
@ -181,7 +178,9 @@ class Test {
}
self.firstRunConfig = false;
self.events.request("blockchain:ready", () => {
self.events.request("runcode:embarkjs:reset", callback);
self.events.request("code-generator:embarkjs:build", () => {
self.events.request("runcode:embarkjs:reset", callback);
});
});
});
});
@ -316,11 +315,6 @@ class Test {
next(err, accounts, web3);
});
},
function waitForProvidersReady(accounts, web3, next) {
self.events.request('console:provider:ready', () => {
next(null, accounts, web3);
});
},
function createContractObject(accounts, web3, next) {
self.events.request('contracts:all', (err, contracts) => {
async.each(contracts, (contract, eachCb) => {

View File

@ -1,5 +1,6 @@
/* global __dirname module process require */
const { __ } = require('embark-i18n');
const { dappPath, embarkPath, normalizePath, toForwardSlashes } = require('embark-utils');
const constants = require('embark-core/constants');
const path = require('path');
@ -18,7 +19,6 @@ class EmbarkWeb3 {
async addWeb3ToEmbarkJS() {
let blockchainConnectorReady = false;
await this.whenRuncodeReady();
const web3LocationPromise = this.getWeb3Location();
@ -61,22 +61,24 @@ class EmbarkWeb3 {
code += `\n const web3ConnectionConfig = require('${configPath}');`;
code += `\n EmbarkJS.Blockchain.connect(web3ConnectionConfig, (err) => {if (err) { console.error(err); } });`;
code += `\n}`;
this.events.request('version:downloadIfNeeded', 'embarkjs-web3', (err, location) => {
if (err) {
this.logger.error(__('Error downloading embarkjs-web3'));
throw err;
}
this.embark.addCodeToEmbarkJS(code);
this.embark.addProviderInit("blockchain", code, () => { return true; });
code = "EmbarkJS.Blockchain.setProvider('web3', {web3});";
// Make sure that we use our web3 for the console and the tests
code += `if (typeof web3 === 'undefined') {
throw new Error('Global web3 is not present');
}
EmbarkJS.Blockchain.setProvider('web3', {web3});`;
const shouldInit = (_config) => {
return true;
};
this.embark.addConsoleProviderInit("blockchain", code, () => { return true; });
this.embark.addConsoleProviderInit('blockchain', code, shouldInit);
}
whenRuncodeReady() {
return new Promise((resolve) => {
this.events.on('runcode:ready', () => {
resolve();
this.embark.addGeneratedCode((cb) => {
return cb(null, code, 'embarkjs-web3', location);
});
});
}

View File

@ -50,7 +50,6 @@ class Whisper {
}
}
this.setServiceCheck();
this.addWhisperToEmbarkJS();
this.addSetProvider();
this.registerAPICalls();
cb();
@ -58,6 +57,10 @@ class Whisper {
});
});
// TODO: it will have the issue of waiting for the ipfs to start when the code is generator
// TODO: could be solved by having a list of services to wait on before attempting to execute code in the console
this.addWhisperToEmbarkJS();
this.events.request('processes:launch', 'whisper');
}
@ -117,7 +120,6 @@ class Whisper {
}
addWhisperToEmbarkJS() {
const self = this;
// TODO: make this a shouldAdd condition
if (this.communicationConfig === {}) {
return;
@ -129,12 +131,23 @@ class Whisper {
let linkedModulePath = path.join(this.modulesPath, 'embarkjs-whisper');
if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\');
const code = `
const __embarkWhisperNewWeb3 = require('${linkedModulePath}');
EmbarkJS.Messages.registerProvider('whisper', __embarkWhisperNewWeb3.default || __embarkWhisperNewWeb3);
`;
this.events.request('version:downloadIfNeeded', 'embarkjs-whisper', (err, location) => {
if (err) {
this.logger.error(__('Error downloading embarkjs-whisper'));
throw err;
}
self.embark.addCodeToEmbarkJS(code);
const code = `
const __embarkWhisperNewWeb3 = require('${linkedModulePath}');
EmbarkJS.Messages.registerProvider('whisper', __embarkWhisperNewWeb3.default || __embarkWhisperNewWeb3);
`;
this.embark.addProviderInit("communication", code, () => { return true; });
this.embark.addConsoleProviderInit("communication", code, () => { return true; });
this.embark.addGeneratedCode((cb) => {
return cb(null, code, `embarkjs-whisper`, location);
});
});
}
addSetProvider() {
@ -149,6 +162,12 @@ class Whisper {
port: connection.port || '8546',
type: connection.type || 'ws'
};
// TODO: fix storage to also use addProviderInit
// execute code called addProviderInit WHEN contracts have been deployed etc..
// TODO: diff between addConsoleProviderInit and addProviderInit
// or maybe best way is todo everything in the module
const code = `\nEmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)});`;
this.embark.addProviderInit('communication', code, shouldInit);

View File

@ -107,6 +107,7 @@
"embark-deploy-tracker": "^4.1.0-beta.3",
"embark-deployment": "^4.1.0-beta.3",
"embark-ens": "^4.1.0-beta.3",
"embark-graph": "^4.1.0-beta.3",
"embark-i18n": "^4.1.0-beta.3",
"embark-library-manager": "^4.1.0-beta.3",
"embark-listener": "^4.1.0-beta.3",

View File

@ -165,9 +165,7 @@ class EmbarkController {
}
engine.startService("fileWatcher");
engine.events.request('code-generator:embarkjs:build', () => {
callback();
});
callback();
},
function startDashboard(callback) {
if (!options.useDashboard) {
@ -242,9 +240,7 @@ class EmbarkController {
engine.startService('compiler');
}
engine.events.request('code-generator:embarkjs:build', () => {
callback();
});
callback();
},
function buildOrBuildAndDeploy(callback) {
if (options.onlyCompile) {
@ -329,18 +325,10 @@ class EmbarkController {
engine.startService("cockpit");
engine.startService("pluginCommand");
engine.events.request('code-generator:embarkjs:build', () => {
engine.events.request('blockchain:ready', callback);
});
engine.events.request('blockchain:ready', callback);
},
function ipcConnect(callback) {
// Do specific work in case we are connected to a socket:
// - Setup Web3
// - Apply history
if(isSecondaryProcess(engine)) {
return callback();
}
engine.events.request("console:provider:ready", callback);
return callback();
},
function deploy(callback) {
// Skip if we are connected to a websocket, the server will do it
@ -413,9 +401,7 @@ class EmbarkController {
engine.startService("codeGenerator");
engine.startService("graph");
engine.events.request('code-generator:embarkjs:build', () => {
engine.events.request('contracts:build', {}, callback);
});
engine.events.request('contracts:build', {}, callback);
}
], (err) => {
if (err) {
@ -591,9 +577,7 @@ class EmbarkController {
engine.startService("storage");
engine.startService("codeGenerator");
engine.events.request('code-generator:embarkjs:build', () => {
callback();
});
callback();
},
function listLoadedPlugin(callback) {
let pluginList = engine.plugins.listPlugins();
@ -688,9 +672,7 @@ class EmbarkController {
}
engine.startService("testRunner");
engine.events.request('code-generator:embarkjs:build', () => {
callback();
});
callback();
},
function runTests(callback) {
engine.events.request('tests:run', options, callback);

View File

@ -191,17 +191,20 @@ class Engine {
this.registerModulePackage('embark-code-generator', {plugins: self.plugins, env: self.env});
const generateCode = function (modifiedAssets) {
self.events.request("module:storage:onReady", () => {
self.events.request("code-generator:embarkjs:build", () => {
self.events.emit('code-generator-ready', modifiedAssets);
});
const generateCode = function (modifiedAssets, cb) {
self.events.request("code-generator:embarkjs:build", () => {
self.events.emit('code-generator-ready', modifiedAssets);
cb();
});
};
const cargo = async.cargo((tasks, callback) => {
const modifiedAssets = tasks.map(task => task.modifiedAsset).filter(asset => asset); // filter null elements
generateCode(modifiedAssets);
self.events.once('outputDone', callback);
generateCode(modifiedAssets, () => {
if (this.context.includes('test')) {
return callback();
}
self.events.once('outputDone', callback);
});
});
const addToCargo = function (modifiedAsset) {
cargo.push({modifiedAsset});
@ -297,6 +300,8 @@ class Engine {
}
web3Service(options) {
this.registerModulePackage('embark-web3');
this.registerModulePackage('embark-blockchain-process', {
client: this.client,
locale: this.locale,
@ -312,7 +317,6 @@ class Engine {
wait: options.wait
});
this.registerModulePackage('embark-web3');
this.registerModulePackage('embark-whisper');
}

View File

@ -31,6 +31,7 @@ var Plugin = function(options) {
this.apiCalls = [];
this.imports = [];
this.embarkjs_code = [];
this.generated_code = [];
this.embarkjs_init_code = {};
this.embarkjs_init_console_code = {};
this.fs = fs;
@ -229,14 +230,17 @@ Plugin.prototype.registerUploadCommand = function(cmd, cb) {
Plugin.prototype.addCodeToEmbarkJS = function(code) {
this.addPluginType('embarkjsCode');
// TODO: what is this/why
if (!this.embarkjs_code.some((existingCode) => deepEqual(existingCode, code))) {
this.embarkjs_code.push(code);
this.events.request('blockchain:ready', () => {
this.events.emit('runcode:embarkjs-code:updated', code, () => {});
});
}
};
Plugin.prototype.addGeneratedCode = function(codeCb) {
this.addPluginType('generatedCode');
this.generated_code.push(codeCb);
};
Plugin.prototype.addProviderInit = function(providerType, code, initCondition) {
this.embarkjs_init_code[providerType] = this.embarkjs_init_code[providerType] || [];
this.embarkjs_init_code[providerType].push([code, initCondition]);
@ -249,9 +253,6 @@ Plugin.prototype.addConsoleProviderInit = function(providerType, code, initCondi
const toAdd = [code, initCondition];
if (!this.embarkjs_init_console_code[providerType].some((initConsoleCode) => deepEqual(initConsoleCode, toAdd))) {
this.embarkjs_init_console_code[providerType].push(toAdd);
this.events.request('blockchain:ready', () => {
this.events.emit('runcode:init-console-code:updated', code, () => {});
});
}
};

View File

@ -20,7 +20,6 @@ class IPFS {
this.embark = embark;
this.fs = embark.fs;
this.isServiceRegistered = false;
this.addedToEmbarkJs = false;
this.addedToConsole = false;
this.storageProcessesLauncher = null;
this.usingRunningNode = false;
@ -43,7 +42,6 @@ class IPFS {
return cb(__("IPFS process is running in a separate process and cannot be started by Embark."));
}
this.startProcess((err, newProcessStarted) => {
this.addStorageProviderToEmbarkJS();
this.addObjectToConsole();
this.events.emit("ipfs:process:started", err, newProcessStarted);
cb();
@ -64,6 +62,10 @@ class IPFS {
this.logger.info(msg);
}
});
// TODO: it will have the issue of waiting for the ipfs to start when the code is generator
// TODO: could be solved by having a list of services to wait on before attempting to execute code in the console
this.addStorageProviderToEmbarkJS();
}
downloadIpfsApi(cb) {
@ -131,8 +133,6 @@ class IPFS {
}
addStorageProviderToEmbarkJS() {
if(this.addedToEmbarkJs) return;
this.addedToEmbarkJs = true;
this.events.request('version:downloadIfNeeded', 'ipfs-api', (err, location) => {
if (err) {
this.logger.error(__('Error downloading IPFS API'));
@ -146,19 +146,30 @@ class IPFS {
}
this.events.emit('runcode:register', 'IpfsApi', require('ipfs-api'), () => {
let linkedModulePath = path.join(this.modulesPath, 'embarkjs-ipfs');
if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\');
const code = `
const __embarkIPFS = require('${linkedModulePath}');
EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS);
`;
this.embark.addCodeToEmbarkJS(code);
this.embark.addConsoleProviderInit("storage", code, (storageConfig) => storageConfig.enabled);
});
});
});
let linkedModulePath = path.join(this.modulesPath, 'embarkjs-ipfs');
if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\');
const code = `
const __embarkIPFS = require('${linkedModulePath}');
EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS);
`;
this.events.request('version:downloadIfNeeded', 'embarkjs-ipfs', (err, location) => {
if (err) {
this.logger.error(__('Error downloading embarkjs-ipfs'));
throw err;
}
this.embark.addProviderInit("storage", code, () => { return true; });
this.embark.addConsoleProviderInit("storage", code, () => { return true; });
this.embark.addGeneratedCode((cb) => {
return cb(null, code, `embarkjs-ipfs`, location);
});
});
});
}

View File

@ -20,7 +20,6 @@ class Swarm {
this.embark = embark;
this.fs = embark.fs;
this.isServiceRegistered = false;
this.addedToEmbarkJs = false;
this.addedToConsole = false;
this.storageProcessesLauncher = null;
this.usingRunningNode = false;
@ -63,7 +62,6 @@ class Swarm {
return cb(__("Swarm process is running in a separate process and cannot be started by Embark."));
}
this.startProcess((err, newProcessStarted) => {
this.addProviderToEmbarkJS();
this.addObjectToConsole();
this.events.emit("swarm:process:started", err, newProcessStarted);
cb();
@ -84,6 +82,10 @@ class Swarm {
this.logger.info(msg);
}
});
// TODO: it will have the issue of waiting for the ipfs to start when the code is generator
// TODO: could be solved by having a list of services to wait on before attempting to execute code in the console
this.addProviderToEmbarkJS();
}
addObjectToConsole() {
@ -123,18 +125,27 @@ class Swarm {
}
addProviderToEmbarkJS() {
if(this.addedToEmbarkJs) return;
this.addedToEmbarkJs = true;
let linkedModulePath = path.join(this.modulesPath, 'embarkjs-swarm');
if (process.platform === 'win32') linkedModulePath = linkedModulePath.replace(/\\/g, '\\\\');
const code = `
const __embarkSwarm = require('${linkedModulePath}');
EmbarkJS.Storage.registerProvider('swarm', __embarkSwarm.default || __embarkSwarm);
`;
this.events.request('version:downloadIfNeeded', 'embarkjs-swarm', (err, location) => {
if (err) {
this.logger.error(__('Error downloading embarkjs-swarm'));
throw err;
}
this.embark.addCodeToEmbarkJS(code);
const code = `
const __embarkSwarm = require('${linkedModulePath}');
EmbarkJS.Storage.registerProvider('swarm', __embarkSwarm.default || __embarkSwarm);
`;
this.embark.addProviderInit("storage", code, () => { return true; });
this.embark.addConsoleProviderInit("storage", code, () => { return true; });
this.embark.addGeneratedCode((cb) => {
return cb(null, code, 'embarkjs-swarm', location);
});
});
}
startProcess(callback) {

View File

@ -183,6 +183,7 @@ class TemplateGenerator {
delete pkgJson.devDependencies['rimraf'];
}
delete pkgJson.files;
delete pkgJson.gitHead;
pkgJson.name = name;
if (!pkgJson.scripts) pkgJson.scripts = {};
delete pkgJson.scripts.ci;

View File

@ -1,4 +0,0 @@
engine-strict = true
package-lock = false
save-exact = true
scripts-prepend-node-path = true

View File

@ -1,44 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [4.1.0-beta.3](https://github.com/embark-framework/embark/compare/v4.1.0-beta.2...v4.1.0-beta.3) (2019-06-07)
**Note:** Version bump only for package embarkjs-connector-web3
# [4.1.0-beta.2](https://github.com/embark-framework/embark/compare/v4.1.0-beta.1...v4.1.0-beta.2) (2019-05-22)
**Note:** Version bump only for package embarkjs-connector-web3
# [4.1.0-beta.1](https://github.com/embark-framework/embark/compare/v4.1.0-beta.0...v4.1.0-beta.1) (2019-05-15)
**Note:** Version bump only for package embarkjs-connector-web3
# [4.0.0](https://github.com/embark-framework/embark/compare/v4.0.0-beta.2...v4.0.0) (2019-03-18)
**Note:** Version bump only for package embarkjs-connector-web3
# [4.0.0-beta.1](https://github.com/embark-framework/embark/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2019-03-18)
### Features
* add repository.directory field to package.json ([a9c5e1a](https://github.com/embark-framework/embark/commit/a9c5e1a))
* normalize README and package.json bugs, homepage, description ([5418f16](https://github.com/embark-framework/embark/commit/5418f16))

View File

@ -1,6 +0,0 @@
# `embarkjs-connector-web3`
> Web3.js Connector for EmbarkJS
Visit [embark.status.im](https://embark.status.im/) to get started with
[Embark](https://github.com/embark-framework/embark).

View File

@ -1,58 +0,0 @@
/*global Web3*/
const embarkJSConnectorWeb3 = {};
embarkJSConnectorWeb3.init = function(config) {
global.web3 = config.web3 || global.web3;
// Check if the global web3 object uses the old web3 (0.x)
if (global.web3 && typeof global.web3.version !== 'string') {
// If so, use a new instance using 1.0, but use its provider
this.web3 = new Web3(global.web3.currentProvider);
} else {
this.web3 = global.web3 || new Web3();
}
global.web3 = this.web3;
};
embarkJSConnectorWeb3.getInstance = function () {
return this.web3;
};
embarkJSConnectorWeb3.getAccounts = function () {
return this.web3.eth.getAccounts(...arguments);
};
embarkJSConnectorWeb3.getNewProvider = function (providerName, ...args) {
return new Web3.providers[providerName](...args);
};
embarkJSConnectorWeb3.setProvider = function (provider) {
return this.web3.setProvider(provider);
};
embarkJSConnectorWeb3.getCurrentProvider = function () {
return this.web3.currentProvider;
};
embarkJSConnectorWeb3.getDefaultAccount = function () {
return this.web3.eth.defaultAccount;
};
embarkJSConnectorWeb3.setDefaultAccount = function (account) {
this.web3.eth.defaultAccount = account;
};
embarkJSConnectorWeb3.newContract = function (options) {
return new this.web3.eth.Contract(options.abi, options.address);
};
embarkJSConnectorWeb3.send = function () {
return this.web3.eth.sendTransaction(...arguments);
};
embarkJSConnectorWeb3.toWei = function () {
return this.web3.toWei(...arguments);
};
embarkJSConnectorWeb3.getNetworkId = function () {
return this.web3.eth.net.getId();
};

View File

@ -1,115 +0,0 @@
const { dappPath, embarkPath, normalizePath, toForwardSlashes } = require('embark-utils');
const path = require('path');
class EmbarkJSConnectorWeb3 {
constructor(embark, _options) {
this.embark = embark;
this.events = embark.events;
this.fs = embark.fs;
this.config = embark.config;
this.constants = embark.constants;
this.registerProvider();
}
async registerProvider() {
let blockchainConnectorReady = false;
await this.whenRuncodeReady();
const web3LocationPromise = this.getWeb3Location();
this.events.setCommandHandler('blockchain:connector:ready', (cb) => {
if (blockchainConnectorReady) {
return cb();
}
this.events.once("blockchain:connector:ready", () => {
cb();
});
});
web3LocationPromise.then((_web3Location) => {
blockchainConnectorReady = true;
this.events.emit('blockchain:connector:ready');
});
let web3Location = await web3LocationPromise;
web3Location = normalizePath(web3Location, true);
await this.registerVar('__Web3', require(web3Location));
const symlinkLocation = await this.generateSymlink(web3Location);
let code = `\nconst Web3 = global.__Web3 || require('${symlinkLocation}');`;
code += `\nglobal.Web3 = Web3;`;
const connectorCode = this.fs.readFileSync(path.join(__dirname, 'embarkJSConnectorWeb3.js'), 'utf8');
code += connectorCode;
code += "\nEmbarkJS.Blockchain.registerProvider('web3', embarkJSConnectorWeb3);";
code += "\nEmbarkJS.Blockchain.setProvider('web3', {});";
const configPath = toForwardSlashes(dappPath(this.config.embarkConfig.generationDir, this.constants.dappArtifacts.dir, this.constants.dappArtifacts.blockchain));
code += `\nif (!global.__Web3) {`; // Only connect when in the Dapp
code += `\n const web3ConnectionConfig = require('${configPath}');`;
code += `\n EmbarkJS.Blockchain.connect(web3ConnectionConfig, (err) => {if (err) { console.error(err); } });`;
code += `\n}`;
this.embark.addCodeToEmbarkJS(code);
code = "EmbarkJS.Blockchain.setProvider('web3', {web3});";
const shouldInit = (_config) => {
return true;
};
this.embark.addConsoleProviderInit('blockchain', code, shouldInit);
}
whenRuncodeReady() {
return new Promise((resolve) => {
this.events.on('runcode:ready', () => {
resolve();
});
});
}
getWeb3Location() {
return new Promise((resolve, reject) => {
this.events.request("version:get:web3", (web3Version) => {
if (web3Version === "1.0.0-beta") {
const nodePath = embarkPath('node_modules');
const web3Path = require.resolve("web3", {paths: [nodePath]});
return resolve(web3Path);
}
this.events.request("version:getPackageLocation", "web3", web3Version, (err, location) => {
if (err) {
return reject(err);
}
const locationPath = embarkPath(location);
resolve(locationPath);
});
});
});
}
generateSymlink(location) {
return new Promise((resolve, reject) => {
this.events.request('code-generator:symlink:generate', location, 'web3', (err, symlinkDest) => {
if (err) {
return reject(err);
}
resolve(symlinkDest);
});
});
}
registerVar(name, code) {
return new Promise((resolve) => {
this.events.emit('runcode:register', name, code, () => {
resolve();
});
});
}
}
module.exports = EmbarkJSConnectorWeb3;

View File

@ -1,39 +0,0 @@
{
"name": "embarkjs-connector-web3",
"version": "4.1.0-beta.3",
"author": "Iuri Matias <iuri.matias@gmail.com>",
"contributors": [],
"description": "Web3.js Connector for EmbarkJS",
"homepage": "https://github.com/embark-framework/embark/tree/master/packages/embarkjs-connector-web3#readme",
"bugs": "https://github.com/embark-framework/embark/issues",
"keywords": [
"embark",
"web3",
"node",
"ethereum",
"smart-contract"
],
"license": "MIT",
"repository": {
"directory": "packages/embarkjs-connector-web3",
"type": "git",
"url": "https://github.com/embark-framework/embark.git"
},
"main": "index.js",
"files": [
"embarkJSConnectorWeb3.js"
],
"scripts": {
"ci": "npm run qa",
"clean": "npm run reset",
"package": "npm pack",
"qa": "npm run package",
"reset": "npx rimraf embark-*.tgz package"
},
"dependencies": {
"embark-utils": "^4.1.0-beta.3"
},
"devDependencies": {
"rimraf": "2.6.3"
}
}

View File

@ -153,40 +153,39 @@ __embarkENS.registryAddresses = {
"4": "0xe7410170f87102DF0055eB195163A03B7F2Bff4A"
};
__embarkENS.setProvider = function (config) {
__embarkENS.setProvider = function(config) {
const self = this;
const ERROR_MESSAGE = 'ENS is not available in this chain';
self.registration = config.registration;
self.env = config.env;
EmbarkJS.onReady(() => {
EmbarkJS.Blockchain.blockchainConnector.getNetworkId()
.then((id) => {
const registryAddress = self.registryAddresses[id] || config.registryAddress;
self._isAvailable = true;
self.ens = new EmbarkJS.Blockchain.Contract({
abi: config.registryAbi,
address: registryAddress,
web3: EmbarkJS.Blockchain.blockchainConnector.getInstance()
});
self.registrar = new EmbarkJS.Blockchain.Contract({
abi: config.registrarAbi,
address: config.registrarAddress,
web3: EmbarkJS.Blockchain.blockchainConnector.getInstance()
});
self.resolver = new EmbarkJS.Blockchain.Contract({
abi: config.resolverAbi,
address: config.resolverAddress,
web3: EmbarkJS.Blockchain.blockchainConnector.getInstance()
});
})
.catch(err => {
if (err.message.indexOf('Provider not set or invalid') > -1) {
console.warn(ERROR_MESSAGE);
return;
}
console.error(err);
// FIXME EmbarkJS.onReady odesn't work. Possibility of a race condition
EmbarkJS.Blockchain.blockchainConnector.getNetworkId()
.then((id) => {
const registryAddress = self.registryAddresses[id] || config.registryAddress;
self._isAvailable = true;
self.ens = new EmbarkJS.Blockchain.Contract({
abi: config.registryAbi,
address: registryAddress,
web3: EmbarkJS.Blockchain.blockchainConnector.getInstance()
});
});
self.registrar = new EmbarkJS.Blockchain.Contract({
abi: config.registrarAbi,
address: config.registrarAddress,
web3: EmbarkJS.Blockchain.blockchainConnector.getInstance()
});
self.resolver = new EmbarkJS.Blockchain.Contract({
abi: config.resolverAbi,
address: config.resolverAddress,
web3: EmbarkJS.Blockchain.blockchainConnector.getInstance()
});
})
.catch(err => {
if (err.message.indexOf('Provider not set or invalid') > -1) {
console.warn(ERROR_MESSAGE);
return;
}
console.error(err);
});
};
__embarkENS.resolve = function (name, callback) {

View File

@ -5164,15 +5164,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000884, caniuse-lite@^1.0.30000887, caniuse-lite@^1.0.30000929:
version "1.0.30000932"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000932.tgz#d01763e9ce77810962ca7391ff827b5949ce4272"
integrity sha512-4bghJFItvzz8m0T3lLZbacmEY9X1Z2AtIzTr7s7byqZIOumASfr4ynDx7rtm0J85nDmx8vsgR6vnaSoeU8Oh0A==
caniuse-lite@^1.0.30000899:
version "1.0.30000912"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000912.tgz#08e650d4090a9c0ab06bfd2b46b7d3ad6dcaea28"
integrity sha512-M3zAtV36U+xw5mMROlTXpAHClmPAor6GPKAMD5Yi7glCB5sbMPFtnQ3rGpk4XqPdUrrTIaVYSJZxREZWNy8QJg==
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000884, caniuse-lite@^1.0.30000887, caniuse-lite@^1.0.30000899, caniuse-lite@^1.0.30000929:
version "1.0.30000978"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000978.tgz#1e3346c27fc46bce9ac1ccd77863153a263dde56"
integrity sha512-H6gK6kxUzG6oAwg/Jal279z8pHw0BzrpZfwo/CA9FFm/vA0l8IhDfkZtepyJNE2Y4V6Dp3P3ubz6czby1/Mgsw==
capture-exit@^1.2.0:
version "1.2.0"