Browse Source

Squashed 'libjsqrc/ethereumjs/' changes from e908439..16861fc

16861fc version 0.4.2
e4f7dde fixed failing lint
69e7d9d fixed #133
55553d7 add async error test
d02a375 Merge branch 'develop' of github.com:ethereum/web3.js into develop
ff48da1 fixed callback error issue
471bce1 #133 in progress
dc69085 version 0.4.1
2ae0afa critical bugfix
09f2a92 updated examples
a0a36e5 Merge branch 'develop' of https://github.com/ethereum/ethereum.js into develop
2b179a8 updated node install test
8f63640 Merge pull request #203 from frozeman/develop
22ef4a1 added estimateGas method
cd2e462 version 0.4.0
ae7762a Merge pull request #198 from ethereum/minerMethods
d1e1206 removed byte formatter methods
6fd17d9 merged develop
373fd1b Merge pull request #201 from debris/batch
274fc29 Merge pull request #200 from debris/contract_overhaul
b2ff2ff Merge branch 'contract_overhaul' into batch
99a3bda removed redundant lines
7cafac9 Merge branch 'develop' into contract_overhaul
fa8db32 Merge pull request #202 from debris/async_properties
5f9272c asyncGet -> getAsync
cd0df61 gulp
80c0792 async getting properties, remove property setters
744bb9e batch for requests with calls/transacts
8636077 initial support for batch requests
a0b9cfb contract async call && transact
1272780 sendTransaction && call async
6afb1f9 Merge branch 'async-contract-calls' of https://github.com/niran/web3.js into contract_overhaul
611f640 asynchronous contract creation, breaking changes
e3796bf merged develop
edf808a add getWork and submitWork functions and toXBytes utils
9812b01 Merge branch 'blockFilterProposal' of https://github.com/ethereum/ethereum.js into develop
6f466f6 add miner functions
3af8e27 add newblockfilter Proposal
e86552f Use async contract calls when a callback is passed

git-subtree-dir: libjsqrc/ethereumjs
git-subtree-split: 16861fc1944cca721672bb8faa81909d69be2b99
cl-refactor
Marek Kotewicz 10 years ago
parent
commit
89dbcca30b
  1. 2
      bower.json
  2. 577
      dist/web3-light.js
  3. 30
      dist/web3-light.js.map
  4. 4
      dist/web3-light.min.js
  5. 579
      dist/web3.js
  6. 30
      dist/web3.js.map
  7. 4
      dist/web3.min.js
  8. 42
      example/contract.html
  9. 64
      example/event_inc.html
  10. 4
      example/node-app.js
  11. 1
      index.js
  12. 44
      lib/solidity/abi.js
  13. 45
      lib/solidity/utils.js
  14. 1
      lib/utils/utils.js
  15. 2
      lib/version.json
  16. 4
      lib/web3.js
  17. 61
      lib/web3/batch.js
  18. 162
      lib/web3/contract.js
  19. 23
      lib/web3/eth.js
  20. 77
      lib/web3/function.js
  21. 17
      lib/web3/method.js
  22. 40
      lib/web3/property.js
  23. 27
      lib/web3/requestmanager.js
  24. 15
      lib/web3/watches.js
  25. 2
      package.js
  26. 2
      package.json
  27. 106
      test/abi.formatConstructorParams.js
  28. 69
      test/async.js
  29. 86
      test/batch.js
  30. 100
      test/contract.js
  31. 23
      test/method.request.js
  32. 2
      test/node/app.js
  33. 2
      test/node/package.json
  34. 21
      test/polling.js
  35. 20
      test/web3.eth.blockNumber.js
  36. 41
      test/web3.eth.call.js
  37. 21
      test/web3.eth.contract.js
  38. 25
      test/web3.eth.estimateGas.js
  39. 10
      test/web3.eth.filter.js
  40. 16
      test/web3.eth.getWork.js
  41. 17
      test/web3.eth.submitWork.js

2
bower.json

