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)

137 lines (136 loc) 24.7 kB
'use strict'; import HttpClient from '../clients/httpClient'; import ProvisioningProfileClient from '../clients/metaApi/provisioningProfile.client'; import ProvisioningProfileApi from './provisioningProfileApi'; import MetaApiWebsocketClient from '../clients/metaApi/metaApiWebsocket.client'; import MetatraderAccountApi from './metatraderAccountApi'; import MetatraderAccountClient from '../clients/metaApi/metatraderAccount.client'; import MetatraderAccountGeneratorApi from './metatraderAccountGeneratorApi'; import MetatraderAccountGeneratorClient from '../clients/metaApi/metatraderAccountGenerator.client'; import HistoricalMarketDataClient from '../clients/metaApi/historicalMarketData.client'; import ClientApiClient from '../clients/metaApi/clientApi.client'; import ConnectionRegistry from './connectionRegistry'; import { ValidationError } from '../clients/errorHandler'; import OptionsValidator from '../clients/optionsValidator'; import LatencyMonitor from './latencyMonitor'; import ExpertAdvisorClient from '../clients/metaApi/expertAdvisor.client'; import LoggerManager from '../logger'; import DomainClient from '../clients/domain.client'; import TerminalHashManager from './terminalHashManager'; import TokenManagementClient from '../clients/metaApi/tokenManagement.client'; import TokenManagementApi from './tokenManagementApi'; import _ from 'lodash'; let MetaApi = class MetaApi { /** * Enables using Log4js logger with extended log levels for debugging instead of * console.* functions. Note that log4js configuration performed by the user. */ static enableLog4jsLogging() { LoggerManager.useLog4js(); } /** * Returns provisioning profile API * @returns {ProvisioningProfileApi} provisioning profile API */ get provisioningProfileApi() { return this._provisioningProfileApi; } /** * Returns MetaTrader account API * @return {MetatraderAccountApi} MetaTrader account API */ get metatraderAccountApi() { return this._metatraderAccountApi; } /** * Returns MetaTrader account generator API * @return {MetatraderDemoAccountApi} MetaTrader account generator API */ get metatraderAccountGeneratorApi() { return this._metatraderAccountGeneratorApi; } /** * Returns MetaApi application latency monitor * @return {LatencyMonitor} latency monitor */ get latencyMonitor() { return this._latencyMonitor; } /** * Returns token management API * @returns {TokenManagementApi} token management API */ get tokenManagementApi() { return this._tokenManagementApi; } /** * Closes all clients and connections and stops all internal jobs */ close() { this._metaApiWebsocketClient.removeLatencyListener(this._latencyMonitor); this._metaApiWebsocketClient.close(); this._metaApiWebsocketClient.stop(); this._terminalHashManager._stop(); } /** * Constructs MetaApi class instance * @param {String} token authorization token * @param {MetaApiOpts} opts application options */ // eslint-disable-next-line complexity constructor(token, opts){ const validator = new OptionsValidator(); opts = _.omit(opts || {}, [ 'connections' ]); const application = opts.application || 'MetaApi'; const domain = opts.domain || 'agiliumtrade.agiliumtrade.ai'; const requestTimeout = validator.validateNonZero(opts.requestTimeout, 60, 'requestTimeout'); const historicalMarketDataRequestTimeout = validator.validateNonZero(opts.historicalMarketDataRequestTimeout, 240, 'historicalMarketDataRequestTimeout'); const connectTimeout = validator.validateNonZero(opts.connectTimeout, 60, 'connectTimeout'); const packetOrderingTimeout = validator.validateNonZero(opts.packetOrderingTimeout, 60, 'packetOrderingTimeout'); const retryOpts = opts.retryOpts || {}; const packetLogger = opts.packetLogger || {}; const synchronizationThrottler = opts.synchronizationThrottler || {}; const accountGeneratorRequestTimeout = validator.validateNonZero(opts.accountGeneratorRequestTimeout, 240, 'accountGeneratorRequestTimeout'); if (!application.match(/[a-zA-Z0-9_]+/)) { throw new ValidationError('Application name must be non-empty string consisting from letters, digits and _ only'); } const useSharedClientApi = opts.useSharedClientApi || false; const refreshSubscriptionsOpts = opts.refreshSubscriptionsOpts || {}; const httpClient = new HttpClient(requestTimeout, retryOpts); const domainClient = new DomainClient(httpClient, token, domain); const historicalMarketDataHttpClient = new HttpClient(historicalMarketDataRequestTimeout, retryOpts); const accountGeneratorHttpClient = new HttpClient(accountGeneratorRequestTimeout, retryOpts); const clientApiClient = new ClientApiClient(httpClient, domainClient); const tokenManagmentClient = new TokenManagementClient(httpClient, domainClient); this._terminalHashManager = new TerminalHashManager(clientApiClient, opts.keepHashTrees); this._metaApiWebsocketClient = new MetaApiWebsocketClient(this, domainClient, token, { application, domain, requestTimeout, connectTimeout, packetLogger, packetOrderingTimeout, synchronizationThrottler, retryOpts, useSharedClientApi, region: opts.region, unsubscribeThrottlingIntervalInSeconds: opts.unsubscribeThrottlingIntervalInSeconds, useNativeSocketIoServer: opts.useNativeSocketIoServer }); this._provisioningProfileApi = new ProvisioningProfileApi(new ProvisioningProfileClient(httpClient, domainClient)); this._connectionRegistry = new ConnectionRegistry(opts, this._metaApiWebsocketClient, this._terminalHashManager, application, refreshSubscriptionsOpts); let historicalMarketDataClient = new HistoricalMarketDataClient(historicalMarketDataHttpClient, domainClient); this._metatraderAccountApi = new MetatraderAccountApi(new MetatraderAccountClient(httpClient, domainClient), this._metaApiWebsocketClient, this._connectionRegistry, new ExpertAdvisorClient(httpClient, domainClient), historicalMarketDataClient, application); this._metatraderAccountGeneratorApi = new MetatraderAccountGeneratorApi(new MetatraderAccountGeneratorClient(accountGeneratorHttpClient, domainClient)); this._tokenManagementApi = new TokenManagementApi(tokenManagmentClient); if (opts.enableLatencyTracking || opts.enableLatencyMonitor) { this._latencyMonitor = new LatencyMonitor(); this._metaApiWebsocketClient.addLatencyListener(this._latencyMonitor); } this._logger = LoggerManager.getLogger('MetaAPI'); if (process.env.IS_BROWSER) { if (!this._tokenManagementApi.areTokenResourcesNarrowedDown(token)) { this._logger.warn('USING THE ADMIN TOKEN'); this._logger.info('It seems like you are using a admin API token. Since the token can be retrieven from the browser or ' + 'mobile apps by end user this can lead to your application being compromised, unless you understand what ' + 'are you doing. Please use Token Management API ' + '(https://github.com/metaapi/metaapi-javascript-sdk/blob/master/docs/tokenManagementApi.md) in your ' + 'backend application to produce secure tokens which you can then use in web UI or mobile apps.'); } } } }; /** * MetaApi MetaTrader API SDK */ export { MetaApi as default }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBIdHRwQ2xpZW50IGZyb20gJy4uL2NsaWVudHMvaHR0cENsaWVudCc7XG5pbXBvcnQgUHJvdmlzaW9uaW5nUHJvZmlsZUNsaWVudCBmcm9tICcuLi9jbGllbnRzL21ldGFBcGkvcHJvdmlzaW9uaW5nUHJvZmlsZS5jbGllbnQnO1xuaW1wb3J0IFByb3Zpc2lvbmluZ1Byb2ZpbGVBcGkgZnJvbSAnLi9wcm92aXNpb25pbmdQcm9maWxlQXBpJztcbmltcG9ydCBNZXRhQXBpV2Vic29ja2V0Q2xpZW50IGZyb20gJy4uL2NsaWVudHMvbWV0YUFwaS9tZXRhQXBpV2Vic29ja2V0LmNsaWVudCc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRBcGkgZnJvbSAnLi9tZXRhdHJhZGVyQWNjb3VudEFwaSc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRDbGllbnQgZnJvbSAnLi4vY2xpZW50cy9tZXRhQXBpL21ldGF0cmFkZXJBY2NvdW50LmNsaWVudCc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JBcGkgZnJvbSAnLi9tZXRhdHJhZGVyQWNjb3VudEdlbmVyYXRvckFwaSc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JDbGllbnQgZnJvbSAnLi4vY2xpZW50cy9tZXRhQXBpL21ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yLmNsaWVudCc7XG5pbXBvcnQgSGlzdG9yaWNhbE1hcmtldERhdGFDbGllbnQgZnJvbSAnLi4vY2xpZW50cy9tZXRhQXBpL2hpc3RvcmljYWxNYXJrZXREYXRhLmNsaWVudCc7XG5pbXBvcnQgQ2xpZW50QXBpQ2xpZW50IGZyb20gJy4uL2NsaWVudHMvbWV0YUFwaS9jbGllbnRBcGkuY2xpZW50JztcbmltcG9ydCBDb25uZWN0aW9uUmVnaXN0cnkgZnJvbSAnLi9jb25uZWN0aW9uUmVnaXN0cnknO1xuaW1wb3J0IHtWYWxpZGF0aW9uRXJyb3J9IGZyb20gJy4uL2NsaWVudHMvZXJyb3JIYW5kbGVyJztcbmltcG9ydCBPcHRpb25zVmFsaWRhdG9yIGZyb20gJy4uL2NsaWVudHMvb3B0aW9uc1ZhbGlkYXRvcic7XG5pbXBvcnQgTGF0ZW5jeU1vbml0b3IgZnJvbSAnLi9sYXRlbmN5TW9uaXRvcic7XG5pbXBvcnQgRXhwZXJ0QWR2aXNvckNsaWVudCBmcm9tICcuLi9jbGllbnRzL21ldGFBcGkvZXhwZXJ0QWR2aXNvci5jbGllbnQnO1xuaW1wb3J0IExvZ2dlck1hbmFnZXIgZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCBEb21haW5DbGllbnQgZnJvbSAnLi4vY2xpZW50cy9kb21haW4uY2xpZW50JztcbmltcG9ydCBUZXJtaW5hbEhhc2hNYW5hZ2VyIGZyb20gJy4vdGVybWluYWxIYXNoTWFuYWdlcic7XG5pbXBvcnQgVG9rZW5NYW5hZ2VtZW50Q2xpZW50IGZyb20gJy4uL2NsaWVudHMvbWV0YUFwaS90b2tlbk1hbmFnZW1lbnQuY2xpZW50JztcbmltcG9ydCBUb2tlbk1hbmFnZW1lbnRBcGkgZnJvbSAnLi90b2tlbk1hbmFnZW1lbnRBcGknO1xuaW1wb3J0IHtNZXRhQXBpT3B0c30gZnJvbSAnLi9tZXRhQXBpJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5cbi8qKlxuICogTWV0YUFwaSBNZXRhVHJhZGVyIEFQSSBTREtcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWV0YUFwaSB7XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgdXNpbmcgTG9nNGpzIGxvZ2dlciB3aXRoIGV4dGVuZGVkIGxvZyBsZXZlbHMgZm9yIGRlYnVnZ2luZyBpbnN0ZWFkIG9mXG4gICAqIGNvbnNvbGUuKiBmdW5jdGlvbnMuIE5vdGUgdGhhdCBsb2c0anMgY29uZmlndXJhdGlvbiBwZXJmb3JtZWQgYnkgdGhlIHVzZXIuXG4gICAqL1xuICBzdGF0aWMgZW5hYmxlTG9nNGpzTG9nZ2luZygpIHtcbiAgICBMb2dnZXJNYW5hZ2VyLnVzZUxvZzRqcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgTWV0YUFwaSBjbGFzcyBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gdG9rZW4gYXV0aG9yaXphdGlvbiB0b2tlblxuICAgKiBAcGFyYW0ge01ldGFBcGlPcHRzfSBvcHRzIGFwcGxpY2F0aW9uIG9wdGlvbnNcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG4gIGNvbnN0cnVjdG9yKHRva2VuLCBvcHRzKSB7XG4gICAgY29uc3QgdmFsaWRhdG9yID0gbmV3IE9wdGlvbnNWYWxpZGF0b3IoKTtcbiAgICBvcHRzID0gXy5vbWl0KG9wdHMgfHwge30sIFsnY29ubmVjdGlvbnMnXSk7XG4gICAgY29uc3QgYXBwbGljYXRpb24gPSBvcHRzLmFwcGxpY2F0aW9uIHx8ICdNZXRhQXBpJztcbiAgICBjb25zdCBkb21haW4gPSBvcHRzLmRvbWFpbiB8fCAnYWdpbGl1bXRyYWRlLmFnaWxpdW10cmFkZS5haSc7XG4gICAgY29uc3QgcmVxdWVzdFRpbWVvdXQgPSB2YWxpZGF0b3IudmFsaWRhdGVOb25aZXJvKG9wdHMucmVxdWVzdFRpbWVvdXQsIDYwLCAncmVxdWVzdFRpbWVvdXQnKTtcbiAgICBjb25zdCBoaXN0b3JpY2FsTWFya2V0RGF0YVJlcXVlc3RUaW1lb3V0ID0gdmFsaWRhdG9yLnZhbGlkYXRlTm9uWmVybyhcbiAgICAgIG9wdHMuaGlzdG9yaWNhbE1hcmtldERhdGFSZXF1ZXN0VGltZW91dCwgMjQwLCAnaGlzdG9yaWNhbE1hcmtldERhdGFSZXF1ZXN0VGltZW91dCcpO1xuICAgIGNvbnN0IGNvbm5lY3RUaW1lb3V0ID0gdmFsaWRhdG9yLnZhbGlkYXRlTm9uWmVybyhvcHRzLmNvbm5lY3RUaW1lb3V0LCA2MCwgJ2Nvbm5lY3RUaW1lb3V0Jyk7XG4gICAgY29uc3QgcGFja2V0T3JkZXJpbmdUaW1lb3V0ID0gdmFsaWRhdG9yLnZhbGlkYXRlTm9uWmVybyhvcHRzLnBhY2tldE9yZGVyaW5nVGltZW91dCwgNjAsICdwYWNrZXRPcmRlcmluZ1RpbWVvdXQnKTtcbiAgICBjb25zdCByZXRyeU9wdHMgPSBvcHRzLnJldHJ5T3B0cyB8fCB7fTtcbiAgICBjb25zdCBwYWNrZXRMb2dnZXIgPSBvcHRzLnBhY2tldExvZ2dlciB8fCB7fTtcbiAgICBjb25zdCBzeW5jaHJvbml6YXRpb25UaHJvdHRsZXIgPSBvcHRzLnN5bmNocm9uaXphdGlvblRocm90dGxlciB8fCB7fTtcbiAgICBjb25zdCBhY2NvdW50R2VuZXJhdG9yUmVxdWVzdFRpbWVvdXQgPSB2YWxpZGF0b3IudmFsaWRhdGVOb25aZXJvKG9wdHMuYWNjb3VudEdlbmVyYXRvclJlcXVlc3RUaW1lb3V0LCAyNDAsXG4gICAgICAnYWNjb3VudEdlbmVyYXRvclJlcXVlc3RUaW1lb3V0Jyk7XG4gICAgaWYgKCFhcHBsaWNhdGlvbi5tYXRjaCgvW2EtekEtWjAtOV9dKy8pKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdBcHBsaWNhdGlvbiBuYW1lIG11c3QgYmUgbm9uLWVtcHR5IHN0cmluZyBjb25zaXN0aW5nIGZyb20gbGV0dGVycywgZGlnaXRzIGFuZCBfIG9ubHknKTtcbiAgICB9XG4gICAgY29uc3QgdXNlU2hhcmVkQ2xpZW50QXBpID0gb3B0cy51c2VTaGFyZWRDbGllbnRBcGkgfHwgZmFsc2U7XG4gICAgY29uc3QgcmVmcmVzaFN1YnNjcmlwdGlvbnNPcHRzID0gb3B0cy5yZWZyZXNoU3Vic2NyaXB0aW9uc09wdHMgfHwge307XG4gICAgY29uc3QgaHR0cENsaWVudCA9IG5ldyBIdHRwQ2xpZW50KHJlcXVlc3RUaW1lb3V0LCByZXRyeU9wdHMpO1xuICAgIGNvbnN0IGRvbWFpbkNsaWVudCA9IG5ldyBEb21haW5DbGllbnQoaHR0cENsaWVudCwgdG9rZW4sIGRvbWFpbik7XG4gICAgY29uc3QgaGlzdG9yaWNhbE1hcmtldERhdGFIdHRwQ2xpZW50ID0gbmV3IEh0dHBDbGllbnQoaGlzdG9yaWNhbE1hcmtldERhdGFSZXF1ZXN0VGltZW91dCwgcmV0cnlPcHRzKTtcbiAgICBjb25zdCBhY2NvdW50R2VuZXJhdG9ySHR0cENsaWVudCA9IG5ldyBIdHRwQ2xpZW50KGFjY291bnRHZW5lcmF0b3JSZXF1ZXN0VGltZW91dCwgcmV0cnlPcHRzKTtcbiAgICBjb25zdCBjbGllbnRBcGlDbGllbnQgPSBuZXcgQ2xpZW50QXBpQ2xpZW50KGh0dHBDbGllbnQsIGRvbWFpbkNsaWVudCk7IFxuICAgIGNvbnN0IHRva2VuTWFuYWdtZW50Q2xpZW50ID0gbmV3IFRva2VuTWFuYWdlbWVudENsaWVudChodHRwQ2xpZW50LCBkb21haW5DbGllbnQpOyBcbiAgICB0aGlzLl90ZXJtaW5hbEhhc2hNYW5hZ2VyID0gbmV3IFRlcm1pbmFsSGFzaE1hbmFnZXIoY2xpZW50QXBpQ2xpZW50LCBvcHRzLmtlZXBIYXNoVHJlZXMpO1xuICAgIHRoaXMuX21ldGFBcGlXZWJzb2NrZXRDbGllbnQgPSBuZXcgTWV0YUFwaVdlYnNvY2tldENsaWVudCh0aGlzLCBkb21haW5DbGllbnQsIHRva2VuLCB7XG4gICAgICBhcHBsaWNhdGlvbiwgZG9tYWluLFxuICAgICAgcmVxdWVzdFRpbWVvdXQsIGNvbm5lY3RUaW1lb3V0LCBwYWNrZXRMb2dnZXIsIHBhY2tldE9yZGVyaW5nVGltZW91dCwgc3luY2hyb25pemF0aW9uVGhyb3R0bGVyLCByZXRyeU9wdHMsXG4gICAgICB1c2VTaGFyZWRDbGllbnRBcGksIHJlZ2lvbjogb3B0cy5yZWdpb24sXG4gICAgICB1bnN1YnNjcmliZVRocm90dGxpbmdJbnRlcnZhbEluU2Vjb25kczogb3B0cy51bnN1YnNjcmliZVRocm90dGxpbmdJbnRlcnZhbEluU2Vjb25kcyxcbiAgICAgIHVzZU5hdGl2ZVNvY2tldElvU2VydmVyOiBvcHRzLnVzZU5hdGl2ZVNvY2tldElvU2VydmVyXG4gICAgfSk7XG4gICAgdGhpcy5fcHJvdmlzaW9uaW5nUHJvZmlsZUFwaSA9IG5ldyBQcm92aXNpb25pbmdQcm9maWxlQXBpKG5ldyBQcm92aXNpb25pbmdQcm9maWxlQ2xpZW50KGh0dHBDbGllbnQsIGRvbWFpbkNsaWVudCkpO1xuICAgIHRoaXMuX2Nvbm5lY3Rpb25SZWdpc3RyeSA9IG5ldyBDb25uZWN0aW9uUmVnaXN0cnkob3B0cywgdGhpcy5fbWV0YUFwaVdlYnNvY2tldENsaWVudCwgdGhpcy5fdGVybWluYWxIYXNoTWFuYWdlcixcbiAgICAgIGFwcGxpY2F0aW9uLCByZWZyZXNoU3Vic2NyaXB0aW9uc09wdHMpO1xuICAgIGxldCBoaXN0b3JpY2FsTWFya2V0RGF0YUNsaWVudCA9IG5ldyBIaXN0b3JpY2FsTWFya2V0RGF0YUNsaWVudChoaXN0b3JpY2FsTWFya2V0RGF0YUh0dHBDbGllbnQsIGRvbWFpbkNsaWVudCk7XG4gICAgdGhpcy5fbWV0YXRyYWRlckFjY291bnRBcGkgPSBuZXcgTWV0YXRyYWRlckFjY291bnRBcGkobmV3IE1ldGF0cmFkZXJBY2NvdW50Q2xpZW50KGh0dHBDbGllbnQsIGRvbWFpbkNsaWVudCksXG4gICAgICB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LCB0aGlzLl9jb25uZWN0aW9uUmVnaXN0cnksIFxuICAgICAgbmV3IEV4cGVydEFkdmlzb3JDbGllbnQoaHR0cENsaWVudCwgZG9tYWluQ2xpZW50KSwgaGlzdG9yaWNhbE1hcmtldERhdGFDbGllbnQsIGFwcGxpY2F0aW9uKTtcbiAgICB0aGlzLl9tZXRhdHJhZGVyQWNjb3VudEdlbmVyYXRvckFwaSA9IG5ldyBNZXRhdHJhZGVyQWNjb3VudEdlbmVyYXRvckFwaShcbiAgICAgIG5ldyBNZXRhdHJhZGVyQWNjb3VudEdlbmVyYXRvckNsaWVudChhY2NvdW50R2VuZXJhdG9ySHR0cENsaWVudCwgZG9tYWluQ2xpZW50KSk7XG4gICAgdGhpcy5fdG9rZW5NYW5hZ2VtZW50QXBpID0gbmV3IFRva2VuTWFuYWdlbWVudEFwaSh0b2tlbk1hbmFnbWVudENsaWVudCk7XG4gICAgaWYgKG9wdHMuZW5hYmxlTGF0ZW5jeVRyYWNraW5nIHx8IG9wdHMuZW5hYmxlTGF0ZW5jeU1vbml0b3IpIHtcbiAgICAgIHRoaXMuX2xhdGVuY3lNb25pdG9yID0gbmV3IExhdGVuY3lNb25pdG9yKCk7XG4gICAgICB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LmFkZExhdGVuY3lMaXN0ZW5lcih0aGlzLl9sYXRlbmN5TW9uaXRvcik7XG4gICAgfVxuICAgIFxuICAgIHRoaXMuX2xvZ2dlciA9IExvZ2dlck1hbmFnZXIuZ2V0TG9nZ2VyKCdNZXRhQVBJJyk7XG4gICAgaWYgKHByb2Nlc3MuZW52LklTX0JST1dTRVIpIHtcbiAgICAgIGlmICghdGhpcy5fdG9rZW5NYW5hZ2VtZW50QXBpLmFyZVRva2VuUmVzb3VyY2VzTmFycm93ZWREb3duKHRva2VuKSkge1xuICAgICAgICB0aGlzLl9sb2dnZXIud2FybignVVNJTkcgVEhFIEFETUlOIFRPS0VOJyk7XG4gICAgICAgIHRoaXMuX2xvZ2dlci5pbmZvKFxuICAgICAgICAgICdJdCBzZWVtcyBsaWtlIHlvdSBhcmUgdXNpbmcgYSBhZG1pbiBBUEkgdG9rZW4uIFNpbmNlIHRoZSB0b2tlbiBjYW4gYmUgcmV0cmlldmVuIGZyb20gdGhlIGJyb3dzZXIgb3IgJyArXG4gICAgICAgICAgJ21vYmlsZSBhcHBzIGJ5IGVuZCB1c2VyIHRoaXMgY2FuIGxlYWQgdG8geW91ciBhcHBsaWNhdGlvbiBiZWluZyBjb21wcm9taXNlZCwgdW5sZXNzIHlvdSB1bmRlcnN0YW5kIHdoYXQgJyArXG4gICAgICAgICAgJ2FyZSB5b3UgZG9pbmcuIFBsZWFzZSB1c2UgVG9rZW4gTWFuYWdlbWVudCBBUEkgJyArXG4gICAgICAgICAgJyhodHRwczovL2dpdGh1Yi5jb20vbWV0YWFwaS9tZXRhYXBpLWphdmFzY3JpcHQtc2RrL2Jsb2IvbWFzdGVyL2RvY3MvdG9rZW5NYW5hZ2VtZW50QXBpLm1kKSBpbiB5b3VyICcgK1xuICAgICAgICAgICdiYWNrZW5kIGFwcGxpY2F0aW9uIHRvIHByb2R1Y2Ugc2VjdXJlIHRva2VucyB3aGljaCB5b3UgY2FuIHRoZW4gdXNlIGluIHdlYiBVSSBvciBtb2JpbGUgYXBwcy4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgcHJvdmlzaW9uaW5nIHByb2ZpbGUgQVBJXG4gICAqIEByZXR1cm5zIHtQcm92aXNpb25pbmdQcm9maWxlQXBpfSBwcm92aXNpb25pbmcgcHJvZmlsZSBBUElcbiAgICovXG4gIGdldCBwcm92aXNpb25pbmdQcm9maWxlQXBpKCkge1xuICAgIHJldHVybiB0aGlzLl9wcm92aXNpb25pbmdQcm9maWxlQXBpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgTWV0YVRyYWRlciBhY2NvdW50IEFQSVxuICAgKiBAcmV0dXJuIHtNZXRhdHJhZGVyQWNjb3VudEFwaX0gTWV0YVRyYWRlciBhY2NvdW50IEFQSVxuICAgKi9cbiAgZ2V0IG1ldGF0cmFkZXJBY2NvdW50QXBpKCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhdHJhZGVyQWNjb3VudEFwaTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIE1ldGFUcmFkZXIgYWNjb3VudCBnZW5lcmF0b3IgQVBJXG4gICAqIEByZXR1cm4ge01ldGF0cmFkZXJEZW1vQWNjb3VudEFwaX0gTWV0YVRyYWRlciBhY2NvdW50IGdlbmVyYXRvciBBUElcbiAgICovXG4gIGdldCBtZXRhdHJhZGVyQWNjb3VudEdlbmVyYXRvckFwaSgpIHtcbiAgICByZXR1cm4gdGhpcy5fbWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JBcGk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBNZXRhQXBpIGFwcGxpY2F0aW9uIGxhdGVuY3kgbW9uaXRvclxuICAgKiBAcmV0dXJuIHtMYXRlbmN5TW9uaXRvcn0gbGF0ZW5jeSBtb25pdG9yXG4gICAqL1xuICBnZXQgbGF0ZW5jeU1vbml0b3IoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xhdGVuY3lNb25pdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdG9rZW4gbWFuYWdlbWVudCBBUElcbiAgICogQHJldHVybnMge1Rva2VuTWFuYWdlbWVudEFwaX0gdG9rZW4gbWFuYWdlbWVudCBBUElcbiAgICovXG4gIGdldCB0b2tlbk1hbmFnZW1lbnRBcGkoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Rva2VuTWFuYWdlbWVudEFwaTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgYWxsIGNsaWVudHMgYW5kIGNvbm5lY3Rpb25zIGFuZCBzdG9wcyBhbGwgaW50ZXJuYWwgam9ic1xuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgdGhpcy5fbWV0YUFwaVdlYnNvY2tldENsaWVudC5yZW1vdmVMYXRlbmN5TGlzdGVuZXIodGhpcy5fbGF0ZW5jeU1vbml0b3IpO1xuICAgIHRoaXMuX21ldGFBcGlXZWJzb2NrZXRDbGllbnQuY2xvc2UoKTtcbiAgICB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LnN0b3AoKTtcbiAgICB0aGlzLl90ZXJtaW5hbEhhc2hNYW5hZ2VyLl9zdG9wKCk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJIdHRwQ2xpZW50IiwiUHJvdmlzaW9uaW5nUHJvZmlsZUNsaWVudCIsIlByb3Zpc2lvbmluZ1Byb2ZpbGVBcGkiLCJNZXRhQXBpV2Vic29ja2V0Q2xpZW50IiwiTWV0YXRyYWRlckFjY291bnRBcGkiLCJNZXRhdHJhZGVyQWNjb3VudENsaWVudCIsIk1ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yQXBpIiwiTWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JDbGllbnQiLCJIaXN0b3JpY2FsTWFya2V0RGF0YUNsaWVudCIsIkNsaWVudEFwaUNsaWVudCIsIkNvbm5lY3Rpb25SZWdpc3RyeSIsIlZhbGlkYXRpb25FcnJvciIsIk9wdGlvbnNWYWxpZGF0b3IiLCJMYXRlbmN5TW9uaXRvciIsIkV4cGVydEFkdmlzb3JDbGllbnQiLCJMb2dnZXJNYW5hZ2VyIiwiRG9tYWluQ2xpZW50IiwiVGVybWluYWxIYXNoTWFuYWdlciIsIlRva2VuTWFuYWdlbWVudENsaWVudCIsIlRva2VuTWFuYWdlbWVudEFwaSIsIl8iLCJNZXRhQXBpIiwiZW5hYmxlTG9nNGpzTG9nZ2luZyIsInVzZUxvZzRqcyIsInByb3Zpc2lvbmluZ1Byb2ZpbGVBcGkiLCJfcHJvdmlzaW9uaW5nUHJvZmlsZUFwaSIsIm1ldGF0cmFkZXJBY2NvdW50QXBpIiwiX21ldGF0cmFkZXJBY2NvdW50QXBpIiwibWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JBcGkiLCJfbWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JBcGkiLCJsYXRlbmN5TW9uaXRvciIsIl9sYXRlbmN5TW9uaXRvciIsInRva2VuTWFuYWdlbWVudEFwaSIsIl90b2tlbk1hbmFnZW1lbnRBcGkiLCJjbG9zZSIsIl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50IiwicmVtb3ZlTGF0ZW5jeUxpc3RlbmVyIiwic3RvcCIsIl90ZXJtaW5hbEhhc2hNYW5hZ2VyIiwiX3N0b3AiLCJjb25zdHJ1Y3RvciIsInRva2VuIiwib3B0cyIsInZhbGlkYXRvciIsIm9taXQiLCJhcHBsaWNhdGlvbiIsImRvbWFpbiIsInJlcXVlc3RUaW1lb3V0IiwidmFsaWRhdGVOb25aZXJvIiwiaGlzdG9yaWNhbE1hcmtldERhdGFSZXF1ZXN0VGltZW91dCIsImNvbm5lY3RUaW1lb3V0IiwicGFja2V0T3JkZXJpbmdUaW1lb3V0IiwicmV0cnlPcHRzIiwicGFja2V0TG9nZ2VyIiwic3luY2hyb25pemF0aW9uVGhyb3R0bGVyIiwiYWNjb3VudEdlbmVyYXRvclJlcXVlc3RUaW1lb3V0IiwibWF0Y2giLCJ1c2VTaGFyZWRDbGllbnRBcGkiLCJyZWZyZXNoU3Vic2NyaXB0aW9uc09wdHMiLCJodHRwQ2xpZW50IiwiZG9tYWluQ2xpZW50IiwiaGlzdG9yaWNhbE1hcmtldERhdGFIdHRwQ2xpZW50IiwiYWNjb3VudEdlbmVyYXRvckh0dHBDbGllbnQiLCJjbGllbnRBcGlDbGllbnQiLCJ0b2tlbk1hbmFnbWVudENsaWVudCIsImtlZXBIYXNoVHJlZXMiLCJyZWdpb24iLCJ1bnN1YnNjcmliZVRocm90dGxpbmdJbnRlcnZhbEluU2Vjb25kcyIsInVzZU5hdGl2ZVNvY2tldElvU2VydmVyIiwiX2Nvbm5lY3Rpb25SZWdpc3RyeSIsImhpc3RvcmljYWxNYXJrZXREYXRhQ2xpZW50IiwiZW5hYmxlTGF0ZW5jeVRyYWNraW5nIiwiZW5hYmxlTGF0ZW5jeU1vbml0b3IiLCJhZGRMYXRlbmN5TGlzdGVuZXIiLCJfbG9nZ2VyIiwiZ2V0TG9nZ2VyIiwicHJvY2VzcyIsImVudiIsIklTX0JST1dTRVIiLCJhcmVUb2tlblJlc291cmNlc05hcnJvd2VkRG93biIsIndhcm4iLCJpbmZvIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUVBLE9BQU9BLGdCQUFnQix3QkFBd0I7QUFDL0MsT0FBT0MsK0JBQStCLGdEQUFnRDtBQUN0RixPQUFPQyw0QkFBNEIsMkJBQTJCO0FBQzlELE9BQU9DLDRCQUE0Qiw2Q0FBNkM7QUFDaEYsT0FBT0MsMEJBQTBCLHlCQUF5QjtBQUMxRCxPQUFPQyw2QkFBNkIsOENBQThDO0FBQ2xGLE9BQU9DLG1DQUFtQyxrQ0FBa0M7QUFDNUUsT0FBT0Msc0NBQXNDLHVEQUF1RDtBQUNwRyxPQUFPQyxnQ0FBZ0MsaURBQWlEO0FBQ3hGLE9BQU9DLHFCQUFxQixzQ0FBc0M7QUFDbEUsT0FBT0Msd0JBQXdCLHVCQUF1QjtBQUN0RCxTQUFRQyxlQUFlLFFBQU8sMEJBQTBCO0FBQ3hELE9BQU9DLHNCQUFzQiw4QkFBOEI7QUFDM0QsT0FBT0Msb0JBQW9CLG1CQUFtQjtBQUM5QyxPQUFPQyx5QkFBeUIsMENBQTBDO0FBQzFFLE9BQU9DLG1CQUFtQixZQUFZO0FBQ3RDLE9BQU9DLGtCQUFrQiwyQkFBMkI7QUFDcEQsT0FBT0MseUJBQXlCLHdCQUF3QjtBQUN4RCxPQUFPQywyQkFBMkIsNENBQTRDO0FBQzlFLE9BQU9DLHdCQUF3Qix1QkFBdUI7QUFFdEQsT0FBT0MsT0FBTyxTQUFTO0FBS1IsSUFBQSxBQUFNQyxVQUFOLE1BQU1BO0lBRW5COzs7R0FHQyxHQUNELE9BQU9DLHNCQUFzQjtRQUMzQlAsY0FBY1EsU0FBUztJQUN6QjtJQXdFQTs7O0dBR0MsR0FDRCxJQUFJQyx5QkFBeUI7UUFDM0IsT0FBTyxJQUFJLENBQUNDLHVCQUF1QjtJQUNyQztJQUVBOzs7R0FHQyxHQUNELElBQUlDLHVCQUF1QjtRQUN6QixPQUFPLElBQUksQ0FBQ0MscUJBQXFCO0lBQ25DO0lBRUE7OztHQUdDLEdBQ0QsSUFBSUMsZ0NBQWdDO1FBQ2xDLE9BQU8sSUFBSSxDQUFDQyw4QkFBOEI7SUFDNUM7SUFFQTs7O0dBR0MsR0FDRCxJQUFJQyxpQkFBaUI7UUFDbkIsT0FBTyxJQUFJLENBQUNDLGVBQWU7SUFDN0I7SUFFQTs7O0dBR0MsR0FDRCxJQUFJQyxxQkFBcUI7UUFDdkIsT0FBTyxJQUFJLENBQUNDLG1CQUFtQjtJQUNqQztJQUVBOztHQUVDLEdBQ0RDLFFBQVE7UUFDTixJQUFJLENBQUNDLHVCQUF1QixDQUFDQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUNMLGVBQWU7UUFDdkUsSUFBSSxDQUFDSSx1QkFBdUIsQ0FBQ0QsS0FBSztRQUNsQyxJQUFJLENBQUNDLHVCQUF1QixDQUFDRSxJQUFJO1FBQ2pDLElBQUksQ0FBQ0Msb0JBQW9CLENBQUNDLEtBQUs7SUFDakM7SUF0SEE7Ozs7R0FJQyxHQUNELHNDQUFzQztJQUN0Q0MsWUFBWUMsS0FBSyxFQUFFQyxJQUFJLENBQUU7UUFDdkIsTUFBTUMsWUFBWSxJQUFJL0I7UUFDdEI4QixPQUFPdEIsRUFBRXdCLElBQUksQ0FBQ0YsUUFBUSxDQUFDLEdBQUc7WUFBQztTQUFjO1FBQ3pDLE1BQU1HLGNBQWNILEtBQUtHLFdBQVcsSUFBSTtRQUN4QyxNQUFNQyxTQUFTSixLQUFLSSxNQUFNLElBQUk7UUFDOUIsTUFBTUMsaUJBQWlCSixVQUFVSyxlQUFlLENBQUNOLEtBQUtLLGNBQWMsRUFBRSxJQUFJO1FBQzFFLE1BQU1FLHFDQUFxQ04sVUFBVUssZUFBZSxDQUNsRU4sS0FBS08sa0NBQWtDLEVBQUUsS0FBSztRQUNoRCxNQUFNQyxpQkFBaUJQLFVBQVVLLGVBQWUsQ0FBQ04sS0FBS1EsY0FBYyxFQUFFLElBQUk7UUFDMUUsTUFBTUMsd0JBQXdCUixVQUFVSyxlQUFlLENBQUNOLEtBQUtTLHFCQUFxQixFQUFFLElBQUk7UUFDeEYsTUFBTUMsWUFBWVYsS0FBS1UsU0FBUyxJQUFJLENBQUM7UUFDckMsTUFBTUMsZUFBZVgsS0FBS1csWUFBWSxJQUFJLENBQUM7UUFDM0MsTUFBTUMsMkJBQTJCWixLQUFLWSx3QkFBd0IsSUFBSSxDQUFDO1FBQ25FLE1BQU1DLGlDQUFpQ1osVUFBVUssZUFBZSxDQUFDTixLQUFLYSw4QkFBOEIsRUFBRSxLQUNwRztRQUNGLElBQUksQ0FBQ1YsWUFBWVcsS0FBSyxDQUFDLGtCQUFrQjtZQUN2QyxNQUFNLElBQUk3QyxnQkFBZ0I7UUFDNUI7UUFDQSxNQUFNOEMscUJBQXFCZixLQUFLZSxrQkFBa0IsSUFBSTtRQUN0RCxNQUFNQywyQkFBMkJoQixLQUFLZ0Isd0JBQXdCLElBQUksQ0FBQztRQUNuRSxNQUFNQyxhQUFhLElBQUkzRCxXQUFXK0MsZ0JBQWdCSztRQUNsRCxNQUFNUSxlQUFlLElBQUk1QyxhQUFhMkMsWUFBWWxCLE9BQU9LO1FBQ3pELE1BQU1lLGlDQUFpQyxJQUFJN0QsV0FBV2lELG9DQUFvQ0c7UUFDMUYsTUFBTVUsNkJBQTZCLElBQUk5RCxXQUFXdUQsZ0NBQWdDSDtRQUNsRixNQUFNVyxrQkFBa0IsSUFBSXRELGdCQUFnQmtELFlBQVlDO1FBQ3hELE1BQU1JLHVCQUF1QixJQUFJOUMsc0JBQXNCeUMsWUFBWUM7UUFDbkUsSUFBSSxDQUFDdEIsb0JBQW9CLEdBQUcsSUFBSXJCLG9CQUFvQjhDLGlCQUFpQnJCLEtBQUt1QixhQUFhO1FBQ3ZGLElBQUksQ0FBQzlCLHVCQUF1QixHQUFHLElBQUloQyx1QkFBdUIsSUFBSSxFQUFFeUQsY0FBY25CLE9BQU87WUFDbkZJO1lBQWFDO1lBQ2JDO1lBQWdCRztZQUFnQkc7WUFBY0Y7WUFBdUJHO1lBQTBCRjtZQUMvRks7WUFBb0JTLFFBQVF4QixLQUFLd0IsTUFBTTtZQUN2Q0Msd0NBQXdDekIsS0FBS3lCLHNDQUFzQztZQUNuRkMseUJBQXlCMUIsS0FBSzBCLHVCQUF1QjtRQUN2RDtRQUNBLElBQUksQ0FBQzNDLHVCQUF1QixHQUFHLElBQUl2Qix1QkFBdUIsSUFBSUQsMEJBQTBCMEQsWUFBWUM7UUFDcEcsSUFBSSxDQUFDUyxtQkFBbUIsR0FBRyxJQUFJM0QsbUJBQW1CZ0MsTUFBTSxJQUFJLENBQUNQLHVCQUF1QixFQUFFLElBQUksQ0FBQ0csb0JBQW9CLEVBQzdHTyxhQUFhYTtRQUNmLElBQUlZLDZCQUE2QixJQUFJOUQsMkJBQTJCcUQsZ0NBQWdDRDtRQUNoRyxJQUFJLENBQUNqQyxxQkFBcUIsR0FBRyxJQUFJdkIscUJBQXFCLElBQUlDLHdCQUF3QnNELFlBQVlDLGVBQzVGLElBQUksQ0FBQ3pCLHVCQUF1QixFQUFFLElBQUksQ0FBQ2tDLG1CQUFtQixFQUN0RCxJQUFJdkQsb0JBQW9CNkMsWUFBWUMsZUFBZVUsNEJBQTRCekI7UUFDakYsSUFBSSxDQUFDaEIsOEJBQThCLEdBQUcsSUFBSXZCLDhCQUN4QyxJQUFJQyxpQ0FBaUN1RCw0QkFBNEJGO1FBQ25FLElBQUksQ0FBQzNCLG1CQUFtQixHQUFHLElBQUlkLG1CQUFtQjZDO1FBQ2xELElBQUl0QixLQUFLNkIscUJBQXFCLElBQUk3QixLQUFLOEIsb0JBQW9CLEVBQUU7WUFDM0QsSUFBSSxDQUFDekMsZUFBZSxHQUFHLElBQUlsQjtZQUMzQixJQUFJLENBQUNzQix1QkFBdUIsQ0FBQ3NDLGtCQUFrQixDQUFDLElBQUksQ0FBQzFDLGVBQWU7UUFDdEU7UUFFQSxJQUFJLENBQUMyQyxPQUFPLEdBQUczRCxjQUFjNEQsU0FBUyxDQUFDO1FBQ3ZDLElBQUlDLFFBQVFDLEdBQUcsQ0FBQ0MsVUFBVSxFQUFFO1lBQzFCLElBQUksQ0FBQyxJQUFJLENBQUM3QyxtQkFBbUIsQ0FBQzhDLDZCQUE2QixDQUFDdEMsUUFBUTtnQkFDbEUsSUFBSSxDQUFDaUMsT0FBTyxDQUFDTSxJQUFJLENBQUM7Z0JBQ2xCLElBQUksQ0FBQ04sT0FBTyxDQUFDTyxJQUFJLENBQ2YseUdBQ0EsNkdBQ0Esb0RBQ0Esd0dBQ0E7WUFFSjtRQUNGO0lBQ0Y7QUFtREY7QUFwSUE7O0NBRUMsR0FDRCxTQUFxQjVELHFCQWlJcEIifQ==