web3.js/lib/web3/filter.js

178 lines
5.7 KiB
JavaScript
Raw Normal View History

2015-01-13 18:28:49 +01:00
/*
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 filter.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* Gav Wood <g@ethdev.com>
* @date 2014
*/
2015-03-08 18:18:52 +01:00
var utils = require('../utils/utils');
2015-02-05 23:11:16 +01:00
/// 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.getLogs === 'function' &&
2015-02-05 23:11:16 +01:00
typeof i.uninstallFilter === 'function' &&
typeof i.startPolling === 'function' &&
typeof i.stopPolling === 'function';
2015-01-13 18:28:49 +01:00
};
2015-02-05 23:11:16 +01:00
/// 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) {
/*jshint maxcomplexity:5 */
2015-02-05 23:11:16 +01:00
if (typeof options === 'string') {
return options;
}
2015-01-13 18:28:49 +01:00
2015-02-05 23:11:16 +01:00
options = options || {};
2015-01-13 18:28:49 +01:00
2015-03-10 14:49:23 +01:00
if (options.topic) {
console.warn('"topic" is deprecated, is "topics" instead');
options.topics = options.topic;
}
if (options.earliest) {
console.warn('"earliest" is deprecated, is "fromBlock" instead');
options.fromBlock = options.earliest;
}
if (options.latest) {
console.warn('"latest" is deprecated, is "toBlock" instead');
options.toBlock = options.latest;
}
if (options.skip) {
console.warn('"skip" is deprecated, is "offset" instead');
options.offset = options.skip;
}
if (options.max) {
console.warn('"max" is deprecated, is "limit" instead');
options.limit = options.max;
}
// make sure topics, get converted to hex
2015-03-10 14:49:23 +01:00
if(options.topics instanceof Array) {
options.topics = options.topics.map(function(topic){
return utils.toHex(topic);
});
2015-01-13 18:28:49 +01:00
}
2015-02-05 23:11:16 +01:00
// evaluate lazy properties
return {
2015-03-10 14:49:23 +01:00
fromBlock: utils.toHex(options.fromBlock),
toBlock: utils.toHex(options.toBlock),
limit: utils.toHex(options.limit),
offset: utils.toHex(options.offset),
2015-02-05 23:11:16 +01:00
to: options.to,
2015-03-10 14:49:23 +01:00
address: options.address,
topics: options.topics
2015-02-05 23:11:16 +01:00
};
2015-01-13 18:28:49 +01:00
};
2015-02-05 23:11:16 +01:00
/// 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;
}
2015-01-13 18:28:49 +01:00
2015-02-05 23:11:16 +01:00
options = getOptions(options);
var callbacks = [];
var filterId = implementation.newFilter(options);
2015-02-27 12:41:07 +01:00
// call the callbacks
2015-02-05 23:11:16 +01:00
var onMessages = function (messages) {
messages.forEach(function (message) {
message = formatter ? formatter(message) : message;
2015-02-05 23:11:16 +01:00
callbacks.forEach(function (callback) {
callback(message);
});
});
};
2015-02-06 11:36:27 +01:00
implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);
2015-02-05 23:11:16 +01:00
var watch = function(callback) {
2015-02-05 23:11:16 +01:00
callbacks.push(callback);
};
var stopWatching = function() {
2015-02-05 23:11:16 +01:00
implementation.stopPolling(filterId);
implementation.uninstallFilter(filterId);
callbacks = [];
};
var get = function () {
2015-03-10 17:07:16 +01:00
var results = implementation.getLogs(filterId);
return (results instanceof Array)
? results.map(function(message){
return formatter ? formatter(message) : message;
})
: results;
};
2015-02-05 23:11:16 +01:00
return {
watch: watch,
stopWatching: stopWatching,
get: get,
// DEPRECATED methods
changed: function(){
2015-02-25 17:01:23 +01:00
console.warn('watch().changed() is deprecated please use filter().watch() instead.');
return watch.apply(this, arguments);
},
arrived: function(){
2015-02-25 17:01:23 +01:00
console.warn('watch().arrived() is deprecated please use filter().watch() instead.');
return watch.apply(this, arguments);
},
happened: function(){
2015-02-25 17:01:23 +01:00
console.warn('watch().happened() is deprecated please use filter().watch() instead.');
return watch.apply(this, arguments);
},
uninstall: function(){
2015-02-25 17:01:23 +01:00
console.warn('watch().uninstall() is deprecated please use filter().stopWatching() instead.');
return stopWatching.apply(this, arguments);
},
messages: function(){
2015-02-25 17:01:23 +01:00
console.warn('watch().messages() is deprecated please use filter().get() instead.');
return get.apply(this, arguments);
},
logs: function(){
2015-02-25 17:01:23 +01:00
console.warn('watch().logs() is deprecated please use filter().get() instead.');
return get.apply(this, arguments);
}
2015-02-05 23:11:16 +01:00
};
2015-01-13 18:28:49 +01:00
};
2015-02-05 23:11:16 +01:00
module.exports = filter;