@ -1,7 +1,7 @@
{ {
"name": "web3", "name": "web3",
"namespace": "ethereum", "namespace": "ethereum",
"version": "0.3.6", "version": "0.4.2",
"description": "Ethereum Compatible JavaScript API", "description": "Ethereum Compatible JavaScript API",
"main": [ "main": [
"./dist/web3.js", "./dist/web3.js",

577
dist/web3-light.js

@ -15,52 +15,6 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/ */
/**
* @file abi.js
* @author Marek Kotewicz <marek@ethdev.com>
* @author Gav Wood <g@ethdev.com>
* @date 2014
*/
var coder = require('./coder');
var utils = require('./utils');
var formatConstructorParams = function (abi, params) {
var constructor = utils.getConstructor(abi, params.length);
if (!constructor) {
if (params.length > 0) {
console.warn("didn't found matching constructor, using default one");
}
return '';
}
return coder.encodeParams(constructor.inputs.map(function (input) {
return input.type;
}), params);
};
module.exports = {
formatConstructorParams: formatConstructorParams
};
},{"./coder":2,"./utils":5}],2:[function(require,module,exports){
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** /**
* @file coder.js * @file coder.js
* @author Marek Kotewicz <marek@ethdev.com> * @author Marek Kotewicz <marek@ethdev.com>
@ -328,7 +282,7 @@ var coder = new SolidityCoder([
module.exports = coder; module.exports = coder;
},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){ },{"../utils/utils":6,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -548,7 +502,7 @@ module.exports = {
}; };
},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(require,module,exports){ },{"../utils/config":5,"../utils/utils":6,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -760,54 +714,7 @@ SolidityParam.decodeArray = function (bytes, index) {
module.exports = SolidityParam; module.exports = SolidityParam;
},{"../utils/utils":8}],5:[function(require,module,exports){ },{"../utils/utils":6}],4:[function(require,module,exports){
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file utils.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/**
* Returns the contstructor with matching number of arguments
*
* @method getConstructor
* @param {Array} abi
* @param {Number} numberOfArgs
* @returns {Object} constructor function abi
*/
var getConstructor = function (abi, numberOfArgs) {
return abi.filter(function (f) {
return f.type === 'constructor' && f.inputs.length === numberOfArgs;
})[0];
};
//var getSupremeType = function (type) {
//return type.substr(0, type.indexOf('[')) + ']';
//};
module.exports = {
getConstructor: getConstructor
};
},{}],6:[function(require,module,exports){
'use strict'; 'use strict';
// go env doesn't have and need XMLHttpRequest // go env doesn't have and need XMLHttpRequest
@ -818,7 +725,7 @@ if (typeof XMLHttpRequest === 'undefined') {
} }
},{}],7:[function(require,module,exports){ },{}],5:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -890,7 +797,7 @@ module.exports = {
}; };
},{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){ },{"bignumber.js":"bignumber.js"}],6:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1256,6 +1163,7 @@ var toAddress = function (address) {
return '0x' + padLeft(toHex(address).substr(2), 40); return '0x' + padLeft(toHex(address).substr(2), 40);
}; };
/** /**
* Returns true if object is BigNumber, otherwise false * Returns true if object is BigNumber, otherwise false
* *
@ -1366,12 +1274,12 @@ module.exports = {
}; };
},{"bignumber.js":"bignumber.js"}],9:[function(require,module,exports){ },{"bignumber.js":"bignumber.js"}],7:[function(require,module,exports){
module.exports={ module.exports={
"version": "0.3.6" "version": "0.4.2"
} }
},{}],10:[function(require,module,exports){ },{}],8:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1411,6 +1319,7 @@ var RequestManager = require('./web3/requestmanager');
var c = require('./utils/config'); var c = require('./utils/config');
var Method = require('./web3/method'); var Method = require('./web3/method');
var Property = require('./web3/property'); var Property = require('./web3/property');
var Batch = require('./web3/batch');
var web3Methods = [ var web3Methods = [
new Method({ new Method({
@ -1503,6 +1412,9 @@ web3.toBigNumber = utils.toBigNumber;
web3.toWei = utils.toWei; web3.toWei = utils.toWei;
web3.fromWei = utils.fromWei; web3.fromWei = utils.fromWei;
web3.isAddress = utils.isAddress; web3.isAddress = utils.isAddress;
web3.createBatch = function () {
return new Batch();
};
// ADD defaultblock // ADD defaultblock
Object.defineProperty(web3.eth, 'defaultBlock', { Object.defineProperty(web3.eth, 'defaultBlock', {
@ -1538,7 +1450,70 @@ setupMethods(web3.shh, shh.methods);
module.exports = web3; module.exports = web3;
},{"./utils/config":7,"./utils/utils":8,"./version.json":9,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":21,"./web3/net":22,"./web3/property":23,"./web3/requestmanager":25,"./web3/shh":26,"./web3/watches":27}],11:[function(require,module,exports){ },{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/batch":9,"./web3/db":11,"./web3/eth":13,"./web3/filter":15,"./web3/formatters":16,"./web3/method":20,"./web3/net":21,"./web3/property":22,"./web3/requestmanager":24,"./web3/shh":25,"./web3/watches":26}],9:[function(require,module,exports){
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file batch.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var RequestManager = require('./requestmanager');
var Batch = function () {
this.requests = [];
};
/**
* Should be called to add create new request to batch request
*
* @method add
* @param {Object} jsonrpc requet object
*/
Batch.prototype.add = function (request) {
this.requests.push(request);
};
/**
* Should be called to execute batch request
*
* @method execute
*/
Batch.prototype.execute = function () {
var requests = this.requests;
RequestManager.getInstance().sendBatch(requests, function (err, results) {
results = results || [];
requests.map(function (request, index) {
return results[index] || {};
}).map(function (result, index) {
return requests[index].format ? requests[index].format(result.result) : result.result;
}).forEach(function (result, index) {
if (requests[index].callback) {
requests[index].callback(err, result);
}
});
});
};
module.exports = Batch;
},{"./requestmanager":24}],10:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1562,13 +1537,39 @@ module.exports = web3;
*/ */
var web3 = require('../web3'); var web3 = require('../web3');
var solAbi = require('../solidity/abi');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var coder = require('../solidity/coder');
var SolidityEvent = require('./event'); var SolidityEvent = require('./event');
var SolidityFunction = require('./function'); var SolidityFunction = require('./function');
var addFunctionsToContract = function (contract, desc) { /**
desc.filter(function (json) { * Should be called to encode constructor params
*
* @method encodeConstructorParams
* @param {Array} abi
* @param {Array} constructor params
*/
var encodeConstructorParams = function (abi, params) {
return abi.filter(function (json) {
return json.type === 'constructor' && json.inputs.length === params.length;
}).map(function (json) {
return json.inputs.map(function (input) {
return input.type;
});
}).map(function (types) {
return coder.encodeParams(types, params);
})[0] || '';
};
/**
* Should be called to add functions to contract object
*
* @method addFunctionsToContract
* @param {Contract} contract
* @param {Array} abi
*/
var addFunctionsToContract = function (contract, abi) {
abi.filter(function (json) {
return json.type === 'function'; return json.type === 'function';
}).map(function (json) { }).map(function (json) {
return new SolidityFunction(json, contract.address); return new SolidityFunction(json, contract.address);
@ -1577,8 +1578,15 @@ var addFunctionsToContract = function (contract, desc) {
}); });
}; };
var addEventsToContract = function (contract, desc) { /**
desc.filter(function (json) { * Should be called to add events to contract object
*
* @method addEventsToContract
* @param {Contract} contract
* @param {Array} abi
*/
var addEventsToContract = function (contract, abi) {
abi.filter(function (json) {
return json.type === 'event'; return json.type === 'event';
}).map(function (json) { }).map(function (json) {
return new SolidityEvent(json, contract.address); return new SolidityEvent(json, contract.address);
@ -1588,65 +1596,106 @@ var addEventsToContract = function (contract, desc) {
}; };
/** /**
* This method should be called when we want to call / transact some solidity method from javascript * Should be called to create new ContractFactory
* it returns an object which has same methods available as solidity contract description
* usage example:
*
* var abi = [{
* name: 'myMethod',
* inputs: [{ name: 'a', type: 'string' }],
* outputs: [{name: 'd', type: 'string' }]
* }]; // contract abi
* *
* var MyContract = web3.eth.contract(abi); // creation of contract prototype * @method contract
* * @param {Array} abi
* var contractInstance = new MyContract('0x0123123121'); * @returns {ContractFactory} new contract factory
*
* contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)
* contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)
* contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction
*
* @param abi - abi json description of the contract, which is being created
* @returns contract object
*/ */
var contract = function (abi) { var contract = function (abi) {
return new ContractFactory(abi);
};
// return prototype /**
return Contract.bind(null, abi); * Should be called to create new ContractFactory instance
*
* @method ContractFactory
* @param {Array} abi
*/
var ContractFactory = function (abi) {
this.abi = abi;
}; };
var Contract = function (abi, options) { /**
* 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 if no callback was passed,
* otherwise calls callback function (err, contract)
*/
ContractFactory.prototype.new = function () {
// parse arguments
var options = {}; // required!
var callback;
this.address = ''; var args = Array.prototype.slice.call(arguments);
if (utils.isAddress(options)) { if (utils.isFunction(args[args.length - 1])) {
this.address = options; callback = args.pop();
} else { // is an object! }
// TODO, parse the rest of the args
options = options || {}; var last = args[args.length - 1];
var args = Array.prototype.slice.call(arguments, 2); if (utils.isObject(last) && !utils.isArray(last)) {
var bytes = solAbi.formatConstructorParams(abi, args); options = args.pop();
}
// throw an error if there are no options
var bytes = encodeConstructorParams(this.abi, args);
options.data += bytes; options.data += bytes;
this.address = web3.eth.sendTransaction(options);
if (!callback) {
var address = web3.eth.sendTransaction(options);
return this.at(address);
} }
addFunctionsToContract(this, abi); var self = this;
addEventsToContract(this, abi); web3.eth.sendTransaction(options, function (err, address) {
if (err) {
callback(err);
}
self.at(address, callback);
});
}; };
Contract.prototype.call = function () { /**
console.error('contract.call is deprecated'); * Should be called to get access to existing contract on a blockchain
return this; *
* @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) {
// TODO: address is required
if (callback) {
callback(null, new Contract(this.abi, address));
}
return new Contract(this.abi, address);
}; };
Contract.prototype.sendTransaction = function () { /**
console.error('contract.sendTransact is deprecated'); * Should be called to create new contract instance
return this; *
* @method Contract
* @param {Array} abi
* @param {Address} contract address
*/
var Contract = function (abi, address) {
this.address = address;
addFunctionsToContract(this, abi);
addEventsToContract(this, abi);
}; };
module.exports = contract; module.exports = contract;
},{"../solidity/abi":1,"../utils/utils":8,"../web3":10,"./event":15,"./function":18}],12:[function(require,module,exports){ },{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./event":14,"./function":17}],11:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1704,7 +1753,7 @@ module.exports = {
methods: methods methods: methods
}; };
},{"./method":21}],13:[function(require,module,exports){ },{"./method":20}],12:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1744,7 +1793,7 @@ module.exports = {
}; };
},{}],14:[function(require,module,exports){ },{}],13:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1921,6 +1970,14 @@ var call = new Method({
inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter] inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]
}); });
var estimateGas = new Method({
name: 'estimateGas',
call: 'eth_estimateGas',
params: 1,
inputFormatter: [formatters.inputTransactionFormatter],
outputFormatter: utils.toDecimal
});
var compileSolidity = new Method({ var compileSolidity = new Method({
name: 'compile.solidity', name: 'compile.solidity',
call: 'eth_compileSolidity', call: 'eth_compileSolidity',
@ -1939,6 +1996,18 @@ var compileSerpent = new Method({
params: 1 params: 1
}); });
var submitWork = new Method({
name: 'submitWork',
call: 'eth_submitWork',
params: 3
});
var getWork = new Method({
name: 'getWork',
call: 'eth_getWork',
params: 0
});
var methods = [ var methods = [
getBalance, getBalance,
getStorageAt, getStorageAt,
@ -1952,10 +2021,13 @@ var methods = [
getTransactionFromBlock, getTransactionFromBlock,
getTransactionCount, getTransactionCount,
call, call,
estimateGas,
sendTransaction, sendTransaction,
compileSolidity, compileSolidity,
compileLLL, compileLLL,
compileSerpent, compileSerpent,
submitWork,
getWork
]; ];
/// @returns an array of objects describing web3.eth api properties /// @returns an array of objects describing web3.eth api properties
@ -1998,7 +2070,7 @@ module.exports = {
}; };
},{"../utils/utils":8,"./formatters":17,"./method":21,"./property":23}],15:[function(require,module,exports){ },{"../utils/utils":6,"./formatters":16,"./method":20,"./property":22}],14:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2194,7 +2266,7 @@ SolidityEvent.prototype.attachToContract = function (contract) {
module.exports = SolidityEvent; module.exports = SolidityEvent;
},{"../solidity/coder":2,"../utils/utils":8,"../web3":10,"./formatters":17}],16:[function(require,module,exports){ },{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./formatters":16}],15:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2351,7 +2423,7 @@ Filter.prototype.get = function (callback) {
module.exports = Filter; module.exports = Filter;
},{"../utils/utils":8,"./formatters":17,"./requestmanager":25}],17:[function(require,module,exports){ },{"../utils/utils":6,"./formatters":16,"./requestmanager":24}],16:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2571,7 +2643,7 @@ module.exports = {
}; };
},{"../utils/config":7,"../utils/utils":8}],18:[function(require,module,exports){ },{"../utils/config":5,"../utils/utils":6}],17:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2613,18 +2685,23 @@ var SolidityFunction = function (json, address) {
this._address = address; this._address = address;
}; };
SolidityFunction.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array!
}
};
/** /**
* Should be used to create payload from arguments * Should be used to create payload from arguments
* *
* @method toPayload * @method toPayload
* @param {...} solidity function params * @param {Array} solidity function params
* @param {Object} optional payload options * @param {Object} optional payload options
*/ */
SolidityFunction.prototype.toPayload = function () { SolidityFunction.prototype.toPayload = function (args) {
var args = Array.prototype.slice.call(arguments);
var options = {}; var options = {};
if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {
options = args.pop(); options = args[args.length - 1];
} }
options.to = this._address; options.to = this._address;
options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);
@ -2641,19 +2718,41 @@ SolidityFunction.prototype.signature = function () {
return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); return web3.sha3(web3.fromAscii(this._name)).slice(2, 10);
}; };
SolidityFunction.prototype.unpackOutput = function (output) {
if (output === null) {
return;
}
output = output.length >= 2 ? output.slice(2) : output;
var result = coder.decodeParams(this._outputTypes, output);
return result.length === 1 ? result[0] : result;
};
/** /**
* Should be used to call function * Calls a contract function.
* *
* @method call * @method call
* @param {Object} options * @param {...Object} Contract function arguments
* @param {function} If the last argument is a function, the contract function
* call will be asynchronous, and the callback will be passed the
* error and result.
* @return {String} output bytes * @return {String} output bytes
*/ */
SolidityFunction.prototype.call = function () { SolidityFunction.prototype.call = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
if (!callback) {
var output = web3.eth.call(payload); var output = web3.eth.call(payload);
output = output.length >= 2 ? output.slice(2) : output; return this.unpackOutput(output);
var result = coder.decodeParams(this._outputTypes, output); }
return result.length === 1 ? result[0] : result;
var self = this;
web3.eth.call(payload, function (error, output) {
callback(error, self.unpackOutput(output));
});
}; };
/** /**
@ -2663,8 +2762,16 @@ SolidityFunction.prototype.call = function () {
* @param {Object} options * @param {Object} options
*/ */
SolidityFunction.prototype.sendTransaction = function () { SolidityFunction.prototype.sendTransaction = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
if (!callback) {
web3.eth.sendTransaction(payload); web3.eth.sendTransaction(payload);
return;
}
web3.eth.sendTransaction(payload, callback);
}; };
/** /**
@ -2687,6 +2794,25 @@ SolidityFunction.prototype.typeName = function () {
return utils.extractTypeName(this._name); return utils.extractTypeName(this._name);
}; };
/**
* Should be called to get rpc requests from solidity function
*
* @method request
* @returns {Object}
*/
SolidityFunction.prototype.request = function () {
var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
var format = this.unpackOutput.bind(this);
return {
callback: callback,
payload: payload,
format: format
};
};
/** /**
* Should be called to execute function * Should be called to execute function
* *
@ -2712,6 +2838,7 @@ SolidityFunction.prototype.execute = function () {
*/ */
SolidityFunction.prototype.attachToContract = function (contract) { SolidityFunction.prototype.attachToContract = function (contract) {
var execute = this.execute.bind(this); var execute = this.execute.bind(this);
execute.request = this.request.bind(this);
execute.call = this.call.bind(this); execute.call = this.call.bind(this);
execute.sendTransaction = this.sendTransaction.bind(this); execute.sendTransaction = this.sendTransaction.bind(this);
var displayName = this.displayName(); var displayName = this.displayName();
@ -2724,7 +2851,7 @@ SolidityFunction.prototype.attachToContract = function (contract) {
module.exports = SolidityFunction; module.exports = SolidityFunction;
},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(require,module,exports){ },{"../solidity/coder":1,"../utils/utils":6,"../web3":8}],18:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2816,7 +2943,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
module.exports = HttpProvider; module.exports = HttpProvider;
},{"./errors":13,"xmlhttprequest":6}],20:[function(require,module,exports){ },{"./errors":12,"xmlhttprequest":4}],19:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2909,7 +3036,7 @@ Jsonrpc.prototype.toBatchPayload = function (messages) {
module.exports = Jsonrpc; module.exports = Jsonrpc;
},{}],21:[function(require,module,exports){ },{}],20:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2966,7 +3093,6 @@ Method.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) { if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array! return args.pop(); // modify the args array!
} }
return null;
}; };
/** /**
@ -3019,6 +3145,7 @@ Method.prototype.formatOutput = function (result) {
*/ */
Method.prototype.attachToObject = function (obj) { Method.prototype.attachToObject = function (obj) {
var func = this.send.bind(this); var func = this.send.bind(this);
func.request = this.request.bind(this);
func.call = this.call; // that's ugly. filter.js uses it func.call = this.call; // that's ugly. filter.js uses it
var name = this.name.split('.'); var name = this.name.split('.');
if (name.length > 1) { if (name.length > 1) {
@ -3049,6 +3176,19 @@ Method.prototype.toPayload = function (args) {
}; };
}; };
/**
* Should be called to create pure JSONRPC request which can be used in batch request
*
* @method request
* @param {...} params
* @return {Object} jsonrpc request
*/
Method.prototype.request = function () {
var payload = this.toPayload(Array.prototype.slice.call(arguments));
payload.format = this.formatOutput.bind(this);
return payload;
};
/** /**
* Should send request to the API * Should send request to the API
* *
@ -3061,7 +3201,7 @@ Method.prototype.send = function () {
if (payload.callback) { if (payload.callback) {
var self = this; var self = this;
return RequestManager.getInstance().sendAsync(payload, function (err, result) { return RequestManager.getInstance().sendAsync(payload, function (err, result) {
payload.callback(null, self.formatOutput(result)); payload.callback(err, self.formatOutput(result));
}); });
} }
return this.formatOutput(RequestManager.getInstance().send(payload)); return this.formatOutput(RequestManager.getInstance().send(payload));
@ -3070,7 +3210,7 @@ Method.prototype.send = function () {
module.exports = Method; module.exports = Method;
},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(require,module,exports){ },{"../utils/utils":6,"./errors":12,"./requestmanager":24}],21:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3120,7 +3260,7 @@ module.exports = {
}; };
},{"../utils/utils":8,"./property":23}],23:[function(require,module,exports){ },{"../utils/utils":6,"./property":22}],22:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3186,16 +3326,23 @@ Property.prototype.formatOutput = function (result) {
Property.prototype.attachToObject = function (obj) { Property.prototype.attachToObject = function (obj) {
var proto = { var proto = {
get: this.get.bind(this), get: this.get.bind(this),
set: this.set.bind(this)
}; };
var name = this.name.split('.'); var names = this.name.split('.');
if (name.length > 1) { var name = names[0];
obj[name[0]] = obj[name[0]] || {}; if (names.length > 1) {
Object.defineProperty(obj[name[0]], name[1], proto); obj[names[0]] = obj[names[0]] || {};
} else { obj = obj[names[0]];
Object.defineProperty(obj, name[0], proto); name = names[1];
} }
Object.defineProperty(obj, name, proto);
var toAsyncName = function (prefix, name) {
return prefix + name.charAt(0).toUpperCase() + name.slice(1);
};
obj[toAsyncName('get', name)] = this.getAsync.bind(this);
}; };
/** /**
@ -3211,22 +3358,27 @@ Property.prototype.get = function () {
}; };
/** /**
* Should be used to set value of the property * Should be used to asynchrounously get value of property
* *
* @method set * @method getAsync
* @param {Object} new value of the property * @param {Function}
*/ */
Property.prototype.set = function (value) { Property.prototype.getAsync = function (callback) {
return RequestManager.getInstance().send({ var self = this;
method: this.setter, RequestManager.getInstance().sendAsync({
params: [this.formatInput(value)] method: this.getter
}, function (err, result) {
if (err) {
return callback(err);
}
callback(err, self.formatOutput(result));
}); });
}; };
module.exports = Property; module.exports = Property;
},{"./requestmanager":25}],24:[function(require,module,exports){ },{"./requestmanager":24}],23:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3261,7 +3413,7 @@ QtSyncProvider.prototype.send = function (payload) {
module.exports = QtSyncProvider; module.exports = QtSyncProvider;
},{}],25:[function(require,module,exports){ },{}],24:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3369,6 +3521,33 @@ RequestManager.prototype.sendAsync = function (data, callback) {
}); });
}; };
/**
* Should be called to asynchronously send batch request
*
* @method sendBatch
* @param {Array} batch data
* @param {Function} callback
*/
RequestManager.prototype.sendBatch = function (data, callback) {
if (!this.provider) {
return callback(errors.InvalidProvider());
}
var payload = Jsonrpc.getInstance().toBatchPayload(data);
this.provider.sendAsync(payload, function (err, results) {
if (err) {
return callback(err);
}
if (!utils.isArray(results)) {
return callback(errors.InvalidResponse(results));
}
callback(err, results);
});
};
/** /**
* Should be used to set provider of request manager * Should be used to set provider of request manager
* *
@ -3482,7 +3661,7 @@ RequestManager.prototype.poll = function () {
module.exports = RequestManager; module.exports = RequestManager;
},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(require,module,exports){ },{"../utils/config":5,"../utils/utils":6,"./errors":12,"./jsonrpc":19}],25:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3552,7 +3731,7 @@ module.exports = {
}; };
},{"./formatters":17,"./method":21}],27:[function(require,module,exports){ },{"./formatters":16,"./method":20}],26:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3580,7 +3759,20 @@ var Method = require('./method');
/// @returns an array of objects describing web3.eth.filter api methods /// @returns an array of objects describing web3.eth.filter api methods
var eth = function () { var eth = function () {
var newFilterCall = function (args) { var newFilterCall = function (args) {
return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter'; var type = args[0];
switch(type) {
case 'latest':
args.pop();
this.params = 0;
return 'eth_newBlockFilter';
case 'pending':
args.pop();
this.params = 0;
return 'eth_newPendingTransactionFilter';
default:
return 'eth_newFilter';
}
}; };
var newFilter = new Method({ var newFilter = new Method({
@ -3655,7 +3847,7 @@ module.exports = {
}; };
},{"./method":21}],28:[function(require,module,exports){ },{"./method":20}],27:[function(require,module,exports){
},{}],"bignumber.js":[function(require,module,exports){ },{}],"bignumber.js":[function(require,module,exports){
'use strict'; 'use strict';
@ -3668,7 +3860,6 @@ var web3 = require('./lib/web3');
web3.providers.HttpProvider = require('./lib/web3/httpprovider'); web3.providers.HttpProvider = require('./lib/web3/httpprovider');
web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); web3.providers.QtSyncProvider = require('./lib/web3/qtsync');
web3.eth.contract = require('./lib/web3/contract'); web3.eth.contract = require('./lib/web3/contract');
web3.abi = require('./lib/solidity/abi');
// dont override global variable // dont override global variable
if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {
@ -3678,7 +3869,7 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {
module.exports = web3; module.exports = web3;
},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]) },{"./lib/web3":8,"./lib/web3/contract":10,"./lib/web3/httpprovider":18,"./lib/web3/qtsync":23}]},{},["web3"])
//# sourceMappingURL=web3-light.js.map //# sourceMappingURL=web3-light.js.map

30
dist/web3-light.js.map

File diff suppressed because one or more lines are too long

4
dist/web3-light.min.js

File diff suppressed because one or more lines are too long

579
dist/web3.js

@ -15,52 +15,6 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/ */
/**
* @file abi.js
* @author Marek Kotewicz <marek@ethdev.com>
* @author Gav Wood <g@ethdev.com>
* @date 2014
*/
var coder = require('./coder');
var utils = require('./utils');
var formatConstructorParams = function (abi, params) {
var constructor = utils.getConstructor(abi, params.length);
if (!constructor) {
if (params.length > 0) {
console.warn("didn't found matching constructor, using default one");
}
return '';
}
return coder.encodeParams(constructor.inputs.map(function (input) {
return input.type;
}), params);
};
module.exports = {
formatConstructorParams: formatConstructorParams
};
},{"./coder":2,"./utils":5}],2:[function(require,module,exports){
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** /**
* @file coder.js * @file coder.js
* @author Marek Kotewicz <marek@ethdev.com> * @author Marek Kotewicz <marek@ethdev.com>
@ -328,7 +282,7 @@ var coder = new SolidityCoder([
module.exports = coder; module.exports = coder;
},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){ },{"../utils/utils":6,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -548,7 +502,7 @@ module.exports = {
}; };
},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(require,module,exports){ },{"../utils/config":5,"../utils/utils":6,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -760,54 +714,7 @@ SolidityParam.decodeArray = function (bytes, index) {
module.exports = SolidityParam; module.exports = SolidityParam;
},{"../utils/utils":8}],5:[function(require,module,exports){ },{"../utils/utils":6}],4:[function(require,module,exports){
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file utils.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/**
* Returns the contstructor with matching number of arguments
*
* @method getConstructor
* @param {Array} abi
* @param {Number} numberOfArgs
* @returns {Object} constructor function abi
*/
var getConstructor = function (abi, numberOfArgs) {
return abi.filter(function (f) {
return f.type === 'constructor' && f.inputs.length === numberOfArgs;
})[0];
};
//var getSupremeType = function (type) {
//return type.substr(0, type.indexOf('[')) + ']';
//};
module.exports = {
getConstructor: getConstructor
};
},{}],6:[function(require,module,exports){
'use strict'; 'use strict';
// go env doesn't have and need XMLHttpRequest // go env doesn't have and need XMLHttpRequest
@ -818,7 +725,7 @@ if (typeof XMLHttpRequest === 'undefined') {
} }
},{}],7:[function(require,module,exports){ },{}],5:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -890,7 +797,7 @@ module.exports = {
}; };
},{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){ },{"bignumber.js":"bignumber.js"}],6:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1256,6 +1163,7 @@ var toAddress = function (address) {
return '0x' + padLeft(toHex(address).substr(2), 40); return '0x' + padLeft(toHex(address).substr(2), 40);
}; };
/** /**
* Returns true if object is BigNumber, otherwise false * Returns true if object is BigNumber, otherwise false
* *
@ -1366,12 +1274,12 @@ module.exports = {
}; };
},{"bignumber.js":"bignumber.js"}],9:[function(require,module,exports){ },{"bignumber.js":"bignumber.js"}],7:[function(require,module,exports){
module.exports={ module.exports={
"version": "0.3.6" "version": "0.4.2"
} }
},{}],10:[function(require,module,exports){ },{}],8:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1411,6 +1319,7 @@ var RequestManager = require('./web3/requestmanager');
var c = require('./utils/config'); var c = require('./utils/config');
var Method = require('./web3/method'); var Method = require('./web3/method');
var Property = require('./web3/property'); var Property = require('./web3/property');
var Batch = require('./web3/batch');
var web3Methods = [ var web3Methods = [
new Method({ new Method({
@ -1503,6 +1412,9 @@ web3.toBigNumber = utils.toBigNumber;
web3.toWei = utils.toWei; web3.toWei = utils.toWei;
web3.fromWei = utils.fromWei; web3.fromWei = utils.fromWei;
web3.isAddress = utils.isAddress; web3.isAddress = utils.isAddress;
web3.createBatch = function () {
return new Batch();
};
// ADD defaultblock // ADD defaultblock
Object.defineProperty(web3.eth, 'defaultBlock', { Object.defineProperty(web3.eth, 'defaultBlock', {
@ -1538,7 +1450,70 @@ setupMethods(web3.shh, shh.methods);
module.exports = web3; module.exports = web3;
},{"./utils/config":7,"./utils/utils":8,"./version.json":9,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":21,"./web3/net":22,"./web3/property":23,"./web3/requestmanager":25,"./web3/shh":26,"./web3/watches":27}],11:[function(require,module,exports){ },{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/batch":9,"./web3/db":11,"./web3/eth":13,"./web3/filter":15,"./web3/formatters":16,"./web3/method":20,"./web3/net":21,"./web3/property":22,"./web3/requestmanager":24,"./web3/shh":25,"./web3/watches":26}],9:[function(require,module,exports){
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file batch.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var RequestManager = require('./requestmanager');
var Batch = function () {
this.requests = [];
};
/**
* Should be called to add create new request to batch request
*
* @method add
* @param {Object} jsonrpc requet object
*/
Batch.prototype.add = function (request) {
this.requests.push(request);
};
/**
* Should be called to execute batch request
*
* @method execute
*/
Batch.prototype.execute = function () {
var requests = this.requests;
RequestManager.getInstance().sendBatch(requests, function (err, results) {
results = results || [];
requests.map(function (request, index) {
return results[index] || {};
}).map(function (result, index) {
return requests[index].format ? requests[index].format(result.result) : result.result;
}).forEach(function (result, index) {
if (requests[index].callback) {
requests[index].callback(err, result);
}
});
});
};
module.exports = Batch;
},{"./requestmanager":24}],10:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1562,13 +1537,39 @@ module.exports = web3;
*/ */
var web3 = require('../web3'); var web3 = require('../web3');
var solAbi = require('../solidity/abi');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var coder = require('../solidity/coder');
var SolidityEvent = require('./event'); var SolidityEvent = require('./event');
var SolidityFunction = require('./function'); var SolidityFunction = require('./function');
var addFunctionsToContract = function (contract, desc) { /**
desc.filter(function (json) { * Should be called to encode constructor params
*
* @method encodeConstructorParams
* @param {Array} abi
* @param {Array} constructor params
*/
var encodeConstructorParams = function (abi, params) {
return abi.filter(function (json) {
return json.type === 'constructor' && json.inputs.length === params.length;
}).map(function (json) {
return json.inputs.map(function (input) {
return input.type;
});
}).map(function (types) {
return coder.encodeParams(types, params);
})[0] || '';
};
/**
* Should be called to add functions to contract object
*
* @method addFunctionsToContract
* @param {Contract} contract
* @param {Array} abi
*/
var addFunctionsToContract = function (contract, abi) {
abi.filter(function (json) {
return json.type === 'function'; return json.type === 'function';
}).map(function (json) { }).map(function (json) {
return new SolidityFunction(json, contract.address); return new SolidityFunction(json, contract.address);
@ -1577,8 +1578,15 @@ var addFunctionsToContract = function (contract, desc) {
}); });
}; };
var addEventsToContract = function (contract, desc) { /**
desc.filter(function (json) { * Should be called to add events to contract object
*
* @method addEventsToContract
* @param {Contract} contract
* @param {Array} abi
*/
var addEventsToContract = function (contract, abi) {
abi.filter(function (json) {
return json.type === 'event'; return json.type === 'event';
}).map(function (json) { }).map(function (json) {
return new SolidityEvent(json, contract.address); return new SolidityEvent(json, contract.address);
@ -1588,65 +1596,106 @@ var addEventsToContract = function (contract, desc) {
}; };
/** /**
* This method should be called when we want to call / transact some solidity method from javascript * Should be called to create new ContractFactory
* it returns an object which has same methods available as solidity contract description
* usage example:
*
* var abi = [{
* name: 'myMethod',
* inputs: [{ name: 'a', type: 'string' }],
* outputs: [{name: 'd', type: 'string' }]
* }]; // contract abi
* *
* var MyContract = web3.eth.contract(abi); // creation of contract prototype * @method contract
* * @param {Array} abi
* var contractInstance = new MyContract('0x0123123121'); * @returns {ContractFactory} new contract factory
*
* contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)
* contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)
* contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction
*
* @param abi - abi json description of the contract, which is being created
* @returns contract object
*/ */
var contract = function (abi) { var contract = function (abi) {
return new ContractFactory(abi);
};
// return prototype /**
return Contract.bind(null, abi); * Should be called to create new ContractFactory instance
*
* @method ContractFactory
* @param {Array} abi
*/
var ContractFactory = function (abi) {
this.abi = abi;
}; };
var Contract = function (abi, options) { /**
* 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 if no callback was passed,
* otherwise calls callback function (err, contract)
*/
ContractFactory.prototype.new = function () {
// parse arguments
var options = {}; // required!
var callback;
this.address = ''; var args = Array.prototype.slice.call(arguments);
if (utils.isAddress(options)) { if (utils.isFunction(args[args.length - 1])) {
this.address = options; callback = args.pop();
} else { // is an object! }
// TODO, parse the rest of the args
options = options || {}; var last = args[args.length - 1];
var args = Array.prototype.slice.call(arguments, 2); if (utils.isObject(last) && !utils.isArray(last)) {
var bytes = solAbi.formatConstructorParams(abi, args); options = args.pop();
}
// throw an error if there are no options
var bytes = encodeConstructorParams(this.abi, args);
options.data += bytes; options.data += bytes;
this.address = web3.eth.sendTransaction(options);
if (!callback) {
var address = web3.eth.sendTransaction(options);
return this.at(address);
} }
addFunctionsToContract(this, abi); var self = this;
addEventsToContract(this, abi); web3.eth.sendTransaction(options, function (err, address) {
if (err) {
callback(err);
}
self.at(address, callback);
});
}; };
Contract.prototype.call = function () { /**
console.error('contract.call is deprecated'); * Should be called to get access to existing contract on a blockchain
return this; *
* @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) {
// TODO: address is required
if (callback) {
callback(null, new Contract(this.abi, address));
}
return new Contract(this.abi, address);
}; };
Contract.prototype.sendTransaction = function () { /**
console.error('contract.sendTransact is deprecated'); * Should be called to create new contract instance
return this; *
* @method Contract
* @param {Array} abi
* @param {Address} contract address
*/
var Contract = function (abi, address) {
this.address = address;
addFunctionsToContract(this, abi);
addEventsToContract(this, abi);
}; };
module.exports = contract; module.exports = contract;
},{"../solidity/abi":1,"../utils/utils":8,"../web3":10,"./event":15,"./function":18}],12:[function(require,module,exports){ },{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./event":14,"./function":17}],11:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1704,7 +1753,7 @@ module.exports = {
methods: methods methods: methods
}; };
},{"./method":21}],13:[function(require,module,exports){ },{"./method":20}],12:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1744,7 +1793,7 @@ module.exports = {
}; };
},{}],14:[function(require,module,exports){ },{}],13:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1921,6 +1970,14 @@ var call = new Method({
inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter] inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]
}); });
var estimateGas = new Method({
name: 'estimateGas',
call: 'eth_estimateGas',
params: 1,
inputFormatter: [formatters.inputTransactionFormatter],
outputFormatter: utils.toDecimal
});
var compileSolidity = new Method({ var compileSolidity = new Method({
name: 'compile.solidity', name: 'compile.solidity',
call: 'eth_compileSolidity', call: 'eth_compileSolidity',
@ -1939,6 +1996,18 @@ var compileSerpent = new Method({
params: 1 params: 1
}); });
var submitWork = new Method({
name: 'submitWork',
call: 'eth_submitWork',
params: 3
});
var getWork = new Method({
name: 'getWork',
call: 'eth_getWork',
params: 0
});
var methods = [ var methods = [
getBalance, getBalance,
getStorageAt, getStorageAt,
@ -1952,10 +2021,13 @@ var methods = [
getTransactionFromBlock, getTransactionFromBlock,
getTransactionCount, getTransactionCount,
call, call,
estimateGas,
sendTransaction, sendTransaction,
compileSolidity, compileSolidity,
compileLLL, compileLLL,
compileSerpent, compileSerpent,
submitWork,
getWork
]; ];
/// @returns an array of objects describing web3.eth api properties /// @returns an array of objects describing web3.eth api properties
@ -1998,7 +2070,7 @@ module.exports = {
}; };
},{"../utils/utils":8,"./formatters":17,"./method":21,"./property":23}],15:[function(require,module,exports){ },{"../utils/utils":6,"./formatters":16,"./method":20,"./property":22}],14:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2194,7 +2266,7 @@ SolidityEvent.prototype.attachToContract = function (contract) {
module.exports = SolidityEvent; module.exports = SolidityEvent;
},{"../solidity/coder":2,"../utils/utils":8,"../web3":10,"./formatters":17}],16:[function(require,module,exports){ },{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./formatters":16}],15:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2351,7 +2423,7 @@ Filter.prototype.get = function (callback) {
module.exports = Filter; module.exports = Filter;
},{"../utils/utils":8,"./formatters":17,"./requestmanager":25}],17:[function(require,module,exports){ },{"../utils/utils":6,"./formatters":16,"./requestmanager":24}],16:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2571,7 +2643,7 @@ module.exports = {
}; };
},{"../utils/config":7,"../utils/utils":8}],18:[function(require,module,exports){ },{"../utils/config":5,"../utils/utils":6}],17:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2613,18 +2685,23 @@ var SolidityFunction = function (json, address) {
this._address = address; this._address = address;
}; };
SolidityFunction.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array!
}
};
/** /**
* Should be used to create payload from arguments * Should be used to create payload from arguments
* *
* @method toPayload * @method toPayload
* @param {...} solidity function params * @param {Array} solidity function params
* @param {Object} optional payload options * @param {Object} optional payload options
*/ */
SolidityFunction.prototype.toPayload = function () { SolidityFunction.prototype.toPayload = function (args) {
var args = Array.prototype.slice.call(arguments);
var options = {}; var options = {};
if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {
options = args.pop(); options = args[args.length - 1];
} }
options.to = this._address; options.to = this._address;
options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);
@ -2641,19 +2718,41 @@ SolidityFunction.prototype.signature = function () {
return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); return web3.sha3(web3.fromAscii(this._name)).slice(2, 10);
}; };
SolidityFunction.prototype.unpackOutput = function (output) {
if (output === null) {
return;
}
output = output.length >= 2 ? output.slice(2) : output;
var result = coder.decodeParams(this._outputTypes, output);
return result.length === 1 ? result[0] : result;
};
/** /**
* Should be used to call function * Calls a contract function.
* *
* @method call * @method call
* @param {Object} options * @param {...Object} Contract function arguments
* @param {function} If the last argument is a function, the contract function
* call will be asynchronous, and the callback will be passed the
* error and result.
* @return {String} output bytes * @return {String} output bytes
*/ */
SolidityFunction.prototype.call = function () { SolidityFunction.prototype.call = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
if (!callback) {
var output = web3.eth.call(payload); var output = web3.eth.call(payload);
output = output.length >= 2 ? output.slice(2) : output; return this.unpackOutput(output);
var result = coder.decodeParams(this._outputTypes, output); }
return result.length === 1 ? result[0] : result;
var self = this;
web3.eth.call(payload, function (error, output) {
callback(error, self.unpackOutput(output));
});
}; };
/** /**
@ -2663,8 +2762,16 @@ SolidityFunction.prototype.call = function () {
* @param {Object} options * @param {Object} options
*/ */
SolidityFunction.prototype.sendTransaction = function () { SolidityFunction.prototype.sendTransaction = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
if (!callback) {
web3.eth.sendTransaction(payload); web3.eth.sendTransaction(payload);
return;
}
web3.eth.sendTransaction(payload, callback);
}; };
/** /**
@ -2687,6 +2794,25 @@ SolidityFunction.prototype.typeName = function () {
return utils.extractTypeName(this._name); return utils.extractTypeName(this._name);
}; };
/**
* Should be called to get rpc requests from solidity function
*
* @method request
* @returns {Object}
*/
SolidityFunction.prototype.request = function () {
var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
var format = this.unpackOutput.bind(this);
return {
callback: callback,
payload: payload,
format: format
};
};
/** /**
* Should be called to execute function * Should be called to execute function
* *
@ -2712,6 +2838,7 @@ SolidityFunction.prototype.execute = function () {
*/ */
SolidityFunction.prototype.attachToContract = function (contract) { SolidityFunction.prototype.attachToContract = function (contract) {
var execute = this.execute.bind(this); var execute = this.execute.bind(this);
execute.request = this.request.bind(this);
execute.call = this.call.bind(this); execute.call = this.call.bind(this);
execute.sendTransaction = this.sendTransaction.bind(this); execute.sendTransaction = this.sendTransaction.bind(this);
var displayName = this.displayName(); var displayName = this.displayName();
@ -2724,7 +2851,7 @@ SolidityFunction.prototype.attachToContract = function (contract) {
module.exports = SolidityFunction; module.exports = SolidityFunction;
},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(require,module,exports){ },{"../solidity/coder":1,"../utils/utils":6,"../web3":8}],18:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2816,7 +2943,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
module.exports = HttpProvider; module.exports = HttpProvider;
},{"./errors":13,"xmlhttprequest":6}],20:[function(require,module,exports){ },{"./errors":12,"xmlhttprequest":4}],19:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2909,7 +3036,7 @@ Jsonrpc.prototype.toBatchPayload = function (messages) {
module.exports = Jsonrpc; module.exports = Jsonrpc;
},{}],21:[function(require,module,exports){ },{}],20:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -2966,7 +3093,6 @@ Method.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) { if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array! return args.pop(); // modify the args array!
} }
return null;
}; };
/** /**
@ -3019,6 +3145,7 @@ Method.prototype.formatOutput = function (result) {
*/ */
Method.prototype.attachToObject = function (obj) { Method.prototype.attachToObject = function (obj) {
var func = this.send.bind(this); var func = this.send.bind(this);
func.request = this.request.bind(this);
func.call = this.call; // that's ugly. filter.js uses it func.call = this.call; // that's ugly. filter.js uses it
var name = this.name.split('.'); var name = this.name.split('.');
if (name.length > 1) { if (name.length > 1) {
@ -3049,6 +3176,19 @@ Method.prototype.toPayload = function (args) {
}; };
}; };
/**
* Should be called to create pure JSONRPC request which can be used in batch request
*
* @method request
* @param {...} params
* @return {Object} jsonrpc request
*/
Method.prototype.request = function () {
var payload = this.toPayload(Array.prototype.slice.call(arguments));
payload.format = this.formatOutput.bind(this);
return payload;
};
/** /**
* Should send request to the API * Should send request to the API
* *
@ -3061,7 +3201,7 @@ Method.prototype.send = function () {
if (payload.callback) { if (payload.callback) {
var self = this; var self = this;
return RequestManager.getInstance().sendAsync(payload, function (err, result) { return RequestManager.getInstance().sendAsync(payload, function (err, result) {
payload.callback(null, self.formatOutput(result)); payload.callback(err, self.formatOutput(result));
}); });
} }
return this.formatOutput(RequestManager.getInstance().send(payload)); return this.formatOutput(RequestManager.getInstance().send(payload));
@ -3070,7 +3210,7 @@ Method.prototype.send = function () {
module.exports = Method; module.exports = Method;
},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(require,module,exports){ },{"../utils/utils":6,"./errors":12,"./requestmanager":24}],21:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3120,7 +3260,7 @@ module.exports = {
}; };
},{"../utils/utils":8,"./property":23}],23:[function(require,module,exports){ },{"../utils/utils":6,"./property":22}],22:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3186,16 +3326,23 @@ Property.prototype.formatOutput = function (result) {
Property.prototype.attachToObject = function (obj) { Property.prototype.attachToObject = function (obj) {
var proto = { var proto = {
get: this.get.bind(this), get: this.get.bind(this),
set: this.set.bind(this)
}; };
var name = this.name.split('.'); var names = this.name.split('.');
if (name.length > 1) { var name = names[0];
obj[name[0]] = obj[name[0]] || {}; if (names.length > 1) {
Object.defineProperty(obj[name[0]], name[1], proto); obj[names[0]] = obj[names[0]] || {};
} else { obj = obj[names[0]];
Object.defineProperty(obj, name[0], proto); name = names[1];
} }
Object.defineProperty(obj, name, proto);
var toAsyncName = function (prefix, name) {
return prefix + name.charAt(0).toUpperCase() + name.slice(1);
};
obj[toAsyncName('get', name)] = this.getAsync.bind(this);
}; };
/** /**
@ -3211,22 +3358,27 @@ Property.prototype.get = function () {
}; };
/** /**
* Should be used to set value of the property * Should be used to asynchrounously get value of property
* *
* @method set * @method getAsync
* @param {Object} new value of the property * @param {Function}
*/ */
Property.prototype.set = function (value) { Property.prototype.getAsync = function (callback) {
return RequestManager.getInstance().send({ var self = this;
method: this.setter, RequestManager.getInstance().sendAsync({
params: [this.formatInput(value)] method: this.getter
}, function (err, result) {
if (err) {
return callback(err);
}
callback(err, self.formatOutput(result));
}); });
}; };
module.exports = Property; module.exports = Property;
},{"./requestmanager":25}],24:[function(require,module,exports){ },{"./requestmanager":24}],23:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3261,7 +3413,7 @@ QtSyncProvider.prototype.send = function (payload) {
module.exports = QtSyncProvider; module.exports = QtSyncProvider;
},{}],25:[function(require,module,exports){ },{}],24:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3369,6 +3521,33 @@ RequestManager.prototype.sendAsync = function (data, callback) {
}); });
}; };
/**
* Should be called to asynchronously send batch request
*
* @method sendBatch
* @param {Array} batch data
* @param {Function} callback
*/
RequestManager.prototype.sendBatch = function (data, callback) {
if (!this.provider) {
return callback(errors.InvalidProvider());
}
var payload = Jsonrpc.getInstance().toBatchPayload(data);
this.provider.sendAsync(payload, function (err, results) {
if (err) {
return callback(err);
}
if (!utils.isArray(results)) {
return callback(errors.InvalidResponse(results));
}
callback(err, results);
});
};
/** /**
* Should be used to set provider of request manager * Should be used to set provider of request manager
* *
@ -3482,7 +3661,7 @@ RequestManager.prototype.poll = function () {
module.exports = RequestManager; module.exports = RequestManager;
},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(require,module,exports){ },{"../utils/config":5,"../utils/utils":6,"./errors":12,"./jsonrpc":19}],25:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3552,7 +3731,7 @@ module.exports = {
}; };
},{"./formatters":17,"./method":21}],27:[function(require,module,exports){ },{"./formatters":16,"./method":20}],26:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -3580,7 +3759,20 @@ var Method = require('./method');
/// @returns an array of objects describing web3.eth.filter api methods /// @returns an array of objects describing web3.eth.filter api methods
var eth = function () { var eth = function () {
var newFilterCall = function (args) { var newFilterCall = function (args) {
return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter'; var type = args[0];
switch(type) {
case 'latest':
args.pop();
this.params = 0;
return 'eth_newBlockFilter';
case 'pending':
args.pop();
this.params = 0;
return 'eth_newPendingTransactionFilter';
default:
return 'eth_newFilter';
}
}; };
var newFilter = new Method({ var newFilter = new Method({
@ -3655,7 +3847,7 @@ module.exports = {
}; };
},{"./method":21}],28:[function(require,module,exports){ },{"./method":20}],27:[function(require,module,exports){
},{}],"bignumber.js":[function(require,module,exports){ },{}],"bignumber.js":[function(require,module,exports){
/*! bignumber.js v2.0.7 https://github.com/MikeMcl/bignumber.js/LICENCE */ /*! bignumber.js v2.0.7 https://github.com/MikeMcl/bignumber.js/LICENCE */
@ -6342,12 +6534,11 @@ module.exports = {
} }
})(this); })(this);
},{"crypto":28}],"web3":[function(require,module,exports){ },{"crypto":27}],"web3":[function(require,module,exports){
var web3 = require('./lib/web3'); var web3 = require('./lib/web3');
web3.providers.HttpProvider = require('./lib/web3/httpprovider'); web3.providers.HttpProvider = require('./lib/web3/httpprovider');
web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); web3.providers.QtSyncProvider = require('./lib/web3/qtsync');
web3.eth.contract = require('./lib/web3/contract'); web3.eth.contract = require('./lib/web3/contract');
web3.abi = require('./lib/solidity/abi');
// dont override global variable // dont override global variable
if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {
@ -6357,7 +6548,7 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {
module.exports = web3; module.exports = web3;
},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]) },{"./lib/web3":8,"./lib/web3/contract":10,"./lib/web3/httpprovider":18,"./lib/web3/qtsync":23}]},{},["web3"])
//# sourceMappingURL=web3.js.map //# sourceMappingURL=web3.js.map

