UNPKG

aelf-sdk-lys1988

Version:

aelf-sdk js library

263 lines (228 loc) 8.33 kB
/* This file is part of web3.js. web3.js is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. web3.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see <http://www.gnu.org/licenses/>. */ /** * @file contract.js * @author Marek Kotewicz <marek@ethdev.com> * @date 2014 */ var utils = require('../../utils/utils'); var ContractMethod = require('./method.js'); /** * Should be called to add functions to contract object * * @method addFunctionsToContract * @param {Contract} contract * @param {Array} abi */ var addMethodsToContract = function (contract, wallet) { contract.abi.Methods.map(function (methodAbi) { return new ContractMethod(contract._chain, methodAbi, contract.address, wallet); }).forEach(function (f) { f.attachToContract(contract); }); }; /** * Should be called to check if the contract gets properly deployed on the blockchain. * * @method checkForContractAddress * @param {Object} contract * @param {Function} callback * @returns {Undefined} */ var checkForContractAddress = function(contract, wallet, callback){ var count = 0, callbackFired = false; // wait for receipt var filter = contract._eth.filter('latest', function(e){ if (!e && !callbackFired) { count++; // stop watching after 50 blocks (timeout) if (count > 50) { filter.stopWatching(function() {}); callbackFired = true; if (callback) callback(new Error('Contract transaction couldn\'t be found after 50 blocks')); else throw new Error('Contract transaction couldn\'t be found after 50 blocks'); } else { contract._eth.getTransactionReceipt(contract.transactionHash, function(e, receipt){ if(receipt && receipt.blockHash && !callbackFired) { contract._eth.getCode(receipt.contractAddress, function(e, code){ /*jshint maxcomplexity: 6 */ if(callbackFired || !code) return; filter.stopWatching(function() {}); callbackFired = true; if(code.length > 3) { // console.log('Contract code deployed!'); contract.address = receipt.contractAddress; // attach events and methods again after we have addMethodsToContract(contract, wallet); // call callback for the second time if(callback) callback(null, contract); } else { if(callback) callback(new Error('The contract code couldn\'t be stored, please check your gas amount.')); else throw new Error('The contract code couldn\'t be stored, please check your gas amount.'); } }); } }); } } }); }; /** * Should be called to create new ContractFactory instance * * @method ContractFactory * @param {Array} abi */ var ContractFactory = function (chain, abi, wallet) { this.chain = chain; this.abi = abi; this.wallet = wallet; /** * Should be called to create new contract on a blockchain * * @method new * @param {Any} contract constructor param1 (optional) * @param {Any} contract constructor param2 (optional) * @param {Object} contract transaction object (required) * @param {Function} callback * @returns {Contract} returns contract instance */ // this.new = function () { // /*jshint maxcomplexity: 7 */ // // var contract = new Contract(this.chain, this.abi); // // // parse arguments // var options = {}; // required! // var callback; // // var args = Array.prototype.slice.call(arguments); // if (utils.isFunction(args[args.length - 1])) { // callback = args.pop(); // } // // var last = args[args.length - 1]; // if (utils.isObject(last) && !utils.isArray(last)) { // options = args.pop(); // } // // // if (options.value > 0) { // // var constructorAbi = abi.filter(function (json) { // // return json.type === 'constructor' && json.inputs.length === args.length; // // })[0] || {}; // // // if (!constructorAbi.payable) { // // throw new Error('Cannot send value to non-payable constructor'); // // } // // } // // var bytes = encodeConstructorParams(this.abi, args); // options.data += bytes; // // if (callback) { // // // wait for the contract address and check if the code was deployed // this.eth.sendTransaction(options, function (err, hash) { // if (err) { // callback(err); // } else { // // add the transaction hash // contract.transactionHash = hash; // // // call callback for the first time // callback(null, contract); // // checkForContractAddress(contract, this.wallet, callback); // } // }); // } else { // var hash = this.eth.sendTransaction(options); // // add the transaction hash // contract.transactionHash = hash; // checkForContractAddress(contract, this.wallet); // } // // return contract; // }; // // this.new.getData = this.getData.bind(this); }; /** * Should be called to create new ContractFactory * * @method contract * @param {Array} abi * @returns {ContractFactory} new contract factory */ //var contract = function (abi) { //return new ContractFactory(abi); //}; /** * Should be called to get access to existing contract on a blockchain * * @method at * @param {Address} contract address (required) * @param {Function} callback {optional) * @returns {Contract} returns contract if no callback was passed, * otherwise calls callback function (err, contract) */ ContractFactory.prototype.at = function (address, callback) { var contract = new Contract(this.chain, this.abi, address); // this functions are not part of prototype, // because we dont want to spoil the interface addMethodsToContract(contract, this.wallet); //console.log("address: ", address); //console.log("abi: ", this.abi); if (callback) { callback(null, contract); } return contract; }; /** * Gets the data, which is data to deploy plus constructor params * * @method getData */ ContractFactory.prototype.getData = function () { var options = {}; // required! var args = Array.prototype.slice.call(arguments); var last = args[args.length - 1]; if (utils.isObject(last) && !utils.isArray(last)) { options = args.pop(); } var bytes = encodeConstructorParams(this.abi, args); options.data += bytes; return options.data; }; /** * Should be called to create new contract instance * * @method Contract * @param {Array} abi * @param {Address} contract address */ var Contract = function (chain, abi, address) { this._chain = chain; this.transactionHash = null; this.address = address; this.abi = abi; }; module.exports = ContractFactory;