Browse Source

Squashed 'libjsqrc/ethereumjs/' changes from 82cc5f6..9a85b09

9a85b09 version upgrade
ec6f9b3 added transactionCount && uncleCount methods
b96a7aa gulp cleanup
d6128f2 coveralls badge points to master
efee649 coveralls badge
339f565 travis coveralls
27d53dd travis coveralls
001077e Merge pull request #59 from cubedro/master
9902977 updated dist
af7c26b check request.status in httpsync.js to prevent throwing errors when undefined
ad8112c Merge pull request #15 from ethereum/master
d1e6b20 updated README
c184728 version upgrade
3d652e8 fixed web3.reset()
26561e4 fixed #51
03661d3 eth_polling_timeout const
9e806cc Merge branch 'master' into develop
82d32bb providermanager -> requestmanager
a86fccf web3 refactor (in progress)
c29f4a1 filters refactor
9d84609 Merge branch 'master' of https://github.com/ethereum/ethereum.js
859a199 Merge pull request #55 from ethereum/develop
fd5146d Merge pull request #12 from debris/master

git-subtree-dir: libjsqrc/ethereumjs
git-subtree-split: 9a85b098a082f9ed38bcf92ab5ee6ba64489d7cf
cl-refactor
Marek Kotewicz 10 years ago
parent
commit
4fbeff27d6
  1. 1
      .gitignore
  2. 2
      .travis.yml
  3. 8
      README.md
  4. 2
      bower.json
  5. 712
      dist/ethereum.js
  6. 26
      dist/ethereum.js.map
  7. 2
      dist/ethereum.min.js
  8. 97
      gulpfile.js
  9. 4
      index.js
  10. 3
      lib/const.js
  11. 5
      lib/contract.js
  12. 35
      lib/db.js
  13. 85
      lib/eth.js
  14. 142
      lib/filter.js
  15. 8
      lib/httpsync.js
  16. 102
      lib/providermanager.js
  17. 103
      lib/requestmanager.js
  18. 37
      lib/shh.js
  19. 49
      lib/watches.js
  20. 177
      lib/web3.js
  21. 18
      package.json
  22. 2
      test/eth.methods.js
  23. 27
      test/filter.methods.js
  24. 11
      test/web3.methods.js

1
.gitignore

@ -5,6 +5,7 @@
# git config --global core.excludesfile ~/.gitignore_global
*.swp
/coverage
/tmp
*/**/*un~
*un~

2
.travis.yml

@ -9,5 +9,5 @@ script:
- "jshint *.js lib"
after_script:
- npm run-script build
- npm test
- npm run-script test-coveralls

8
README.md