30
dist/web3.js.map

File diff suppressed because one or more lines are too long

4
dist/web3.min.js

File diff suppressed because one or more lines are too long

42
example/contract.html

@ -8,14 +8,16 @@
var web3 = require('web3'); var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545")); web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));
// solidity source code // solidity code code
/*var source = "" +*/ var source = "" +
/*"contract test {\n" +*/ "contract test {\n" +
/*" function multiply(uint a) constant returns(uint d) {\n" +*/ " function multiply(uint a) constant returns(uint d) {\n" +
/*" return a * 7;\n" +*/ " return a * 7;\n" +
/*" }\n" +*/ " }\n" +
/*"}\n";*/ "}\n";
var source = "605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056";
var code = web3.eth.compile.solidity(source).code;
/*var code = "605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056";*/
// contract description, this is autogenerated using solc CLI // contract description, this is autogenerated using solc CLI
var desc = [{ var desc = [{
@ -37,16 +39,31 @@
function createExampleContract() { function createExampleContract() {
// hide create button // hide create button
document.getElementById('create').style.visibility = 'hidden'; document.getElementById('create').style.visibility = 'hidden';
document.getElementById('source').innerText = source; document.getElementById('code').innerText = code;
// let's assume that coinbase is our account // let's assume that coinbase is our account
web3.eth.defaultAccount = web3.eth.coinbase; web3.eth.defaultAccount = web3.eth.coinbase;
var watch = web3.eth.filter('latest');
// create contract // create contract
var Contract = web3.eth.contract(desc); myContract = web3.eth.contract(desc).new({data: code});
myContract = new Contract({data: source}); console.log('address: ' + myContract.address);
document.getElementById('status').innerText = "transaction sent, waiting for confirmation";
watch.watch(function (err, hash) {
var block = web3.eth.getBlock(hash, true);
var contractMined = block.transactions.reduce(function (mined, th) {
// TODO: compiled code do not have 0x prefix
return mined || (th.from === web3.eth.defaultAccount && th.input.indexOf(code) !== -1);
}, false);
if (contractMined) {
document.getElementById('status').innerText = 'Mined!';
document.getElementById('call').style.visibility = 'visible'; document.getElementById('call').style.visibility = 'visible';
} }
});
}
function callExampleContract() { function callExampleContract() {
// this should be generated by ethereum // this should be generated by ethereum
@ -61,7 +78,8 @@
</head> </head>
<body> <body>
<h1>contract</h1> <h1>contract</h1>
<div id="source"></div> <div id="code"></div>
<div id="status"></div>
<div id='create'> <div id='create'>
<button type="button" onClick="createExampleContract();">create example contract</button> <button type="button" onClick="createExampleContract();">create example contract</button>
</div> </div>

64
example/event_inc.html

@ -6,19 +6,20 @@
var web3 = require('web3'); var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
/*var source = "" + */ var source = "" +
/*"contract Contract { " +*/ "contract Contract { " +
/*" event Incremented(bool indexed odd, uint x); " +*/ " event Incremented(bool indexed odd, uint x); " +
/*" function Contract() { " +*/ " function Contract() { " +
/*" x = 69; " +*/ " x = 70; " +
/*" } " +*/ " } " +
/*" function inc() { " +*/ " function inc() { " +
/*" ++x; " +*/ " ++x; " +
/*" Incremented(x % 2 == 1, x); " +*/ " Incremented(x % 2 == 1, x); " +
/*" } " +*/ " } " +
/*" uint x; " +*/ " uint x; " +
/*"}";*/ "}";
var source = "5b60456000600050819055505b608c8060196000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063371303c014602e57005b6034603a565b60006000f35b6000600081815054600101919050819055506001600260006000505406147f6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad600060006000505481526020016000a25b56"; var code = web3.eth.compile.solidity(source).code;
/*var code = "5b60456000600050819055505b608c8060196000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063371303c014602e57005b6034603a565b60006000f35b6000600081815054600101919050819055506001600260006000505406147f6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad600060006000505481526020016000a25b56";*/
var desc = [{ var desc = [{
"constant" : false, "constant" : false,
@ -51,13 +52,40 @@
var createContract = function () { var createContract = function () {
// let's assume that we have a private key to coinbase ;) // let's assume that we have a private key to coinbase ;)
web3.eth.defaultAccount = web3.eth.coinbase; web3.eth.defaultAccount = web3.eth.coinbase;
var Contract = web3.eth.contract(desc);
contract = new Contract({data: source}); var watch = web3.eth.filter('latest');
contract = web3.eth.contract(desc).new({data: code});
console.log('address: ' + contract.address);
document.getElementById('create').style.visibility = 'hidden';
document.getElementById('status').innerText = "transaction sent, waiting for confirmation";
watch.watch(function (err, hash) {
var block = web3.eth.getBlock(hash, true);
var contractMined = block.transactions.reduce(function (mined, th) {
// TODO: compiled code do not have 0x prefix
return mined || (th.from === web3.eth.defaultAccount && th.input.indexOf(code) !== -1);
}, false);
if (contractMined) {
document.getElementById('status').innerText = 'Mined!';
document.getElementById('call').style.visibility = 'visible';
}
});
contract.Incremented({odd: true}).watch(update); contract.Incremented({odd: true}).watch(update);
}; };
var counter = 0;
var callContract = function () { var callContract = function () {
counter++;
var all = 70 + counter;
document.getElementById('count').innerText = 'Transaction sent ' + counter + ' times. ' +
'Expected x value is: ' + (all - (all % 2 ? 0 : 1)) + ' ' +
'Waiting for the blocks to be mined...';
contract.inc(); contract.inc();
}; };
@ -66,12 +94,14 @@
</head> </head>
<body> <body>
<div id="status"></div>
<div> <div>
<button type="button" onClick="createContract();">create contract</button> <button id="create" type="button" onClick="createContract();">create contract</button>
</div> </div>
<div> <div>
<button type="button" onClick="callContract();">test1</button> <button id="call" style="visibility: hidden;" type="button" onClick="callContract();">test1</button>
</div> </div>
<div id='count'></div>
<div id="result"> <div id="result">
</div> </div>
</body> </body>

4
example/node-app.js

@ -2,11 +2,11 @@
var web3 = require("../index.js"); var web3 = require("../index.js");
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080')); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
var coinbase = web3.eth.coinbase; var coinbase = web3.eth.coinbase;
console.log(coinbase); console.log(coinbase);
var balance = web3.eth.getBalance(coinbase); var balance = web3.eth.getBalance(coinbase);
console.log(balance); console.log(balance.toString(10));

1
index.js

@ -2,7 +2,6 @@ var web3 = require('./lib/web3');
web3.providers.HttpProvider = require('./lib/web3/httpprovider'); web3.providers.HttpProvider = require('./lib/web3/httpprovider');
web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); web3.providers.QtSyncProvider = require('./lib/web3/qtsync');
web3.eth.contract = require('./lib/web3/contract'); web3.eth.contract = require('./lib/web3/contract');
web3.abi = require('./lib/solidity/abi');
// dont override global variable // dont override global variable
if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {

44
lib/solidity/abi.js

@ -1,44 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file abi.js
* @author Marek Kotewicz <marek@ethdev.com>
* @author Gav Wood <g@ethdev.com>
* @date 2014
*/
var coder = require('./coder');
var utils = require('./utils');
var formatConstructorParams = function (abi, params) {
var constructor = utils.getConstructor(abi, params.length);
if (!constructor) {
if (params.length > 0) {
console.warn("didn't found matching constructor, using default one");
}
return '';
}
return coder.encodeParams(constructor.inputs.map(function (input) {
return input.type;
}), params);
};
module.exports = {
formatConstructorParams: formatConstructorParams
};

45
lib/solidity/utils.js

@ -1,45 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file utils.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/**
* Returns the contstructor with matching number of arguments
*
* @method getConstructor
* @param {Array} abi
* @param {Number} numberOfArgs
* @returns {Object} constructor function abi
*/
var getConstructor = function (abi, numberOfArgs) {
return abi.filter(function (f) {
return f.type === 'constructor' && f.inputs.length === numberOfArgs;
})[0];
};
//var getSupremeType = function (type) {
//return type.substr(0, type.indexOf('[')) + ']';
//};
module.exports = {
getConstructor: getConstructor
};

1
lib/utils/utils.js

@ -363,6 +363,7 @@ var toAddress = function (address) {
return '0x' + padLeft(toHex(address).substr(2), 40); return '0x' + padLeft(toHex(address).substr(2), 40);
}; };
/** /**
* Returns true if object is BigNumber, otherwise false * Returns true if object is BigNumber, otherwise false
* *

2
lib/version.json

@ -1,3 +1,3 @@
{ {
"version": "0.3.6" "version": "0.4.2"
} }

4
lib/web3.js

@ -37,6 +37,7 @@ var RequestManager = require('./web3/requestmanager');
var c = require('./utils/config'); var c = require('./utils/config');
var Method = require('./web3/method'); var Method = require('./web3/method');
var Property = require('./web3/property'); var Property = require('./web3/property');
var Batch = require('./web3/batch');
var web3Methods = [ var web3Methods = [
new Method({ new Method({
@ -129,6 +130,9 @@ web3.toBigNumber = utils.toBigNumber;
web3.toWei = utils.toWei; web3.toWei = utils.toWei;
web3.fromWei = utils.fromWei; web3.fromWei = utils.fromWei;
web3.isAddress = utils.isAddress; web3.isAddress = utils.isAddress;
web3.createBatch = function () {
return new Batch();
};
// ADD defaultblock // ADD defaultblock
Object.defineProperty(web3.eth, 'defaultBlock', { Object.defineProperty(web3.eth, 'defaultBlock', {

61
lib/web3/batch.js

@ -0,0 +1,61 @@
/*
This file is part of ethereum.js.
ethereum.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.
ethereum.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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file batch.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var RequestManager = require('./requestmanager');
var Batch = function () {
this.requests = [];
};
/**
* Should be called to add create new request to batch request
*
* @method add
* @param {Object} jsonrpc requet object
*/
Batch.prototype.add = function (request) {
this.requests.push(request);
};
/**
* Should be called to execute batch request
*
* @method execute
*/
Batch.prototype.execute = function () {
var requests = this.requests;
RequestManager.getInstance().sendBatch(requests, function (err, results) {
results = results || [];
requests.map(function (request, index) {
return results[index] || {};
}).map(function (result, index) {
return requests[index].format ? requests[index].format(result.result) : result.result;
}).forEach(function (result, index) {
if (requests[index].callback) {
requests[index].callback(err, result);
}
});
});
};
module.exports = Batch;

162
lib/web3/contract.js

@ -21,13 +21,39 @@
*/ */
var web3 = require('../web3'); var web3 = require('../web3');
var solAbi = require('../solidity/abi');
var utils = require('../utils/utils'); var utils = require('../utils/utils');
var coder = require('../solidity/coder');
var SolidityEvent = require('./event'); var SolidityEvent = require('./event');
var SolidityFunction = require('./function'); var SolidityFunction = require('./function');
var addFunctionsToContract = function (contract, desc) { /**
desc.filter(function (json) { * Should be called to encode constructor params
*
* @method encodeConstructorParams
* @param {Array} abi
* @param {Array} constructor params
*/
var encodeConstructorParams = function (abi, params) {
return abi.filter(function (json) {
return json.type === 'constructor' && json.inputs.length === params.length;
}).map(function (json) {
return json.inputs.map(function (input) {
return input.type;
});
}).map(function (types) {
return coder.encodeParams(types, params);
})[0] || '';
};
/**
* Should be called to add functions to contract object
*
* @method addFunctionsToContract
* @param {Contract} contract
* @param {Array} abi
*/
var addFunctionsToContract = function (contract, abi) {
abi.filter(function (json) {
return json.type === 'function'; return json.type === 'function';
}).map(function (json) { }).map(function (json) {
return new SolidityFunction(json, contract.address); return new SolidityFunction(json, contract.address);
@ -36,8 +62,15 @@ var addFunctionsToContract = function (contract, desc) {
}); });
}; };
var addEventsToContract = function (contract, desc) { /**
desc.filter(function (json) { * Should be called to add events to contract object
*
* @method addEventsToContract
* @param {Contract} contract
* @param {Array} abi
*/
var addEventsToContract = function (contract, abi) {
abi.filter(function (json) {
return json.type === 'event'; return json.type === 'event';
}).map(function (json) { }).map(function (json) {
return new SolidityEvent(json, contract.address); return new SolidityEvent(json, contract.address);
@ -47,59 +80,100 @@ var addEventsToContract = function (contract, desc) {
}; };
/** /**
* This method should be called when we want to call / transact some solidity method from javascript * Should be called to create new ContractFactory
* it returns an object which has same methods available as solidity contract description
* usage example:
*
* var abi = [{
* name: 'myMethod',
* inputs: [{ name: 'a', type: 'string' }],
* outputs: [{name: 'd', type: 'string' }]
* }]; // contract abi
*
* var MyContract = web3.eth.contract(abi); // creation of contract prototype
*
* var contractInstance = new MyContract('0x0123123121');
*
* contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)
* contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)
* contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction
* *
* @param abi - abi json description of the contract, which is being created * @method contract
* @returns contract object * @param {Array} abi
* @returns {ContractFactory} new contract factory
*/ */
var contract = function (abi) { var contract = function (abi) {
return new ContractFactory(abi);
};
// return prototype /**
return Contract.bind(null, abi); * Should be called to create new ContractFactory instance
*
* @method ContractFactory
* @param {Array} abi
*/
var ContractFactory = function (abi) {
this.abi = abi;
}; };
var Contract = function (abi, options) { /**
* 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 if no callback was passed,
* otherwise calls callback function (err, contract)
*/
ContractFactory.prototype.new = function () {
// 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();
}
this.address = ''; // throw an error if there are no options
if (utils.isAddress(options)) {
this.address = options; var bytes = encodeConstructorParams(this.abi, args);
} else { // is an object!
// TODO, parse the rest of the args
options = options || {};
var args = Array.prototype.slice.call(arguments, 2);
var bytes = solAbi.formatConstructorParams(abi, args);
options.data += bytes; options.data += bytes;
this.address = web3.eth.sendTransaction(options);
if (!callback) {
var address = web3.eth.sendTransaction(options);
return this.at(address);
} }
addFunctionsToContract(this, abi); var self = this;
addEventsToContract(this, abi); web3.eth.sendTransaction(options, function (err, address) {
if (err) {
callback(err);
}
self.at(address, callback);
});
}; };
Contract.prototype.call = function () { /**
console.error('contract.call is deprecated'); * Should be called to get access to existing contract on a blockchain
return this; *
* @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) {
// TODO: address is required
if (callback) {
callback(null, new Contract(this.abi, address));
}
return new Contract(this.abi, address);
}; };
Contract.prototype.sendTransaction = function () { /**
console.error('contract.sendTransact is deprecated'); * Should be called to create new contract instance
return this; *
* @method Contract
* @param {Array} abi
* @param {Address} contract address
*/
var Contract = function (abi, address) {
this.address = address;
addFunctionsToContract(this, abi);
addEventsToContract(this, abi);
}; };
module.exports = contract; module.exports = contract;

23
lib/web3/eth.js

@ -174,6 +174,14 @@ var call = new Method({
inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter] inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]
}); });
var estimateGas = new Method({
name: 'estimateGas',
call: 'eth_estimateGas',
params: 1,
inputFormatter: [formatters.inputTransactionFormatter],
outputFormatter: utils.toDecimal
});
var compileSolidity = new Method({ var compileSolidity = new Method({
name: 'compile.solidity', name: 'compile.solidity',
call: 'eth_compileSolidity', call: 'eth_compileSolidity',
@ -192,6 +200,18 @@ var compileSerpent = new Method({
params: 1 params: 1
}); });
var submitWork = new Method({
name: 'submitWork',
call: 'eth_submitWork',
params: 3
});
var getWork = new Method({
name: 'getWork',
call: 'eth_getWork',
params: 0
});
var methods = [ var methods = [
getBalance, getBalance,
getStorageAt, getStorageAt,
@ -205,10 +225,13 @@ var methods = [
getTransactionFromBlock, getTransactionFromBlock,
getTransactionCount, getTransactionCount,
call, call,
estimateGas,
sendTransaction, sendTransaction,
compileSolidity, compileSolidity,
compileLLL, compileLLL,
compileSerpent, compileSerpent,
submitWork,
getWork
]; ];
/// @returns an array of objects describing web3.eth api properties /// @returns an array of objects describing web3.eth api properties

77
lib/web3/function.js

@ -39,18 +39,23 @@ var SolidityFunction = function (json, address) {
this._address = address; this._address = address;
}; };
SolidityFunction.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array!
}
};
/** /**
* Should be used to create payload from arguments * Should be used to create payload from arguments
* *
* @method toPayload * @method toPayload
* @param {...} solidity function params * @param {Array} solidity function params
* @param {Object} optional payload options * @param {Object} optional payload options
*/ */
SolidityFunction.prototype.toPayload = function () { SolidityFunction.prototype.toPayload = function (args) {
var args = Array.prototype.slice.call(arguments);
var options = {}; var options = {};
if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {
options = args.pop(); options = args[args.length - 1];
} }
options.to = this._address; options.to = this._address;
options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);
@ -67,19 +72,41 @@ SolidityFunction.prototype.signature = function () {
return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); return web3.sha3(web3.fromAscii(this._name)).slice(2, 10);
}; };
SolidityFunction.prototype.unpackOutput = function (output) {
if (output === null) {
return;
}
output = output.length >= 2 ? output.slice(2) : output;
var result = coder.decodeParams(this._outputTypes, output);
return result.length === 1 ? result[0] : result;
};
/** /**
* Should be used to call function * Calls a contract function.
* *
* @method call * @method call
* @param {Object} options * @param {...Object} Contract function arguments
* @param {function} If the last argument is a function, the contract function
* call will be asynchronous, and the callback will be passed the
* error and result.
* @return {String} output bytes * @return {String} output bytes
*/ */
SolidityFunction.prototype.call = function () { SolidityFunction.prototype.call = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
if (!callback) {
var output = web3.eth.call(payload); var output = web3.eth.call(payload);
output = output.length >= 2 ? output.slice(2) : output; return this.unpackOutput(output);
var result = coder.decodeParams(this._outputTypes, output); }
return result.length === 1 ? result[0] : result;
var self = this;
web3.eth.call(payload, function (error, output) {
callback(error, self.unpackOutput(output));
});
}; };
/** /**
@ -89,8 +116,16 @@ SolidityFunction.prototype.call = function () {
* @param {Object} options * @param {Object} options
*/ */
SolidityFunction.prototype.sendTransaction = function () { SolidityFunction.prototype.sendTransaction = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
if (!callback) {
web3.eth.sendTransaction(payload); web3.eth.sendTransaction(payload);
return;
}
web3.eth.sendTransaction(payload, callback);
}; };
/** /**
@ -113,6 +148,25 @@ SolidityFunction.prototype.typeName = function () {
return utils.extractTypeName(this._name); return utils.extractTypeName(this._name);
}; };
/**
* Should be called to get rpc requests from solidity function
*
* @method request
* @returns {Object}
*/
SolidityFunction.prototype.request = function () {
var args = Array.prototype.slice.call(arguments);
var callback = this.extractCallback(args);
var payload = this.toPayload(args);
var format = this.unpackOutput.bind(this);
return {
callback: callback,
payload: payload,
format: format
};
};
/** /**
* Should be called to execute function * Should be called to execute function
* *
@ -138,6 +192,7 @@ SolidityFunction.prototype.execute = function () {
*/ */
SolidityFunction.prototype.attachToContract = function (contract) { SolidityFunction.prototype.attachToContract = function (contract) {
var execute = this.execute.bind(this); var execute = this.execute.bind(this);
execute.request = this.request.bind(this);
execute.call = this.call.bind(this); execute.call = this.call.bind(this);
execute.sendTransaction = this.sendTransaction.bind(this); execute.sendTransaction = this.sendTransaction.bind(this);
var displayName = this.displayName(); var displayName = this.displayName();

17
lib/web3/method.js

@ -54,7 +54,6 @@ Method.prototype.extractCallback = function (args) {
if (utils.isFunction(args[args.length - 1])) { if (utils.isFunction(args[args.length - 1])) {
return args.pop(); // modify the args array! return args.pop(); // modify the args array!
} }
return null;
}; };
/** /**
@ -107,6 +106,7 @@ Method.prototype.formatOutput = function (result) {
*/ */
Method.prototype.attachToObject = function (obj) { Method.prototype.attachToObject = function (obj) {
var func = this.send.bind(this); var func = this.send.bind(this);
func.request = this.request.bind(this);
func.call = this.call; // that's ugly. filter.js uses it func.call = this.call; // that's ugly. filter.js uses it
var name = this.name.split('.'); var name = this.name.split('.');
if (name.length > 1) { if (name.length > 1) {
@ -137,6 +137,19 @@ Method.prototype.toPayload = function (args) {
}; };
}; };
/**
* Should be called to create pure JSONRPC request which can be used in batch request
*
* @method request
* @param {...} params
* @return {Object} jsonrpc request
*/
Method.prototype.request = function () {
var payload = this.toPayload(Array.prototype.slice.call(arguments));
payload.format = this.formatOutput.bind(this);
return payload;
};
/** /**
* Should send request to the API * Should send request to the API
* *
@ -149,7 +162,7 @@ Method.prototype.send = function () {
if (payload.callback) { if (payload.callback) {
var self = this; var self = this;
return RequestManager.getInstance().sendAsync(payload, function (err, result) { return RequestManager.getInstance().sendAsync(payload, function (err, result) {
payload.callback(null, self.formatOutput(result)); payload.callback(err, self.formatOutput(result));
}); });
} }
return this.formatOutput(RequestManager.getInstance().send(payload)); return this.formatOutput(RequestManager.getInstance().send(payload));

40
lib/web3/property.js

@ -63,16 +63,23 @@ Property.prototype.formatOutput = function (result) {
Property.prototype.attachToObject = function (obj) { Property.prototype.attachToObject = function (obj) {
var proto = { var proto = {
get: this.get.bind(this), get: this.get.bind(this),
set: this.set.bind(this)
}; };
var name = this.name.split('.'); var names = this.name.split('.');
if (name.length > 1) { var name = names[0];
obj[name[0]] = obj[name[0]] || {}; if (names.length > 1) {
Object.defineProperty(obj[name[0]], name[1], proto); obj[names[0]] = obj[names[0]] || {};
} else { obj = obj[names[0]];
Object.defineProperty(obj, name[0], proto); name = names[1];
} }
Object.defineProperty(obj, name, proto);
var toAsyncName = function (prefix, name) {
return prefix + name.charAt(0).toUpperCase() + name.slice(1);
};
obj[toAsyncName('get', name)] = this.getAsync.bind(this);
}; };
/** /**
@ -88,15 +95,20 @@ Property.prototype.get = function () {
}; };
/** /**
* Should be used to set value of the property * Should be used to asynchrounously get value of property
* *
* @method set * @method getAsync
* @param {Object} new value of the property * @param {Function}
*/ */
Property.prototype.set = function (value) { Property.prototype.getAsync = function (callback) {
return RequestManager.getInstance().send({ var self = this;
method: this.setter, RequestManager.getInstance().sendAsync({
params: [this.formatInput(value)] method: this.getter
}, function (err, result) {
if (err) {
return callback(err);
}
callback(err, self.formatOutput(result));
}); });
}; };

27
lib/web3/requestmanager.js

@ -105,6 +105,33 @@ RequestManager.prototype.sendAsync = function (data, callback) {
}); });
}; };
/**
* Should be called to asynchronously send batch request
*
* @method sendBatch
* @param {Array} batch data
* @param {Function} callback
*/
RequestManager.prototype.sendBatch = function (data, callback) {
if (!this.provider) {
return callback(errors.InvalidProvider());
}
var payload = Jsonrpc.getInstance().toBatchPayload(data);
this.provider.sendAsync(payload, function (err, results) {
if (err) {
return callback(err);
}
if (!utils.isArray(results)) {
return callback(errors.InvalidResponse(results));
}
callback(err, results);
});
};
/** /**
* Should be used to set provider of request manager * Should be used to set provider of request manager
* *

15
lib/web3/watches.js

@ -25,7 +25,20 @@ var Method = require('./method');
/// @returns an array of objects describing web3.eth.filter api methods /// @returns an array of objects describing web3.eth.filter api methods
var eth = function () { var eth = function () {
var newFilterCall = function (args) { var newFilterCall = function (args) {
return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter'; var type = args[0];
switch(type) {
case 'latest':
args.pop();
this.params = 0;
return 'eth_newBlockFilter';
case 'pending':
args.pop();
this.params = 0;
return 'eth_newPendingTransactionFilter';
default:
return 'eth_newFilter';
}
}; };
var newFilter = new Method({ var newFilter = new Method({

2
package.js

@ -1,7 +1,7 @@
/* jshint ignore:start */ /* jshint ignore:start */
Package.describe({ Package.describe({
name: 'ethereum:web3', name: 'ethereum:web3',
version: '0.3.6', version: '0.4.2',
summary: 'Ethereum JavaScript API, middleware to talk to a ethreum node over RPC', summary: 'Ethereum JavaScript API, middleware to talk to a ethreum node over RPC',
git: 'https://github.com/ethereum/ethereum.js', git: 'https://github.com/ethereum/ethereum.js',
// By default, Meteor will default to using README.md for documentation. // By default, Meteor will default to using README.md for documentation.

2
package.json

@ -1,7 +1,7 @@
{ {
"name": "web3", "name": "web3",
"namespace": "ethereum", "namespace": "ethereum",
"version": "0.3.6", "version": "0.4.2",
"description": "Ethereum JavaScript API, middleware to talk to a ethereum node over RPC", "description": "Ethereum JavaScript API, middleware to talk to a ethereum node over RPC",
"main": "./index.js", "main": "./index.js",
"directories": { "directories": {

106
test/abi.formatConstructorParams.js

@ -1,106 +0,0 @@
var chai = require('chai');
var assert = require('assert');
var abi = require('../lib/solidity/abi');
describe('lib/solidity/abi', function () {
describe('formatConstructorParams', function () {
it('should format uint256 properly', function () {
// given
var description = [{
"name": "test",
"type": "constructor",
"inputs": [{
"name": "a",
"type": "uint256"
}
]
}];
// when
var bytes = abi.formatConstructorParams(description, [2]);
// then
assert.equal(bytes, '0000000000000000000000000000000000000000000000000000000000000002');
});
it('should not find matching constructor', function () {
// given
var description = [{
"name": "test",
"type": "constructor",
"inputs": [{
"name": "a",
"type": "uint256"
}
]
}];
// when
var bytes = abi.formatConstructorParams(description, []);
// then
assert.equal(bytes, '');
});
it('should not find matching constructor2', function () {
// given
var description = [{
"name": "test",
"type": "constructor",
"inputs": [{
"name": "a",
"type": "uint256"
}
]
}];
// when
var bytes = abi.formatConstructorParams(description, [1,2]);
// then
assert.equal(bytes, '');
});
it('should not find matching constructor3', function () {
// given
var description = [{
"name": "test",
"type": "function",
"inputs": [{
"name": "a",
"type": "uint256"
}
]
}];
// when
var bytes = abi.formatConstructorParams(description, [2]);
// then
assert.equal(bytes, '');
});
it('should find matching constructor with multiple args', function () {
// given
var description = [{
"name": "test",
"type": "constructor",
"inputs": [{
"name": "a",
"type": "uint256"
}, {
"name": "b",
"type": "uint256"
}]
}];
// when
var bytes = abi.formatConstructorParams(description, ['1', '5']);
// then
assert.equal(bytes, '00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005');
});
});
});

69
test/async.js

@ -0,0 +1,69 @@
var chai = require('chai');
var assert = chai.assert;
var web3 = require('../index');
var FakeHttpProvider = require('./helpers/FakeHttpProvider');
// use sendTransaction as dummy
var method = 'sendTransaction';
var tests = [{
result: '0xb',
formattedResult: '0xb',
call: 'eth_'+ method
}];
describe('async', function () {
tests.forEach(function (test, index) {
it('test: ' + index, function (done) {
// given
var provider = new FakeHttpProvider();
web3.setProvider(provider);
provider.injectResult(test.result);
provider.injectValidation(function (payload) {
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, test.call);
assert.deepEqual(payload.params, [{}]);
});
// when
web3.eth[method]({}, function(error, result){
// then
assert.isNull(error);
assert.strictEqual(test.formattedResult, result);
done();
});
});
it('error test: ' + index, function (done) {
// given
var provider = new FakeHttpProvider();
web3.setProvider(provider);
provider.injectError({
message: test.result,
code: -32603
});
provider.injectValidation(function (payload) {
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, test.call);
assert.deepEqual(payload.params, [{}]);
});
// when
web3.eth[method]({}, function(error, result){
// then
assert.isUndefined(result);
assert.strictEqual(test.formattedResult, error.message);
done();
});
});
});
});

86
test/batch.js

@ -0,0 +1,86 @@
var chai = require('chai');
var assert = chai.assert;
var web3 = require('../index');
var FakeHttpProvider = require('./helpers/FakeHttpProvider');
var bn = require('bignumber.js');
describe('lib/web3/batch', function () {
describe('execute', function () {
it('should execute batch request', function (done) {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
var result = '0x126';
var result2 = '0x127';
provider.injectBatchResults([result, result2]);
var counter = 0;
var callback = function (err, r) {
counter++;
assert.deepEqual(new bn(result), r);
};
var callback2 = function (err, r) {
assert.equal(counter, 1);
assert.deepEqual(new bn(result2), r);
done();
};
var batch = web3.createBatch();
batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback));
batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000005', 'latest', callback2));
batch.execute();
});
it('should execute batch request', function (done) {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
var abi = [{
"name": "balance(address)",
"type": "function",
"inputs": [{
"name": "who",
"type": "address"
}],
"constant": true,
"outputs": [{
"name": "value",
"type": "uint256"
}]
}];
var address = '0x0000000000000000000000000000000000000000';
var result = '0x126';
var result2 = '0x0000000000000000000000000000000000000000000000000000000000000123';
var signature = '0x001122334455';
// TODO: fix this, maybe in browser sha3?
provider.injectResult(signature);
var counter = 0;
var callback = function (err, r) {
counter++;
assert.deepEqual(new bn(result), r);
};
var callback2 = function (err, r) {
assert.equal(counter, 1);
assert.deepEqual(new bn(result2), r);
done();
};
var batch = web3.createBatch();
batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback));
batch.add(web3.eth.contract(abi).at(address).balance.request(address, callback2));
provider.injectBatchResults([result, result2]);
batch.execute();
});
});
});

100
test/contract.js

@ -116,8 +116,7 @@ describe('web3.eth.contract', function () {
} }
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
var res = 0; var res = 0;
contract.Changed({from: address}).watch(function(err, result) { contract.Changed({from: address}).watch(function(err, result) {
@ -155,8 +154,7 @@ describe('web3.eth.contract', function () {
} }
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
contract.balance(address); contract.balance(address);
}); });
@ -186,8 +184,7 @@ describe('web3.eth.contract', function () {
} }
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
contract.send(address, 17); contract.send(address, 17);
}); });
@ -218,8 +215,7 @@ describe('web3.eth.contract', function () {
} }
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
contract.balance(address, {from: address, gas: 50000}); contract.balance(address, {from: address, gas: 50000});
@ -251,8 +247,7 @@ describe('web3.eth.contract', function () {
} }
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
contract.balance.call(address, {from: address, gas: 50000}); contract.balance.call(address, {from: address, gas: 50000});
@ -287,8 +282,7 @@ describe('web3.eth.contract', function () {
} }
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
contract.send(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000}); contract.send(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000});
}); });
@ -322,12 +316,48 @@ describe('web3.eth.contract', function () {
} }
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
contract.send.sendTransaction(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000}); contract.send.sendTransaction(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000});
}); });
it('should explicitly sendTransaction with optional params and call callback without error', function (done) {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
var sha3 = '0x5131231231231231231231';
var address = '0x1234567890123456789012345678901234567890';
provider.injectResult(sha3);
var step = 0;
provider.injectValidation(function (payload) {
if (step === 0) {
step = 1;
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'web3_sha3');
assert.equal(payload.params[0], web3.fromAscii('send(address,uint256)'));
} else if (step === 1) {
assert.equal(payload.method, 'eth_sendTransaction');
assert.deepEqual(payload.params, [{
data: sha3.slice(0, 10) +
'0000000000000000000000001234567890123456789012345678901234567890' +
'0000000000000000000000000000000000000000000000000000000000000011' ,
to: address,
from: address,
gas: '0xc350',
gasPrice: '0xbb8',
value: '0x2710'
}]);
}
});
var contract = web3.eth.contract(desc).at(address);
contract.send.sendTransaction(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000}, function (err) {
assert.equal(err, null);
done();
});
});
it('should call testArr method and properly parse result', function () { it('should call testArr method and properly parse result', function () {
var provider = new FakeHttpProvider2(); var provider = new FakeHttpProvider2();
web3.setProvider(provider); web3.setProvider(provider);
@ -356,12 +386,48 @@ describe('web3.eth.contract', function () {
step++; step++;
}); });
var Contract = web3.eth.contract(desc); var contract = web3.eth.contract(desc).at(address);
var contract = new Contract(address);
var result = contract.testArr([3]); var result = contract.testArr([3]);
assert.deepEqual(new BigNumber(5), result); assert.deepEqual(new BigNumber(5), result);
}); });
it('should call testArr method, properly parse result and return the result async', function (done) {
var provider = new FakeHttpProvider2();
web3.setProvider(provider);
web3.reset();
var sha3 = '0x5131231231231231231231';
var address = '0x1234567890123456789012345678901234567890';
provider.injectResultList([{
result: sha3
}, {
result: '0x0000000000000000000000000000000000000000000000000000000000000005'
}]);
var step = 0;
provider.injectValidation(function (payload) {
if (step === 1) { // getting sha3 is first
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
data: sha3.slice(0, 10) +
'0000000000000000000000000000000000000000000000000000000000000020' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003',
to: address
},
'latest'
]);
}
step++;
});
var contract = web3.eth.contract(desc).at(address);
contract.testArr([3], function (err, result) {
assert.deepEqual(new BigNumber(5), result);
done();
});
}); });
}); });
});

