diff --git a/dapps/tests/app/test/simple_storage_deploy_spec.js b/dapps/tests/app/test/simple_storage_deploy_spec.js index 6975294b2f..66ff6bc7cd 100644 --- a/dapps/tests/app/test/simple_storage_deploy_spec.js +++ b/dapps/tests/app/test/simple_storage_deploy_spec.js @@ -6,14 +6,10 @@ contract("SimpleStorage Deploy", function () { let simpleStorageInstance; before(function() { return new Promise(async (resolve, reject) => { - const gas = await SimpleStorage.deploy({arguments: [150]}).estimateGas(); - Utils.secureSend(web3, SimpleStorage.deploy({arguments: [150]}), {gas, from: web3.eth.defaultAccount}, true, function(err, receipt) { - if(err) { - return reject(err); - } - simpleStorageInstance = SimpleStorage; - simpleStorageInstance.options.address = receipt.contractAddress; + SimpleStorage.deploy([150]); + SimpleStorage.deployed().then(instance => { + simpleStorageInstance = instance; resolve(); }); }); diff --git a/packages/embarkjs/embarkjs/src/lib/blockchain.js b/packages/embarkjs/embarkjs/src/lib/blockchain.js index a34202c950..953046c05c 100644 --- a/packages/embarkjs/embarkjs/src/lib/blockchain.js +++ b/packages/embarkjs/embarkjs/src/lib/blockchain.js @@ -1,6 +1,7 @@ /* global ethereum */ -import {reduce} from './async'; +import { reduce } from './async'; +import utils from './utils'; let Blockchain = { Contract: Contract, @@ -244,7 +245,7 @@ function Contract(options) { this.abi = options.abi || options.abiDefinition; this.address = options.address || options.deployedAddress; this.gas = options.gas; - this.code = '0x' + options.code; + this.code = utils.hexPrefix(options.code); this.blockchainConnector = Blockchain.blockchainConnector; @@ -311,40 +312,50 @@ function Contract(options) { } }); + // Assign helpers too + for(const method of ["deploy", "new", "at", "send", "deployed"]) { + // Make sure we don't override original methods here. + if (originalMethods.includes(method)) { + console.log(method + " is a reserved word and will not be aliased as a helper"); + continue; + } + + ContractClass[method] = Contract.prototype[method].bind(this); + } + + this.contractClass = ContractClass; + return ContractClass; } -Contract.prototype.deploy = function(args, _options) { - var self = this; - var contractParams; - var options = _options || {}; - - contractParams = args || []; +Contract.prototype.deploy = function(args, _options, _txOptions) { + const self = this; + const options = Object.assign({ + arguments: args || [], + data: this.code + }, _options); - contractParams.push({ + const txOptions = Object.assign({ from: this.blockchainConnector.getDefaultAccount(), - data: this.code, - gas: options.gas || 800000 + gas: this.gas + }, _txOptions); + + const contract = this.blockchainConnector.newContract({abi: this.abi}); + + this._deployPromise = new Promise((resolve, reject) => { + contract.deploy.apply(contract, [options]).send(txOptions).then(instance => { + resolve(new Contract({ + abi: self.abi, + code: self.code, + address: instance.options.address + })); + + // Delete the deploy promise as we don't need to track it anymore. + delete self._deployPromise; + }).catch(reject); }); - - const contractObject = this.blockchainConnector.newContract({abi: this.abi}); - - return new Promise(function (resolve, reject) { - contractParams.push(function(err, transaction) { - if (err) { - reject(err); - } else if (transaction.address !== undefined) { - resolve(new Contract({ - abi: self.abi, - code: self.code, - address: transaction.address - })); - } - }); - - contractObject["new"].apply(contractObject, contractParams); - }); + return this._deployPromise; }; Contract.prototype.new = Contract.prototype.deploy; @@ -369,6 +380,24 @@ Contract.prototype.send = function(value, unit, _options) { return this.blockchainConnector.send(options); }; +Contract.prototype.deployed = function() { + if (this.address === undefined && this._deployPromise === undefined) { + const err = Error("contract deployment hasn't happened yet"); + return Promise.reject(err); + } + + // This keeps the original deploy promise so we can fire it as soon as web3 tells us + // it's done. + if (this._deployPromise) { + return this._deployPromise; + } + + // Already deployed, just resolve. + return Promise.resolve(this); +}; + +Blockchain.Contract = Contract; + class BlockchainConnectionError extends Error { constructor(connectionErrors) { super("Could not establish a connection to a node."); diff --git a/packages/embarkjs/embarkjs/src/lib/utils.js b/packages/embarkjs/embarkjs/src/lib/utils.js index dc434af17f..d3f31a17d8 100644 --- a/packages/embarkjs/embarkjs/src/lib/utils.js +++ b/packages/embarkjs/embarkjs/src/lib/utils.js @@ -3,6 +3,12 @@ const Web3 = global.Web3 || require('web3'); let Utils = { + hexPrefix: function(str) { + if (!(str && str.match)) return; + if (str.match(/^0x/)) return str; + + return `0x${str}`; + }, fromAscii: function(str) { var _web3 = new Web3(); return _web3.utils ? _web3.utils.fromAscii(str) : _web3.fromAscii(str); diff --git a/packages/embarkjs/web3/src/index.js b/packages/embarkjs/web3/src/index.js index e4e3b5f5cd..886d2ac9c1 100644 --- a/packages/embarkjs/web3/src/index.js +++ b/packages/embarkjs/web3/src/index.js @@ -48,11 +48,12 @@ __embarkWeb3.newContract = function (options) { }; __embarkWeb3.send = function () { + console.log('ARGUEMTNS', ...arguments); return this.web3.eth.sendTransaction(...arguments); }; __embarkWeb3.toWei = function () { - return this.web3.toWei(...arguments); + return this.web3.utils.toWei(...arguments); }; __embarkWeb3.getNetworkId = function () { diff --git a/packages/plugins/mocha-tests/src/lib/index.js b/packages/plugins/mocha-tests/src/lib/index.js index fe6032a2bd..4c33f40f7e 100644 --- a/packages/plugins/mocha-tests/src/lib/index.js +++ b/packages/plugins/mocha-tests/src/lib/index.js @@ -131,6 +131,7 @@ class MochaTestRunner { compiledContracts[contract.className] = {}; } instance.options.from = accounts[0]; + instance.options.code = contract.code; instance.options.gas = GAS_LIMIT; Object.setPrototypeOf(compiledContracts[contract.className], instance); }