feat: support selecting what library to generate artifacts

feat: support selecting what library to generate artifacts

feat: support selecting what library to generate artifacts

feat: support selecting what library to generate artifacts

feat: support selecting what library to generate artifacts

working web3 artifacts

remove unnecessary request

address code review issues

fixes

update tests

WIP: add index.js in packages/plugins/embarkjs/

This is a pattern established in #2285

remove comment

fix some code review issues
This commit is contained in:
Iuri Matias 2020-02-07 15:24:16 -05:00
parent db9e959169
commit ee1eb4ed96
25 changed files with 169 additions and 51 deletions

View File

@ -4,7 +4,14 @@ import EmbarkJS from 'Embark/EmbarkJS';
// e.g if you have a contract named SimpleStorage:
//import SimpleStorage from 'Embark/contracts/SimpleStorage';
EmbarkJS.onReady((err) => {
// You can execute contract calls after the connection
});
// OR if using "library: 'web3'" in config/contracts.js
// import web3 from '../../embarkArtifacts/web3.js';
// import SimpleStorage from '../embarkArtifacts/contracts/SimpleStorage';
// web3.onReady(async () => {
// let accounts = await web3.eth.getAccounts();
//})

View File

@ -1,6 +1,8 @@
module.exports = {
// default applies to all environments
default: {
library: 'embarkjs', // can also be 'web3'
// order of connections the dapp should connect to
dappConnection: [
"$EMBARK",

View File

@ -1,6 +1,8 @@
module.exports = {
// default applies to all environments
default: {
library: 'embarkjs', // can be also be 'web3'
// order of connections the dapp should connect to
dappConnection: [
"$EMBARK",

View File

@ -47,6 +47,7 @@ export function getContractDefaults(embarkConfigVersions) {
return {
default: {
library: "embarkjs",
versions,
dappConnection: [
"$WEB3",

View File

@ -22,6 +22,9 @@
{
"path": "../../plugins/debugger"
},
{
"path": "../../plugins/embarkjs"
},
{
"path": "../../plugins/ens"
},
@ -88,9 +91,6 @@
{
"path": "../../stack/deployment"
},
{
"path": "../../stack/embarkjs"
},
{
"path": "../../stack/library-manager"
},

View File

@ -212,6 +212,7 @@ describe('embark.Config', function () {
dappConnection: ['$WEB3', 'ws://localhost:8546', 'localhost:8545'],
dappAutoEnable: true,
"gas": "400000",
"library": "embarkjs",
"strategy": "implicit",
"contracts": {
"SimpleStorage": {
@ -234,6 +235,7 @@ describe('embark.Config', function () {
dappConnection: ['$WEB3', 'ws://localhost:8546', 'localhost:8545'],
dappAutoEnable: true,
"gas": "auto",
"library": "embarkjs",
"strategy": "implicit",
"contracts": {
"SimpleStorage": {

View File

@ -0,0 +1 @@
module.exports = require('./dist');

View File

@ -4,7 +4,7 @@
"author": "Iuri Matias <iuri.matias@gmail.com>",
"contributors": [],
"description": "EmbarkJS APIs for Embark",
"homepage": "https://github.com/embarklabs/embark/tree/master/packages/stack/embarkjs#readme",
"homepage": "https://github.com/embarklabs/embark/tree/master/packages/plugins/embarkjs#readme",
"bugs": "https://github.com/embarklabs/embark/issues",
"keywords": [
"blockchain",
@ -21,7 +21,7 @@
],
"license": "MIT",
"repository": {
"directory": "packages/stack/embarkjs",
"directory": "packages/plugins/embarkjs",
"type": "git",
"url": "https://github.com/embarklabs/embark.git"
},
@ -50,7 +50,8 @@
"ejs": "2.6.1",
"embark-core": "^5.3.0-nightly.7",
"embark-i18n": "^5.3.0-nightly.5",
"embarkjs": "^5.3.0-nightly.6"
"embarkjs": "^5.3.0-nightly.6",
"web3": "1.2.6"
},
"devDependencies": {
"embark-solo": "^5.2.3",

View File

@ -1,4 +1,5 @@
import {__} from 'embark-i18n';
import Web3 from 'web3';
require('ejs');
const Templates = {
@ -9,17 +10,21 @@ const Templates = {
class EmbarkJS {
constructor(embark, _options) {
constructor(embark) {
this.embark = embark;
this.embarkConfig = embark.config.embarkConfig;
this.blockchainConfig = embark.config.blockchainConfig;
this.events = embark.events;
this.logger = embark.logger;
this.config = embark.config;
this.contractArtifacts = {};
this.enabled = true;
this.events.request("runcode:whitelist", 'embarkjs', () => {
this.registerEmbarkJS();
});
// note: since other plugins like ens currently expect these command handlers to exist
// we used a condition instead just returning immediatly so that the handlers still exist
if (!this.config.blockchainConfig.enabled || this.config.contractsConfig.library !== 'embarkjs') {
this.enabled = false;
}
this.embarkJSPlugins = {};
this.customEmbarkJSPlugins = {};
@ -46,11 +51,61 @@ class EmbarkJS {
this.events.setCommandHandler("embarkjs:contract:generate", this.addContractArtifact.bind(this));
this.events.setCommandHandler("embarkjs:contract:runInVm", this.runInVm.bind(this));
if (!this.enabled) return;
this.events.request("runcode:whitelist", 'embarkjs', () => {
this.registerEmbarkJS();
});
embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSArtifact.bind(this));
embark.registerActionForEvent("pipeline:generateAll:before", this.addContractIndexArtifact.bind(this));
this.setupEmbarkJS();
embark.registerActionForEvent("deployment:contract:deployed", {priority: 40}, 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));
}
async setupEmbarkJS() {
this.events.on("blockchain:started", async () => {
await this.registerWeb3Object();
this.events.request("embarkjs:console:setProvider", 'blockchain', 'web3', '{web3}');
});
this.events.request("embarkjs:plugin:register", 'blockchain', 'web3', 'embarkjs-web3');
await this.events.request2("embarkjs:console:register", 'blockchain', 'web3', 'embarkjs-web3');
}
async registerWeb3Object() {
if (!this.enabled) return;
const provider = await this.events.request2("blockchain:client:provider", "ethereum");
const web3 = new Web3(provider);
this.events.request("runcode:whitelist", 'web3', () => {});
await this.events.request2("runcode:register", 'web3', web3);
const accounts = await web3.eth.getAccounts();
if (accounts.length) {
await this.events.request2('runcode:eval', `web3.eth.defaultAccount = '${accounts[0]}'`);
}
this.events.request('console:register:helpCmd', {
cmdName: "web3",
cmdHelp: __("instantiated web3.js object configured to the current environment")
}, () => {});
}
async registerInVm(params, cb) {
if (!this.enabled) return;
this.events.request("embarkjs:contract:runInVm", params.contract, cb);
}
registerArtifact(params, cb) {
if (!this.enabled) return;
this.events.request("embarkjs:contract:generate", params.contract, cb);
}
async registerEmbarkJS() {
if (!this.enabled) return;
const checkEmbarkJS = `return (typeof EmbarkJS === 'undefined');`;
const embarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS);
@ -59,6 +114,7 @@ class EmbarkJS {
}
async registerEmbarkJSPlugin(stackName, pluginName, packageName, cb) {
if (!this.enabled) return cb();
await this.registerEmbarkJS();
let moduleName = stackName;
@ -77,6 +133,7 @@ class EmbarkJS {
}
async registerCustomEmbarkJSPluginInVm(stackName, pluginName, packageName, options, cb) {
if (!this.enabled) return cb();
await this.registerEmbarkJS();
const customPluginCode = `
@ -92,6 +149,7 @@ class EmbarkJS {
}
addEmbarkJSArtifact(_params, cb) {
if (!this.enabled) return cb();
const embarkjsCode = Templates.embarkjs_artifact({
plugins: this.embarkJSPlugins,
hasWebserver: this.embark.config.webServerConfig.enabled,
@ -108,6 +166,7 @@ class EmbarkJS {
}
async setProvider(stackName, pluginName, config) {
if (!this.enabled) return;
let moduleName = stackName;
if (moduleName === 'messages') moduleName = 'Messages';
if (moduleName === 'storage') moduleName = 'Storage';
@ -136,6 +195,7 @@ class EmbarkJS {
}
async addContractArtifact(contract, cb) {
if (!this.enabled) return cb();
const abi = JSON.stringify(contract.abiDefinition);
const gasLimit = 6000000;
this.contractArtifacts[contract.className] = contract.className + '.js';
@ -151,6 +211,7 @@ class EmbarkJS {
}
async addContractIndexArtifact(_options, cb) {
if (!this.enabled) return cb();
let indexCode = 'module.exports = {';
Object.keys(this.contractArtifacts).forEach(className => {
indexCode += `\n"${className}": require('./${this.contractArtifacts[className]}').default,`;
@ -166,6 +227,7 @@ class EmbarkJS {
}
async runInVm(contract, cb) {
if (!this.enabled) return cb();
const abi = contract.abiDefinition;
const gasLimit = 6000000;
const provider = await this.events.request2("blockchain:client:provider", "ethereum");

View File

@ -99,12 +99,6 @@ class FunctionConfigs {
// TODO: for this to work correctly we need to add a default from address to the contract
if (contract.deploy === false) continue;
// eslint-disable-next-line no-await-in-loop
const contractRegisteredInVM = await this.checkContractRegisteredInVM(contract);
if (!contractRegisteredInVM) {
// eslint-disable-next-line no-await-in-loop
await this.events.request2("embarkjs:contract:runInVm", contract);
}
// eslint-disable-next-line no-await-in-loop
let contractInstance = await this.events.request2("runcode:eval", contract.className);
args.contracts[contract.className] = contractInstance;
}

View File

@ -1,4 +1,5 @@
<%- className %>Abi = <%- abi %>;
<%- className %>Config = <%- JSON.stringify(contract) %>;
<%- className %>Abi = <%- JSON.stringify(abi) %>;
<%- className %> = new web3.eth.Contract(<%- className %>Abi);
<%- className %>.options.address = '<%- contract.deployedAddress %>';
<%- className %>.address = '<%- contract.deployedAddress %>';

View File

@ -1,4 +1,4 @@
const web3 = require("./web3_init.js").default
const web3 = require("../web3.js").default
let <%- className %>Abi = <%- abi %>;
let <%- className %> = new web3.eth.Contract(<%- className %>Abi);
@ -6,7 +6,7 @@ let <%- className %> = new web3.eth.Contract(<%- className %>Abi);
<%- className %>.address = '<%- contract.deployedAddress %>';
<%- className %>.options.from = web3.eth.defaultAccount;
web3.execWhenReady(() => {
web3.onReady(() => {
<%- className %>.options.from = web3.eth.defaultAccount;
if (!<%- className %>.currentProvider) {
<%- className %>.setProvider(web3.currentProvider);

View File

@ -1,6 +0,0 @@
import EmbarkJS from '../embarkjs':
const <%- className %>Config = <%- JSON.stringify(contract) %>;
const <%- className %> = new EmbarkJS.Blockchain.Contract(<%- className %>Config);
export default <%- className %>;

View File

@ -2,39 +2,40 @@ const {__} = require('embark-i18n');
const Web3 = require('web3');
require('ejs');
// const Templates = {
// vanilla_contract: require('./vanilla-contract.js.ejs'),
// contract_artifact: require('./contract-artifact.js.ejs'),
// web3_init: require('./web3_init.js.ejs')
// };
const Templates = {
contract_artifact: require('./contract-artifact.js.ejs'),
web3_init: require('./web3_init.js.ejs'),
console_contract: require('./console-contract.js.ejs')
};
const GAS_LIMIT = 6000000;
class EmbarkWeb3 {
constructor(embark, _options) {
constructor(embark) {
this.embarkConfig = embark.config.embarkConfig;
this.contractsConfig = embark.config.contractsConfig;
this.embark = embark;
this.logger = embark.logger;
this.events = embark.events;
this.config = embark.config;
this.contractArtifacts = {};
if (this.config.blockchainConfig.enabled) {
this.setupEmbarkJS();
if (!this.config.blockchainConfig.enabled || this.config.contractsConfig.library !== 'web3') {
return;
}
this.events.on("blockchain:started", async () => {
await this.registerWeb3Object();
});
embark.registerActionForEvent("pipeline:generateAll:before", this.addWeb3JSArtifact.bind(this));
embark.registerActionForEvent("deployment:contract:deployed", {priority: 40}, 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));
}
async setupEmbarkJS() {
this.events.on("blockchain:started", async () => {
await this.registerWeb3Object();
this.events.request("embarkjs:console:setProvider", 'blockchain', 'web3', '{web3}');
});
this.events.request("embarkjs:plugin:register", 'blockchain', 'web3', 'embarkjs-web3');
await this.events.request2("embarkjs:console:register", 'blockchain', 'web3', 'embarkjs-web3');
}
async registerWeb3Object() {
const provider = await this.events.request2("blockchain:client:provider", "ethereum");
const web3 = new Web3(provider);
@ -52,11 +53,59 @@ class EmbarkWeb3 {
}
async registerInVm(params, cb) {
this.events.request("embarkjs:contract:runInVm", params.contract, cb);
const contract = params.contract;
const abi = contract.abiDefinition;
const gasLimit = GAS_LIMIT;
const provider = await this.events.request2("blockchain:client:provider", "ethereum");
const contractCode = Templates.console_contract({ className: contract.className, abi: abi, contract: contract, gasLimit: gasLimit, provider: provider });
try {
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);
} catch (err) {
return cb(err);
}
cb();
}
registerArtifact(params, cb) {
this.events.request("embarkjs:contract:generate", params.contract, cb);
const contract = params.contract;
const abi = JSON.stringify(contract.abiDefinition);
const gasLimit = GAS_LIMIT;
this.contractArtifacts[contract.className] = contract.className + '.js';
const 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);
}
async addWeb3JSArtifact(_params, cb) {
const dappConnection = this.contractsConfig.dappConnection;
if (dappConnection.includes('$EMBARK')) {
let endpoint = await this.events.request2('proxy:endpoint:get');
dappConnection[dappConnection.indexOf('$EMBARK')] = endpoint;
}
const web3jsCode = Templates.web3_init({
connectionList: this.contractsConfig.dappConnection,
autoEnable: this.contractsConfig.dappAutoEnable
});
// TODO: generate a .node file
this.events.request("pipeline:register", {
path: [this.embarkConfig.generationDir],
file: 'web3.js',
format: 'js',
content: web3jsCode
}, cb);
}
}

View File

@ -5,7 +5,7 @@ let web3 = new Web3();
let todo = [];
let done = false;
web3.execWhenReady = function(cb) {
web3.onReady = function(cb) {
if (done) {
return cb();
}
@ -46,7 +46,7 @@ let doConnect = function(connectionList, opts, doneCb) {
if (typeof window !== 'undefined' && window.ethereum) {
try {
if (Blockchain.autoEnable) {
if (opts.autoEnable) {
await ethereum.enable();
}
blockchainConnector.setProvider(ethereum);
@ -138,6 +138,7 @@ __whenEnvIsLoaded(() => {
let connectList = [<%- connectionList.map(x => "'" + x + "'").join(",") %>];
doConnect(connectList, {
autoEnable: <%- autoEnable %>,
warnAboutMetamask: false, // TODO: can/should be part as the code generation instead...
}, () => {
todo.forEach((x) => x.apply(x))

View File

@ -198,7 +198,8 @@ export default class Blockchain {
return cb(err);
}
const config = {
provider: contractsConfig.library || 'web3',
provider: 'web3',
library: contractsConfig.library || 'embarkjs',
dappConnection: results,
dappAutoEnable: contractsConfig.dappAutoEnable,
warnIfMetamask: this.blockchainConfig.isDev,

View File

@ -64,6 +64,9 @@
{
"path": "packages/plugins/deploy-tracker"
},
{
"path": "packages/plugins/embarkjs"
},
{
"path": "packages/plugins/ens"
},
@ -166,9 +169,6 @@
{
"path": "packages/stack/deployment"
},
{
"path": "packages/stack/embarkjs"
},
{
"path": "packages/stack/library-manager"
},