/* 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 . */ /** @file filter.js * @authors: * Jeffrey Wilcke * Marek Kotewicz * Marian Oancea * Gav Wood * @date 2014 */ var utils = require('../utils/utils'); /// 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' && 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) { /*jshint maxcomplexity:5 */ if (typeof options === 'string') { return options; } options = options || {}; if (options.topics) console.warn('"topics" is deprecated, is "topic" instead'); // make sure topics, get converted to hex if(options.topic instanceof Array) { options.topic = options.topic.map(function(topic){ return utils.toHex(topic); }); } // 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 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; } options = getOptions(options); var callbacks = []; var filterId = implementation.newFilter(options); // call the callbacks var onMessages = function (messages) { messages.forEach(function (message) { message = formatter ? formatter(message) : message; callbacks.forEach(function (callback) { callback(message); }); }); }; implementation.startPolling(filterId, onMessages, implementation.uninstallFilter); var watch = function(callback) { callbacks.push(callback); }; var stopWatching = function() { implementation.stopPolling(filterId); implementation.uninstallFilter(filterId); callbacks = []; }; var get = function () { return implementation.getLogs(filterId); }; return { watch: watch, stopWatching: stopWatching, get: get, // DEPRECATED methods changed: function(){ console.warn('watch().changed() is deprecated please use filter().watch() instead.'); return watch.apply(this, arguments); }, arrived: function(){ console.warn('watch().arrived() is deprecated please use filter().watch() instead.'); return watch.apply(this, arguments); }, happened: function(){ console.warn('watch().happened() is deprecated please use filter().watch() instead.'); return watch.apply(this, arguments); }, uninstall: function(){ console.warn('watch().uninstall() is deprecated please use filter().stopWatching() instead.'); return stopWatching.apply(this, arguments); }, messages: function(){ console.warn('watch().messages() is deprecated please use filter().get() instead.'); return get.apply(this, arguments); }, logs: function(){ console.warn('watch().logs() is deprecated please use filter().get() instead.'); return get.apply(this, arguments); } }; }; module.exports = filter;