23
test/method.request.js

@ -0,0 +1,23 @@
var chai = require('chai');
var assert = chai.assert;
var web3 = require('../index');
describe('lib/web3/method', function () {
describe('request', function () {
it('should create proper request', function () {
var callback = function (err, result) {};
var expected = {
method: 'eth_getBalance',
callback: callback,
params: ['0x0000000000000000000000000000000000000000', 'latest'],
};
var request = web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback);
expected.format = request.format;
assert.deepEqual(request, expected);
});
});
});

2
test/node/app.js

@ -1,4 +1,4 @@
var web3 = require('ethereum.js'); var web3 = require('web3');
console.log(web3.version.api); console.log(web3.version.api);

2
test/node/package.json

@ -9,6 +9,6 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"ethereum.js": "ethereum/ethereum.js#master" "web3": "ethereum/web3.js#master"
} }
} }

21
test/polling.js

@ -6,15 +6,26 @@ var utils = require('../lib/utils/utils');
var tests = [{ var tests = [{
protocol: 'eth', protocol: 'eth',
args: ['pending'], args: ['latest'],
firstResult: 1, firstResult: 1,
firstPayload: { firstPayload: {
method: "eth_newBlockFilter", method: "eth_newBlockFilter",
params: [ params: []
"pending" },
] secondResult: ['0x1234'],
secondPayload: {
method: "eth_getFilterChanges"
}
},
{
protocol: 'eth',
args: ['pending'],
firstResult: 1,
firstPayload: {
method: "eth_newPendingTransactionFilter",
params: []
}, },
secondResult: [null], secondResult: ['0x1234'],
secondPayload: { secondPayload: {
method: "eth_getFilterChanges" method: "eth_getFilterChanges"
} }

20
test/web3.eth.blockNumber.js

@ -32,6 +32,26 @@ describe('web3.eth', function () {
// then // then
assert.strictEqual(test.formattedResult, result); assert.strictEqual(test.formattedResult, result);
}); });
it('async get property test: ' + index, function (done) {
// given
var provider = new FakeHttpProvider();
web3.setProvider(provider);
provider.injectResult(test.result);
provider.injectValidation(function (payload) {
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, test.call);
assert.deepEqual(payload.params, []);
});
// when
web3.eth.getBlockNumber(function (err, result) {
assert.strictEqual(test.formattedResult, result);
done();
});
});
}); });
}); });
}); });

