UNPKG

@parity/light.js

Version:

A high-level reactive JS library optimized for light clients

89 lines (88 loc) 4.01 kB
"use strict"; // 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;