From 718d19f7d3f4daf8e91d3bf412348c9a25404e2b Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 5 Sep 2019 16:04:52 -0400 Subject: [PATCH] re-add embarkjs generation (#1858) * fix embarkjs generation fix ens setProvider fix embarkjs objects fix generated embarkjs provider generate contracts fix embarkjs-ens * address some of the issues in the code review * address some of the issues in the code review * address some of the issues in the code review * address some of the issues in the code review --- dapps/tests/app/app/js/index.js | 6 +- packages/embark-code-runner/src/index.ts | 3 + .../src/contract_deployer.js | 14 +- packages/embark-ens/src/index.js | 53 +------ packages/embark-ipfs/src/index.js | 93 ++++--------- packages/embark-namesystem/src/index.js | 13 ++ packages/embark-swarm/src/index.js | 88 ++++-------- .../src/embarkjs-contract-artifact.js.ejs | 6 + packages/embark-web3/src/index.js | 82 +++-------- packages/embark-whisper/src/api.js | 20 ++- packages/embark-whisper/src/index.js | 63 +-------- packages/embark/src/cmd/cmd_controller.js | 2 +- packages/embark/src/lib/core/engine.js | 1 + packages/embark/src/lib/core/events.js | 9 ++ .../src/lib/modules/blockchain/index.js | 1 + .../src/lib/modules/communication/index.js | 10 +- .../embark-embarkjs/embarkjs-artifact.js.ejs | 44 ++++++ .../embarkjs-console-contract.js.ejs | 2 + .../embarkjs-contract-artifact.js.ejs | 6 + .../src/lib/modules/embark-embarkjs/index.js | 130 ++++++++++++++++++ packages/embarkjs-ens/src/index.js | 4 +- packages/embarkjs-swarm/package.json | 3 +- packages/embarkjs-swarm/src/index.js | 13 +- packages/embarkjs/src/blockchain.js | 4 +- packages/embarkjs/src/storage.js | 2 +- 25 files changed, 349 insertions(+), 323 deletions(-) create mode 100644 packages/embark-web3/src/embarkjs-contract-artifact.js.ejs create mode 100644 packages/embark/src/lib/modules/embark-embarkjs/embarkjs-artifact.js.ejs create mode 100644 packages/embark/src/lib/modules/embark-embarkjs/embarkjs-console-contract.js.ejs create mode 100644 packages/embark/src/lib/modules/embark-embarkjs/embarkjs-contract-artifact.js.ejs create mode 100644 packages/embark/src/lib/modules/embark-embarkjs/index.js diff --git a/dapps/tests/app/app/js/index.js b/dapps/tests/app/app/js/index.js index 0f681f421..044ba502b 100644 --- a/dapps/tests/app/app/js/index.js +++ b/dapps/tests/app/app/js/index.js @@ -2,9 +2,11 @@ // import {SimpleStorage} from '../../embarkArtifacts/contracts'; import $ from 'jquery'; import SimpleStorage from '../../embarkArtifacts/contracts/SimpleStorage.js'; -import web3 from '../../embarkArtifacts/contracts/web3_init'; -window.web3 = web3; +// import web3 from '../../embarkArtifacts/contracts/web3_init'; +// window.web3 = web3; window.SimpleStorage = SimpleStorage; +import EmbarkJS from '../../embarkArtifacts/embarkjs.js'; +window.EmbarkJS = EmbarkJS; $("#blockchain button.set").click(function() { var value = parseInt($("#blockchain input.text").val(), 10); diff --git a/packages/embark-code-runner/src/index.ts b/packages/embark-code-runner/src/index.ts index d05fa0881..8d1047c0e 100644 --- a/packages/embark-code-runner/src/index.ts +++ b/packages/embark-code-runner/src/index.ts @@ -1,3 +1,4 @@ +import { __ } from 'embark-i18n'; import * as fs from "./fs"; import VM from "./vm"; @@ -60,6 +61,8 @@ class CodeRunner { this.vm.doEval(code, tolerateError, (err, result) => { if (err) { + this.logger.error(__("Error running code: %s", code)); + this.logger.error(err.toString()); return cb(err); } diff --git a/packages/embark-deployment/src/contract_deployer.js b/packages/embark-deployment/src/contract_deployer.js index f02dd94c9..0e9394579 100644 --- a/packages/embark-deployment/src/contract_deployer.js +++ b/packages/embark-deployment/src/contract_deployer.js @@ -30,7 +30,6 @@ class ContractDeployer { }); }, (params, next) => { - if (!params.shouldDeploy) { return this.plugins.emitAndRunActionsForEvent('deployment:contract:undeployed', {contract}, (err, _params) => { next(err, null); @@ -38,13 +37,12 @@ class ContractDeployer { } // TODO: implement `blockchainType` a la `this.deployer[contract.blockchainType].apply(this.deployer, [contract, next])` - this.deployer["ethereum"].apply(this.deployer, [contract, next]); - }, - (receipt, next) => { - if (!receipt) return next(); - this.plugins.emitAndRunActionsForEvent('deployment:contract:deployed', {contract, receipt}, (err, _params) => { - next(err); - }); + this.deployer["ethereum"].apply(this.deployer, [contract, (err, receipt) => { + if (!receipt) return next(err); + this.plugins.emitAndRunActionsForEvent('deployment:contract:deployed', { contract, receipt }, (err, _params) => { + next(err); + }); + }]); } ], (err) => { if (err) { diff --git a/packages/embark-ens/src/index.js b/packages/embark-ens/src/index.js index d71bfc066..202cc6af9 100644 --- a/packages/embark-ens/src/index.js +++ b/packages/embark-ens/src/index.js @@ -118,12 +118,9 @@ class ENS { this.enabled = true; this.doSetENSProvider = this.config.namesystemConfig.provider === 'ens'; - this.registerEmbarkJSNaming(); this.registerEvents(); this.registerConsoleCommands(); this.events.request2("runcode:whitelist", 'eth-ens-namehash'); - this.events.request2("runcode:whitelist", 'embarkjs'); - this.events.request2("runcode:whitelist", 'embarkjs-ens'); this.initated = true; cb(); } @@ -202,8 +199,7 @@ class ENS { setProviderAndRegisterDomains(cb = (() => {})) { this.getEnsConfig(async (config) => { if (this.doSetENSProvider) { - this.addENSArtifact(config); - this.connectEmbarkJSProvider(config); + this.setupEmbarkJS(config); } const web3 = await this.web3; @@ -219,6 +215,12 @@ class ENS { }); } + async setupEmbarkJS(config) { + this.events.request("embarkjs:plugin:register", 'names', 'ens', 'embarkjs-ens'); + await this.events.request2("embarkjs:console:register", 'names', 'ens', 'embarkjs-ens'); + this.events.request("embarkjs:console:setProvider", 'names', 'ens', config); + } + associateStorageToEns(options, cb) { const self = this; // Code inspired by https://github.com/monkybrain/ipfs-to-ens @@ -417,47 +419,6 @@ class ENS { ); } - addENSArtifact(config, cb = () => {}) { - const code = ` - var EmbarkJS; - if (typeof EmbarkJS === 'undefined') { - EmbarkJS = require('embarkjs'); - } - const __embarkENS = require('embarkjs-ens'); - EmbarkJS.Names.registerProvider('ens', __embarkENS.default || __embarkENS); - EmbarkJS.Names.setProvider('ens', ${JSON.stringify(config)}); - `; - - this.events.request("pipeline:register", { - path: [this.config.embarkConfig.generationDir, 'ens'], - file: 'init.js', - format: 'js', - content: code - }, cb); - - } - - async registerEmbarkJSNaming() { - const checkEmbarkJS = `return (typeof EmbarkJS === 'undefined');`; - const EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS); - - if (EmbarkJSNotDefined) { - await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs')); - } - - const registerProviderCode = ` - const __embarkENS = require('embarkjs-ens'); - EmbarkJS.Names.registerProvider('ens', __embarkENS.default || __embarkENS); - `; - - await this.events.request2('runcode:eval', registerProviderCode); - } - - async connectEmbarkJSProvider(config) { - let providerCode = `\nEmbarkJS.Names.setProvider('ens', ${JSON.stringify(config)});`; - await this.events.request2('runcode:eval', providerCode); - } - async configureContractsAndRegister(_options, cb) { const NO_REGISTRATION = 'NO_REGISTRATION'; const self = this; diff --git a/packages/embark-ipfs/src/index.js b/packages/embark-ipfs/src/index.js index b0ef32517..b05f56d22 100644 --- a/packages/embark-ipfs/src/index.js +++ b/packages/embark-ipfs/src/index.js @@ -39,13 +39,8 @@ class IPFS { return; } - this.events.request("runcode:whitelist", 'ipfs-api', () => {}); - this.events.request("runcode:whitelist", 'embarkjs', () => {}); - this.events.request("runcode:whitelist", 'embarkjs-ipfs', () => {}); - this.events.on("storage:started", this.registerIpfsObject.bind(this)); - this.events.on("storage:started", this.connectEmbarkJSProvider.bind(this)); - - this.embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSIpfsArtifact.bind(this)); + this.setupIpfsApi(); + this.setupEmbarkJS(); this.events.request("storage:node:register", "ipfs", (readyCb) => { this.events.request('processes:register', 'storage', { @@ -72,8 +67,35 @@ class IPFS { upload_ipfs.deploy(readyCb); }); + } - this.registerEmbarkJSStorage(); + async setupIpfsApi() { + this.events.request("runcode:whitelist", 'ipfs-api', () => {}); + this.events.on("storage:started", this.registerIpfsObject.bind(this)); + this.registerIpfsObject(); + this.registerIpfsHelp(); + } + + async registerIpfsObject() { + const {host, port} = this.config; + let ipfs = IpfsApi(host, port); + await this.events.request2("runcode:register", "ipfs", ipfs); + } + + async registerIpfsHelp() { + await this.events.request2('console:register:helpCmd', { + cmdName: "ipfs", + cmdHelp: __("instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)") + }); + } + + async setupEmbarkJS() { + this.events.request("embarkjs:plugin:register", 'storage', 'ipfs', 'embarkjs-ipfs'); + await this.events.request2("embarkjs:console:register", 'storage', 'ipfs', 'embarkjs-ipfs'); + this.events.on("storage:started", () => { + let config = this.embark.config.storageConfig.dappConnection || []; + this.events.request("embarkjs:console:setProvider", 'storage', 'ipfs', config); + }); } get config() { @@ -115,61 +137,6 @@ class IPFS { return this._enabled; } - async addEmbarkJSIpfsArtifact(params, cb) { - const code = ` - var EmbarkJS; - if (typeof EmbarkJS === 'undefined') { - EmbarkJS = require('embarkjs'); - } - const __embarkIPFS = require('embarkjs-ipfs'); - EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS); - EmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3}); - `; - this.events.request("pipeline:register", { - path: [this.embarkConfig.generationDir, 'storage'], - file: 'init.js', - format: 'js', - content: code - }, cb); - } - - async registerIpfsObject() { - const {host, port} = this.config; - let ipfs = IpfsApi(host, port); - await this.events.request2("runcode:register", "ipfs", ipfs); - this.registerIpfsHelp(); - } - - async registerIpfsHelp() { - await this.events.request2('console:register:helpCmd', { - cmdName: "ipfs", - cmdHelp: __("instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)") - }); - } - - async registerEmbarkJSStorage() { - let checkEmbarkJS = ` - return (typeof EmbarkJS === 'undefined'); - `; - let EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS); - - if (EmbarkJSNotDefined) { - await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs')); - } - - const registerProviderCode = ` - const __embarkIPFS = require('embarkjs-ipfs'); - EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS.default || __embarkIPFS); - `; - - await this.events.request2('runcode:eval', registerProviderCode); - } - - async connectEmbarkJSProvider() { - let providerCode = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});`; - await this.events.request2('runcode:eval', providerCode); - } - registerServiceCheck() { this.events.on('check:backOnline:IPFS', () => { this.logger.info(__('IPFS node detected') + '...'); diff --git a/packages/embark-namesystem/src/index.js b/packages/embark-namesystem/src/index.js index b74344945..cebfdef82 100644 --- a/packages/embark-namesystem/src/index.js +++ b/packages/embark-namesystem/src/index.js @@ -1,9 +1,12 @@ import {__} from 'embark-i18n'; +import {canonicalHost, defaultHost} from 'embark-utils'; export default class Namesystem { constructor(embark, _options) { this.embark = embark; this.events = this.embark.events; + this.embarkConfig = embark.config.embarkConfig; + this.namesystemConfig = this.embark.config.namesystemConfig; this.namesystemNodes = {}; this.events.setCommandHandler("namesystem:node:register", (clientName, startCb) => { @@ -22,5 +25,15 @@ export default class Namesystem { } ]); }); + embark.registerActionForEvent("pipeline:generateAll:before", this.addArtifactFile.bind(this)); + } + + addArtifactFile(_params, cb) { + this.events.request("pipeline:register", { + path: [this.embarkConfig.generationDir, 'config'], + file: 'namesystem.json', + format: 'json', + content: this.namesystemConfig + }, cb); } } diff --git a/packages/embark-swarm/src/index.js b/packages/embark-swarm/src/index.js index 3de3065ab..49c071b84 100644 --- a/packages/embark-swarm/src/index.js +++ b/packages/embark-swarm/src/index.js @@ -1,10 +1,10 @@ import {__} from 'embark-i18n'; +import {buildUrlFromConfig} from 'embark-utils'; const UploadSwarm = require('./upload.js'); const SwarmAPI = require('swarm-api'); const StorageProcessesLauncher = require('./storageProcessesLauncher'); const constants = require('embark-core/constants'); require('colors'); -import {buildUrlFromConfig} from 'embark-utils'; class Swarm { @@ -50,17 +50,12 @@ class Swarm { }); }); - this.events.request("runcode:whitelist", 'swarm-api', () => {}); - this.events.request("runcode:whitelist", 'embarkjs', () => {}); - this.events.request("runcode:whitelist", 'embarkjs-swarm', () => {}); - this.events.on("storage:started", this.registerSwarmObject.bind(this)); - this.events.on("storage:started", this.connectEmbarkJSProvider.bind(this)); - - this.embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSSwarmArtifact.bind(this)); - this.providerUrl = buildUrlFromConfig(this.config); this.swarm = new SwarmAPI({gateway: this.providerUrl}); + this.setupSwarmAPI(); + this.setupEmbarkJS(); + this.events.request("storage:node:register", "swarm", (readyCb) => { this.events.request("processes:register", "storage", { launchFn: (cb) => { @@ -96,8 +91,27 @@ class Swarm { upload_swarm.deploy(readyCb); }); + } - this.registerEmbarkJSStorage(); + setupSwarmAPI() { + this.events.request("runcode:whitelist", 'swarm-api', () => {}); + this.events.on("storage:started", async () => { + await this.events.request2("runcode:register", "swarm", this.swarm); + await this.events.request2('console:register:helpCmd', { + cmdName: "swarm", + cmdHelp: __("instantiated swarm-api object configured to the current environment (available if swarm is enabled)") + }); + }); + } + + async setupEmbarkJS() { + this.events.request("embarkjs:plugin:register", 'storage', 'swarm', 'embarkjs-swarm'); + await this.events.request2("embarkjs:console:register", 'storage', 'swarm', 'embarkjs-swarm'); + + this.events.on("storage:started", () => { + let config = this.embark.config.storageConfig.dappConnection || []; + this.events.request("embarkjs:console:setProvider", 'storage', 'swarm', config); + }); } get config() { @@ -138,60 +152,6 @@ class Swarm { return this._enabled; } - async addEmbarkJSSwarmArtifact(params, cb) { - const code = ` - var EmbarkJS; - if (typeof EmbarkJS === 'undefined') { - EmbarkJS = require('embarkjs'); - } - const __embarkSwarm = require('embarkjs-swarm'); - EmbarkJS.Storage.registerProvider('swarm', __embarkSwarm.default || __embarkSwarm); - EmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3}); - `; - this.events.request("pipeline:register", { - path: [this.embarkConfig.generationDir, 'storage'], - file: 'init.js', - format: 'js', - content: code - }, cb); - } - - async registerSwarmObject() { - await this.events.request2("runcode:register", "swarm", this.swarm); - this.registerSwarmHelp(); - } - - async registerSwarmHelp() { - await this.events.request2('console:register:helpCmd', { - cmdName: "swarm", - cmdHelp: __("instantiated swarm-api object configured to the current environment (available if swarm is enabled)") - }); - } - - async registerEmbarkJSStorage() { - let checkEmbarkJS = ` - return (typeof EmbarkJS === 'undefined'); - `; - let embarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS); - - if (embarkJSNotDefined) { - await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs')); - } - - const registerProviderCode = ` - const __embarkSwarm = require('embarkjs-swarm'); - EmbarkJS.Storage.registerProvider('swarm', __embarkSwarm.default || __embarkSwarm); - `; - - await this.events.request2('runcode:eval', registerProviderCode); - } - - async connectEmbarkJSProvider() { - // TODO: should initialize its own object web3 instead of relying on a global one - let providerCode = `\nEmbarkJS.Storage.setProviders(${JSON.stringify(this.embark.config.storageConfig.dappConnection || [])}, {web3});`; - await this.events.request2('runcode:eval', providerCode); - } - registerServiceCheck() { this.events.on('check:backOnline:Swarm', () => { this.logger.info(__('Swarm node detected...')); diff --git a/packages/embark-web3/src/embarkjs-contract-artifact.js.ejs b/packages/embark-web3/src/embarkjs-contract-artifact.js.ejs new file mode 100644 index 000000000..b913a39bd --- /dev/null +++ b/packages/embark-web3/src/embarkjs-contract-artifact.js.ejs @@ -0,0 +1,6 @@ +import EmbarkJS from '../embarkjs': + +const <%- className %>Config = <%- JSON.stringify(contract) %>; +const <%- className %> = new EmbarkJS.Blockchain.Contract(<%- className %>Config); + +export default <%- className %>; diff --git a/packages/embark-web3/src/index.js b/packages/embark-web3/src/index.js index 818ac5e8a..98e0976ad 100644 --- a/packages/embark-web3/src/index.js +++ b/packages/embark-web3/src/index.js @@ -1,5 +1,3 @@ -/* global __dirname module process require */ - const {__} = require('embark-i18n'); const Web3 = require('web3'); const async = require('async'); @@ -17,30 +15,43 @@ class EmbarkWeb3 { this.embark = embark; this.logger = embark.logger; this.events = embark.events; - this.fs = embark.fs; this.config = embark.config; - this.events.request("runcode:whitelist", 'web3', () => { }); + this.setupWeb3Api(); + this.setupEmbarkJS(); - this.events.on("blockchain:started", this.registerWeb3Object.bind(this)); - embark.registerActionForEvent("pipeline:generateAll:before", this.addWeb3Artifact.bind(this)); embark.registerActionForEvent("deployment:contract:deployed", this.registerInVm.bind(this)); embark.registerActionForEvent("deployment:contract:undeployed", this.registerInVm.bind(this)); embark.registerActionForEvent("deployment:contract:deployed", this.registerArtifact.bind(this)); embark.registerActionForEvent("deployment:contract:undeployed", this.registerArtifact.bind(this)); + } - this.registerWeb3Help(); + async setupEmbarkJS() { + this.events.request("embarkjs:plugin:register", 'blockchain', 'web3', 'embarkjs-web3'); + await this.events.request2("embarkjs:console:register", 'blockchain', 'web3', 'embarkjs-web3'); + this.events.on("blockchain:started", async () => { + await this.registerWeb3Object() + this.events.request("embarkjs:console:setProvider", 'blockchain', 'web3', '{web3}'); + }); + } + + async setupWeb3Api() { + this.events.request("runcode:whitelist", 'web3', () => { }); + this.events.on("blockchain:started", this.registerWeb3Object.bind(this)); } async registerWeb3Object() { + const checkWeb3 = `return (typeof web3 === 'undefined');`; + const web3NotDefined = await this.events.request2('runcode:eval', checkWeb3); + + if (!web3NotDefined) return; + const provider = await this.events.request2("blockchain:client:provider", "ethereum"); const web3 = new Web3(provider); await this.events.request2("runcode:register", 'web3', web3); const accounts = await web3.eth.getAccounts(); await this.events.request2('runcode:eval', `web3.eth.defaultAccount = '${accounts[0]}'`); - } - async registerWeb3Help() { await this.events.request2('console:register:helpCmd', { cmdName: "web3", cmdHelp: __("instantiated web3.js object configured to the current environment") @@ -48,60 +59,11 @@ class EmbarkWeb3 { } async registerInVm(params, cb) { - let contract = params.contract; - let abi = JSON.stringify(contract.abiDefinition); - let gasLimit = 6000000; - const provider = await this.events.request2("blockchain:client:provider", "ethereum"); - let contractCode = Templates.vanilla_contract({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit, provider: provider }); - - try { - await this.events.request2('runcode:eval', contractCode); - let result = await this.events.request2('runcode:eval', contract.className); - result.currentProvider = provider; - await this.events.request2("runcode:register", contract.className, result); - cb(); - } catch (err) { - cb(err); - } - } - - addWeb3Artifact(_params, cb) { - async.map(this.config.contractsConfig.dappConnection, (conn, mapCb) => { - if (conn === '$EMBARK') { - // Connect to Embark's endpoint (proxy) - return this.events.request("proxy:endpoint:get", mapCb); - } - mapCb(null, conn); - }, (err, results) => { - if (err) { - this.logger.error(__('Error getting dapp connection')); - return cb(err); - } - let web3Code = Templates.web3_init({connectionList: results}); - - // TODO: generate a .node file - this.events.request("pipeline:register", { - path: [this.embarkConfig.generationDir, 'contracts'], - file: 'web3_init.js', - format: 'js', - content: web3Code - }, cb); - }); + this.events.request("embarkjs:contract:runInVm", params.contract, cb); } registerArtifact(params, cb) { - let contract = params.contract; - let abi = JSON.stringify(contract.abiDefinition); - let gasLimit = 6000000; - - let contractCode = Templates.contract_artifact({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit }); - - this.events.request("pipeline:register", { - path: [this.embarkConfig.generationDir, 'contracts'], - file: contract.className + '.js', - format: 'js', - content: contractCode - }, cb); + this.events.request("embarkjs:contract:generate", params.contract, cb); } } diff --git a/packages/embark-whisper/src/api.js b/packages/embark-whisper/src/api.js index 5a74d30cb..f4299bef2 100644 --- a/packages/embark-whisper/src/api.js +++ b/packages/embark-whisper/src/api.js @@ -1,6 +1,8 @@ +import {buildUrlFromConfig, canonicalHost, defaultHost} from 'embark-utils'; const {parallel} = require('async'); const {fromEvent} = require('rxjs'); const {map, takeUntil} = require('rxjs/operators'); +const Web3 = require('web3'); import whisper from 'embarkjs-whisper'; @@ -9,15 +11,25 @@ const listenTo = whisper.real_listenTo; class API { - constructor(embark, web3) { + constructor(embark) { this.embark = embark; this.logger = embark.logger; - this.web3 = web3; - this.registerAPICalls(); + this.communicationConfig = embark.config.communicationConfig; + + embark.events.on("blockchain:started", this.registerAPICalls.bind(this)); } - registerAPICalls() { + async registerAPICalls() { const self = this; + + const connection = this.communicationConfig.connection || {}; + const config = { + host: canonicalHost(connection.host || defaultHost), + port: connection.port || '8546', + type: connection.type || 'ws' + }; + this.web3 = new Web3(buildUrlFromConfig(config)); + if (self.apiCallsRegistered) { return; } diff --git a/packages/embark-whisper/src/index.js b/packages/embark-whisper/src/index.js index 32eb0568d..a8cb34048 100644 --- a/packages/embark-whisper/src/index.js +++ b/packages/embark-whisper/src/index.js @@ -1,6 +1,5 @@ import { __ } from 'embark-i18n'; import {dappPath, canonicalHost, defaultHost} from 'embark-utils'; -let Web3 = require('web3'); const constants = require('embark-core/constants'); const API = require('./api.js'); @@ -11,28 +10,22 @@ class Whisper { this.fs = embark.fs; this.communicationConfig = embark.config.communicationConfig; this.embarkConfig = embark.config.embarkConfig; - this.web3 = new Web3(); this.embark = embark; - this.web3Ready = false; this.webSocketsChannels = {}; this.modulesPath = dappPath(embark.config.embarkConfig.generationDir, constants.dappArtifacts.symlinkDir); - this.api = new API(embark, this.web3); + this.api = new API(embark); this.api.registerAPICalls(); - this.events.request("runcode:whitelist", 'embarkjs', () => { }); - this.events.request("runcode:whitelist", 'embarkjs-whisper', () => { }); + this.events.request("embarkjs:plugin:register", 'messages', 'whisper', 'embarkjs-whisper'); + this.events.request("embarkjs:console:register", 'messages', 'whisper', 'embarkjs-whisper'); // TODO: should launch its own whisper node // this.events.on("communication:started", this.connectEmbarkJSProvider.bind(this)); this.events.on("blockchain:started", this.connectEmbarkJSProvider.bind(this)); - embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSWhisperArtifact.bind(this)); - this.events.request("communication:node:register", "whisper", (readyCb) => { // TODO: should launch its own whisper node - console.dir("--- whisper readyCb"); - console.dir('--- registering whisper node'); // this.events.request('processes:register', 'communication', { // launchFn: (cb) => { // this.startProcess(cb); @@ -44,51 +37,6 @@ class Whisper { // }); // this.registerServiceCheck() }); - - this.registerEmbarkJSCommunication(); - } - - async addEmbarkJSWhisperArtifact(params, cb) { - let connection = this.communicationConfig.connection || {}; - const config = { - server: canonicalHost(connection.host || defaultHost), - port: connection.port || '8546', - type: connection.type || 'ws' - }; - - const code = ` - var EmbarkJS; - if (typeof EmbarkJS === 'undefined') { - EmbarkJS = require('embarkjs'); - } - const __embarkWhisper = require('embarkjs-whisper'); - EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper); - EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)}); - `; - this.events.request("pipeline:register", { - path: [this.embarkConfig.generationDir, 'storage'], - file: 'init.js', - format: 'js', - content: code - }, cb); - } - - async registerEmbarkJSCommunication() { - let checkEmbarkJS = ` - return (typeof EmbarkJS === 'undefined'); - `; - let EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS); - - if (EmbarkJSNotDefined) { - await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs')); - } - - const registerProviderCode = ` - const __embarkWhisper = require('embarkjs-whisper'); - EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper); - `; - - await this.events.request2('runcode:eval', registerProviderCode); } async connectEmbarkJSProvider() { @@ -98,11 +46,8 @@ class Whisper { port: connection.port || '8546', type: connection.type || 'ws' }; - const code = ` - EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)}); - `; - await this.events.request2('runcode:eval', code); + this.events.request("embarkjs:console:setProvider", 'messages', 'whisper', config); } } diff --git a/packages/embark/src/cmd/cmd_controller.js b/packages/embark/src/cmd/cmd_controller.js index 1e7bfb5bb..76f368b03 100644 --- a/packages/embark/src/cmd/cmd_controller.js +++ b/packages/embark/src/cmd/cmd_controller.js @@ -162,6 +162,7 @@ class EmbarkController { engine.registerModuleGroup("stackComponents"); // TODO: replace with individual plugins + engine.registerModuleGroup("namesystem"); engine.registerModuleGroup("blockchain"); engine.registerModuleGroup("compiler"); engine.registerModuleGroup("contracts"); @@ -171,7 +172,6 @@ class EmbarkController { engine.registerModuleGroup("storage"); engine.registerModuleGroup("communication"); engine.registerModuleGroup("cockpit"); - engine.registerModuleGroup("namesystem"); engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins}); const plugin = engine.plugins.createPlugin('cmdcontrollerplugin', {}); diff --git a/packages/embark/src/lib/core/engine.js b/packages/embark/src/lib/core/engine.js index ee107caa1..a917b00d7 100644 --- a/packages/embark/src/lib/core/engine.js +++ b/packages/embark/src/lib/core/engine.js @@ -168,6 +168,7 @@ class Engine { this.registerModule('communication'); this.registerModulePackage('embark-namesystem'); this.registerModulePackage('embark-process-logs-api-manager'); + this.registerModule('embark-embarkjs', {plugins: this.plugins}); } blockchainComponents() { diff --git a/packages/embark/src/lib/core/events.js b/packages/embark/src/lib/core/events.js index 4c55fb7a5..608e122d9 100644 --- a/packages/embark/src/lib/core/events.js +++ b/packages/embark/src/lib/core/events.js @@ -12,6 +12,7 @@ function warnIfLegacy(eventName) { } function getOrigin() { + if (!(process && process.env && process.env.DEBUGEVENTS)) return ""; let origin = ((new Error().stack).split("at ")[3]).trim(); origin = origin.split("(")[0].trim(); return origin; @@ -118,6 +119,14 @@ EmbarkEmitter.prototype.request2 = function() { this._emit('request:' + requestName, ...other_args); }); + let ogStack = (new Error().stack); + + promise.catch((e) => { + console.dir(ogStack); + log("\n======== Exception ========", requestName, "\n " + ogStack + "\n=============="); + return e; + }); + return promise; }; diff --git a/packages/embark/src/lib/modules/blockchain/index.js b/packages/embark/src/lib/modules/blockchain/index.js index 8b03f682f..ddb4a71f7 100644 --- a/packages/embark/src/lib/modules/blockchain/index.js +++ b/packages/embark/src/lib/modules/blockchain/index.js @@ -51,6 +51,7 @@ class Blockchain { return cb(err); } let config = { + provider: contractsConfig.library || 'web3', dappConnection: results, dappAutoEnable: contractsConfig.dappAutoEnable, warnIfMetamask: this.blockchainConfig.isDev, diff --git a/packages/embark/src/lib/modules/communication/index.js b/packages/embark/src/lib/modules/communication/index.js index 1ab468b67..ae33dc349 100644 --- a/packages/embark/src/lib/modules/communication/index.js +++ b/packages/embark/src/lib/modules/communication/index.js @@ -1,4 +1,5 @@ import { __ } from 'embark-i18n'; +import {canonicalHost, defaultHost} from 'embark-utils'; class Communication { constructor(embark, _options){ @@ -29,15 +30,14 @@ class Communication { } addArtifactFile(_params, cb) { - let config = { - // TODO: for consistency we should change this to be dappConnection or connection - connection: this.communicationConfig.connection - }; + const connection = this.communicationConfig.connection; + this.communicationConfig.connection.server = canonicalHost(connection.host || defaultHost); + this.events.request("pipeline:register", { path: [this.embarkConfig.generationDir, 'config'], file: 'communication.json', format: 'json', - content: config + content: this.communicationConfig }, cb); } diff --git a/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-artifact.js.ejs b/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-artifact.js.ejs new file mode 100644 index 000000000..a9380fc64 --- /dev/null +++ b/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-artifact.js.ejs @@ -0,0 +1,44 @@ +import EmbarkJS from 'embarkjs'; + +<% for (let pluginName in (plugins['messages'] || [])) { %> +const __embark<%- pluginName %> = require('<%- plugins['messages'][pluginName] %>'); +EmbarkJS.Messages.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>); +<% }; %> + +<% for (let pluginName in (plugins['storage'] || [])) { %> +const __embark<%- pluginName %> = require('<%- plugins['storage'][pluginName] %>'); +EmbarkJS.Storage.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>); +<% }; %> + +<% for (let pluginName in (plugins['blockchain'] || [])) { %> +const __embark<%- pluginName %> = require('<%- plugins['blockchain'][pluginName] %>'); +EmbarkJS.Blockchain.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>); +<% }; %> + +<% for (let pluginName in (plugins['names'] || [])) { %> +const __embark<%- pluginName %> = require('<%- plugins['names'][pluginName] %>'); +EmbarkJS.Names.registerProvider('<%- pluginName %>', __embark<%- pluginName %>.default || __embark<%- pluginName %>); +<% }; %> + +<% if (plugins['messages'] && Object.values(plugins['messages']).length > 0) { %> +const communicationConfig = require('./config/communication.json'); +EmbarkJS.Messages.setProvider(communicationConfig.provider, communicationConfig.connection); +<% }; %> + +<% if (plugins['storage'] && Object.values(plugins['storage']).length > 0) { %> +const storageConfig = require('./config/storage.json'); +EmbarkJS.Storage.setProviders(storageConfig.dappConnection); +<% }; %> + +<% if (plugins['blockchain'] && Object.values(plugins['blockchain']).length > 0) { %> +const blockchainConfig = require('./config/blockchain.json'); +EmbarkJS.Blockchain.setProvider(blockchainConfig.provider, {}); +EmbarkJS.Blockchain.connect(blockchainConfig, (err) => {if (err) { console.error(err); } }); +<% }; %> + +<% if (plugins['names'] && Object.values(plugins['names']).length > 0) { %> +const namesConfig = require('./config/namesystem.json'); +EmbarkJS.Names.setProvider(namesConfig.provider, namesConfig); +<% }; %> + +export default EmbarkJS; diff --git a/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-console-contract.js.ejs b/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-console-contract.js.ejs new file mode 100644 index 000000000..bde4621b0 --- /dev/null +++ b/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-console-contract.js.ejs @@ -0,0 +1,2 @@ +<%- className %>Config = <%- JSON.stringify(contract) %>; +<%- className %> = new EmbarkJS.Blockchain.Contract(<%- className %>Config); diff --git a/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-contract-artifact.js.ejs b/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-contract-artifact.js.ejs new file mode 100644 index 000000000..6c85d4519 --- /dev/null +++ b/packages/embark/src/lib/modules/embark-embarkjs/embarkjs-contract-artifact.js.ejs @@ -0,0 +1,6 @@ +import EmbarkJS from '../embarkjs'; + +const <%- className %>Config = <%- JSON.stringify(contract) %>; +const <%- className %> = new EmbarkJS.Blockchain.Contract(<%- className %>Config); + +export default <%- className %>; diff --git a/packages/embark/src/lib/modules/embark-embarkjs/index.js b/packages/embark/src/lib/modules/embark-embarkjs/index.js new file mode 100644 index 000000000..7c9805aa2 --- /dev/null +++ b/packages/embark/src/lib/modules/embark-embarkjs/index.js @@ -0,0 +1,130 @@ +import {__} from 'embark-i18n'; + +require('ejs'); +const Templates = { + embarkjs_artifact: require('./embarkjs-artifact.js.ejs'), + embarkjs_contract_artifact: require('./embarkjs-contract-artifact.js.ejs'), + embarkjs_console_contract: require('./embarkjs-console-contract.js.ejs') +}; + +class EmbarkJS { + + constructor(embark, _options) { + this.embark = embark; + this.embarkConfig = embark.config.embarkConfig; + this.events = embark.events; + this.logger = embark.logger; + + this.events.request("runcode:whitelist", 'embarkjs', () => { + this.registerEmbarkJS(); + }); + + this.embarkJSPlugins = {}; + this.events.setCommandHandler("embarkjs:plugin:register", (stackName, pluginName, packageName) => { + this.embarkJSPlugins[stackName] = this.embarkJSPlugins[stackName] || {}; + this.embarkJSPlugins[stackName][pluginName] = packageName; + }); + + this.events.setCommandHandler("embarkjs:console:register", (stackName, pluginName, packageName, cb) => { + this.events.request("runcode:whitelist", packageName, () => { }); + this.registerEmbarkJSPlugin(stackName, pluginName, packageName, cb || (() => {})); + }); + + 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:runInVm", this.runInVm.bind(this)); + + embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSArtifact.bind(this)); + } + + async registerEmbarkJS() { + const checkEmbarkJS = `return (typeof EmbarkJS === 'undefined');`; + const embarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS); + + if (!embarkJSNotDefined) return; + await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs')); + } + + async registerEmbarkJSPlugin(stackName, pluginName, packageName, cb) { + await this.registerEmbarkJS(); + + let moduleName = stackName; + if (moduleName === 'messages') moduleName = 'Messages'; + if (moduleName === 'storage') moduleName = 'Storage'; + if (moduleName === 'blockchain') moduleName = 'Blockchain'; + if (moduleName === 'names') moduleName = 'Names'; + + const registerProviderCode = ` + const __embark_${stackName}_${pluginName} = require('${packageName}'); + EmbarkJS.${moduleName}.registerProvider('${pluginName}', __embark_${stackName}_${pluginName}.default || __embark_${stackName}_${pluginName}); + `; + + await this.events.request2('runcode:eval', registerProviderCode); + cb(); + } + + addEmbarkJSArtifact(_params, cb) { + let embarkjsCode = Templates.embarkjs_artifact({ plugins: this.embarkJSPlugins }); + + // TODO: generate a .node file + this.events.request("pipeline:register", { + path: [this.embarkConfig.generationDir], + file: 'embarkjs.js', + format: 'js', + content: embarkjsCode + }, cb); + } + + async setProvider(stackName, pluginName, config) { + let moduleName = stackName; + if (moduleName === 'messages') moduleName = 'Messages'; + if (moduleName === 'storage') moduleName = 'Storage'; + if (moduleName === 'blockchain') moduleName = 'Blockchain'; + if (moduleName === 'names') moduleName = 'Names'; + + let code = ""; + if (stackName === 'storage') { + code = `EmbarkJS.${moduleName}.setProviders(${JSON.stringify(config)});`; + } else if (stackName === 'blockchain') { + code = `EmbarkJS.${moduleName}.setProvider('${pluginName}', ${config});`; + } else { + code = `EmbarkJS.${moduleName}.setProvider('${pluginName}', ${JSON.stringify(config)});`; + } + await this.events.request2('runcode:eval', code); + } + + async addContractArtifact(contract, cb) { + const abi = JSON.stringify(contract.abiDefinition); + const gasLimit = 6000000; + + const contractCode = Templates.embarkjs_contract_artifact({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit }); + + this.events.request("pipeline:register", { + path: [this.embarkConfig.generationDir, 'contracts'], + file: contract.className + '.js', + format: 'js', + content: contractCode + }, cb); + } + + async runInVm(contract, cb) { + const abi = contract.abiDefinition; + const gasLimit = 6000000; + const provider = await this.events.request2("blockchain:client:provider", "ethereum"); + const contractCode = Templates.embarkjs_console_contract({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit, provider: provider }); + + try { + await this.registerEmbarkJS(); + await this.events.request2('runcode:eval', contractCode); + const result = await this.events.request2('runcode:eval', contract.className); + result.currentProvider = provider; + await this.events.request2("runcode:register", contract.className, result); + cb(); + } catch (err) { + cb(err); + } + } + +} + +module.exports = EmbarkJS; diff --git a/packages/embarkjs-ens/src/index.js b/packages/embarkjs-ens/src/index.js index 0dfaf38f0..364414e5e 100644 --- a/packages/embarkjs-ens/src/index.js +++ b/packages/embarkjs-ens/src/index.js @@ -1,5 +1,6 @@ /* global global require */ -const EmbarkJS = global.EmbarkJS || require('embarkjs'); +let EmbarkJS = global.EmbarkJS || require('embarkjs'); +EmbarkJS = EmbarkJS.default || EmbarkJS; const ENSFunctions = require('./ENSFunctions').default; const Web3 = require('web3'); const namehash = require('eth-ens-namehash'); @@ -159,6 +160,7 @@ __embarkENS.setProvider = function(config) { self.registration = config.registration; self.env = config.env; self.ready = false; + // FIXME EmbarkJS.onReady doesn't work. Possibility of a race condition EmbarkJS.Blockchain.blockchainConnector.getNetworkId() .then((id) => { diff --git a/packages/embarkjs-swarm/package.json b/packages/embarkjs-swarm/package.json index b3f137287..5f9077513 100644 --- a/packages/embarkjs-swarm/package.json +++ b/packages/embarkjs-swarm/package.json @@ -51,7 +51,8 @@ }, "dependencies": { "@babel/runtime-corejs2": "7.3.1", - "swarm-api": "0.1.2" + "swarm-api": "0.1.2", + "web3": "1.0.0-beta.37" }, "devDependencies": { "@babel/cli": "7.2.3", diff --git a/packages/embarkjs-swarm/src/index.js b/packages/embarkjs-swarm/src/index.js index 146667bf6..08c0c81bf 100644 --- a/packages/embarkjs-swarm/src/index.js +++ b/packages/embarkjs-swarm/src/index.js @@ -1,5 +1,6 @@ -let __embarkSwarm = {_swarmConnection: undefined}; +const __embarkSwarm = {_swarmConnection: undefined}; let SwarmAPI = require('swarm-api'); +const Web3 = require('web3'); if (SwarmAPI.default) { SwarmAPI = SwarmAPI.default; } @@ -13,15 +14,15 @@ __embarkSwarm.setProvider = function (options) { this._connectError = new Error(`Cannot connect to Swarm node on ${this._connectUrl}`); return new Promise((resolve, reject) => { - if(!options.web3) { - reject(__("A web3 object must be passed in to __embarkSwarm.setProvider")); + let web3; + if (!options.web3) { + web3 = new Web3(this._connectUrl); } - const {web3, useOnlyGivenProvider} = options; try { - if (!web3.bzz.currentProvider && !useOnlyGivenProvider) { + if (!web3.bzz.currentProvider) { this._swarmConnection = new SwarmAPI({gateway: this._connectUrl}); } - else if (useOnlyGivenProvider && web3.bzz.givenProvider !== null) { + else { this._swarmConnection = new SwarmAPI({gateway: web3.bzz.givenProvider}); } resolve(this); diff --git a/packages/embarkjs/src/blockchain.js b/packages/embarkjs/src/blockchain.js index 223badeed..e41ee879d 100644 --- a/packages/embarkjs/src/blockchain.js +++ b/packages/embarkjs/src/blockchain.js @@ -221,8 +221,8 @@ let Contract = function(options) { var self = this; var ContractClass; - this.abi = options.abi; - this.address = options.address; + this.abi = options.abi || options.abiDefinition; + this.address = options.address || options.deployedAddress; this.gas = options.gas; this.code = '0x' + options.code; diff --git a/packages/embarkjs/src/storage.js b/packages/embarkjs/src/storage.js index fb3696ae0..47c13603b 100644 --- a/packages/embarkjs/src/storage.js +++ b/packages/embarkjs/src/storage.js @@ -78,7 +78,7 @@ Storage.setProviders = function (dappConnOptions, addlOpts) { detectSeries(dappConnOptions, (dappConn, callback) => { let options = dappConn; if (dappConn === '$BZZ') options = {"useOnlyGivenProvider": true}; - options = {...options, ...addlOpts}; + options = {...options, ...addlOpts, ...dappConn}; try { self.setProvider(dappConn === '$BZZ' ? dappConn : dappConn.provider, options).then(() => { self.isAvailable().then((isAvailable) => {