Skip to content

Commit

Permalink
feat(@embark/plugins): introduce API to register a contract factory
Browse files Browse the repository at this point in the history
This commit introduces two new plugin APIs `registerTestContractFactory()` and
`registerCustomContractGenerator()`, which can be used to register a factory function
for the creation of web3 contract instances within tests, and custom code generation
  for `embark console` respectively.

Example:

```
// some.plugin.js

module.exports = function (embark) {
  embark.registerTestContractFactory(function (contractRecipe, web3) {
    // do something with web3 and contractRecipe and return contract instance here
  });
};
```

**Notice that**:

- This factory function is used for contract instance creation within tests.
  A `contractRecipe` and a `web3` instance is accessible within the factory.

Example:

```
// some.plugin.js

module.exports = function (embark) {
  embark.registerCustomContractGenerator(function (contractRecipe) {
    // returns code string that will be eval'ed
  });
};
```

**Notice that**:

- Once registered, this generator will be used for **all** contract instances
  that will be created for `embark console`, including built-in once like
  ENSRegistry.

- While this does affect contract creation in client-side code, it doesn't
  actually affect the instances created for deployment hooks **if** deployment
  hooks are written as functions.

Closes #1066
  • Loading branch information
0x-r4bbit committed Nov 30, 2018
1 parent 0a380bd commit 4aa2451
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 13 deletions.
12 changes: 12 additions & 0 deletions src/lib/core/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ var Plugin = function(options) {
this.clientWeb3Providers = [];
this.beforeDeploy = [];
this.contractsGenerators = [];
this.generateCustomContractCode = null;
this.testContractFactory = null;
this.pipeline = [];
this.pipelineFiles = [];
this.console = [];
Expand Down Expand Up @@ -120,6 +122,16 @@ Plugin.prototype.registerContractsGeneration = function(cb) {
this.addPluginType('contractGeneration');
};

Plugin.prototype.registerCustomContractGenerator = function (cb) {
this.generateCustomContractCode = cb;
this.addPluginType('customContractGeneration');
};

Plugin.prototype.registerTestContractFactory = function(cb) {
this.testContractFactory = cb;
this.addPluginType('testContractFactory');
};

Plugin.prototype.registerPipeline = function(matcthingFiles, cb) {
// TODO: generate error for more than one pipeline per plugin
this.pipeline.push({matcthingFiles: matcthingFiles, cb: cb});
Expand Down
12 changes: 12 additions & 0 deletions src/lib/modules/code_generator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class CodeGenerator {
cb(self.generateContractCode(contract, gasLimit));
});

self.events.setCommandHandler('code-generator:contract:custom', (contract, cb) => {
cb(self.generateCustomContractCode(contract));
});

self.events.setCommandHandler('code-generator:embarkjs:provider-code', (cb) => {
cb(self.getEmbarkJsProviderCode());
});
Expand Down Expand Up @@ -171,6 +175,14 @@ class CodeGenerator {
return block;
}

generateCustomContractCode(contract) {
const customContractGeneratorPlugin = this.plugins.getPluginsFor('customContractGeneration').splice(-1)[0];
if (!customContractGeneratorPlugin) {
return null;
}
return customContractGeneratorPlugin.generateCustomContractCode(contract);
}

generateNamesInitialization(useEmbarkJS) {
if (!useEmbarkJS || this.namesystemConfig === {}) return "";

Expand Down
42 changes: 30 additions & 12 deletions src/lib/modules/deployment/contract_deployer.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,18 @@ class ContractDeployer {
contract.deployedAddress = trackedContract.address;
self.events.emit("deploy:contract:deployed", contract);

// TODO: can be moved into a afterDeploy event
// just need to figure out the gasLimit coupling issue
self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit || false, (contractCode) => {
self.events.request('runcode:eval', contractCode, () => {}, true);
return callback();
self.events.request('code-generator:contract:custom', contract, (customContractCode) => {
if (!customContractCode) {
// TODO: can be moved into a afterDeploy event
// just need to figure out the gasLimit coupling issue
self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit || false, (contractCode) => {
self.events.request('runcode:eval', contractCode, () => {}, true);
return callback();
});
} else {
self.events.request('runcode:eval', customContractCode, () => {}, true);
return callback();
}
});
}

Expand Down Expand Up @@ -306,14 +313,25 @@ class ContractDeployer {
self.events.emit("deploy:contract:receipt", receipt);
self.events.emit("deploy:contract:deployed", contract);

// TODO: can be moved into a afterDeploy event
// just need to figure out the gasLimit coupling issue
self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit || false, (contractCode) => {
self.events.request('runcode:eval', contractCode, () => {}, true);
self.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, () => {
return next(null, receipt);
});

self.events.request('code-generator:contract:custom', contract, (customContractCode) => {
if (!customContractCode) {
// TODO: can be moved into a afterDeploy event
// just need to figure out the gasLimit coupling issue
self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit || false, (contractCode) => {
self.events.request('runcode:eval', contractCode, () => {}, true);
self.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, () => {
return next(null, receipt);
});
});
} else {
self.events.request('runcode:eval', customContractCode, () => {}, true);
self.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, () => {
return next(null, receipt);
});
}
});

});
}
], callback);
Expand Down
5 changes: 4 additions & 1 deletion src/lib/modules/tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Test {
this.options = options || {};
this.simOptions = {};
this.events = options.events;
this.plugins = options.config.plugins;
this.logger = options.logger;
this.ipc = options.ipc;
this.configObj = options.config;
Expand Down Expand Up @@ -268,7 +269,9 @@ class Test {
self.contracts[contract.className] = {};
}

const newContract = Test.getWeb3Contract(contract, web3);
const testContractFactoryPlugin = self.plugins.getPluginsFor('testContractFactory').slice(-1)[0];

const newContract = testContractFactoryPlugin ? testContractFactoryPlugin.testContractFactory(contract, web3) : Test.getWeb3Contract(contract, web3);
Object.setPrototypeOf(self.contracts[contract.className], newContract);

eachCb();
Expand Down

0 comments on commit 4aa2451

Please sign in to comment.