Beta 7 with some repo names changed.
This commit is contained in:
1 parent
0f7b40cca7
commit
963c19493a
3408 files changed
+462217
-15516
No files matched your search
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file index.js
|
||||
* @author Fabian Vogelsteller <fabian@ethereum.org>
|
||||
* @date 2017
|
||||
*/
|
||||
"use strict";
|
||||
var Subscription = require('./subscription.js');
|
||||
var Subscriptions = function Subscriptions(options) {
|
||||
this.name = options.name;
|
||||
this.type = options.type;
|
||||
this.subscriptions = options.subscriptions || {};
|
||||
this.requestManager = null;
|
||||
};
|
||||
Subscriptions.prototype.setRequestManager = function (rm) {
|
||||
this.requestManager = rm;
|
||||
};
|
||||
Subscriptions.prototype.attachToObject = function (obj) {
|
||||
var func = this.buildCall();
|
||||
var name = this.name.split('.');
|
||||
if (name.length > 1) {
|
||||
obj[name[0]] = obj[name[0]] || {};
|
||||
obj[name[0]][name[1]] = func;
|
||||
}
|
||||
else {
|
||||
obj[name[0]] = func;
|
||||
}
|
||||
};
|
||||
Subscriptions.prototype.buildCall = function () {
|
||||
var _this = this;
|
||||
return function () {
|
||||
if (!_this.subscriptions[arguments[0]]) {
|
||||
console.warn('Subscription ' + JSON.stringify(arguments[0]) + ' doesn\'t exist. Subscribing anyway.');
|
||||
}
|
||||
var subscription = new Subscription({
|
||||
subscription: _this.subscriptions[arguments[0]] || {},
|
||||
requestManager: _this.requestManager,
|
||||
type: _this.type
|
||||
});
|
||||
return subscription.subscribe.apply(subscription, arguments);
|
||||
};
|
||||
};
|
||||
module.exports = {
|
||||
subscriptions: Subscriptions,
|
||||
subscription: Subscription
|
||||
};
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file subscription.js
|
||||
* @author Fabian Vogelsteller <fabian@ethereum.org>
|
||||
* @date 2017
|
||||
*/
|
||||
"use strict";
|
||||
var _ = require('underscore');
|
||||
var errors = require('web3-core-helpers').errors;
|
||||
var EventEmitter = require('eventemitter3');
|
||||
var formatters = require('web3-core-helpers').formatters;
|
||||
function Subscription(options) {
|
||||
EventEmitter.call(this);
|
||||
this.id = null;
|
||||
this.callback = _.identity;
|
||||
this.arguments = null;
|
||||
this.lastBlock = null; // "from" block tracker for backfilling events on reconnection
|
||||
this.options = {
|
||||
subscription: options.subscription,
|
||||
type: options.type,
|
||||
requestManager: options.requestManager
|
||||
};
|
||||
}
|
||||
// INHERIT
|
||||
Subscription.prototype = Object.create(EventEmitter.prototype);
|
||||
Subscription.prototype.constructor = Subscription;
|
||||
/**
|
||||
* Should be used to extract callback from array of arguments. Modifies input param
|
||||
*
|
||||
* @method extractCallback
|
||||
* @param {Array} arguments
|
||||
* @return {Function|Null} callback, if exists
|
||||
*/
|
||||
Subscription.prototype._extractCallback = function (args) {
|
||||
if (_.isFunction(args[args.length - 1])) {
|
||||
return args.pop(); // modify the args array!
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Should be called to check if the number of arguments is correct
|
||||
*
|
||||
* @method validateArgs
|
||||
* @param {Array} arguments
|
||||
* @throws {Error} if it is not
|
||||
*/
|
||||
Subscription.prototype._validateArgs = function (args) {
|
||||
var subscription = this.options.subscription;
|
||||
if (!subscription)
|
||||
subscription = {};
|
||||
if (!subscription.params)
|
||||
subscription.params = 0;
|
||||
if (args.length !== subscription.params) {
|
||||
throw errors.InvalidNumberOfParams(args.length, subscription.params, subscription.subscriptionName);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Should be called to format input args of method
|
||||
*
|
||||
* @method formatInput
|
||||
* @param {Array}
|
||||
* @return {Array}
|
||||
*/
|
||||
Subscription.prototype._formatInput = function (args) {
|
||||
var subscription = this.options.subscription;
|
||||
if (!subscription) {
|
||||
return args;
|
||||
}
|
||||
if (!subscription.inputFormatter) {
|
||||
return args;
|
||||
}
|
||||
var formattedArgs = subscription.inputFormatter.map(function (formatter, index) {
|
||||
return formatter ? formatter(args[index]) : args[index];
|
||||
});
|
||||
return formattedArgs;
|
||||
};
|
||||
/**
|
||||
* Should be called to format output(result) of method
|
||||
*
|
||||
* @method formatOutput
|
||||
* @param result {Object}
|
||||
* @return {Object}
|
||||
*/
|
||||
Subscription.prototype._formatOutput = function (result) {
|
||||
var subscription = this.options.subscription;
|
||||
return (subscription && subscription.outputFormatter && result) ? subscription.outputFormatter(result) : result;
|
||||
};
|
||||
/**
|
||||
* Should create payload from given input args
|
||||
*
|
||||
* @method toPayload
|
||||
* @param {Array} args
|
||||
* @return {Object}
|
||||
*/
|
||||
Subscription.prototype._toPayload = function (args) {
|
||||
var params = [];
|
||||
this.callback = this._extractCallback(args) || _.identity;
|
||||
if (!this.subscriptionMethod) {
|
||||
this.subscriptionMethod = args.shift();
|
||||
// replace subscription with given name
|
||||
if (this.options.subscription.subscriptionName) {
|
||||
this.subscriptionMethod = this.options.subscription.subscriptionName;
|
||||
}
|
||||
}
|
||||
if (!this.arguments) {
|
||||
this.arguments = this._formatInput(args);
|
||||
this._validateArgs(this.arguments);
|
||||
args = []; // make empty after validation
|
||||
}
|
||||
// re-add subscriptionName
|
||||
params.push(this.subscriptionMethod);
|
||||
params = params.concat(this.arguments);
|
||||
if (args.length) {
|
||||
throw new Error('Only a callback is allowed as parameter on an already instantiated subscription.');
|
||||
}
|
||||
return {
|
||||
method: this.options.type + '_subscribe',
|
||||
params: params
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Unsubscribes and clears callbacks
|
||||
*
|
||||
* @method unsubscribe
|
||||
* @return {Object}
|
||||
*/
|
||||
Subscription.prototype.unsubscribe = function (callback) {
|
||||
this.options.requestManager.removeSubscription(this.id, callback);
|
||||
this.id = null;
|
||||
this.lastBlock = null;
|
||||
this.removeAllListeners();
|
||||
};
|
||||
/**
|
||||
* Subscribes and watches for changes
|
||||
*
|
||||
* @method subscribe
|
||||
* @param {String} subscription the subscription
|
||||
* @param {Object} options the options object with address topics and fromBlock
|
||||
* @return {Object}
|
||||
*/
|
||||
Subscription.prototype.subscribe = function () {
|
||||
var _this = this;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var payload = this._toPayload(args);
|
||||
if (!payload) {
|
||||
return this;
|
||||
}
|
||||
// throw error, if provider is not set
|
||||
if (!this.options.requestManager.provider) {
|
||||
setTimeout(function () {
|
||||
var err1 = new Error('No provider set.');
|
||||
_this.callback(err1, null, _this);
|
||||
_this.emit('error', err1);
|
||||
}, 0);
|
||||
return this;
|
||||
}
|
||||
// throw error, if provider doesnt support subscriptions
|
||||
if (!this.options.requestManager.provider.on) {
|
||||
setTimeout(function () {
|
||||
var err2 = new Error('The current provider doesn\'t support subscriptions: ' +
|
||||
_this.options.requestManager.provider.constructor.name);
|
||||
_this.callback(err2, null, _this);
|
||||
_this.emit('error', err2);
|
||||
}, 0);
|
||||
return this;
|
||||
}
|
||||
// Re-subscription only: continue fetching from the last block we received.
|
||||
// a dropped connection may have resulted in gaps in the logs...
|
||||
if (this.lastBlock && _.isObject(this.options.params)) {
|
||||
payload.params[1] = this.options.params;
|
||||
payload.params[1].fromBlock = formatters.inputBlockNumberFormatter(this.lastBlock + 1);
|
||||
}
|
||||
// if id is there unsubscribe first
|
||||
if (this.id) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
// store the params in the options object
|
||||
this.options.params = payload.params[1];
|
||||
// get past logs, if fromBlock is available
|
||||
if (payload.params[0] === 'logs' && _.isObject(payload.params[1]) && payload.params[1].hasOwnProperty('fromBlock') && isFinite(payload.params[1].fromBlock)) {
|
||||
// send the subscription request
|
||||
// copy the params to avoid race-condition with deletion below this block
|
||||
var blockParams = Object.assign({}, payload.params[1]);
|
||||
this.options.requestManager.send({
|
||||
method: 'eth_getLogs',
|
||||
params: [blockParams]
|
||||
}, function (err, logs) {
|
||||
if (!err) {
|
||||
logs.forEach(function (log) {
|
||||
var output = _this._formatOutput(log);
|
||||
_this.callback(null, output, _this);
|
||||
_this.emit('data', output);
|
||||
});
|
||||
// TODO subscribe here? after the past logs?
|
||||
}
|
||||
else {
|
||||
setTimeout(function () {
|
||||
_this.callback(err, null, _this);
|
||||
_this.emit('error', err);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
// create subscription
|
||||
// TODO move to separate function? so that past logs can go first?
|
||||
if (typeof payload.params[1] === 'object')
|
||||
delete payload.params[1].fromBlock;
|
||||
this.options.requestManager.send(payload, function (err, result) {
|
||||
if (!err && result) {
|
||||
_this.id = result;
|
||||
_this.method = payload.params[0];
|
||||
_this.emit('connected', result);
|
||||
// call callback on notifications
|
||||
_this.options.requestManager.addSubscription(_this, function (error, result) {
|
||||
if (!error) {
|
||||
if (!_.isArray(result)) {
|
||||
result = [result];
|
||||
}
|
||||
result.forEach(function (resultItem) {
|
||||
var output = _this._formatOutput(resultItem);
|
||||
// Track current block (for gaps introduced by dropped connections)
|
||||
_this.lastBlock = _.isObject(output) ? output.blockNumber : null;
|
||||
if (_.isFunction(_this.options.subscription.subscriptionHandler)) {
|
||||
return _this.options.subscription.subscriptionHandler.call(_this, output);
|
||||
}
|
||||
else {
|
||||
_this.emit('data', output);
|
||||
}
|
||||
// call the callback, last so that unsubscribe there won't affect the emit above
|
||||
_this.callback(null, output, _this);
|
||||
});
|
||||
}
|
||||
else {
|
||||
_this.callback(error, false, _this);
|
||||
_this.emit('error', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
setTimeout(function () {
|
||||
_this.callback(err, false, _this);
|
||||
_this.emit('error', err);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
// return an object to cancel the subscription
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Resubscribe
|
||||
*
|
||||
* @method resubscribe
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
Subscription.prototype.resubscribe = function () {
|
||||
this.options.requestManager.removeSubscription(this.id); // unsubscribe
|
||||
this.id = null;
|
||||
this.subscribe(this.callback);
|
||||
};
|
||||
module.exports = Subscription;
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"_from": "web3-core-subscriptions@1.3.0",
|
||||
"_id": "web3-core-subscriptions@1.3.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-MUUQUAhJDb+Nz3S97ExVWveH4utoUnsbPWP+q1HJH437hEGb4vunIb9KvN3hFHLB+aHJfPeStM/4yYTz5PeuyQ==",
|
||||
"_location": "/web3-core-subscriptions",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "web3-core-subscriptions@1.3.0",
|
||||
"name": "web3-core-subscriptions",
|
||||
"escapedName": "web3-core-subscriptions",
|
||||
"rawSpec": "1.3.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "1.3.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/web3-core-method",
|
||||
"/web3-eth",
|
||||
"/web3-eth-contract",
|
||||
"/web3-shh"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.3.0.tgz",
|
||||
"_shasum": "c2622ccd2b84f4687475398ff966b579dba0847e",
|
||||
"_spec": "web3-core-subscriptions@1.3.0",
|
||||
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\BackendServers\\node_modules\\web3-core-method",
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"eventemitter3": "4.0.4",
|
||||
"underscore": "1.9.1",
|
||||
"web3-core-helpers": "1.3.0"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Manages web3 subscriptions. This is an internal package.",
|
||||
"devDependencies": {
|
||||
"dtslint": "^3.4.1",
|
||||
"typescript": "^3.9.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"gitHead": "a88944fff1f62b2b6f00e3de52446d24d9e92cc6",
|
||||
"license": "LGPL-3.0",
|
||||
"main": "lib/index.js",
|
||||
"name": "web3-core-subscriptions",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ethereum/web3.js/tree/1.x/packages/web3-core-subscriptions"
|
||||
},
|
||||
"scripts": {
|
||||
"dtslint": "dtslint --localTs ../../node_modules/typescript/lib types",
|
||||
"tsc": "tsc -b tsconfig.json"
|
||||
},
|
||||
"types": "types/index.d.ts",
|
||||
"version": "1.3.0"
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file index.js
|
||||
* @author Fabian Vogelsteller <fabian@ethereum.org>
|
||||
* @date 2017
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var Subscription = require('./subscription.js');
|
||||
|
||||
|
||||
var Subscriptions = function Subscriptions(options) {
|
||||
this.name = options.name;
|
||||
this.type = options.type;
|
||||
this.subscriptions = options.subscriptions || {};
|
||||
this.requestManager = null;
|
||||
};
|
||||
|
||||
|
||||
Subscriptions.prototype.setRequestManager = function (rm) {
|
||||
this.requestManager = rm;
|
||||
};
|
||||
|
||||
|
||||
Subscriptions.prototype.attachToObject = function (obj) {
|
||||
var func = this.buildCall();
|
||||
var name = this.name.split('.');
|
||||
if (name.length > 1) {
|
||||
obj[name[0]] = obj[name[0]] || {};
|
||||
obj[name[0]][name[1]] = func;
|
||||
} else {
|
||||
obj[name[0]] = func;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Subscriptions.prototype.buildCall = function() {
|
||||
var _this = this;
|
||||
|
||||
return function(){
|
||||
if(!_this.subscriptions[arguments[0]]) {
|
||||
console.warn('Subscription '+ JSON.stringify(arguments[0]) +' doesn\'t exist. Subscribing anyway.');
|
||||
}
|
||||
|
||||
var subscription = new Subscription({
|
||||
subscription: _this.subscriptions[arguments[0]] || {}, // Subscript might not exist
|
||||
requestManager: _this.requestManager,
|
||||
type: _this.type
|
||||
});
|
||||
|
||||
return subscription.subscribe.apply(subscription, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
subscriptions: Subscriptions,
|
||||
subscription: Subscription
|
||||
};
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
web3.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
web3.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @file subscription.js
|
||||
* @author Fabian Vogelsteller <fabian@ethereum.org>
|
||||
* @date 2017
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var _ = require('underscore');
|
||||
var errors = require('web3-core-helpers').errors;
|
||||
var EventEmitter = require('eventemitter3');
|
||||
var formatters = require('web3-core-helpers').formatters;
|
||||
|
||||
function Subscription(options) {
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.id = null;
|
||||
this.callback = _.identity;
|
||||
this.arguments = null;
|
||||
this.lastBlock = null; // "from" block tracker for backfilling events on reconnection
|
||||
|
||||
this.options = {
|
||||
subscription: options.subscription,
|
||||
type: options.type,
|
||||
requestManager: options.requestManager
|
||||
};
|
||||
}
|
||||
|
||||
// INHERIT
|
||||
Subscription.prototype = Object.create(EventEmitter.prototype);
|
||||
Subscription.prototype.constructor = Subscription;
|
||||
|
||||
|
||||
/**
|
||||
* Should be used to extract callback from array of arguments. Modifies input param
|
||||
*
|
||||
* @method extractCallback
|
||||
* @param {Array} arguments
|
||||
* @return {Function|Null} callback, if exists
|
||||
*/
|
||||
|
||||
Subscription.prototype._extractCallback = function (args) {
|
||||
if (_.isFunction(args[args.length - 1])) {
|
||||
return args.pop(); // modify the args array!
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be called to check if the number of arguments is correct
|
||||
*
|
||||
* @method validateArgs
|
||||
* @param {Array} arguments
|
||||
* @throws {Error} if it is not
|
||||
*/
|
||||
|
||||
Subscription.prototype._validateArgs = function (args) {
|
||||
var subscription = this.options.subscription;
|
||||
|
||||
if(!subscription)
|
||||
subscription = {};
|
||||
|
||||
if(!subscription.params)
|
||||
subscription.params = 0;
|
||||
|
||||
if (args.length !== subscription.params) {
|
||||
throw errors.InvalidNumberOfParams(
|
||||
args.length,
|
||||
subscription.params,
|
||||
subscription.subscriptionName
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be called to format input args of method
|
||||
*
|
||||
* @method formatInput
|
||||
* @param {Array}
|
||||
* @return {Array}
|
||||
*/
|
||||
|
||||
Subscription.prototype._formatInput = function (args) {
|
||||
var subscription = this.options.subscription;
|
||||
|
||||
if (!subscription) {
|
||||
return args;
|
||||
}
|
||||
|
||||
if (!subscription.inputFormatter) {
|
||||
return args;
|
||||
}
|
||||
|
||||
var formattedArgs = subscription.inputFormatter.map(function (formatter, index) {
|
||||
return formatter ? formatter(args[index]) : args[index];
|
||||
});
|
||||
|
||||
return formattedArgs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be called to format output(result) of method
|
||||
*
|
||||
* @method formatOutput
|
||||
* @param result {Object}
|
||||
* @return {Object}
|
||||
*/
|
||||
|
||||
Subscription.prototype._formatOutput = function (result) {
|
||||
var subscription = this.options.subscription;
|
||||
|
||||
return (subscription && subscription.outputFormatter && result) ? subscription.outputFormatter(result) : result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Should create payload from given input args
|
||||
*
|
||||
* @method toPayload
|
||||
* @param {Array} args
|
||||
* @return {Object}
|
||||
*/
|
||||
Subscription.prototype._toPayload = function (args) {
|
||||
var params = [];
|
||||
this.callback = this._extractCallback(args) || _.identity;
|
||||
|
||||
if (!this.subscriptionMethod) {
|
||||
this.subscriptionMethod = args.shift();
|
||||
|
||||
// replace subscription with given name
|
||||
if (this.options.subscription.subscriptionName) {
|
||||
this.subscriptionMethod = this.options.subscription.subscriptionName;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.arguments) {
|
||||
this.arguments = this._formatInput(args);
|
||||
this._validateArgs(this.arguments);
|
||||
args = []; // make empty after validation
|
||||
|
||||
}
|
||||
|
||||
// re-add subscriptionName
|
||||
params.push(this.subscriptionMethod);
|
||||
params = params.concat(this.arguments);
|
||||
|
||||
|
||||
if (args.length) {
|
||||
throw new Error('Only a callback is allowed as parameter on an already instantiated subscription.');
|
||||
}
|
||||
|
||||
return {
|
||||
method: this.options.type + '_subscribe',
|
||||
params: params
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Unsubscribes and clears callbacks
|
||||
*
|
||||
* @method unsubscribe
|
||||
* @return {Object}
|
||||
*/
|
||||
Subscription.prototype.unsubscribe = function(callback) {
|
||||
this.options.requestManager.removeSubscription(this.id, callback);
|
||||
this.id = null;
|
||||
this.lastBlock = null;
|
||||
this.removeAllListeners();
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribes and watches for changes
|
||||
*
|
||||
* @method subscribe
|
||||
* @param {String} subscription the subscription
|
||||
* @param {Object} options the options object with address topics and fromBlock
|
||||
* @return {Object}
|
||||
*/
|
||||
Subscription.prototype.subscribe = function() {
|
||||
var _this = this;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var payload = this._toPayload(args);
|
||||
|
||||
if(!payload) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// throw error, if provider is not set
|
||||
if(!this.options.requestManager.provider) {
|
||||
setTimeout(function(){
|
||||
var err1 = new Error('No provider set.');
|
||||
_this.callback(err1, null, _this);
|
||||
_this.emit('error', err1);
|
||||
},0);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// throw error, if provider doesnt support subscriptions
|
||||
if(!this.options.requestManager.provider.on) {
|
||||
setTimeout(function(){
|
||||
var err2 = new Error(
|
||||
'The current provider doesn\'t support subscriptions: ' +
|
||||
_this.options.requestManager.provider.constructor.name
|
||||
);
|
||||
_this.callback(err2, null, _this);
|
||||
_this.emit('error', err2);
|
||||
},0);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Re-subscription only: continue fetching from the last block we received.
|
||||
// a dropped connection may have resulted in gaps in the logs...
|
||||
if (this.lastBlock && _.isObject(this.options.params)){
|
||||
payload.params[1] = this.options.params;
|
||||
payload.params[1].fromBlock = formatters.inputBlockNumberFormatter(this.lastBlock + 1);
|
||||
}
|
||||
|
||||
// if id is there unsubscribe first
|
||||
if (this.id) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
|
||||
// store the params in the options object
|
||||
this.options.params = payload.params[1];
|
||||
|
||||
// get past logs, if fromBlock is available
|
||||
if(payload.params[0] === 'logs' && _.isObject(payload.params[1]) && payload.params[1].hasOwnProperty('fromBlock') && isFinite(payload.params[1].fromBlock)) {
|
||||
// send the subscription request
|
||||
|
||||
// copy the params to avoid race-condition with deletion below this block
|
||||
var blockParams = Object.assign({}, payload.params[1]);
|
||||
|
||||
this.options.requestManager.send({
|
||||
method: 'eth_getLogs',
|
||||
params: [blockParams]
|
||||
}, function (err, logs) {
|
||||
if(!err) {
|
||||
logs.forEach(function(log){
|
||||
var output = _this._formatOutput(log);
|
||||
_this.callback(null, output, _this);
|
||||
_this.emit('data', output);
|
||||
});
|
||||
|
||||
// TODO subscribe here? after the past logs?
|
||||
|
||||
} else {
|
||||
setTimeout(function(){
|
||||
_this.callback(err, null, _this);
|
||||
_this.emit('error', err);
|
||||
},0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// create subscription
|
||||
// TODO move to separate function? so that past logs can go first?
|
||||
|
||||
if(typeof payload.params[1] === 'object')
|
||||
delete payload.params[1].fromBlock;
|
||||
|
||||
this.options.requestManager.send(payload, function (err, result) {
|
||||
if(!err && result) {
|
||||
_this.id = result;
|
||||
_this.method = payload.params[0];
|
||||
_this.emit('connected', result);
|
||||
|
||||
// call callback on notifications
|
||||
_this.options.requestManager.addSubscription(_this, function(error, result) {
|
||||
if (!error) {
|
||||
if (!_.isArray(result)) {
|
||||
result = [result];
|
||||
}
|
||||
|
||||
result.forEach(function(resultItem) {
|
||||
var output = _this._formatOutput(resultItem);
|
||||
|
||||
// Track current block (for gaps introduced by dropped connections)
|
||||
_this.lastBlock = _.isObject(output) ? output.blockNumber : null;
|
||||
|
||||
if (_.isFunction(_this.options.subscription.subscriptionHandler)) {
|
||||
return _this.options.subscription.subscriptionHandler.call(_this, output);
|
||||
} else {
|
||||
_this.emit('data', output);
|
||||
}
|
||||
|
||||
// call the callback, last so that unsubscribe there won't affect the emit above
|
||||
_this.callback(null, output, _this);
|
||||
});
|
||||
} else {
|
||||
_this.callback(error, false, _this);
|
||||
_this.emit('error', error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setTimeout(function(){
|
||||
_this.callback(err, false, _this);
|
||||
_this.emit('error', err);
|
||||
},0);
|
||||
}
|
||||
});
|
||||
|
||||
// return an object to cancel the subscription
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resubscribe
|
||||
*
|
||||
* @method resubscribe
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
Subscription.prototype.resubscribe = function () {
|
||||
this.options.requestManager.removeSubscription(this.id); // unsubscribe
|
||||
this.id = null;
|
||||
|
||||
this.subscribe(this.callback);
|
||||
};
|
||||
|
||||
module.exports = Subscription;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib"
|
||||
},
|
||||
"include": [
|
||||
"./src"
|
||||
]
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"target": "es6",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"noEmit": true,
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"web3-core-subscriptions": ["."]
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "dtslint/dtslint.json",
|
||||
"rules": {
|
||||
"semicolon": false,
|
||||
"no-import-default-of-export-equals": false,
|
||||
"file-name-casing": [true, "kebab-case"],
|
||||
"whitespace": false,
|
||||
"no-unnecessary-class": false,
|
||||
"unified-signatures": false,
|
||||
"no-redundant-jsdoc": false
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user