@parity/light.js
Version:
A high-level reactive JS library optimized for light clients
89 lines (88 loc) • 4.01 kB
JavaScript
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
// SPDX-License-Identifier: MIT
Object.defineProperty(exports, "__esModule", { value: true });
var debug = require("debug");
var operators_1 = require("rxjs/operators");
var memoizee = require("memoizee");
var rxjs_1 = require("rxjs");
var api_1 = require("../../api");
var distinctReplayRefCountDelay_1 = require("../../utils/operators/distinctReplayRefCountDelay");
// For unavailable pubsubs, poll every 1s instead
exports.POLL_INTERVAL = 1000;
// Drop the pubsub connection or polling after 2s without subscribers
exports.UNSUB_DELAY = 2000;
/**
* Create a polling function, calls the `fallback` JSONRPC on each second, or
* on previous call's result, whichever comes last.
*
* @ignore
*/
function createPoll(fallback, api, pollInterval) {
if (pollInterval === void 0) { pollInterval = exports.POLL_INTERVAL; }
var _a = fallback.split('_'), fallbackNamespace = _a[0], fallbackMethod = _a[1];
return rxjs_1.timer(0, pollInterval).pipe(operators_1.exhaustMap(function () { return api[fallbackNamespace][fallbackMethod](); }));
}
/**
* Given an api, returns an Observable that emits on each pubsub event.
* Pure function version of {@link createPubsubObservable}.
*
* @ignore
* @param pubsub - The pubsub method to subscribe to.
* @param fallback - If pubsub doesn't work, poll this method every
* POLL_INTERVAL ms.
*/
var createPubsubObservableWithApi = memoizee(function (pubsub, fallback, api) {
var _a = pubsub.split('_'), namespace = _a[0], method = _a[1];
var observable;
// There's a chance the provider doesn't support pubsub, for example
// MetaMaskProvider. In this case, as suggested on their Github, the best
// solution for now is to poll.
if (!api.isPubSub) {
debug('@parity/light.js:api')("Pubsub not available for " + (api.provider ? api.provider.constructor.name : 'current Api') + " provider, polling \"" + fallback + "\" every " + exports.POLL_INTERVAL + "ms.");
observable = createPoll(fallback, api);
}
else {
observable = rxjs_1.Observable.create(function (observer) {
var subscription = api.pubsub[namespace][method](function (error, result) {
// TODO use @parity/api type for result
if (error) {
observer.error(error);
}
else {
observer.next(result);
}
}).catch(function () {
// If we get an error during subscription, then default to fallback.
// TODO Should this be done on @parity/api?
debug('@parity/light.js:api')("Pubsub not available for method \"" + pubsub + "\", polling \"" + fallback + "\" every " + exports.POLL_INTERVAL + "ms");
createPoll(fallback, api).subscribe(function (e) { return observer.next(e); }, function (e) { return observer.error(e); }, function () { return observer.complete(); });
});
return function () {
return subscription.then(function (subscriptionId) {
return subscriptionId
? api.pubsub.unsubscribe(subscriptionId)
: Promise.resolve();
});
};
});
}
return observable.pipe(distinctReplayRefCountDelay_1.distinctReplayRefCountDelay(exports.UNSUB_DELAY));
});
/**
* Given a provider, returns an Observable that emits on each pubsub event.
*
* @ignore
* @example onAccountsChanged$, onEveryBlock$...
*/
var createPubsubObservable = function (pubsub, fallback, _a) {
var provider = (_a === void 0 ? {} : _a).provider;
// Evaluate api only once we subscribe
return rxjs_1.defer(function () {
var api = provider ? api_1.createApiFromProvider(provider) : api_1.getApi();
return createPubsubObservableWithApi(pubsub, fallback, api);
});
};
exports.default = createPubsubObservable;
;