41
test/web3.eth.call.js

@ -0,0 +1,41 @@
var web3 = require('../index');
var testMethod = require('./helpers/test.method.js');
var method = 'call';
var tests = [{
args: [{
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
data: '0x23455654',
gas: 11,
gasPrice: 11
}],
formattedArgs: [{
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
data: '0x23455654',
gas: '0xb',
gasPrice: '0xb'
}, 'latest'],
result: '0x31981',
formattedResult: '0x31981',
call: 'eth_'+ method
},{
args: [{
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
data: '0x23455654',
gas: 11,
gasPrice: 11
}, 11],
formattedArgs: [{
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
data: '0x23455654',
gas: '0xb',
gasPrice: '0xb'
}, '0xb'],
result: '0x31981',
formattedResult: '0x31981',
call: 'eth_'+ method
}];
testMethod.runTests('eth', method, tests);

21
test/web3.eth.contract.js

@ -25,8 +25,7 @@ describe('web3.eth.contract', function() {
var address = '0x1234567890123456789012345678901234567890'; var address = '0x1234567890123456789012345678901234567890';
// when // when
var Con = contract(description); var myCon = contract(description).at(address);
var myCon = new Con(address);
// then // then
assert.equal('function', typeof myCon.test); assert.equal('function', typeof myCon.test);
@ -54,8 +53,7 @@ describe('web3.eth.contract', function() {
var address = '0x1234567890123456789012345678901234567890'; var address = '0x1234567890123456789012345678901234567890';
// when // when
var Con = contract(description); var myCon = contract(description).at(address);
var myCon = new Con(address);
// then // then
assert.equal('function', typeof myCon.test); assert.equal('function', typeof myCon.test);
@ -97,8 +95,7 @@ describe('web3.eth.contract', function() {
var address = '0x1234567890123456789012345678901234567890'; var address = '0x1234567890123456789012345678901234567890';
// when // when
var Con = contract(description); var myCon = contract(description).at(address);
var myCon = new Con(address);
// then // then
assert.equal('function', typeof myCon.test); assert.equal('function', typeof myCon.test);
@ -142,8 +139,7 @@ describe('web3.eth.contract', function() {
var address = '0x1234567890123456789012345678901234567890'; var address = '0x1234567890123456789012345678901234567890';
// when // when
var Con = contract(description); var myCon = contract(description).at(address);
var myCon = new Con(address);
// then // then
assert.equal('function', typeof myCon.test); assert.equal('function', typeof myCon.test);
@ -171,8 +167,7 @@ describe('web3.eth.contract', function() {
var address = '0x1234567890123456789012345678901234567890'; var address = '0x1234567890123456789012345678901234567890';
// when // when
var Con = contract(description); var myCon = contract(description).at(address);
var myCon = new Con(address);
// then // then
assert.equal('undefined', typeof myCon.test); assert.equal('undefined', typeof myCon.test);
@ -200,8 +195,7 @@ describe('web3.eth.contract', function() {
var address = '0x1234567890123456789012345678901234567890'; var address = '0x1234567890123456789012345678901234567890';
// when // when
var Con = contract(description); var myCon = contract(description).at(address);
var myCon = new Con(address);
// then // then
assert.equal('function', typeof myCon.test); assert.equal('function', typeof myCon.test);
@ -233,8 +227,7 @@ describe('web3.eth.contract', function() {
done(); done();
}); });
var Con = contract(description); var myCon = contract(description).new(2, {data: code});
var myCon = new Con({data: code}, 2);
}); });
}); });

25
test/web3.eth.estimateGas.js

@ -0,0 +1,25 @@
var web3 = require('../index');
var testMethod = require('./helpers/test.method.js');
var method = 'estimateGas';
var tests = [{
args: [{
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
data: '0x23455654',
gas: 11,
gasPrice: 11
}],
formattedArgs: [{
to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
data: '0x23455654',
gas: '0xb',
gasPrice: '0xb'
}],
result: '0x31981',
formattedResult: 203137,
call: 'eth_'+ method
}];
testMethod.runTests('eth', method, tests);

10
test/web3.eth.filter.js

@ -37,11 +37,17 @@ var tests = [{
formattedResult: '0xf', formattedResult: '0xf',
call: 'eth_newFilter' call: 'eth_newFilter'
},{ },{
args: ['pending'], args: ['latest'],
formattedArgs: ['pending'], formattedArgs: [],
result: '0xf', result: '0xf',
formattedResult: '0xf', formattedResult: '0xf',
call: 'eth_newBlockFilter' call: 'eth_newBlockFilter'
},{
args: ['pending'],
formattedArgs: [],
result: '0xf',
formattedResult: '0xf',
call: 'eth_newPendingTransactionFilter'
}]; }];
describe('web3.eth', function () { describe('web3.eth', function () {

16
test/web3.eth.getWork.js

@ -0,0 +1,16 @@
var chai = require('chai');
var web3 = require('../index');
var testMethod = require('./helpers/test.method.js');
var method = 'getWork';
var tests = [{
args: [],
formattedArgs: [],
result: true,
formattedResult: true,
call: 'eth_'+ method
}];
testMethod.runTests('eth', method, tests);

17
test/web3.eth.submitWork.js

@ -0,0 +1,17 @@
var chai = require('chai');
var web3 = require('../index');
var testMethod = require('./helpers/test.method.js');
var method = 'submitWork';
var tests = [
{
args: ['0x567890abcdef5555', '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', '0xcdef1234567890abcdef1234567890abcdef0x1234567890abcf1234567890ab'],
formattedArgs: ['0x567890abcdef5555', '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', '0xcdef1234567890abcdef1234567890abcdef0x1234567890abcf1234567890ab'],
result: true,
formattedResult: true,
call: 'eth_'+ method
}];
testMethod.runTests('eth', method, tests);
Loading…
Cancel
Save