@ -3,7 +3,7 @@
This is the Ethereum compatible [JavaScript API](https://github.com/ethereum/wiki/wiki/JavaScript-API)
which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC) spec. It's available on npm as a node module and also for bower and component as an embeddable js
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url]
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url][![Coverage Status][coveralls-image]][coveralls-url]
<!-- [![browser support](https://ci.testling.com/ethereum/ethereum.js.png)](https://ci.testling.com/ethereum/ethereum.js) -->
@ -30,9 +30,9 @@ Require the library:
var web3 = require('web3');
Set a provider (QtProvider, WebSocketProvider, HttpRpcProvider)
Set a provider (QtSyncProvider, HttpSyncProvider)
var web3.setProvider(new web3.providers.WebSocketProvider('ws://localhost:40404/eth'));
web3.setProvider(new web3.providers.HttpSyncProvider());
There you go, now you can use it:
@ -93,4 +93,6 @@ ethereum -ws -loglevel=4
[dep-url]: https://david-dm.org/ethereum/ethereum.js
[dep-dev-image]: https://david-dm.org/ethereum/ethereum.js/dev-status.svg
[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies
[coveralls-image]: https://coveralls.io/repos/ethereum/ethereum.js/badge.svg?branch=master
[coveralls-url]: https://coveralls.io/r/ethereum/ethereum.js?branch=master

2
bower.json

@ -1,7 +1,7 @@
{
"name": "ethereum.js",
"namespace": "ethereum",
"version": "0.0.13",
"version": "0.0.15",
"description": "Ethereum Compatible JavaScript API",
"main": ["./dist/ethereum.js", "./dist/ethereum.min.js"],
"dependencies": {

712
dist/ethereum.js

@ -210,7 +210,7 @@ module.exports = {
};
},{"./const":2,"./formatters":6,"./types":11,"./utils":12,"./web3":13}],2:[function(require,module,exports){
},{"./const":2,"./formatters":8,"./types":14,"./utils":15,"./web3":17}],2:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -264,7 +264,8 @@ module.exports = {
ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
ETH_POLLING_TIMEOUT: 1000
};
@ -295,6 +296,7 @@ var web3 = require('./web3');
var abi = require('./abi');
var utils = require('./utils');
var eventImpl = require('./event');
var filter = require('./filter');
var exportNatspecGlobals = function (vars) {
// it's used byt natspec.js
@ -416,11 +418,11 @@ var addEventsToContract = function (contract, desc, address) {
var signature = abi.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, signature, e);
var o = event.apply(null, params);
o._onWatchEventResult = function (data) {
var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.watch(o);
return web3.eth.watch(o, undefined, undefined, outputFormatter);
};
// this property should be used by eth.filter to check if object is an event
@ -487,7 +489,131 @@ var contract = function (address, desc) {
module.exports = contract;
},{"./abi":1,"./event":4,"./utils":12,"./web3":13}],4:[function(require,module,exports){
},{"./abi":1,"./event":6,"./filter":7,"./utils":15,"./web3":17}],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 db.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/// @returns an array of objects describing web3.db api methods
var methods = function () {
return [
{ name: 'put', call: 'db_put' },
{ name: 'get', call: 'db_get' },
{ name: 'putString', call: 'db_putString' },
{ name: 'getString', call: 'db_getString' }
];
};
module.exports = {
methods: methods
};
},{}],5:[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 eth.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/// @returns an array of objects describing web3.eth api methods
var methods = function () {
var blockCall = function (args) {
return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
};
var transactionCall = function (args) {
return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
};
var uncleCall = function (args) {
return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
};
var transactionCountCall = function (args) {
return typeof args[0] === "string" ? 'eth_transactionCountByHash' : 'eth_transactionCountByNumber';
};
var uncleCountCall = function (args) {
return typeof args[0] === "string" ? 'eth_uncleCountByHash' : 'eth_uncleCountByNumber';
};
return [
{ name: 'balanceAt', call: 'eth_balanceAt' },
{ name: 'stateAt', call: 'eth_stateAt' },
{ name: 'storageAt', call: 'eth_storageAt' },
{ name: 'countAt', call: 'eth_countAt'},
{ name: 'codeAt', call: 'eth_codeAt' },
{ name: 'transact', call: 'eth_transact' },
{ name: 'call', call: 'eth_call' },
{ name: 'block', call: blockCall },
{ name: 'transaction', call: transactionCall },
{ name: 'uncle', call: uncleCall },
{ name: 'compilers', call: 'eth_compilers' },
{ name: 'flush', call: 'eth_flush' },
{ name: 'lll', call: 'eth_lll' },
{ name: 'solidity', call: 'eth_solidity' },
{ name: 'serpent', call: 'eth_serpent' },
{ name: 'logs', call: 'eth_logs' },
{ name: 'transactionCount', call: transactionCountCall },
{ name: 'uncleCount', call: uncleCountCall }
];
};
/// @returns an array of objects describing web3.eth api properties
var properties = function () {
return [
{ name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
{ name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
{ name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
{ name: 'gasPrice', getter: 'eth_gasPrice' },
{ name: 'accounts', getter: 'eth_accounts' },
{ name: 'peerCount', getter: 'eth_peerCount' },
{ name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
{ name: 'number', getter: 'eth_number'}
];
};
module.exports = {
methods: methods,
properties: properties
};
},{}],6:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -624,7 +750,7 @@ module.exports = {
};
},{"./abi":1,"./utils":12}],5:[function(require,module,exports){
},{"./abi":1,"./utils":15}],7:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -650,84 +776,96 @@ module.exports = {
* @date 2014
*/
var web3 = require('./web3'); // jshint ignore:line
/// should be used when we want to watch something
/// it's using inner polling mechanism and is notified about changes
/// TODO: change 'options' name cause it may be not the best matching one, since we have events
var Filter = function(options, impl) {
if (typeof options !== "string") {
// topics property is deprecated, warn about it!
if (options.topics) {
console.warn('"topics" is deprecated, use "topic" instead');
}
this._onWatchResult = options._onWatchEventResult;
// evaluate lazy properties
options = {
to: options.to,
topic: options.topic,
earliest: options.earliest,
latest: options.latest,
max: options.max,
skip: options.skip,
address: options.address
};
/// Should be called to check if filter implementation is valid
/// @returns true if it is, otherwise false
var implementationIsValid = function (i) {
return !!i &&
typeof i.newFilter === 'function' &&
typeof i.getMessages === 'function' &&
typeof i.uninstallFilter === 'function' &&
typeof i.startPolling === 'function' &&
typeof i.stopPolling === 'function';
};
/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones
/// @param should be string or object
/// @returns options string or object
var getOptions = function (options) {
if (typeof options === 'string') {
return options;
}
options = options || {};
if (options.topics) {
console.warn('"topics" is deprecated, is "topic" instead');
}
this.impl = impl;
this.callbacks = [];
this.id = impl.newFilter(options);
web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this));
// evaluate lazy properties
return {
to: options.to,
topic: options.topic,
earliest: options.earliest,
latest: options.latest,
max: options.max,
skip: options.skip,
address: options.address
};
};
/// alias for changed*
Filter.prototype.arrived = function(callback) {
this.changed(callback);
};
Filter.prototype.happened = function(callback) {
this.changed(callback);
};
/// Should be used when we want to watch something
/// it's using inner polling mechanism and is notified about changes
/// @param options are filter options
/// @param implementation, an abstract polling implementation
/// @param formatter (optional), callback function which formats output before 'real' callback
var filter = function(options, implementation, formatter) {
if (!implementationIsValid(implementation)) {
console.error('filter implemenation is invalid');
return;
}
/// gets called when there is new eth/shh message
Filter.prototype.changed = function(callback) {
this.callbacks.push(callback);
};
options = getOptions(options);
var callbacks = [];
var filterId = implementation.newFilter(options);
var onMessages = function (messages) {
messages.forEach(function (message) {
messages = formatter ? formatter(message) : message;
callbacks.forEach(function (callback) {
callback(message);
});
});
};
/// trigger calling new message from people
Filter.prototype.trigger = function(messages) {
for (var i = 0; i < this.callbacks.length; i++) {
for (var j = 0; j < messages.length; j++) {
var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j];
this.callbacks[i].call(this, message);
}
}
};
implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);
/// should be called to uninstall current filter
Filter.prototype.uninstall = function() {
this.impl.uninstallFilter(this.id);
web3.provider.stopPolling(this.id);
};
var changed = function (callback) {
callbacks.push(callback);
};
/// should be called to manually trigger getting latest messages from the client
Filter.prototype.messages = function() {
return this.impl.getMessages(this.id);
};
var messages = function () {
return implementation.getMessages(filterId);
};
var uninstall = function (callback) {
implementation.stopPolling(filterId);
implementation.uninstallFilter(filterId);
callbacks = [];
};
/// alias for messages
Filter.prototype.logs = function () {
return this.messages();
return {
changed: changed,
arrived: changed,
happened: changed,
messages: messages,
logs: messages,
uninstall: uninstall
};
};
module.exports = Filter;
module.exports = filter;
},{"./web3":13}],6:[function(require,module,exports){
},{}],8:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -883,7 +1021,7 @@ module.exports = {
};
},{"./const":2,"./utils":12}],7:[function(require,module,exports){
},{"./const":2,"./utils":15}],9:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -918,20 +1056,22 @@ var HttpSyncProvider = function (host) {
HttpSyncProvider.prototype.send = function (payload) {
//var data = formatJsonRpcObject(payload);
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.send(JSON.stringify(payload));
// check request.status
var result = request.responseText;
// check request.status
if(request.status !== 200)
return;
return JSON.parse(result);
};
module.exports = HttpSyncProvider;
},{}],8:[function(require,module,exports){
},{}],10:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -998,7 +1138,42 @@ module.exports = {
},{}],9:[function(require,module,exports){
},{}],11:[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 qtsync.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* @date 2014
*/
var QtSyncProvider = function () {
};
QtSyncProvider.prototype.send = function (payload) {
var result = navigator.qt.callMethod(JSON.stringify(payload));
return JSON.parse(result);
};
module.exports = QtSyncProvider;
},{}],12:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -1015,7 +1190,7 @@ module.exports = {
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 providermanager.js
/** @file requestmanager.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
@ -1024,85 +1199,86 @@ module.exports = {
* @date 2014
*/
var web3 = require('./web3');
var jsonrpc = require('./jsonrpc');
var c = require('./const');
/**
* Provider manager object prototype
* It's responsible for passing messages to providers
* If no provider is set it's responsible for queuing requests
* It's also responsible for polling the ethereum node for incoming messages
* Default poll timeout is 12 seconds
* If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling,
* and provider manager polling mechanism is not used
* Default poll timeout is 1 second
*/
var ProviderManager = function() {
this.polls = [];
this.provider = undefined;
var requestManager = function() {
var polls = [];
var provider;
var self = this;
var poll = function () {
self.polls.forEach(function (data) {
var result = self.send(data.data);
if (!(result instanceof Array) || result.length === 0) {
return;
}
var send = function (data) {
var payload = jsonrpc.toPayload(data.method, data.params);
if (!provider) {
console.error('provider is not set');
return null;
}
data.callback(result);
});
var result = provider.send(payload);
setTimeout(poll, 1000);
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return null;
}
return result.result;
};
poll();
};
/// sends outgoing requests
/// @params data - an object with at least 'method' property
ProviderManager.prototype.send = function(data) {
var payload = jsonrpc.toPayload(data.method, data.params);
if (this.provider === undefined) {
console.error('provider is not set');
return null;
}
var result = this.provider.send(payload);
var setProvider = function (p) {
provider = p;
};
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return null;
}
var startPolling = function (data, pollId, callback, uninstall) {
polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
};
return result.result;
};
var stopPolling = function (pollId) {
for (var i = polls.length; i--;) {
var poll = polls[i];
if (poll.id === pollId) {
polls.splice(i, 1);
}
}
};
/// setups provider, which will be used for sending messages
ProviderManager.prototype.set = function(provider) {
this.provider = provider;
};
var reset = function () {
polls.forEach(function (poll) {
poll.uninstall(poll.id);
});
polls = [];
};
/// this method is only used, when we do not have native qt bindings and have to do polling on our own
/// should be callled, on start watching for eth/shh changes
ProviderManager.prototype.startPolling = function (data, pollId, callback) {
this.polls.push({data: data, id: pollId, callback: callback});
};
var poll = function () {
polls.forEach(function (data) {
var result = send(data.data);
if (!(result instanceof Array) || result.length === 0) {
return;
}
data.callback(result);
});
setTimeout(poll, c.ETH_POLLING_TIMEOUT);
};
poll();
/// should be called to stop polling for certain watch changes
ProviderManager.prototype.stopPolling = function (pollId) {
for (var i = this.polls.length; i--;) {
var poll = this.polls[i];
if (poll.id === pollId) {
this.polls.splice(i, 1);
}
}
return {
send: send,
setProvider: setProvider,
startPolling: startPolling,
stopPolling: stopPolling,
reset: reset
};
};
module.exports = ProviderManager;
module.exports = requestManager;
},{"./jsonrpc":8,"./web3":13}],10:[function(require,module,exports){
},{"./const":2,"./jsonrpc":10}],13:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -1119,25 +1295,29 @@ module.exports = ProviderManager;
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 qtsync.js
/** @file shh.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* @date 2014
* @date 2015
*/
var QtSyncProvider = function () {
/// @returns an array of objects describing web3.shh api methods
var methods = function () {
return [
{ name: 'post', call: 'shh_post' },
{ name: 'newIdentity', call: 'shh_newIdentity' },
{ name: 'haveIdentity', call: 'shh_haveIdentity' },
{ name: 'newGroup', call: 'shh_newGroup' },
{ name: 'addToGroup', call: 'shh_addToGroup' }
];
};
QtSyncProvider.prototype.send = function (payload) {
var result = navigator.qt.callMethod(JSON.stringify(payload));
return JSON.parse(result);
module.exports = {
methods: methods
};
module.exports = QtSyncProvider;
},{}],11:[function(require,module,exports){
},{}],14:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -1218,7 +1398,7 @@ module.exports = {
};
},{"./formatters":6}],12:[function(require,module,exports){
},{"./formatters":8}],15:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -1362,7 +1542,7 @@ module.exports = {
};
},{"./const":2}],13:[function(require,module,exports){
},{"./const":2}],16:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -1379,100 +1559,14 @@ module.exports = {
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 web3.js
/** @file watches.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* Gav Wood <g@ethdev.com>
* @date 2014
* @date 2015
*/
if ("build" !== 'build') {/*
var BigNumber = require('bignumber.js');
*/}
var utils = require('./utils');
/// @returns an array of objects describing web3 api methods
var web3Methods = function () {
return [
{ name: 'sha3', call: 'web3_sha3' }
];
};
/// @returns an array of objects describing web3.eth api methods
var ethMethods = function () {
var blockCall = function (args) {
return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
};
var transactionCall = function (args) {
return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
};
var uncleCall = function (args) {
return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
};
var methods = [
{ name: 'balanceAt', call: 'eth_balanceAt' },
{ name: 'stateAt', call: 'eth_stateAt' },
{ name: 'storageAt', call: 'eth_storageAt' },
{ name: 'countAt', call: 'eth_countAt'},
{ name: 'codeAt', call: 'eth_codeAt' },
{ name: 'transact', call: 'eth_transact' },
{ name: 'call', call: 'eth_call' },
{ name: 'block', call: blockCall },
{ name: 'transaction', call: transactionCall },
{ name: 'uncle', call: uncleCall },
{ name: 'compilers', call: 'eth_compilers' },
{ name: 'flush', call: 'eth_flush' },
{ name: 'lll', call: 'eth_lll' },
{ name: 'solidity', call: 'eth_solidity' },
{ name: 'serpent', call: 'eth_serpent' },
{ name: 'logs', call: 'eth_logs' }
];
return methods;
};
/// @returns an array of objects describing web3.eth api properties
var ethProperties = function () {
return [
{ name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
{ name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
{ name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
{ name: 'gasPrice', getter: 'eth_gasPrice' },
{ name: 'accounts', getter: 'eth_accounts' },
{ name: 'peerCount', getter: 'eth_peerCount' },
{ name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
{ name: 'number', getter: 'eth_number'}
];
};
/// @returns an array of objects describing web3.db api methods
var dbMethods = function () {
return [
{ name: 'put', call: 'db_put' },
{ name: 'get', call: 'db_get' },
{ name: 'putString', call: 'db_putString' },
{ name: 'getString', call: 'db_getString' }
];
};
/// @returns an array of objects describing web3.shh api methods
var shhMethods = function () {
return [
{ name: 'post', call: 'shh_post' },
{ name: 'newIdentity', call: 'shh_newIdentity' },
{ name: 'haveIdentity', call: 'shh_haveIdentity' },
{ name: 'newGroup', call: 'shh_newGroup' },
{ name: 'addToGroup', call: 'shh_addToGroup' }
];
};
/// @returns an array of objects describing web3.eth.watch api methods
var ethWatchMethods = function () {
var eth = function () {
var newFilter = function (args) {
return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';
};
@ -1485,7 +1579,7 @@ var ethWatchMethods = function () {
};
/// @returns an array of objects describing web3.shh.watch api methods
var shhWatchMethods = function () {
var shh = function () {
return [
{ name: 'newFilter', call: 'shh_newFilter' },
{ name: 'uninstallFilter', call: 'shh_uninstallFilter' },
@ -1493,6 +1587,57 @@ var shhWatchMethods = function () {
];
};
module.exports = {
eth: eth,
shh: shh
};
},{}],17:[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 web3.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* Gav Wood <g@ethdev.com>
* @date 2014
*/
if ("build" !== 'build') {/*
var BigNumber = require('bignumber.js');
*/}
var eth = require('./eth');
var db = require('./db');
var shh = require('./shh');
var watches = require('./watches');
var filter = require('./filter');
var utils = require('./utils');
var requestManager = require('./requestmanager');
/// @returns an array of objects describing web3 api methods
var web3Methods = function () {
return [
{ name: 'sha3', call: 'web3_sha3' }
];
};
/// creates methods in a given object based on method description on input
/// setups api calls for these methods
var setupMethods = function (obj, methods) {
@ -1500,7 +1645,7 @@ var setupMethods = function (obj, methods) {
obj[method.name] = function () {
var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call;
return web3.provider.send({
return web3.manager.send({
method: call,
params: args
});
@ -1514,14 +1659,14 @@ var setupProperties = function (obj, properties) {
properties.forEach(function (property) {
var proto = {};
proto.get = function () {
return web3.provider.send({
return web3.manager.send({
method: property.getter
});
};
if (property.setter) {
proto.set = function (val) {
return web3.provider.send({
return web3.manager.send({
method: property.setter,
params: [val]
});
@ -1531,10 +1676,30 @@ var setupProperties = function (obj, properties) {
});
};
var startPolling = function (method, id, callback, uninstall) {
web3.manager.startPolling({
method: method,
params: [id]
}, id, callback, uninstall);
};
var stopPolling = function (id) {
web3.manager.stopPolling(id);
};
var ethWatch = {
startPolling: startPolling.bind(null, 'eth_changed'),
stopPolling: stopPolling
};
var shhWatch = {
startPolling: startPolling.bind(null, 'shh_changed'),
stopPolling: stopPolling
};
/// setups web3 object, and it's in-browser executed methods
var web3 = {
_callbacks: {},
_events: {},
manager: requestManager(),
providers: {},
/// @returns ascii string representation of hex value prefixed with 0x
@ -1573,11 +1738,12 @@ var web3 = {
/// @param filter may be a string, object or event
/// @param indexed is optional, this is an object with optional event indexed params
/// @param options is optional, this is an object with optional event options ('max'...)
watch: function (filter, indexed, options) {
if (filter._isEvent) {
return filter(indexed, options);
/// TODO: fix it, 4 params? no way
watch: function (fil, indexed, options, formatter) {
if (fil._isEvent) {
return fil(indexed, options);
}
return new web3.filter(filter, ethWatch);
return filter(fil, ethWatch, formatter);
}
},
@ -1586,54 +1752,44 @@ var web3 = {
/// shh object prototype
shh: {
/// @param filter may be a string, object or event
watch: function (filter, indexed) {
return new web3.filter(filter, shhWatch);
watch: function (fil) {
return filter(fil, shhWatch);
}
},
setProvider: function (provider) {
web3.manager.setProvider(provider);
},
/// Should be called to reset state of web3 object
/// Resets everything except manager
reset: function () {
web3.manager.reset();
}
};
/// setups all api methods
setupMethods(web3, web3Methods());
setupMethods(web3.eth, ethMethods());
setupProperties(web3.eth, ethProperties());
setupMethods(web3.db, dbMethods());
setupMethods(web3.shh, shhMethods());
var ethWatch = {
changed: 'eth_changed'
};
setupMethods(ethWatch, ethWatchMethods());
var shhWatch = {
changed: 'shh_changed'
};
setupMethods(shhWatch, shhWatchMethods());
web3.setProvider = function(provider) {
web3.provider.set(provider);
};
setupMethods(web3.eth, eth.methods());
setupProperties(web3.eth, eth.properties());
setupMethods(web3.db, db.methods());
setupMethods(web3.shh, shh.methods());
setupMethods(ethWatch, watches.eth());
setupMethods(shhWatch, watches.shh());
module.exports = web3;
},{"./utils":12}],"web3":[function(require,module,exports){
},{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":15,"./watches":16}],"web3":[function(require,module,exports){
var web3 = require('./lib/web3');
var ProviderManager = require('./lib/providermanager');
web3.provider = new ProviderManager();
web3.filter = require('./lib/filter');
web3.providers.HttpSyncProvider = require('./lib/httpsync');
web3.providers.QtSyncProvider = require('./lib/qtsync');
web3.eth.contract = require('./lib/contract');
web3.abi = require('./lib/abi');
module.exports = web3;
},{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":9,"./lib/qtsync":10,"./lib/web3":13}]},{},["web3"])
},{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":17}]},{},["web3"])
//# sourceMappingURL=ethereum.js.map

26
dist/ethereum.js.map

File diff suppressed because one or more lines are too long

2
dist/ethereum.min.js

File diff suppressed because one or more lines are too long

97
gulpfile.js

@ -15,90 +15,55 @@ var unreach = require('unreachable-branch-transform');
var source = require('vinyl-source-stream');
var exorcist = require('exorcist');
var bower = require('bower');
var streamify = require('gulp-streamify');
var DEST = './dist/';
var build = function(src, dst, ugly) {
var result = browserify({
debug: true,
insert_global_vars: false,
detectGlobals: false,
bundleExternal: false
})
.require('./' + src + '.js', {expose: 'web3'})
.add('./' + src + '.js')
.transform('envify', {
NODE_ENV: 'build'
})
.transform('unreachable-branch-transform');
if (ugly) {
result = result.transform('uglifyify', {
mangle: false,
compress: {
dead_code: false,
conditionals: true,
unused: false,
hoist_funs: true,
hoist_vars: true,
negate_iife: false
},
beautify: true,
warnings: true
});
}
return result.bundle()
.pipe(exorcist(path.join( DEST, dst + '.js.map')))
.pipe(source(dst + '.js'))
.pipe(gulp.dest( DEST ));
};
var uglifyFile = function(file) {
return gulp.src( DEST + file + '.js')
.pipe(uglify())
.pipe(rename(file + '.min.js'))
.pipe(gulp.dest( DEST ));
var src = 'index';
var dst = 'ethereum';
var browserifyOptions = {
debug: true,
insert_global_vars: false,
detectGlobals: false,
bundleExternal: false
};
gulp.task('bower', function(cb){
bower.commands.install().on('end', function (installed){
console.log(installed);
cb();
});
bower.commands.install().on('end', function (installed){
console.log(installed);
cb();
});
});
gulp.task('clean', ['lint'], function(cb) {
del([ DEST ], cb);
del([ DEST ], cb);
});
gulp.task('lint', function(){
return gulp.src(['./*.js', './lib/*.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'));
return gulp.src(['./*.js', './lib/*.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
gulp.task('build', ['clean'], function () {
return build('index', 'ethereum', true);
});
gulp.task('buildDev', ['clean'], function () {
return build('index', 'ethereum', false);
});
gulp.task('uglify', ['build'], function(){
return uglifyFile('ethereum');
});
gulp.task('uglifyDev', ['buildDev'], function(){
return uglifyFile('ethereum');
return browserify(browserifyOptions)
.require('./' + src + '.js', {expose: 'web3'})
.add('./' + src + '.js')
.transform('envify', { NODE_ENV: 'build' })
.transform('unreachable-branch-transform')
.bundle()
.pipe(exorcist(path.join( DEST, dst + '.js.map')))
.pipe(source(dst + '.js'))
.pipe(gulp.dest( DEST ))
.pipe(streamify(uglify()))
.pipe(rename(dst + '.min.js'))
.pipe(gulp.dest( DEST ));
});
gulp.task('watch', function() {
gulp.watch(['./lib/*.js'], ['lint', 'prepare', 'build']);
gulp.watch(['./lib/*.js'], ['lint', 'build']);
});
gulp.task('release', ['bower', 'lint', 'build', 'uglify']);
gulp.task('dev', ['bower', 'lint', 'buildDev', 'uglifyDev']);
gulp.task('dev', ['bower', 'lint', 'build']);
gulp.task('default', ['dev']);

4
index.js

@ -1,11 +1,7 @@
var web3 = require('./lib/web3');
var ProviderManager = require('./lib/providermanager');
web3.provider = new ProviderManager();
web3.filter = require('./lib/filter');
web3.providers.HttpSyncProvider = require('./lib/httpsync');
web3.providers.QtSyncProvider = require('./lib/qtsync');
web3.eth.contract = require('./lib/contract');
web3.abi = require('./lib/abi');
module.exports = web3;

3
lib/const.js

@ -51,6 +51,7 @@ module.exports = {
ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
ETH_POLLING_TIMEOUT: 1000
};

5
lib/contract.js

@ -24,6 +24,7 @@ var web3 = require('./web3');
var abi = require('./abi');
var utils = require('./utils');
var eventImpl = require('./event');
var filter = require('./filter');
var exportNatspecGlobals = function (vars) {
// it's used byt natspec.js
@ -145,11 +146,11 @@ var addEventsToContract = function (contract, desc, address) {
var signature = abi.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, signature, e);
var o = event.apply(null, params);
o._onWatchEventResult = function (data) {
var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.watch(o);
return web3.eth.watch(o, undefined, undefined, outputFormatter);
};
// this property should be used by eth.filter to check if object is an event

35
lib/db.js

@ -0,0 +1,35 @@
/*
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 db.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/// @returns an array of objects describing web3.db api methods
var methods = function () {
return [
{ name: 'put', call: 'db_put' },
{ name: 'get', call: 'db_get' },
{ name: 'putString', call: 'db_putString' },
{ name: 'getString', call: 'db_getString' }
];
};
module.exports = {
methods: methods
};

85
lib/eth.js

@ -0,0 +1,85 @@
/*
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 eth.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/// @returns an array of objects describing web3.eth api methods
var methods = function () {
var blockCall = function (args) {
return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
};
var transactionCall = function (args) {
return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
};
var uncleCall = function (args) {
return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
};
var transactionCountCall = function (args) {
return typeof args[0] === "string" ? 'eth_transactionCountByHash' : 'eth_transactionCountByNumber';
};
var uncleCountCall = function (args) {
return typeof args[0] === "string" ? 'eth_uncleCountByHash' : 'eth_uncleCountByNumber';
};
return [
{ name: 'balanceAt', call: 'eth_balanceAt' },
{ name: 'stateAt', call: 'eth_stateAt' },
{ name: 'storageAt', call: 'eth_storageAt' },
{ name: 'countAt', call: 'eth_countAt'},
{ name: 'codeAt', call: 'eth_codeAt' },
{ name: 'transact', call: 'eth_transact' },
{ name: 'call', call: 'eth_call' },
{ name: 'block', call: blockCall },
{ name: 'transaction', call: transactionCall },
{ name: 'uncle', call: uncleCall },
{ name: 'compilers', call: 'eth_compilers' },
{ name: 'flush', call: 'eth_flush' },
{ name: 'lll', call: 'eth_lll' },
{ name: 'solidity', call: 'eth_solidity' },
{ name: 'serpent', call: 'eth_serpent' },
{ name: 'logs', call: 'eth_logs' },
{ name: 'transactionCount', call: transactionCountCall },
{ name: 'uncleCount', call: uncleCountCall }
];
};
/// @returns an array of objects describing web3.eth api properties
var properties = function () {
return [
{ name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
{ name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
{ name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
{ name: 'gasPrice', getter: 'eth_gasPrice' },
{ name: 'accounts', getter: 'eth_accounts' },
{ name: 'peerCount', getter: 'eth_peerCount' },
{ name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
{ name: 'number', getter: 'eth_number'}
];
};
module.exports = {
methods: methods,
properties: properties
};

142
lib/filter.js

@ -23,79 +23,91 @@
* @date 2014
*/
var web3 = require('./web3'); // jshint ignore:line
/// should be used when we want to watch something
/// it's using inner polling mechanism and is notified about changes
/// TODO: change 'options' name cause it may be not the best matching one, since we have events
var Filter = function(options, impl) {
if (typeof options !== "string") {
// topics property is deprecated, warn about it!
if (options.topics) {
console.warn('"topics" is deprecated, use "topic" instead');
}
this._onWatchResult = options._onWatchEventResult;
// evaluate lazy properties
options = {
to: options.to,
topic: options.topic,
earliest: options.earliest,
latest: options.latest,
max: options.max,
skip: options.skip,
address: options.address
};
}
this.impl = impl;
this.callbacks = [];
this.id = impl.newFilter(options);
web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this));
/// Should be called to check if filter implementation is valid
/// @returns true if it is, otherwise false
var implementationIsValid = function (i) {
return !!i &&
typeof i.newFilter === 'function' &&
typeof i.getMessages === 'function' &&
typeof i.uninstallFilter === 'function' &&
typeof i.startPolling === 'function' &&
typeof i.stopPolling === 'function';
};
/// alias for changed*
Filter.prototype.arrived = function(callback) {
this.changed(callback);
};
Filter.prototype.happened = function(callback) {
this.changed(callback);
};
/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones
/// @param should be string or object
/// @returns options string or object
var getOptions = function (options) {
if (typeof options === 'string') {
return options;
}
/// gets called when there is new eth/shh message
Filter.prototype.changed = function(callback) {
this.callbacks.push(callback);
};
options = options || {};
/// trigger calling new message from people
Filter.prototype.trigger = function(messages) {
for (var i = 0; i < this.callbacks.length; i++) {
for (var j = 0; j < messages.length; j++) {
var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j];
this.callbacks[i].call(this, message);
}
if (options.topics) {
console.warn('"topics" is deprecated, is "topic" instead');
}
};
/// should be called to uninstall current filter
Filter.prototype.uninstall = function() {
this.impl.uninstallFilter(this.id);
web3.provider.stopPolling(this.id);
// evaluate lazy properties
return {
to: options.to,
topic: options.topic,
earliest: options.earliest,
latest: options.latest,
max: options.max,
skip: options.skip,
address: options.address
};
};
/// should be called to manually trigger getting latest messages from the client
Filter.prototype.messages = function() {
return this.impl.getMessages(this.id);
};
/// Should be used when we want to watch something
/// it's using inner polling mechanism and is notified about changes
/// @param options are filter options
/// @param implementation, an abstract polling implementation
/// @param formatter (optional), callback function which formats output before 'real' callback
var filter = function(options, implementation, formatter) {
if (!implementationIsValid(implementation)) {
console.error('filter implemenation is invalid');
return;
}
/// alias for messages
Filter.prototype.logs = function () {
return this.messages();
options = getOptions(options);
var callbacks = [];
var filterId = implementation.newFilter(options);
var onMessages = function (messages) {
messages.forEach(function (message) {
messages = formatter ? formatter(message) : message;
callbacks.forEach(function (callback) {
callback(message);
});
});
};
implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);
var changed = function (callback) {
callbacks.push(callback);
};
var messages = function () {
return implementation.getMessages(filterId);
};
var uninstall = function (callback) {
implementation.stopPolling(filterId);
implementation.uninstallFilter(filterId);
callbacks = [];
};
return {
changed: changed,
arrived: changed,
happened: changed,
messages: messages,
logs: messages,
uninstall: uninstall
};
};
module.exports = Filter;
module.exports = filter;

8
lib/httpsync.js

@ -32,13 +32,15 @@ var HttpSyncProvider = function (host) {
HttpSyncProvider.prototype.send = function (payload) {
//var data = formatJsonRpcObject(payload);
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.send(JSON.stringify(payload));
// check request.status
var result = request.responseText;
// check request.status
if(request.status !== 200)
return;
return JSON.parse(result);
};

102
lib/providermanager.js

@ -1,102 +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 providermanager.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* Gav Wood <g@ethdev.com>
* @date 2014
*/
var web3 = require('./web3');
var jsonrpc = require('./jsonrpc');
/**
* Provider manager object prototype
* It's responsible for passing messages to providers
* If no provider is set it's responsible for queuing requests
* It's also responsible for polling the ethereum node for incoming messages
* Default poll timeout is 12 seconds
* If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling,
* and provider manager polling mechanism is not used
*/
var ProviderManager = function() {
this.polls = [];
this.provider = undefined;
var self = this;
var poll = function () {
self.polls.forEach(function (data) {
var result = self.send(data.data);
if (!(result instanceof Array) || result.length === 0) {
return;
}
data.callback(result);
});
setTimeout(poll, 1000);
};
poll();
};
/// sends outgoing requests
/// @params data - an object with at least 'method' property
ProviderManager.prototype.send = function(data) {
var payload = jsonrpc.toPayload(data.method, data.params);
if (this.provider === undefined) {
console.error('provider is not set');
return null;
}
var result = this.provider.send(payload);
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return null;
}
return result.result;
};
/// setups provider, which will be used for sending messages
ProviderManager.prototype.set = function(provider) {
this.provider = provider;
};
/// this method is only used, when we do not have native qt bindings and have to do polling on our own
/// should be callled, on start watching for eth/shh changes
ProviderManager.prototype.startPolling = function (data, pollId, callback) {
this.polls.push({data: data, id: pollId, callback: callback});
};
/// should be called to stop polling for certain watch changes
ProviderManager.prototype.stopPolling = function (pollId) {
for (var i = this.polls.length; i--;) {
var poll = this.polls[i];
if (poll.id === pollId) {
this.polls.splice(i, 1);
}
}
};
module.exports = ProviderManager;

103
lib/requestmanager.js

@ -0,0 +1,103 @@
/*
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 requestmanager.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* Gav Wood <g@ethdev.com>
* @date 2014
*/
var jsonrpc = require('./jsonrpc');
var c = require('./const');
/**
* It's responsible for passing messages to providers
* It's also responsible for polling the ethereum node for incoming messages
* Default poll timeout is 1 second
*/
var requestManager = function() {
var polls = [];
var provider;
var send = function (data) {
var payload = jsonrpc.toPayload(data.method, data.params);
if (!provider) {
console.error('provider is not set');
return null;
}
var result = provider.send(payload);
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return null;
}
return result.result;
};
var setProvider = function (p) {
provider = p;
};
var startPolling = function (data, pollId, callback, uninstall) {
polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
};
var stopPolling = function (pollId) {
for (var i = polls.length; i--;) {
var poll = polls[i];
if (poll.id === pollId) {
polls.splice(i, 1);
}
}
};
var reset = function () {
polls.forEach(function (poll) {
poll.uninstall(poll.id);
});
polls = [];
};
var poll = function () {
polls.forEach(function (data) {
var result = send(data.data);
if (!(result instanceof Array) || result.length === 0) {
return;
}
data.callback(result);
});
setTimeout(poll, c.ETH_POLLING_TIMEOUT);
};
poll();
return {
send: send,
setProvider: setProvider,
startPolling: startPolling,
stopPolling: stopPolling,
reset: reset
};
};
module.exports = requestManager;

37
lib/shh.js

@ -0,0 +1,37 @@
/*
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 shh.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/// @returns an array of objects describing web3.shh api methods
var methods = function () {
return [
{ name: 'post', call: 'shh_post' },
{ name: 'newIdentity', call: 'shh_newIdentity' },
{ name: 'haveIdentity', call: 'shh_haveIdentity' },
{ name: 'newGroup', call: 'shh_newGroup' },
{ name: 'addToGroup', call: 'shh_addToGroup' }
];
};
module.exports = {
methods: methods
};

49
lib/watches.js

@ -0,0 +1,49 @@
/*
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 watches.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/// @returns an array of objects describing web3.eth.watch api methods
var eth = function () {
var newFilter = function (args) {
return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';
};
return [
{ name: 'newFilter', call: newFilter },
{ name: 'uninstallFilter', call: 'eth_uninstallFilter' },
{ name: 'getMessages', call: 'eth_filterLogs' }
];
};
/// @returns an array of objects describing web3.shh.watch api methods
var shh = function () {
return [
{ name: 'newFilter', call: 'shh_newFilter' },
{ name: 'uninstallFilter', call: 'shh_uninstallFilter' },
{ name: 'getMessages', call: 'shh_getMessages' }
];
};
module.exports = {
eth: eth,
shh: shh
};

177
lib/web3.js

@ -27,7 +27,13 @@ if (process.env.NODE_ENV !== 'build') {
var BigNumber = require('bignumber.js');
}
var eth = require('./eth');
var db = require('./db');
var shh = require('./shh');
var watches = require('./watches');
var filter = require('./filter');
var utils = require('./utils');
var requestManager = require('./requestmanager');
/// @returns an array of objects describing web3 api methods
var web3Methods = function () {
@ -36,98 +42,6 @@ var web3Methods = function () {
];
};
/// @returns an array of objects describing web3.eth api methods
var ethMethods = function () {
var blockCall = function (args) {
return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
};
var transactionCall = function (args) {
return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
};
var uncleCall = function (args) {
return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
};
var methods = [
{ name: 'balanceAt', call: 'eth_balanceAt' },
{ name: 'stateAt', call: 'eth_stateAt' },
{ name: 'storageAt', call: 'eth_storageAt' },
{ name: 'countAt', call: 'eth_countAt'},
{ name: 'codeAt', call: 'eth_codeAt' },
{ name: 'transact', call: 'eth_transact' },
{ name: 'call', call: 'eth_call' },
{ name: 'block', call: blockCall },
{ name: 'transaction', call: transactionCall },
{ name: 'uncle', call: uncleCall },
{ name: 'compilers', call: 'eth_compilers' },
{ name: 'flush', call: 'eth_flush' },
{ name: 'lll', call: 'eth_lll' },
{ name: 'solidity', call: 'eth_solidity' },
{ name: 'serpent', call: 'eth_serpent' },
{ name: 'logs', call: 'eth_logs' }
];
return methods;
};
/// @returns an array of objects describing web3.eth api properties
var ethProperties = function () {
return [
{ name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
{ name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
{ name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
{ name: 'gasPrice', getter: 'eth_gasPrice' },
{ name: 'accounts', getter: 'eth_accounts' },
{ name: 'peerCount', getter: 'eth_peerCount' },
{ name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
{ name: 'number', getter: 'eth_number'}
];
};
/// @returns an array of objects describing web3.db api methods
var dbMethods = function () {
return [
{ name: 'put', call: 'db_put' },
{ name: 'get', call: 'db_get' },
{ name: 'putString', call: 'db_putString' },
{ name: 'getString', call: 'db_getString' }
];
};
/// @returns an array of objects describing web3.shh api methods
var shhMethods = function () {
return [
{ name: 'post', call: 'shh_post' },
{ name: 'newIdentity', call: 'shh_newIdentity' },
{ name: 'haveIdentity', call: 'shh_haveIdentity' },
{ name: 'newGroup', call: 'shh_newGroup' },
{ name: 'addToGroup', call: 'shh_addToGroup' }
];
};
/// @returns an array of objects describing web3.eth.watch api methods
var ethWatchMethods = function () {
var newFilter = function (args) {
return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';
};
return [
{ name: 'newFilter', call: newFilter },
{ name: 'uninstallFilter', call: 'eth_uninstallFilter' },
{ name: 'getMessages', call: 'eth_filterLogs' }
];
};
/// @returns an array of objects describing web3.shh.watch api methods
var shhWatchMethods = function () {
return [
{ name: 'newFilter', call: 'shh_newFilter' },
{ name: 'uninstallFilter', call: 'shh_uninstallFilter' },
{ name: 'getMessages', call: 'shh_getMessages' }
];
};
/// creates methods in a given object based on method description on input
/// setups api calls for these methods
var setupMethods = function (obj, methods) {
@ -135,7 +49,7 @@ var setupMethods = function (obj, methods) {
obj[method.name] = function () {
var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call;
return web3.provider.send({
return web3.manager.send({
method: call,
params: args
});
@ -149,14 +63,14 @@ var setupProperties = function (obj, properties) {
properties.forEach(function (property) {
var proto = {};
proto.get = function () {
return web3.provider.send({
return web3.manager.send({
method: property.getter
});
};
if (property.setter) {
proto.set = function (val) {
return web3.provider.send({
return web3.manager.send({
method: property.setter,
params: [val]
});
@ -166,10 +80,30 @@ var setupProperties = function (obj, properties) {
});
};
var startPolling = function (method, id, callback, uninstall) {
web3.manager.startPolling({
method: method,
params: [id]
}, id, callback, uninstall);
};
var stopPolling = function (id) {
web3.manager.stopPolling(id);
};
var ethWatch = {
startPolling: startPolling.bind(null, 'eth_changed'),
stopPolling: stopPolling
};
var shhWatch = {
startPolling: startPolling.bind(null, 'shh_changed'),
stopPolling: stopPolling
};
/// setups web3 object, and it's in-browser executed methods
var web3 = {
_callbacks: {},
_events: {},
manager: requestManager(),
providers: {},
/// @returns ascii string representation of hex value prefixed with 0x
@ -208,11 +142,12 @@ var web3 = {
/// @param filter may be a string, object or event
/// @param indexed is optional, this is an object with optional event indexed params
/// @param options is optional, this is an object with optional event options ('max'...)
watch: function (filter, indexed, options) {
if (filter._isEvent) {
return filter(indexed, options);
/// TODO: fix it, 4 params? no way
watch: function (fil, indexed, options, formatter) {
if (fil._isEvent) {
return fil(indexed, options);
}
return new web3.filter(filter, ethWatch);
return filter(fil, ethWatch, formatter);
}
},
@ -221,36 +156,30 @@ var web3 = {
/// shh object prototype
shh: {
/// @param filter may be a string, object or event
watch: function (filter, indexed) {
return new web3.filter(filter, shhWatch);
watch: function (fil) {
return filter(fil, shhWatch);
}
},
setProvider: function (provider) {
web3.manager.setProvider(provider);
},
/// Should be called to reset state of web3 object
/// Resets everything except manager
reset: function () {
web3.manager.reset();
}
};
/// setups all api methods
setupMethods(web3, web3Methods());
setupMethods(web3.eth, ethMethods());
setupProperties(web3.eth, ethProperties());
setupMethods(web3.db, dbMethods());
setupMethods(web3.shh, shhMethods());
var ethWatch = {
changed: 'eth_changed'
};
setupMethods(ethWatch, ethWatchMethods());
var shhWatch = {
changed: 'shh_changed'
};
setupMethods(shhWatch, shhWatchMethods());
web3.setProvider = function(provider) {
web3.provider.set(provider);
};
setupMethods(web3.eth, eth.methods());
setupProperties(web3.eth, eth.properties());
setupMethods(web3.db, db.methods());
setupMethods(web3.shh, shh.methods());
setupMethods(ethWatch, watches.eth());
setupMethods(shhWatch, watches.shh());
module.exports = web3;

18
package.json

@ -1,38 +1,42 @@
{
"name": "ethereum.js",
"namespace": "ethereum",
"version": "0.0.13",
"version": "0.0.15",
"description": "Ethereum Compatible JavaScript API",
"main": "./index.js",
"directories": {
"lib": "./lib"
},
"dependencies": {
"bignumber.js": ">=2.0.0",
"ws": "*",
"xmlhttprequest": "*",
"bignumber.js": ">=2.0.0"
"xmlhttprequest": "*"
},
"devDependencies": {
"bower": ">=1.3.0",
"browserify": ">=6.0",
"coveralls": "^2.11.2",
"del": ">=0.1.1",
"envify": "^3.0.0",
"exorcist": "^0.1.6",
"gulp": ">=3.4.0",
"gulp-jshint": ">=1.5.0",
"gulp-rename": ">=1.2.0",
"gulp-streamify": "0.0.5",
"gulp-uglify": ">=1.0.0",
"istanbul": "^0.3.5",
"jshint": ">=2.5.0",
"uglifyify": "^2.6.0",
"mocha": ">=2.1.0",
"mocha-lcov-reporter": "0.0.1",
"unreachable-branch-transform": "^0.1.0",
"vinyl-source-stream": "^1.0.0",
"mocha": ">=2.1.0"
"vinyl-source-stream": "^1.0.0"
},
"scripts": {
"build": "gulp",
"watch": "gulp watch",
"lint": "gulp lint",
"test": "mocha"
"test": "mocha",
"test-coveralls": "istanbul cover _mocha -- -R spec && cat coverage/lcov.info | coveralls --verbose"
},
"repository": {
"type": "git",

2
test/eth.methods.js

@ -19,6 +19,8 @@ describe('web3', function() {
u.methodExists(web3.eth, 'solidity');
u.methodExists(web3.eth, 'serpent');
u.methodExists(web3.eth, 'logs');
u.methodExists(web3.eth, 'transactionCount');
u.methodExists(web3.eth, 'uncleCount');
u.propertyExists(web3.eth, 'coinbase');
u.propertyExists(web3.eth, 'listening');

27
test/filter.methods.js

@ -0,0 +1,27 @@
var assert = require('assert');
var filter = require('../lib/filter');
var u = require('./test.utils.js');
var empty = function () {};
var implementation = {
newFilter: empty,
getMessages: empty,
uninstallFilter: empty,
startPolling: empty,
stopPolling: empty,
};
describe('web3', function () {
describe('eth', function () {
describe('filter', function () {
var f = filter({}, implementation);
u.methodExists(f, 'arrived');
u.methodExists(f, 'happened');
u.methodExists(f, 'changed');
u.methodExists(f, 'messages');
u.methodExists(f, 'logs');
u.methodExists(f, 'uninstall');
});
});
});

11
test/web3.methods.js

@ -6,5 +6,16 @@ describe('web3', function() {
u.methodExists(web3, 'sha3');
u.methodExists(web3, 'toAscii');
u.methodExists(web3, 'fromAscii');
u.methodExists(web3, 'toDecimal');
u.methodExists(web3, 'fromDecimal');
u.methodExists(web3, 'toEth');
u.methodExists(web3, 'setProvider');
u.methodExists(web3, 'reset');
u.propertyExists(web3, 'manager');
u.propertyExists(web3, 'providers');
u.propertyExists(web3, 'eth');
u.propertyExists(web3, 'db');
u.propertyExists(web3, 'shh');
});

Loading…
Cancel
Save