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)
148 lines (147 loc) • 28.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return MetaApi;
}
});
const _httpClient = /*#__PURE__*/ _interop_require_default(require("../clients/httpClient"));
const _provisioningProfileclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/provisioningProfile.client"));
const _provisioningProfileApi = /*#__PURE__*/ _interop_require_default(require("./provisioningProfileApi"));
const _metaApiWebsocketclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/metaApiWebsocket.client"));
const _metatraderAccountApi = /*#__PURE__*/ _interop_require_default(require("./metatraderAccountApi"));
const _metatraderAccountclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/metatraderAccount.client"));
const _metatraderAccountGeneratorApi = /*#__PURE__*/ _interop_require_default(require("./metatraderAccountGeneratorApi"));
const _metatraderAccountGeneratorclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/metatraderAccountGenerator.client"));
const _historicalMarketDataclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/historicalMarketData.client"));
const _clientApiclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/clientApi.client"));
const _connectionRegistry = /*#__PURE__*/ _interop_require_default(require("./connectionRegistry"));
const _errorHandler = require("../clients/errorHandler");
const _optionsValidator = /*#__PURE__*/ _interop_require_default(require("../clients/optionsValidator"));
const _latencyMonitor = /*#__PURE__*/ _interop_require_default(require("./latencyMonitor"));
const _expertAdvisorclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/expertAdvisor.client"));
const _logger = /*#__PURE__*/ _interop_require_default(require("../logger"));
const _domainclient = /*#__PURE__*/ _interop_require_default(require("../clients/domain.client"));
const _terminalHashManager = /*#__PURE__*/ _interop_require_default(require("./terminalHashManager"));
const _tokenManagementclient = /*#__PURE__*/ _interop_require_default(require("../clients/metaApi/tokenManagement.client"));
const _tokenManagementApi = /*#__PURE__*/ _interop_require_default(require("./tokenManagementApi"));
const _lodash = /*#__PURE__*/ _interop_require_default(require("lodash"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
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() {
_logger.default.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.default();
opts = _lodash.default.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 _errorHandler.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.default(requestTimeout, retryOpts);
const domainClient = new _domainclient.default(httpClient, token, domain);
const historicalMarketDataHttpClient = new _httpClient.default(historicalMarketDataRequestTimeout, retryOpts);
const accountGeneratorHttpClient = new _httpClient.default(accountGeneratorRequestTimeout, retryOpts);
const clientApiClient = new _clientApiclient.default(httpClient, domainClient);
const tokenManagmentClient = new _tokenManagementclient.default(httpClient, domainClient);
this._terminalHashManager = new _terminalHashManager.default(clientApiClient, opts.keepHashTrees);
this._metaApiWebsocketClient = new _metaApiWebsocketclient.default(this, domainClient, token, {
application,
domain,
requestTimeout,
connectTimeout,
packetLogger,
packetOrderingTimeout,
synchronizationThrottler,
retryOpts,
useSharedClientApi,
region: opts.region,
unsubscribeThrottlingIntervalInSeconds: opts.unsubscribeThrottlingIntervalInSeconds
});
this._provisioningProfileApi = new _provisioningProfileApi.default(new _provisioningProfileclient.default(httpClient, domainClient));
this._connectionRegistry = new _connectionRegistry.default(opts, this._metaApiWebsocketClient, this._terminalHashManager, application, refreshSubscriptionsOpts);
let historicalMarketDataClient = new _historicalMarketDataclient.default(historicalMarketDataHttpClient, domainClient);
this._metatraderAccountApi = new _metatraderAccountApi.default(new _metatraderAccountclient.default(httpClient, domainClient), this._metaApiWebsocketClient, this._connectionRegistry, new _expertAdvisorclient.default(httpClient, domainClient), historicalMarketDataClient, application);
this._metatraderAccountGeneratorApi = new _metatraderAccountGeneratorApi.default(new _metatraderAccountGeneratorclient.default(accountGeneratorHttpClient, domainClient));
this._tokenManagementApi = new _tokenManagementApi.default(tokenManagmentClient);
if (opts.enableLatencyTracking || opts.enableLatencyMonitor) {
this._latencyMonitor = new _latencyMonitor.default();
this._metaApiWebsocketClient.addLatencyListener(this._latencyMonitor);
}
this._logger = _logger.default.getLogger("MetaAPI");
if (process.env.IS_BROWSER) {
if (!this._tokenManagementApi.areTokenResourcesNarrowedDown(token)) {
this._logger.warn("USING THE ADMIN TOKEN");
// eslint-disable-next-line max-len
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.");
}
}
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBIdHRwQ2xpZW50IGZyb20gJy4uL2NsaWVudHMvaHR0cENsaWVudCc7XG5pbXBvcnQgUHJvdmlzaW9uaW5nUHJvZmlsZUNsaWVudCBmcm9tICcuLi9jbGllbnRzL21ldGFBcGkvcHJvdmlzaW9uaW5nUHJvZmlsZS5jbGllbnQnO1xuaW1wb3J0IFByb3Zpc2lvbmluZ1Byb2ZpbGVBcGkgZnJvbSAnLi9wcm92aXNpb25pbmdQcm9maWxlQXBpJztcbmltcG9ydCBNZXRhQXBpV2Vic29ja2V0Q2xpZW50IGZyb20gJy4uL2NsaWVudHMvbWV0YUFwaS9tZXRhQXBpV2Vic29ja2V0LmNsaWVudCc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRBcGkgZnJvbSAnLi9tZXRhdHJhZGVyQWNjb3VudEFwaSc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRDbGllbnQgZnJvbSAnLi4vY2xpZW50cy9tZXRhQXBpL21ldGF0cmFkZXJBY2NvdW50LmNsaWVudCc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JBcGkgZnJvbSAnLi9tZXRhdHJhZGVyQWNjb3VudEdlbmVyYXRvckFwaSc7XG5pbXBvcnQgTWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JDbGllbnQgZnJvbSAnLi4vY2xpZW50cy9tZXRhQXBpL21ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yLmNsaWVudCc7XG5pbXBvcnQgSGlzdG9yaWNhbE1hcmtldERhdGFDbGllbnQgZnJvbSAnLi4vY2xpZW50cy9tZXRhQXBpL2hpc3RvcmljYWxNYXJrZXREYXRhLmNsaWVudCc7XG5pbXBvcnQgQ2xpZW50QXBpQ2xpZW50IGZyb20gJy4uL2NsaWVudHMvbWV0YUFwaS9jbGllbnRBcGkuY2xpZW50JztcbmltcG9ydCBDb25uZWN0aW9uUmVnaXN0cnkgZnJvbSAnLi9jb25uZWN0aW9uUmVnaXN0cnknO1xuaW1wb3J0IHtWYWxpZGF0aW9uRXJyb3J9IGZyb20gJy4uL2NsaWVudHMvZXJyb3JIYW5kbGVyJztcbmltcG9ydCBPcHRpb25zVmFsaWRhdG9yIGZyb20gJy4uL2NsaWVudHMvb3B0aW9uc1ZhbGlkYXRvcic7XG5pbXBvcnQgTGF0ZW5jeU1vbml0b3IgZnJvbSAnLi9sYXRlbmN5TW9uaXRvcic7XG5pbXBvcnQgRXhwZXJ0QWR2aXNvckNsaWVudCBmcm9tICcuLi9jbGllbnRzL21ldGFBcGkvZXhwZXJ0QWR2aXNvci5jbGllbnQnO1xuaW1wb3J0IExvZ2dlck1hbmFnZXIgZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCBEb21haW5DbGllbnQgZnJvbSAnLi4vY2xpZW50cy9kb21haW4uY2xpZW50JztcbmltcG9ydCBUZXJtaW5hbEhhc2hNYW5hZ2VyIGZyb20gJy4vdGVybWluYWxIYXNoTWFuYWdlcic7XG5pbXBvcnQgVG9rZW5NYW5hZ2VtZW50Q2xpZW50IGZyb20gJy4uL2NsaWVudHMvbWV0YUFwaS90b2tlbk1hbmFnZW1lbnQuY2xpZW50JztcbmltcG9ydCBUb2tlbk1hbmFnZW1lbnRBcGkgZnJvbSAnLi90b2tlbk1hbmFnZW1lbnRBcGknO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcblxuLyoqXG4gKiBSZXF1ZXN0IHJldHJ5IG9wdGlvbnNcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFJldHJ5T3B0c1xuICogQHByb3BlcnR5IHtOdW1iZXJ9IFtyZXRyaWVzXSBtYXhpbXVtIGFtb3VudCBvZiByZXF1ZXN0IHJldHJpZXMsIGRlZmF1bHQgdmFsdWUgaXMgNVxuICogQHByb3BlcnR5IHtOdW1iZXJ9IFttaW5EZWxheUluU2Vjb25kc10gbWluaW11bSBkZWxheSBpbiBzZWNvbmRzIHVudGlsIHJlcXVlc3QgcmV0cnksIGRlZmF1bHQgdmFsdWUgaXMgMVxuICogQHByb3BlcnR5IHtOdW1iZXJ9IFttYXhEZWxheUluU2Vjb25kc10gbWF4aW11bSBkZWxheSBpbiBzZWNvbmRzIHVudGlsIHJlcXVlc3QgcmV0cnksIGRlZmF1bHQgdmFsdWUgaXMgMzBcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbbG9uZ1J1bm5pbmdSZXF1ZXN0VGltZW91dEluTWludXRlc10gdGltZW91dCBpbiBtaW51dGVzIGZvciBsb25nIHJ1bm5pbmcgcmVxdWVzdHMsIGRlZmF1bHQgMTBcbiAqL1xuXG4vKipcbiAqIFN1YnNjcmlwdGlvbnMgcmVmcmVzaCBvcHRpb25zXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWZyZXNoU3Vic2NyaXB0aW9uc09wdHNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbbWluRGVsYXlJblNlY29uZHNdIG1pbmltdW0gZGVsYXkgaW4gc2Vjb25kcyB1bnRpbCBzdWJzY3JpcHRpb25zIHJlZnJlc2ggcmVxdWVzdCxcbiAqIGRlZmF1bHQgdmFsdWUgaXMgMVxuICogQHByb3BlcnR5IHtOdW1iZXJ9IFttYXhEZWxheUluU2Vjb25kc10gbWF4aW11bSBkZWxheSBpbiBzZWNvbmRzIHVudGlsIHN1YnNjcmlwdGlvbnMgcmVmcmVzaCByZXF1ZXN0LFxuICogZGVmYXVsdCB2YWx1ZSBpcyA2MDBcbiAqL1xuXG4vKipcbiAqIE1ldGFBcGkgb3B0aW9uc1xuICogQHR5cGVkZWYge09iamVjdH0gTWV0YUFwaU9wdHNcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBbYXBwbGljYXRpb25dIGFwcGxpY2F0aW9uIGlkXG4gKiBAcHJvcGVydHkge1N0cmluZ30gW2RvbWFpbl0gZG9tYWluIHRvIGNvbm5lY3QgdG8sIGRlZmF1bHQgaXMgYWdpbGl1bXRyYWRlLmFnaWxpdW10cmFkZS5haVxuICogQHByb3BlcnR5IHtTdHJpbmd9IFtyZWdpb25dIHJlZ2lvbiB0byBjb25uZWN0IHRvXG4gKiBAcHJvcGVydHkge051bWJlcn0gW3JlcXVlc3RUaW1lb3V0XSB0aW1lb3V0IGZvciBzb2NrZXQgcmVxdWVzdHMgaW4gc2Vjb25kc1xuICogQHByb3BlcnR5IHtOdW1iZXJ9IFtjb25uZWN0VGltZW91dF0gdGltZW91dCBmb3IgY29ubmVjdGluZyB0byBzZXJ2ZXIgaW4gc2Vjb25kc1xuICogQHByb3BlcnR5IHtOdW1iZXJ9IFtwYWNrZXRPcmRlcmluZ1RpbWVvdXRdIHBhY2tldCBvcmRlcmluZyB0aW1lb3V0IGluIHNlY29uZHNcbiAqIEBwcm9wZXJ0eSB7UGFja2V0TG9nZ2VyT3B0c30gW3BhY2tldExvZ2dlcl0gcGFja2V0IGxvZ2dlciBvcHRpb25zXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IFtlbmFibGVMYXRlbmN5TW9uaXRvcl0gYW4gb3B0aW9uIHRvIGVuYWJsZSBsYXRlbmN5IHRyYWNraW5nXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IFtlbmFibGVMYXRlbmN5VHJhY2tpbmddIGFuIG9wdGlvbiB0byBlbmFibGUgbGF0ZW5jeSB0cmFja2luZ1xuICogQHByb3BlcnR5IHtTeW5jaHJvbml6YXRpb25UaHJvdHRsZXJPcHRzfSBbc3luY2hyb25pemF0aW9uVGhyb3R0bGVyXSBvcHRpb25zIGZvciBzeW5jaHJvbml6YXRpb24gdGhyb3R0bGVyXG4gKiBAcHJvcGVydHkge1JldHJ5T3B0c30gW3JldHJ5T3B0c10gb3B0aW9ucyBmb3IgcmVxdWVzdCByZXRyaWVzXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IFt1c2VTaGFyZWRDbGllbnRBcGldIG9wdGlvbiB0byB1c2UgYSBzaGFyZWQgc2VydmVyXG4gKiBAcHJvcGVydHkge1JlZnJlc2hTdWJzY3JpcHRpb25zT3B0c30gW3JlZnJlc2hTdWJzY3JpcHRpb25zT3B0c10gc3Vic2NyaXB0aW9ucyByZWZyZXNoIG9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbdW5zdWJzY3JpYmVUaHJvdHRsaW5nSW50ZXJ2YWxJblNlY29uZHNdIGEgdGltZW91dCBpbiBzZWNvbmRzIGZvciB0aHJvdHRsaW5nIHJlcGVhdCB1bnN1YnNjcmliZVxuICogcmVxdWVzdHMgd2hlbiBzeW5jaHJvbml6YXRpb24gcGFja2V0cyBzdGlsbCBhcnJpdmUgYWZ0ZXIgdW5zdWJzY3JpcHRpb24sIGRlZmF1bHQgaXMgMTAgc2Vjb25kc1xuICogQHByb3BlcnR5IHtudW1iZXJ9IFthY2NvdW50R2VuZXJhdG9yUmVxdWVzdFRpbWVvdXRdIE1UIGFjY291bnQgZ2VuZXJhdG9yIEFQSSByZXF1ZXN0IHRpbWVvdXQuIERlZmF1bHQgaXMgNCBtaW51dGVzXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtrZWVwSGFzaFRyZWVzXSBpZiBzZXQgdG8gdHJ1ZSwgdW51c2VkIGRhdGEgd2lsbCBub3QgYmUgY2xlYXJlZCAoZm9yIHVzZSBpbiBkZWJ1Z2dpbmcpXG4gKi9cblxuLyoqXG4gKiBNZXRhQXBpIE1ldGFUcmFkZXIgQVBJIFNES1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNZXRhQXBpIHtcblxuICAvKipcbiAgICogRW5hYmxlcyB1c2luZyBMb2c0anMgbG9nZ2VyIHdpdGggZXh0ZW5kZWQgbG9nIGxldmVscyBmb3IgZGVidWdnaW5nIGluc3RlYWQgb2ZcbiAgICogY29uc29sZS4qIGZ1bmN0aW9ucy4gTm90ZSB0aGF0IGxvZzRqcyBjb25maWd1cmF0aW9uIHBlcmZvcm1lZCBieSB0aGUgdXNlci5cbiAgICovXG4gIHN0YXRpYyBlbmFibGVMb2c0anNMb2dnaW5nKCkge1xuICAgIExvZ2dlck1hbmFnZXIudXNlTG9nNGpzKCk7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0cyBNZXRhQXBpIGNsYXNzIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0b2tlbiBhdXRob3JpemF0aW9uIHRva2VuXG4gICAqIEBwYXJhbSB7TWV0YUFwaU9wdHN9IG9wdHMgYXBwbGljYXRpb24gb3B0aW9uc1xuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbiAgY29uc3RydWN0b3IodG9rZW4sIG9wdHMpIHtcbiAgICBjb25zdCB2YWxpZGF0b3IgPSBuZXcgT3B0aW9uc1ZhbGlkYXRvcigpO1xuICAgIG9wdHMgPSBfLm9taXQob3B0cyB8fCB7fSwgWydjb25uZWN0aW9ucyddKTtcbiAgICBjb25zdCBhcHBsaWNhdGlvbiA9IG9wdHMuYXBwbGljYXRpb24gfHwgJ01ldGFBcGknO1xuICAgIGNvbnN0IGRvbWFpbiA9IG9wdHMuZG9tYWluIHx8ICdhZ2lsaXVtdHJhZGUuYWdpbGl1bXRyYWRlLmFpJztcbiAgICBjb25zdCByZXF1ZXN0VGltZW91dCA9IHZhbGlkYXRvci52YWxpZGF0ZU5vblplcm8ob3B0cy5yZXF1ZXN0VGltZW91dCwgNjAsICdyZXF1ZXN0VGltZW91dCcpO1xuICAgIGNvbnN0IGhpc3RvcmljYWxNYXJrZXREYXRhUmVxdWVzdFRpbWVvdXQgPSB2YWxpZGF0b3IudmFsaWRhdGVOb25aZXJvKFxuICAgICAgb3B0cy5oaXN0b3JpY2FsTWFya2V0RGF0YVJlcXVlc3RUaW1lb3V0LCAyNDAsICdoaXN0b3JpY2FsTWFya2V0RGF0YVJlcXVlc3RUaW1lb3V0Jyk7XG4gICAgY29uc3QgY29ubmVjdFRpbWVvdXQgPSB2YWxpZGF0b3IudmFsaWRhdGVOb25aZXJvKG9wdHMuY29ubmVjdFRpbWVvdXQsIDYwLCAnY29ubmVjdFRpbWVvdXQnKTtcbiAgICBjb25zdCBwYWNrZXRPcmRlcmluZ1RpbWVvdXQgPSB2YWxpZGF0b3IudmFsaWRhdGVOb25aZXJvKG9wdHMucGFja2V0T3JkZXJpbmdUaW1lb3V0LCA2MCwgJ3BhY2tldE9yZGVyaW5nVGltZW91dCcpO1xuICAgIGNvbnN0IHJldHJ5T3B0cyA9IG9wdHMucmV0cnlPcHRzIHx8IHt9O1xuICAgIGNvbnN0IHBhY2tldExvZ2dlciA9IG9wdHMucGFja2V0TG9nZ2VyIHx8IHt9O1xuICAgIGNvbnN0IHN5bmNocm9uaXphdGlvblRocm90dGxlciA9IG9wdHMuc3luY2hyb25pemF0aW9uVGhyb3R0bGVyIHx8IHt9O1xuICAgIGNvbnN0IGFjY291bnRHZW5lcmF0b3JSZXF1ZXN0VGltZW91dCA9IHZhbGlkYXRvci52YWxpZGF0ZU5vblplcm8ob3B0cy5hY2NvdW50R2VuZXJhdG9yUmVxdWVzdFRpbWVvdXQsIDI0MCxcbiAgICAgICdhY2NvdW50R2VuZXJhdG9yUmVxdWVzdFRpbWVvdXQnKTtcbiAgICBpZiAoIWFwcGxpY2F0aW9uLm1hdGNoKC9bYS16QS1aMC05X10rLykpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ0FwcGxpY2F0aW9uIG5hbWUgbXVzdCBiZSBub24tZW1wdHkgc3RyaW5nIGNvbnNpc3RpbmcgZnJvbSBsZXR0ZXJzLCBkaWdpdHMgYW5kIF8gb25seScpO1xuICAgIH1cbiAgICBjb25zdCB1c2VTaGFyZWRDbGllbnRBcGkgPSBvcHRzLnVzZVNoYXJlZENsaWVudEFwaSB8fCBmYWxzZTtcbiAgICBjb25zdCByZWZyZXNoU3Vic2NyaXB0aW9uc09wdHMgPSBvcHRzLnJlZnJlc2hTdWJzY3JpcHRpb25zT3B0cyB8fCB7fTtcbiAgICBjb25zdCBodHRwQ2xpZW50ID0gbmV3IEh0dHBDbGllbnQocmVxdWVzdFRpbWVvdXQsIHJldHJ5T3B0cyk7XG4gICAgY29uc3QgZG9tYWluQ2xpZW50ID0gbmV3IERvbWFpbkNsaWVudChodHRwQ2xpZW50LCB0b2tlbiwgZG9tYWluKTtcbiAgICBjb25zdCBoaXN0b3JpY2FsTWFya2V0RGF0YUh0dHBDbGllbnQgPSBuZXcgSHR0cENsaWVudChoaXN0b3JpY2FsTWFya2V0RGF0YVJlcXVlc3RUaW1lb3V0LCByZXRyeU9wdHMpO1xuICAgIGNvbnN0IGFjY291bnRHZW5lcmF0b3JIdHRwQ2xpZW50ID0gbmV3IEh0dHBDbGllbnQoYWNjb3VudEdlbmVyYXRvclJlcXVlc3RUaW1lb3V0LCByZXRyeU9wdHMpO1xuICAgIGNvbnN0IGNsaWVudEFwaUNsaWVudCA9IG5ldyBDbGllbnRBcGlDbGllbnQoaHR0cENsaWVudCwgZG9tYWluQ2xpZW50KTsgXG4gICAgY29uc3QgdG9rZW5NYW5hZ21lbnRDbGllbnQgPSBuZXcgVG9rZW5NYW5hZ2VtZW50Q2xpZW50KGh0dHBDbGllbnQsIGRvbWFpbkNsaWVudCk7IFxuICAgIHRoaXMuX3Rlcm1pbmFsSGFzaE1hbmFnZXIgPSBuZXcgVGVybWluYWxIYXNoTWFuYWdlcihjbGllbnRBcGlDbGllbnQsIG9wdHMua2VlcEhhc2hUcmVlcyk7XG4gICAgdGhpcy5fbWV0YUFwaVdlYnNvY2tldENsaWVudCA9IG5ldyBNZXRhQXBpV2Vic29ja2V0Q2xpZW50KHRoaXMsIGRvbWFpbkNsaWVudCwgdG9rZW4sXG4gICAgICB7YXBwbGljYXRpb24sIGRvbWFpbixcbiAgICAgICAgcmVxdWVzdFRpbWVvdXQsIGNvbm5lY3RUaW1lb3V0LCBwYWNrZXRMb2dnZXIsIHBhY2tldE9yZGVyaW5nVGltZW91dCwgc3luY2hyb25pemF0aW9uVGhyb3R0bGVyLCByZXRyeU9wdHMsXG4gICAgICAgIHVzZVNoYXJlZENsaWVudEFwaSwgcmVnaW9uOiBvcHRzLnJlZ2lvbixcbiAgICAgICAgdW5zdWJzY3JpYmVUaHJvdHRsaW5nSW50ZXJ2YWxJblNlY29uZHM6IG9wdHMudW5zdWJzY3JpYmVUaHJvdHRsaW5nSW50ZXJ2YWxJblNlY29uZHN9KTtcbiAgICB0aGlzLl9wcm92aXNpb25pbmdQcm9maWxlQXBpID0gbmV3IFByb3Zpc2lvbmluZ1Byb2ZpbGVBcGkobmV3IFByb3Zpc2lvbmluZ1Byb2ZpbGVDbGllbnQoaHR0cENsaWVudCwgZG9tYWluQ2xpZW50KSk7XG4gICAgdGhpcy5fY29ubmVjdGlvblJlZ2lzdHJ5ID0gbmV3IENvbm5lY3Rpb25SZWdpc3RyeShvcHRzLCB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LCB0aGlzLl90ZXJtaW5hbEhhc2hNYW5hZ2VyLFxuICAgICAgYXBwbGljYXRpb24sIHJlZnJlc2hTdWJzY3JpcHRpb25zT3B0cyk7XG4gICAgbGV0IGhpc3RvcmljYWxNYXJrZXREYXRhQ2xpZW50ID0gbmV3IEhpc3RvcmljYWxNYXJrZXREYXRhQ2xpZW50KGhpc3RvcmljYWxNYXJrZXREYXRhSHR0cENsaWVudCwgZG9tYWluQ2xpZW50KTtcbiAgICB0aGlzLl9tZXRhdHJhZGVyQWNjb3VudEFwaSA9IG5ldyBNZXRhdHJhZGVyQWNjb3VudEFwaShuZXcgTWV0YXRyYWRlckFjY291bnRDbGllbnQoaHR0cENsaWVudCwgZG9tYWluQ2xpZW50KSxcbiAgICAgIHRoaXMuX21ldGFBcGlXZWJzb2NrZXRDbGllbnQsIHRoaXMuX2Nvbm5lY3Rpb25SZWdpc3RyeSwgXG4gICAgICBuZXcgRXhwZXJ0QWR2aXNvckNsaWVudChodHRwQ2xpZW50LCBkb21haW5DbGllbnQpLCBoaXN0b3JpY2FsTWFya2V0RGF0YUNsaWVudCwgYXBwbGljYXRpb24pO1xuICAgIHRoaXMuX21ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yQXBpID0gbmV3IE1ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yQXBpKFxuICAgICAgbmV3IE1ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yQ2xpZW50KGFjY291bnRHZW5lcmF0b3JIdHRwQ2xpZW50LCBkb21haW5DbGllbnQpKTtcbiAgICB0aGlzLl90b2tlbk1hbmFnZW1lbnRBcGkgPSBuZXcgVG9rZW5NYW5hZ2VtZW50QXBpKHRva2VuTWFuYWdtZW50Q2xpZW50KTtcbiAgICBpZiAob3B0cy5lbmFibGVMYXRlbmN5VHJhY2tpbmcgfHwgb3B0cy5lbmFibGVMYXRlbmN5TW9uaXRvcikge1xuICAgICAgdGhpcy5fbGF0ZW5jeU1vbml0b3IgPSBuZXcgTGF0ZW5jeU1vbml0b3IoKTtcbiAgICAgIHRoaXMuX21ldGFBcGlXZWJzb2NrZXRDbGllbnQuYWRkTGF0ZW5jeUxpc3RlbmVyKHRoaXMuX2xhdGVuY3lNb25pdG9yKTtcbiAgICB9XG4gICAgXG4gICAgdGhpcy5fbG9nZ2VyID0gTG9nZ2VyTWFuYWdlci5nZXRMb2dnZXIoJ01ldGFBUEknKTtcbiAgICBpZiAocHJvY2Vzcy5lbnYuSVNfQlJPV1NFUikge1xuICAgICAgaWYgKCF0aGlzLl90b2tlbk1hbmFnZW1lbnRBcGkuYXJlVG9rZW5SZXNvdXJjZXNOYXJyb3dlZERvd24odG9rZW4pKSB7XG4gICAgICAgIHRoaXMuX2xvZ2dlci53YXJuKCdVU0lORyBUSEUgQURNSU4gVE9LRU4nKTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgICAgdGhpcy5fbG9nZ2VyLmluZm8oJ0l0IHNlZW1zIGxpa2UgeW91IGFyZSB1c2luZyBhIGFkbWluIEFQSSB0b2tlbi4gU2luY2UgdGhlIHRva2VuIGNhbiBiZSByZXRyaWV2ZW4gZnJvbSB0aGUgYnJvd3NlciBvciBtb2JpbGUgYXBwcyBieSBlbmQgdXNlciB0aGlzIGNhbiBsZWFkIHRvIHlvdXIgYXBwbGljYXRpb24gYmVpbmcgY29tcHJvbWlzZWQsIHVubGVzcyB5b3UgdW5kZXJzdGFuZCB3aGF0IGFyZSB5b3UgZG9pbmcuIFBsZWFzZSB1c2UgVG9rZW4gTWFuYWdlbWVudCBBUEkgKGh0dHBzOi8vZ2l0aHViLmNvbS9tZXRhYXBpL21ldGFhcGktamF2YXNjcmlwdC1zZGsvYmxvYi9tYXN0ZXIvZG9jcy90b2tlbk1hbmFnZW1lbnRBcGkubWQpIGluIHlvdXIgYmFja2VuZCBhcHBsaWNhdGlvbiB0byBwcm9kdWNlIHNlY3VyZSB0b2tlbnMgd2hpY2ggeW91IGNhbiB0aGVuIHVzZSBpbiB3ZWIgVUkgb3IgbW9iaWxlIGFwcHMuJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgcHJvdmlzaW9uaW5nIHByb2ZpbGUgQVBJXG4gICAqIEByZXR1cm5zIHtQcm92aXNpb25pbmdQcm9maWxlQXBpfSBwcm92aXNpb25pbmcgcHJvZmlsZSBBUElcbiAgICovXG4gIGdldCBwcm92aXNpb25pbmdQcm9maWxlQXBpKCkge1xuICAgIHJldHVybiB0aGlzLl9wcm92aXNpb25pbmdQcm9maWxlQXBpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgTWV0YVRyYWRlciBhY2NvdW50IEFQSVxuICAgKiBAcmV0dXJuIHtNZXRhdHJhZGVyQWNjb3VudEFwaX0gTWV0YVRyYWRlciBhY2NvdW50IEFQSVxuICAgKi9cbiAgZ2V0IG1ldGF0cmFkZXJBY2NvdW50QXBpKCkge1xuICAgIHJldHVybiB0aGlzLl9tZXRhdHJhZGVyQWNjb3VudEFwaTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIE1ldGFUcmFkZXIgYWNjb3VudCBnZW5lcmF0b3IgQVBJXG4gICAqIEByZXR1cm4ge01ldGF0cmFkZXJEZW1vQWNjb3VudEFwaX0gTWV0YVRyYWRlciBhY2NvdW50IGdlbmVyYXRvciBBUElcbiAgICovXG4gIGdldCBtZXRhdHJhZGVyQWNjb3VudEdlbmVyYXRvckFwaSgpIHtcbiAgICByZXR1cm4gdGhpcy5fbWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JBcGk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBNZXRhQXBpIGFwcGxpY2F0aW9uIGxhdGVuY3kgbW9uaXRvclxuICAgKiBAcmV0dXJuIHtMYXRlbmN5TW9uaXRvcn0gbGF0ZW5jeSBtb25pdG9yXG4gICAqL1xuICBnZXQgbGF0ZW5jeU1vbml0b3IoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xhdGVuY3lNb25pdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdG9rZW4gbWFuYWdlbWVudCBBUElcbiAgICogQHJldHVybnMge1Rva2VuTWFuYWdlbWVudEFwaX0gdG9rZW4gbWFuYWdlbWVudCBBUElcbiAgICovXG4gIGdldCB0b2tlbk1hbmFnZW1lbnRBcGkoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Rva2VuTWFuYWdlbWVudEFwaTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgYWxsIGNsaWVudHMgYW5kIGNvbm5lY3Rpb25zIGFuZCBzdG9wcyBhbGwgaW50ZXJuYWwgam9ic1xuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgdGhpcy5fbWV0YUFwaVdlYnNvY2tldENsaWVudC5yZW1vdmVMYXRlbmN5TGlzdGVuZXIodGhpcy5fbGF0ZW5jeU1vbml0b3IpO1xuICAgIHRoaXMuX21ldGFBcGlXZWJzb2NrZXRDbGllbnQuY2xvc2UoKTtcbiAgICB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LnN0b3AoKTtcbiAgICB0aGlzLl90ZXJtaW5hbEhhc2hNYW5hZ2VyLl9zdG9wKCk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJNZXRhQXBpIiwiZW5hYmxlTG9nNGpzTG9nZ2luZyIsIkxvZ2dlck1hbmFnZXIiLCJ1c2VMb2c0anMiLCJwcm92aXNpb25pbmdQcm9maWxlQXBpIiwiX3Byb3Zpc2lvbmluZ1Byb2ZpbGVBcGkiLCJtZXRhdHJhZGVyQWNjb3VudEFwaSIsIl9tZXRhdHJhZGVyQWNjb3VudEFwaSIsIm1ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yQXBpIiwiX21ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yQXBpIiwibGF0ZW5jeU1vbml0b3IiLCJfbGF0ZW5jeU1vbml0b3IiLCJ0b2tlbk1hbmFnZW1lbnRBcGkiLCJfdG9rZW5NYW5hZ2VtZW50QXBpIiwiY2xvc2UiLCJfbWV0YUFwaVdlYnNvY2tldENsaWVudCIsInJlbW92ZUxhdGVuY3lMaXN0ZW5lciIsInN0b3AiLCJfdGVybWluYWxIYXNoTWFuYWdlciIsIl9zdG9wIiwiY29uc3RydWN0b3IiLCJ0b2tlbiIsIm9wdHMiLCJ2YWxpZGF0b3IiLCJPcHRpb25zVmFsaWRhdG9yIiwiXyIsIm9taXQiLCJhcHBsaWNhdGlvbiIsImRvbWFpbiIsInJlcXVlc3RUaW1lb3V0IiwidmFsaWRhdGVOb25aZXJvIiwiaGlzdG9yaWNhbE1hcmtldERhdGFSZXF1ZXN0VGltZW91dCIsImNvbm5lY3RUaW1lb3V0IiwicGFja2V0T3JkZXJpbmdUaW1lb3V0IiwicmV0cnlPcHRzIiwicGFja2V0TG9nZ2VyIiwic3luY2hyb25pemF0aW9uVGhyb3R0bGVyIiwiYWNjb3VudEdlbmVyYXRvclJlcXVlc3RUaW1lb3V0IiwibWF0Y2giLCJWYWxpZGF0aW9uRXJyb3IiLCJ1c2VTaGFyZWRDbGllbnRBcGkiLCJyZWZyZXNoU3Vic2NyaXB0aW9uc09wdHMiLCJodHRwQ2xpZW50IiwiSHR0cENsaWVudCIsImRvbWFpbkNsaWVudCIsIkRvbWFpbkNsaWVudCIsImhpc3RvcmljYWxNYXJrZXREYXRhSHR0cENsaWVudCIsImFjY291bnRHZW5lcmF0b3JIdHRwQ2xpZW50IiwiY2xpZW50QXBpQ2xpZW50IiwiQ2xpZW50QXBpQ2xpZW50IiwidG9rZW5NYW5hZ21lbnRDbGllbnQiLCJUb2tlbk1hbmFnZW1lbnRDbGllbnQiLCJUZXJtaW5hbEhhc2hNYW5hZ2VyIiwia2VlcEhhc2hUcmVlcyIsIk1ldGFBcGlXZWJzb2NrZXRDbGllbnQiLCJyZWdpb24iLCJ1bnN1YnNjcmliZVRocm90dGxpbmdJbnRlcnZhbEluU2Vjb25kcyIsIlByb3Zpc2lvbmluZ1Byb2ZpbGVBcGkiLCJQcm92aXNpb25pbmdQcm9maWxlQ2xpZW50IiwiX2Nvbm5lY3Rpb25SZWdpc3RyeSIsIkNvbm5lY3Rpb25SZWdpc3RyeSIsImhpc3RvcmljYWxNYXJrZXREYXRhQ2xpZW50IiwiSGlzdG9yaWNhbE1hcmtldERhdGFDbGllbnQiLCJNZXRhdHJhZGVyQWNjb3VudEFwaSIsIk1ldGF0cmFkZXJBY2NvdW50Q2xpZW50IiwiRXhwZXJ0QWR2aXNvckNsaWVudCIsIk1ldGF0cmFkZXJBY2NvdW50R2VuZXJhdG9yQXBpIiwiTWV0YXRyYWRlckFjY291bnRHZW5lcmF0b3JDbGllbnQiLCJUb2tlbk1hbmFnZW1lbnRBcGkiLCJlbmFibGVMYXRlbmN5VHJhY2tpbmciLCJlbmFibGVMYXRlbmN5TW9uaXRvciIsIkxhdGVuY3lNb25pdG9yIiwiYWRkTGF0ZW5jeUxpc3RlbmVyIiwiX2xvZ2dlciIsImdldExvZ2dlciIsInByb2Nlc3MiLCJlbnYiLCJJU19CUk9XU0VSIiwiYXJlVG9rZW5SZXNvdXJjZXNOYXJyb3dlZERvd24iLCJ3YXJuIiwiaW5mbyJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7ZUFtRXFCQTs7O21FQWpFRTtrRkFDZTsrRUFDSDsrRUFDQTs2RUFDRjtnRkFDRztzRkFDTTt5RkFDRzttRkFDTjt3RUFDWDsyRUFDRzs4QkFDRDt5RUFDRDt1RUFDRjs0RUFDSzsrREFDTjtxRUFDRDs0RUFDTzs4RUFDRTsyRUFDSDsrREFDakI7Ozs7OztBQTZDQyxJQUFBLEFBQU1BLFVBQU4sTUFBTUE7SUFFbkI7OztHQUdD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