diff --git a/docs/web3-eth-contract.rst b/docs/web3-eth-contract.rst index 6c6d14b..58b9a4e 100644 --- a/docs/web3-eth-contract.rst +++ b/docs/web3-eth-contract.rst @@ -197,6 +197,44 @@ Example ------------------------------------------------------------------------------ +clone +===================== + +.. code-block:: javascript + + myContract.clone() + +Clones the current contract instance. + +---------- +Parameters +---------- + +none + +------- +Returns +------- + + +``Object``: The new contract instance. + +------- +Example +------- + +.. code-block:: javascript + + var contract1 = new eth.Contract(abi, address, {gasPrice: '12345678', from: fromAddress}); + + var contract2 = contract1.clone(); + contract2.options.address = address2; + + (contract1.options.address !== contract2.options.address); + > true + +------------------------------------------------------------------------------ + .. _contract-deploy: diff --git a/packages/web3-eth-contract/src/index.js b/packages/web3-eth-contract/src/index.js index 7aa2c65..cd5be28 100644 --- a/packages/web3-eth-contract/src/index.js +++ b/packages/web3-eth-contract/src/index.js @@ -51,27 +51,27 @@ var Contract = function(jsonInterface, address, options) { var _this = this, args = Array.prototype.slice.call(arguments); - if(!(this instanceof Contract)) + if(!(this instanceof Contract)) { throw new Error('Please use the "new" keyword to instantiate a web3.eth.contract() object!'); + } - if(!jsonInterface || !(jsonInterface instanceof Array)) + if(!jsonInterface || !(jsonInterface instanceof Array)) { throw new Error('You must provide the json interface of the contract when instatiating a contract object.'); + } - // get the options object + + // create the options object this.options = {}; + if(utils.isObject(args[args.length - 1])) { options = args[args.length - 1]; - this.options.data = options.data; - this.options.from = options.from; - this.options.gasPrice = options.gasPrice; - this.options.gas = options.gas || options.gasLimit; + this.options = _.extend(this.options, this._fillWithDefaultOptions(options)); if(utils.isObject(address)) { address = null; } } - // set address Object.defineProperty(this.options, 'address', { set: function(value){ @@ -203,15 +203,17 @@ Contract.prototype._checkListener = function(type, event){ * @return {Object} the options with gaps filled by defaults */ Contract.prototype._fillWithDefaultOptions = function fillWithDefaultOptions(options) { + var gasPrice = options.gasPrice ? String(options.gasPrice): null; options.data = options.data || this.options.data; - options.from = options.from || this.options.from; if(utils.isAddress(options.from)) options.from = options.from.toLowerCase(); - options.gasPrice = options.gasPrice || this.options.gasPrice; + options.from = options.from || this.options.from; + options.gasPrice = gasPrice || this.options.gasPrice; options.gas = options.gas || options.gasLimit || this.options.gas; + // TODO replace with only gasLimit? delete options.gasLimit; @@ -508,7 +510,18 @@ Contract.prototype._generateEventOptions = function() { /** * Adds event listeners and creates a subscription, and remove it once its fired. * - * @method on + * @method clone + * @return {Object} the event subscription + */ +Contract.prototype.clone = function() { + return new Contract(this.options.jsonInterface, this.options.address, this.options); +}; + + +/** + * Adds event listeners and creates a subscription, and remove it once its fired. + * + * @method once * @param {String} event * @param {Object} options * @param {Function} callback @@ -540,7 +553,7 @@ Contract.prototype.once = function(event, options, callback) { /** * Adds event listeners and creates a subscription. * - * @method on + * @method _on * @param {String} event * @param {Object} options * @param {Function} callback diff --git a/test/contract.js b/test/contract.js index fca21f3..e8fdbbb 100644 --- a/test/contract.js +++ b/test/contract.js @@ -113,6 +113,44 @@ describe('contract', function () { assert.throws(test); }); + it('.clone() should properly clone the contract instance', function () { + var provider = new FakeHttpProvider(); + var eth = new Eth(provider); + var fromAddress = '0xDDfFD0A3C12e86b4b5f39B213f7e19d048276daE'; + var abi2 = [{ + "name": "ballerRo", + "type": "function", + "inputs": [{ + "name": "So", + "type": "address" + }], + "constant": true, + "outputs": [{ + "name": "man", + "type": "uint256" + }] + }]; + + var contract1 = new eth.Contract(abi, address, {gas: 1222, gasPrice: 12345678, from: fromAddress}); + var contract2 = contract1.clone(); + + assert.equal(contract1.options.address, address); + assert.equal(contract1.options.gas, 1222); + assert.equal(contract1.options.gasPrice, '12345678'); + assert.deepEqual(contract1.options.jsonInterface, abi); + + + contract2.options.jsonInterface = abi2; + contract2.options.address = fromAddress; + contract2.options.gas = 300; + contract2.options.gasPrice = '234234'; + + assert.isFunction(contract2.methods.ballerRo); + assert.equal(contract2.options.address, fromAddress); + assert.equal(contract2.options.gas, 300); + assert.equal(contract2.options.gasPrice, '234234'); + assert.deepEqual(contract2.options.jsonInterface, abi2); + }); }); describe('internal method', function () { it('_encodeEventABI should return the encoded event object without topics', function () {