UNPKG

metaapi.cloud-sdk

Version:

SDK for MetaApi, a professional cloud forex API which includes MetaTrader REST API and MetaTrader websocket API. Supports both MetaTrader 5 (MT5) and MetaTrader 4 (MT4). CopyFactory copy trading API included. (https://metaapi.cloud)

207 lines (206 loc) 24.5 kB
'use strict'; function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _async_to_generator(fn) { return function() { var self = this, args = arguments; return new Promise(function(resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } import LoggerManager from '../logger'; import MetaApiConnectionInstance from './metaApiConnectionInstance'; let StreamingMetaApiConnectionInstance = class StreamingMetaApiConnectionInstance extends MetaApiConnectionInstance { /** * Opens the connection. Can only be called the first time, next calls will be ignored. * @return {Promise} promise resolving when the connection is opened */ connect() { var _this = this; return _async_to_generator(function*() { if (!_this._opened) { _this._opened = true; try { yield _this._metaApiConnection.connect(_this.instanceId); } catch (err) { yield _this.close(); throw err; } } })(); } /** * Clears the order and transaction history of a specified application and removes application * @return {Promise} promise resolving when the history is cleared and application is removed */ removeApplication() { return this._metaApiConnection.removeApplication(); } /** * Subscribes on market data of specified symbol (see * https://metaapi.cloud/docs/client/websocket/marketDataStreaming/subscribeToMarketData/). * @param {String} symbol symbol (e.g. currency pair or an index) * @param {Array<MarketDataSubscription>} subscriptions array of market data subscription to create or update. Please * note that this feature is not fully implemented on server-side yet * @param {number} [timeoutInSeconds] timeout to wait for prices in seconds, default is 30 * @param {boolean} [waitForQuote] if set to false, the method will resolve without waiting for the first quote to * arrive. Default is to wait for quote if quotes subscription is requested. * @returns {Promise} promise which resolves when subscription request was processed */ subscribeToMarketData(symbol, subscriptions, timeoutInSeconds, waitForQuote = true) { var _this = this; return _async_to_generator(function*() { _this._checkIsConnectionActive(); return _this._metaApiConnection.subscribeToMarketData(symbol, subscriptions, timeoutInSeconds, waitForQuote); })(); } /** * Unsubscribes from market data of specified symbol (see * https://metaapi.cloud/docs/client/websocket/marketDataStreaming/unsubscribeFromMarketData/). * @param {String} symbol symbol (e.g. currency pair or an index) * @param {Array<MarketDataUnsubscription>} subscriptions array of subscriptions to cancel * @returns {Promise} promise which resolves when unsubscription request was processed */ unsubscribeFromMarketData(symbol, subscriptions) { this._checkIsConnectionActive(); return this._metaApiConnection.unsubscribeFromMarketData(symbol, subscriptions); } /** * Returns list of the symbols connection is subscribed to * @returns {Array<String>} list of the symbols connection is subscribed to */ get subscribedSymbols() { return this._metaApiConnection.subscribedSymbols; } /** * Returns subscriptions for a symbol * @param {string} symbol symbol to retrieve subscriptions for * @returns {Array<MarketDataSubscription>} list of market data subscriptions for the symbol */ subscriptions(symbol) { return this._metaApiConnection.subscriptions(symbol); } /** * Sends client uptime stats to the server. * @param {Object} uptime uptime statistics to send to the server * @returns {Promise} promise which resolves when uptime statistics is submitted */ saveUptime(uptime) { this._checkIsConnectionActive(); return this._websocketClient.saveUptime(this._metaApiConnection.account.id, uptime); } /** * Returns local copy of terminal state * @returns {TerminalState} local copy of terminal state */ get terminalState() { return this._metaApiConnection.terminalState; } /** * Returns local history storage * @returns {HistoryStorage} local history storage */ get historyStorage() { return this._metaApiConnection.historyStorage; } /** * Adds synchronization listener * @param {SynchronizationListener} listener synchronization listener to add */ addSynchronizationListener(listener) { this._synchronizationListeners.push(listener); this._websocketClient.addSynchronizationListener(this._metaApiConnection.account.id, listener); } /** * Removes synchronization listener for specific account * @param {SynchronizationListener} listener synchronization listener to remove */ removeSynchronizationListener(listener) { this._synchronizationListeners = this._synchronizationListeners.filter((l)=>l !== listener); this._websocketClient.removeSynchronizationListener(this._metaApiConnection.account.id, listener); } /** * @typedef {Object} SynchronizationOptions * @property {String} [applicationPattern] application regular expression pattern, default is .* * @property {String} [synchronizationId] synchronization id, last synchronization request id will be used by * default * @property {Number} [instanceIndex] index of an account instance to ensure synchronization on, default is to wait * for the first instance to synchronize * @property {Number} [timeoutInSeconds] wait timeout in seconds, default is 5m * @property {Number} [intervalInMilliseconds] interval between account reloads while waiting for a change, default is 1s */ /** * Waits until synchronization to MetaTrader terminal is completed * @param {SynchronizationOptions} opts synchronization options * @return {Promise} promise which resolves when synchronization to MetaTrader terminal is completed * @throws {TimeoutError} if application failed to synchronize with the teminal within timeout allowed */ // eslint-disable-next-line complexity waitSynchronized(opts) { var _this = this; return _async_to_generator(function*() { _this._checkIsConnectionActive(); return _this._metaApiConnection.waitSynchronized(opts); })(); } /** * Queues an event for processing among other synchronization events within same account * @param {String} name event label name * @param {Function} callable async or regular function to execute */ queueEvent(name, callable) { this._websocketClient.queueEvent(this._metaApiConnection.account.id, name, callable); } /** * Closes the connection. The instance of the class should no longer be used after this method is invoked. */ close() { var _this = this; return _async_to_generator(function*() { if (!_this._closed) { for (let listener of _this._synchronizationListeners){ _this._websocketClient.removeSynchronizationListener(_this._metaApiConnection.account.id, listener); } _this._closed = true; yield _this._metaApiConnection.close(_this.instanceId); } })(); } /** * Returns synchronization status * @return {boolean} synchronization status */ get synchronized() { return this._metaApiConnection.synchronized; } /** * Returns MetaApi account * @return {MetatraderAccount} MetaApi account */ get account() { return this._metaApiConnection.account; } /** * Returns connection health monitor instance * @return {ConnectionHealthMonitor} connection health monitor instance */ get healthMonitor() { return this._metaApiConnection.healthMonitor; } /** * Constructs MetaApi MetaTrader streaming Api connection instance * @param {MetaApiWebsocketClient} websocketClient MetaApi websocket client * @param {StreamingMetaApiConnection} metaApiConnection streaming MetaApi connection */ constructor(websocketClient, metaApiConnection){ super(websocketClient, metaApiConnection); this._metaApiConnection = metaApiConnection; this._synchronizationListeners = []; this._logger = LoggerManager.getLogger('StreamingMetaApiConnectionInstance'); } }; /** * Exposes MetaApi MetaTrader streaming API connection instance to consumers */ export { StreamingMetaApiConnectionInstance as default }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBUZXJtaW5hbFN0YXRlIGZyb20gJy4vdGVybWluYWxTdGF0ZSc7XG5pbXBvcnQgQ29ubmVjdGlvbkhlYWx0aE1vbml0b3IgZnJvbSAnLi9jb25uZWN0aW9uSGVhbHRoTW9uaXRvcic7XG5pbXBvcnQgTG9nZ2VyTWFuYWdlciBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IE1ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UgZnJvbSAnLi9tZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlJztcblxuLyoqXG4gKiBFeHBvc2VzIE1ldGFBcGkgTWV0YVRyYWRlciBzdHJlYW1pbmcgQVBJIGNvbm5lY3Rpb24gaW5zdGFuY2UgdG8gY29uc3VtZXJzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN0cmVhbWluZ01ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UgZXh0ZW5kcyBNZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlIHtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBNZXRhQXBpIE1ldGFUcmFkZXIgc3RyZWFtaW5nIEFwaSBjb25uZWN0aW9uIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7TWV0YUFwaVdlYnNvY2tldENsaWVudH0gd2Vic29ja2V0Q2xpZW50IE1ldGFBcGkgd2Vic29ja2V0IGNsaWVudFxuICAgKiBAcGFyYW0ge1N0cmVhbWluZ01ldGFBcGlDb25uZWN0aW9ufSBtZXRhQXBpQ29ubmVjdGlvbiBzdHJlYW1pbmcgTWV0YUFwaSBjb25uZWN0aW9uXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih3ZWJzb2NrZXRDbGllbnQsIG1ldGFBcGlDb25uZWN0aW9uKSB7XG4gICAgc3VwZXIod2Vic29ja2V0Q2xpZW50LCBtZXRhQXBpQ29ubmVjdGlvbik7XG4gICAgdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24gPSBtZXRhQXBpQ29ubmVjdGlvbjtcbiAgICB0aGlzLl9zeW5jaHJvbml6YXRpb25MaXN0ZW5lcnMgPSBbXTtcbiAgICB0aGlzLl9sb2dnZXIgPSBMb2dnZXJNYW5hZ2VyLmdldExvZ2dlcignU3RyZWFtaW5nTWV0YUFwaUNvbm5lY3Rpb25JbnN0YW5jZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wZW5zIHRoZSBjb25uZWN0aW9uLiBDYW4gb25seSBiZSBjYWxsZWQgdGhlIGZpcnN0IHRpbWUsIG5leHQgY2FsbHMgd2lsbCBiZSBpZ25vcmVkLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHJlc29sdmluZyB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIG9wZW5lZFxuICAgKi9cbiAgYXN5bmMgY29ubmVjdCgpIHtcbiAgICBpZiAoIXRoaXMuX29wZW5lZCkge1xuICAgICAgdGhpcy5fb3BlbmVkID0gdHJ1ZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmNvbm5lY3QodGhpcy5pbnN0YW5jZUlkKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBhd2FpdCB0aGlzLmNsb3NlKCk7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXJzIHRoZSBvcmRlciBhbmQgdHJhbnNhY3Rpb24gaGlzdG9yeSBvZiBhIHNwZWNpZmllZCBhcHBsaWNhdGlvbiBhbmQgcmVtb3ZlcyBhcHBsaWNhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHJlc29sdmluZyB3aGVuIHRoZSBoaXN0b3J5IGlzIGNsZWFyZWQgYW5kIGFwcGxpY2F0aW9uIGlzIHJlbW92ZWRcbiAgICovXG4gIHJlbW92ZUFwcGxpY2F0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5yZW1vdmVBcHBsaWNhdGlvbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1YnNjcmliZXMgb24gbWFya2V0IGRhdGEgb2Ygc3BlY2lmaWVkIHN5bWJvbCAoc2VlXG4gICAqIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL2NsaWVudC93ZWJzb2NrZXQvbWFya2V0RGF0YVN0cmVhbWluZy9zdWJzY3JpYmVUb01hcmtldERhdGEvKS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bWJvbCBzeW1ib2wgKGUuZy4gY3VycmVuY3kgcGFpciBvciBhbiBpbmRleClcbiAgICogQHBhcmFtIHtBcnJheTxNYXJrZXREYXRhU3Vic2NyaXB0aW9uPn0gc3Vic2NyaXB0aW9ucyBhcnJheSBvZiBtYXJrZXQgZGF0YSBzdWJzY3JpcHRpb24gdG8gY3JlYXRlIG9yIHVwZGF0ZS4gUGxlYXNlXG4gICAqIG5vdGUgdGhhdCB0aGlzIGZlYXR1cmUgaXMgbm90IGZ1bGx5IGltcGxlbWVudGVkIG9uIHNlcnZlci1zaWRlIHlldFxuICAgKiBAcGFyYW0ge251bWJlcn0gW3RpbWVvdXRJblNlY29uZHNdIHRpbWVvdXQgdG8gd2FpdCBmb3IgcHJpY2VzIGluIHNlY29uZHMsIGRlZmF1bHQgaXMgMzBcbiAgICogQHBhcmFtIHtib29sZWFufSBbd2FpdEZvclF1b3RlXSBpZiBzZXQgdG8gZmFsc2UsIHRoZSBtZXRob2Qgd2lsbCByZXNvbHZlIHdpdGhvdXQgd2FpdGluZyBmb3IgdGhlIGZpcnN0IHF1b3RlIHRvXG4gICAqIGFycml2ZS4gRGVmYXVsdCBpcyB0byB3YWl0IGZvciBxdW90ZSBpZiBxdW90ZXMgc3Vic2NyaXB0aW9uIGlzIHJlcXVlc3RlZC5cbiAgICogQHJldHVybnMge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiBzdWJzY3JpcHRpb24gcmVxdWVzdCB3YXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBzdWJzY3JpYmVUb01hcmtldERhdGEoc3ltYm9sLCBzdWJzY3JpcHRpb25zLCB0aW1lb3V0SW5TZWNvbmRzLCB3YWl0Rm9yUXVvdGUgPSB0cnVlKSB7XG4gICAgdGhpcy5fY2hlY2tJc0Nvbm5lY3Rpb25BY3RpdmUoKTtcbiAgICByZXR1cm4gdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uc3Vic2NyaWJlVG9NYXJrZXREYXRhKHN5bWJvbCwgc3Vic2NyaXB0aW9ucywgdGltZW91dEluU2Vjb25kcywgd2FpdEZvclF1b3RlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnN1YnNjcmliZXMgZnJvbSBtYXJrZXQgZGF0YSBvZiBzcGVjaWZpZWQgc3ltYm9sIChzZWVcbiAgICogaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvY2xpZW50L3dlYnNvY2tldC9tYXJrZXREYXRhU3RyZWFtaW5nL3Vuc3Vic2NyaWJlRnJvbU1hcmtldERhdGEvKS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bWJvbCBzeW1ib2wgKGUuZy4gY3VycmVuY3kgcGFpciBvciBhbiBpbmRleClcbiAgICogQHBhcmFtIHtBcnJheTxNYXJrZXREYXRhVW5zdWJzY3JpcHRpb24+fSBzdWJzY3JpcHRpb25zIGFycmF5IG9mIHN1YnNjcmlwdGlvbnMgdG8gY2FuY2VsXG4gICAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdW5zdWJzY3JpcHRpb24gcmVxdWVzdCB3YXMgcHJvY2Vzc2VkXG4gICAqL1xuICB1bnN1YnNjcmliZUZyb21NYXJrZXREYXRhKHN5bWJvbCwgc3Vic2NyaXB0aW9ucykge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLnVuc3Vic2NyaWJlRnJvbU1hcmtldERhdGEoc3ltYm9sLCBzdWJzY3JpcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGxpc3Qgb2YgdGhlIHN5bWJvbHMgY29ubmVjdGlvbiBpcyBzdWJzY3JpYmVkIHRvXG4gICAqIEByZXR1cm5zIHtBcnJheTxTdHJpbmc+fSBsaXN0IG9mIHRoZSBzeW1ib2xzIGNvbm5lY3Rpb24gaXMgc3Vic2NyaWJlZCB0b1xuICAgKi9cbiAgZ2V0IHN1YnNjcmliZWRTeW1ib2xzKCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5zdWJzY3JpYmVkU3ltYm9scztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHN1YnNjcmlwdGlvbnMgZm9yIGEgc3ltYm9sXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzeW1ib2wgc3ltYm9sIHRvIHJldHJpZXZlIHN1YnNjcmlwdGlvbnMgZm9yXG4gICAqIEByZXR1cm5zIHtBcnJheTxNYXJrZXREYXRhU3Vic2NyaXB0aW9uPn0gbGlzdCBvZiBtYXJrZXQgZGF0YSBzdWJzY3JpcHRpb25zIGZvciB0aGUgc3ltYm9sXG4gICAqL1xuICBzdWJzY3JpcHRpb25zKHN5bWJvbCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5zdWJzY3JpcHRpb25zKHN5bWJvbCk7XG4gIH1cblxuICAvKipcbiAgICogU2VuZHMgY2xpZW50IHVwdGltZSBzdGF0cyB0byB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0ge09iamVjdH0gdXB0aW1lIHVwdGltZSBzdGF0aXN0aWNzIHRvIHNlbmQgdG8gdGhlIHNlcnZlclxuICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHVwdGltZSBzdGF0aXN0aWNzIGlzIHN1Ym1pdHRlZFxuICAgKi9cbiAgc2F2ZVVwdGltZSh1cHRpbWUpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuc2F2ZVVwdGltZSh0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkLCB1cHRpbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgbG9jYWwgY29weSBvZiB0ZXJtaW5hbCBzdGF0ZVxuICAgKiBAcmV0dXJucyB7VGVybWluYWxTdGF0ZX0gbG9jYWwgY29weSBvZiB0ZXJtaW5hbCBzdGF0ZVxuICAgKi9cbiAgZ2V0IHRlcm1pbmFsU3RhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLnRlcm1pbmFsU3RhdGU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBsb2NhbCBoaXN0b3J5IHN0b3JhZ2VcbiAgICogQHJldHVybnMge0hpc3RvcnlTdG9yYWdlfSBsb2NhbCBoaXN0b3J5IHN0b3JhZ2VcbiAgICovXG4gIGdldCBoaXN0b3J5U3RvcmFnZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uaGlzdG9yeVN0b3JhZ2U7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBzeW5jaHJvbml6YXRpb24gbGlzdGVuZXJcbiAgICogQHBhcmFtIHtTeW5jaHJvbml6YXRpb25MaXN0ZW5lcn0gbGlzdGVuZXIgc3luY2hyb25pemF0aW9uIGxpc3RlbmVyIHRvIGFkZFxuICAgKi9cbiAgYWRkU3luY2hyb25pemF0aW9uTGlzdGVuZXIobGlzdGVuZXIpIHtcbiAgICB0aGlzLl9zeW5jaHJvbml6YXRpb25MaXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7XG4gICAgdGhpcy5fd2Vic29ja2V0Q2xpZW50LmFkZFN5bmNocm9uaXphdGlvbkxpc3RlbmVyKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIHN5bmNocm9uaXphdGlvbiBsaXN0ZW5lciBmb3Igc3BlY2lmaWMgYWNjb3VudFxuICAgKiBAcGFyYW0ge1N5bmNocm9uaXphdGlvbkxpc3RlbmVyfSBsaXN0ZW5lciBzeW5jaHJvbml6YXRpb24gbGlzdGVuZXIgdG8gcmVtb3ZlXG4gICAqL1xuICByZW1vdmVTeW5jaHJvbml6YXRpb25MaXN0ZW5lcihsaXN0ZW5lcikge1xuICAgIHRoaXMuX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycyA9IHRoaXMuX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycy5maWx0ZXIobCA9PiBsICE9PSBsaXN0ZW5lcik7XG4gICAgdGhpcy5fd2Vic29ja2V0Q2xpZW50LnJlbW92ZVN5bmNocm9uaXphdGlvbkxpc3RlbmVyKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBTeW5jaHJvbml6YXRpb25PcHRpb25zXG4gICAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBbYXBwbGljYXRpb25QYXR0ZXJuXSBhcHBsaWNhdGlvbiByZWd1bGFyIGV4cHJlc3Npb24gcGF0dGVybiwgZGVmYXVsdCBpcyAuKlxuICAgKiBAcHJvcGVydHkge1N0cmluZ30gW3N5bmNocm9uaXphdGlvbklkXSBzeW5jaHJvbml6YXRpb24gaWQsIGxhc3Qgc3luY2hyb25pemF0aW9uIHJlcXVlc3QgaWQgd2lsbCBiZSB1c2VkIGJ5XG4gICAqIGRlZmF1bHRcbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFtpbnN0YW5jZUluZGV4XSBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIHRvIGVuc3VyZSBzeW5jaHJvbml6YXRpb24gb24sIGRlZmF1bHQgaXMgdG8gd2FpdFxuICAgKiBmb3IgdGhlIGZpcnN0IGluc3RhbmNlIHRvIHN5bmNocm9uaXplXG4gICAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbdGltZW91dEluU2Vjb25kc10gd2FpdCB0aW1lb3V0IGluIHNlY29uZHMsIGRlZmF1bHQgaXMgNW1cbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFtpbnRlcnZhbEluTWlsbGlzZWNvbmRzXSBpbnRlcnZhbCBiZXR3ZWVuIGFjY291bnQgcmVsb2FkcyB3aGlsZSB3YWl0aW5nIGZvciBhIGNoYW5nZSwgZGVmYXVsdCBpcyAxc1xuICAgKi9cblxuICAvKipcbiAgICogV2FpdHMgdW50aWwgc3luY2hyb25pemF0aW9uIHRvIE1ldGFUcmFkZXIgdGVybWluYWwgaXMgY29tcGxldGVkXG4gICAqIEBwYXJhbSB7U3luY2hyb25pemF0aW9uT3B0aW9uc30gb3B0cyBzeW5jaHJvbml6YXRpb24gb3B0aW9uc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gc3luY2hyb25pemF0aW9uIHRvIE1ldGFUcmFkZXIgdGVybWluYWwgaXMgY29tcGxldGVkXG4gICAqIEB0aHJvd3Mge1RpbWVvdXRFcnJvcn0gaWYgYXBwbGljYXRpb24gZmFpbGVkIHRvIHN5bmNocm9uaXplIHdpdGggdGhlIHRlbWluYWwgd2l0aGluIHRpbWVvdXQgYWxsb3dlZFxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbiAgYXN5bmMgd2FpdFN5bmNocm9uaXplZChvcHRzKSB7XG4gICAgdGhpcy5fY2hlY2tJc0Nvbm5lY3Rpb25BY3RpdmUoKTtcbiAgICByZXR1cm4gdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24ud2FpdFN5bmNocm9uaXplZChvcHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRdWV1ZXMgYW4gZXZlbnQgZm9yIHByb2Nlc3NpbmcgYW1vbmcgb3RoZXIgc3luY2hyb25pemF0aW9uIGV2ZW50cyB3aXRoaW4gc2FtZSBhY2NvdW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIGV2ZW50IGxhYmVsIG5hbWVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGFibGUgYXN5bmMgb3IgcmVndWxhciBmdW5jdGlvbiB0byBleGVjdXRlXG4gICAqL1xuICBxdWV1ZUV2ZW50KG5hbWUsIGNhbGxhYmxlKSB7XG4gICAgdGhpcy5fd2Vic29ja2V0Q2xpZW50LnF1ZXVlRXZlbnQodGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uYWNjb3VudC5pZCwgbmFtZSwgY2FsbGFibGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbi4gVGhlIGluc3RhbmNlIG9mIHRoZSBjbGFzcyBzaG91bGQgbm8gbG9uZ2VyIGJlIHVzZWQgYWZ0ZXIgdGhpcyBtZXRob2QgaXMgaW52b2tlZC5cbiAgICovXG4gIGFzeW5jIGNsb3NlKCkge1xuICAgIGlmICghdGhpcy5fY2xvc2VkKXtcbiAgICAgIGZvciAobGV0IGxpc3RlbmVyIG9mIHRoaXMuX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycykge1xuICAgICAgICB0aGlzLl93ZWJzb2NrZXRDbGllbnQucmVtb3ZlU3luY2hyb25pemF0aW9uTGlzdGVuZXIodGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uYWNjb3VudC5pZCwgbGlzdGVuZXIpO1xuICAgICAgfVxuICAgICAgdGhpcy5fY2xvc2VkID0gdHJ1ZTtcbiAgICAgIGF3YWl0IHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmNsb3NlKHRoaXMuaW5zdGFuY2VJZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3luY2hyb25pemF0aW9uIHN0YXR1c1xuICAgKiBAcmV0dXJuIHtib29sZWFufSBzeW5jaHJvbml6YXRpb24gc3RhdHVzXG4gICAqL1xuICBnZXQgc3luY2hyb25pemVkKCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5zeW5jaHJvbml6ZWQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBNZXRhQXBpIGFjY291bnRcbiAgICogQHJldHVybiB7TWV0YXRyYWRlckFjY291bnR9IE1ldGFBcGkgYWNjb3VudFxuICAgKi9cbiAgZ2V0IGFjY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBjb25uZWN0aW9uIGhlYWx0aCBtb25pdG9yIGluc3RhbmNlXG4gICAqIEByZXR1cm4ge0Nvbm5lY3Rpb25IZWFsdGhNb25pdG9yfSBjb25uZWN0aW9uIGhlYWx0aCBtb25pdG9yIGluc3RhbmNlXG4gICAqL1xuICBnZXQgaGVhbHRoTW9uaXRvcigpIHtcbiAgICByZXR1cm4gdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uaGVhbHRoTW9uaXRvcjtcbiAgfVxuXG59XG4iXSwibmFtZXMiOlsiTG9nZ2VyTWFuYWdlciIsIk1ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UiLCJTdHJlYW1pbmdNZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlIiwiY29ubmVjdCIsIl9vcGVuZWQiLCJfbWV0YUFwaUNvbm5lY3Rpb24iLCJpbnN0YW5jZUlkIiwiZXJyIiwiY2xvc2UiLCJyZW1vdmVBcHBsaWNhdGlvbiIsInN1YnNjcmliZVRvTWFya2V0RGF0YSIsInN5bWJvbCIsInN1YnNjcmlwdGlvbnMiLCJ0aW1lb3V0SW5TZWNvbmRzIiwid2FpdEZvclF1b3RlIiwiX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlIiwidW5zdWJzY3JpYmVGcm9tTWFya2V0RGF0YSIsInN1YnNjcmliZWRTeW1ib2xzIiwic2F2ZVVwdGltZSIsInVwdGltZSIsIl93ZWJzb2NrZXRDbGllbnQiLCJhY2NvdW50IiwiaWQiLCJ0ZXJtaW5hbFN0YXRlIiwiaGlzdG9yeVN0b3JhZ2UiLCJhZGRTeW5jaHJvbml6YXRpb25MaXN0ZW5lciIsImxpc3RlbmVyIiwiX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycyIsInB1c2giLCJyZW1vdmVTeW5jaHJvbml6YXRpb25MaXN0ZW5lciIsImZpbHRlciIsImwiLCJ3YWl0U3luY2hyb25pemVkIiwib3B0cyIsInF1ZXVlRXZlbnQiLCJuYW1lIiwiY2FsbGFibGUiLCJfY2xvc2VkIiwic3luY2hyb25pemVkIiwiaGVhbHRoTW9uaXRvciIsImNvbnN0cnVjdG9yIiwid2Vic29ja2V0Q2xpZW50IiwibWV0YUFwaUNvbm5lY3Rpb24iLCJfbG9nZ2VyIiwiZ2V0TG9nZ2VyIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBSUEsT0FBT0EsbUJBQW1CLFlBQVk7QUFDdEMsT0FBT0MsK0JBQStCLDhCQUE4QjtBQUtyRCxJQUFBLEFBQU1DLHFDQUFOLE1BQU1BLDJDQUEyQ0Q7SUFjOUQ7OztHQUdDLEdBQ0QsQUFBTUU7O2VBQU4sb0JBQUE7WUFDRSxJQUFJLENBQUMsTUFBS0MsT0FBTyxFQUFFO2dCQUNqQixNQUFLQSxPQUFPLEdBQUc7Z0JBQ2YsSUFBSTtvQkFD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