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)

209 lines (208 loc) 24.8 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 TerminalState from './terminalState'; import ConnectionHealthMonitor from './connectionHealthMonitor'; 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+fSBsaXN0IG9mIHRoZSBzeW1ib2xzIGNvbm5lY3Rpb24gaXMgc3Vic2NyaWJlZCB0b1xuICAgKi9cbiAgZ2V0IHN1YnNjcmliZWRTeW1ib2xzKCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5zdWJzY3JpYmVkU3ltYm9scztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHN1YnNjcmlwdGlvbnMgZm9yIGEgc3ltYm9sXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzeW1ib2wgc3ltYm9sIHRvIHJldHJpZXZlIHN1YnNjcmlwdGlvbnMgZm9yXG4gICAqIEByZXR1cm5zIHtBcnJheTxNYXJrZXREYXRhU3Vic2NyaXB0aW9uPn0gbGlzdCBvZiBtYXJrZXQgZGF0YSBzdWJzY3JpcHRpb25zIGZvciB0aGUgc3ltYm9sXG4gICAqL1xuICBzdWJzY3JpcHRpb25zKHN5bWJvbCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5zdWJzY3JpcHRpb25zKHN5bWJvbCk7XG4gIH1cblxuICAvKipcbiAgICogU2VuZHMgY2xpZW50IHVwdGltZSBzdGF0cyB0byB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0ge09iamVjdH0gdXB0aW1lIHVwdGltZSBzdGF0aXN0aWNzIHRvIHNlbmQgdG8gdGhlIHNlcnZlclxuICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHVwdGltZSBzdGF0aXN0aWNzIGlzIHN1Ym1pdHRlZFxuICAgKi9cbiAgc2F2ZVVwdGltZSh1cHRpbWUpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuc2F2ZVVwdGltZSh0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkLCB1cHRpbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgbG9jYWwgY29weSBvZiB0ZXJtaW5hbCBzdGF0ZVxuICAgKiBAcmV0dXJucyB7VGVybWluYWxTdGF0ZX0gbG9jYWwgY29weSBvZiB0ZXJtaW5hbCBzdGF0ZVxuICAgKi9cbiAgZ2V0IHRlcm1pbmFsU3RhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLnRlcm1pbmFsU3RhdGU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBsb2NhbCBoaXN0b3J5IHN0b3JhZ2VcbiAgICogQHJldHVybnMge0hpc3RvcnlTdG9yYWdlfSBsb2NhbCBoaXN0b3J5IHN0b3JhZ2VcbiAgICovXG4gIGdldCBoaXN0b3J5U3RvcmFnZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uaGlzdG9yeVN0b3JhZ2U7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBzeW5jaHJvbml6YXRpb24gbGlzdGVuZXJcbiAgICogQHBhcmFtIHtTeW5jaHJvbml6YXRpb25MaXN0ZW5lcn0gbGlzdGVuZXIgc3luY2hyb25pemF0aW9uIGxpc3RlbmVyIHRvIGFkZFxuICAgKi9cbiAgYWRkU3luY2hyb25pemF0aW9uTGlzdGVuZXIobGlzdGVuZXIpIHtcbiAgICB0aGlzLl9zeW5jaHJvbml6YXRpb25MaXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7XG4gICAgdGhpcy5fd2Vic29ja2V0Q2xpZW50LmFkZFN5bmNocm9uaXphdGlvbkxpc3RlbmVyKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIHN5bmNocm9uaXphdGlvbiBsaXN0ZW5lciBmb3Igc3BlY2lmaWMgYWNjb3VudFxuICAgKiBAcGFyYW0ge1N5bmNocm9uaXphdGlvbkxpc3RlbmVyfSBsaXN0ZW5lciBzeW5jaHJvbml6YXRpb24gbGlzdGVuZXIgdG8gcmVtb3ZlXG4gICAqL1xuICByZW1vdmVTeW5jaHJvbml6YXRpb25MaXN0ZW5lcihsaXN0ZW5lcikge1xuICAgIHRoaXMuX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycyA9IHRoaXMuX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycy5maWx0ZXIobCA9PiBsICE9PSBsaXN0ZW5lcik7XG4gICAgdGhpcy5fd2Vic29ja2V0Q2xpZW50LnJlbW92ZVN5bmNocm9uaXphdGlvbkxpc3RlbmVyKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBTeW5jaHJvbml6YXRpb25PcHRpb25zXG4gICAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBbYXBwbGljYXRpb25QYXR0ZXJuXSBhcHBsaWNhdGlvbiByZWd1bGFyIGV4cHJlc3Npb24gcGF0dGVybiwgZGVmYXVsdCBpcyAuKlxuICAgKiBAcHJvcGVydHkge1N0cmluZ30gW3N5bmNocm9uaXphdGlvbklkXSBzeW5jaHJvbml6YXRpb24gaWQsIGxhc3Qgc3luY2hyb25pemF0aW9uIHJlcXVlc3QgaWQgd2lsbCBiZSB1c2VkIGJ5XG4gICAqIGRlZmF1bHRcbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFtpbnN0YW5jZUluZGV4XSBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIHRvIGVuc3VyZSBzeW5jaHJvbml6YXRpb24gb24sIGRlZmF1bHQgaXMgdG8gd2FpdFxuICAgKiBmb3IgdGhlIGZpcnN0IGluc3RhbmNlIHRvIHN5bmNocm9uaXplXG4gICAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbdGltZW91dEluU2Vjb25kc10gd2FpdCB0aW1lb3V0IGluIHNlY29uZHMsIGRlZmF1bHQgaXMgNW1cbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFtpbnRlcnZhbEluTWlsbGlzZWNvbmRzXSBpbnRlcnZhbCBiZXR3ZWVuIGFjY291bnQgcmVsb2FkcyB3aGlsZSB3YWl0aW5nIGZvciBhIGNoYW5nZSwgZGVmYXVsdCBpcyAxc1xuICAgKi9cblxuICAvKipcbiAgICogV2FpdHMgdW50aWwgc3luY2hyb25pemF0aW9uIHRvIE1ldGFUcmFkZXIgdGVybWluYWwgaXMgY29tcGxldGVkXG4gICAqIEBwYXJhbSB7U3luY2hyb25pemF0aW9uT3B0aW9uc30gb3B0cyBzeW5jaHJvbml6YXRpb24gb3B0aW9uc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gc3luY2hyb25pemF0aW9uIHRvIE1ldGFUcmFkZXIgdGVybWluYWwgaXMgY29tcGxldGVkXG4gICAqIEB0aHJvd3Mge1RpbWVvdXRFcnJvcn0gaWYgYXBwbGljYXRpb24gZmFpbGVkIHRvIHN5bmNocm9uaXplIHdpdGggdGhlIHRlbWluYWwgd2l0aGluIHRpbWVvdXQgYWxsb3dlZFxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbiAgYXN5bmMgd2FpdFN5bmNocm9uaXplZChvcHRzKSB7XG4gICAgdGhpcy5fY2hlY2tJc0Nvbm5lY3Rpb25BY3RpdmUoKTtcbiAgICByZXR1cm4gdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24ud2FpdFN5bmNocm9uaXplZChvcHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRdWV1ZXMgYW4gZXZlbnQgZm9yIHByb2Nlc3NpbmcgYW1vbmcgb3RoZXIgc3luY2hyb25pemF0aW9uIGV2ZW50cyB3aXRoaW4gc2FtZSBhY2NvdW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIGV2ZW50IGxhYmVsIG5hbWVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGFibGUgYXN5bmMgb3IgcmVndWxhciBmdW5jdGlvbiB0byBleGVjdXRlXG4gICAqL1xuICBxdWV1ZUV2ZW50KG5hbWUsIGNhbGxhYmxlKSB7XG4gICAgdGhpcy5fd2Vic29ja2V0Q2xpZW50LnF1ZXVlRXZlbnQodGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uYWNjb3VudC5pZCwgbmFtZSwgY2FsbGFibGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbi4gVGhlIGluc3RhbmNlIG9mIHRoZSBjbGFzcyBzaG91bGQgbm8gbG9uZ2VyIGJlIHVzZWQgYWZ0ZXIgdGhpcyBtZXRob2QgaXMgaW52b2tlZC5cbiAgICovXG4gIGFzeW5jIGNsb3NlKCkge1xuICAgIGlmICghdGhpcy5fY2xvc2VkKXtcbiAgICAgIGZvciAobGV0IGxpc3RlbmVyIG9mIHRoaXMuX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycykge1xuICAgICAgICB0aGlzLl93ZWJzb2NrZXRDbGllbnQucmVtb3ZlU3luY2hyb25pemF0aW9uTGlzdGVuZXIodGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uYWNjb3VudC5pZCwgbGlzdGVuZXIpO1xuICAgICAgfVxuICAgICAgdGhpcy5fY2xvc2VkID0gdHJ1ZTtcbiAgICAgIGF3YWl0IHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmNsb3NlKHRoaXMuaW5zdGFuY2VJZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3luY2hyb25pemF0aW9uIHN0YXR1c1xuICAgKiBAcmV0dXJuIHtib29sZWFufSBzeW5jaHJvbml6YXRpb24gc3RhdHVzXG4gICAqL1xuICBnZXQgc3luY2hyb25pemVkKCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5zeW5jaHJvbml6ZWQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBNZXRhQXBpIGFjY291bnRcbiAgICogQHJldHVybiB7TWV0YXRyYWRlckFjY291bnR9IE1ldGFBcGkgYWNjb3VudFxuICAgKi9cbiAgZ2V0IGFjY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBjb25uZWN0aW9uIGhlYWx0aCBtb25pdG9yIGluc3RhbmNlXG4gICAqIEByZXR1cm4ge0Nvbm5lY3Rpb25IZWFsdGhNb25pdG9yfSBjb25uZWN0aW9uIGhlYWx0aCBtb25pdG9yIGluc3RhbmNlXG4gICAqL1xuICBnZXQgaGVhbHRoTW9uaXRvcigpIHtcbiAgICByZXR1cm4gdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uaGVhbHRoTW9uaXRvcjtcbiAgfVxuXG59XG4iXSwibmFtZXMiOlsiVGVybWluYWxTdGF0ZSIsIkNvbm5lY3Rpb25IZWFsdGhNb25pdG9yIiwiTG9nZ2VyTWFuYWdlciIsIk1ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UiLCJTdHJlYW1pbmdNZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlIiwiY29ubmVjdCIsIl9vcGVuZWQiLCJfbWV0YUFwaUNvbm5lY3Rpb24iLCJpbnN0YW5jZUlkIiwiZXJyIiwiY2xvc2UiLCJyZW1vdmVBcHBsaWNhdGlvbiIsInN1YnNjcmliZVRvTWFya2V0RGF0YSIsInN5bWJvbCIsInN1YnNjcmlwdGlvbnMiLCJ0aW1lb3V0SW5TZWNvbmRzIiwid2FpdEZvclF1b3RlIiwiX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlIiwidW5zdWJzY3JpYmVGcm9tTWFya2V0RGF0YSIsInN1YnNjcmliZWRTeW1ib2xzIiwic2F2ZVVwdGltZSIsInVwdGltZSIsIl93ZWJzb2NrZXRDbGllbnQiLCJhY2NvdW50IiwiaWQiLCJ0ZXJtaW5hbFN0YXRlIiwiaGlzdG9yeVN0b3JhZ2UiLCJhZGRTeW5jaHJvbml6YXRpb25MaXN0ZW5lciIsImxpc3RlbmVyIiwiX3N5bmNocm9uaXphdGlvbkxpc3RlbmVycyIsInB1c2giLCJyZW1vdmVTeW5jaHJvbml6YXRpb25MaXN0ZW5lciIsImZpbHRlciIsImwiLCJ3YWl0U3luY2hyb25pemVkIiwib3B0cyIsInF1ZXVlRXZlbnQiLCJuYW1lIiwiY2FsbGFibGUiLCJfY2xvc2VkIiwic3luY2hyb25pemVkIiwiaGVhbHRoTW9uaXRvciIsImNvbnN0cnVjdG9yIiwid2Vic29ja2V0Q2xpZW50IiwibWV0YUFwaUNvbm5lY3Rpb24iLCJfbG9nZ2VyIiwiZ2V0TG9nZ2VyIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsT0FBT0EsbUJBQW1CLGtCQUFrQjtBQUM1QyxPQUFPQyw2QkFBNkIsNEJBQTRCO0FBQ2hFLE9BQU9DLG1CQUFtQixZQUFZO0FBQ3RDLE9BQU9DLCtCQUErQiw4QkFBOEI7QUFLckQsSUFBQSxBQUFNQyxxQ0FBTixNQUFNQSwyQ0FBMkNEO0lBYzlEOzs7R0FH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