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)
192 lines (191 loc) • 23.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
HttpClientMock: function() {
return HttpClientMock;
},
default: function() {
return HttpClient;
}
});
const _errorHandler = require("../../clients/errorHandler");
const _timeoutError = /*#__PURE__*/ _interop_require_default(require("../../clients/timeoutError"));
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const axios = require("axios");
let HttpClient = class HttpClient {
/**
* Performs a request. Response errors are returned as ApiError or subclasses.
* @param {Object} options request options
* @param {Boolean} isExtendedTimeout whether to run the request with an extended timeout
* @returns {Object|String|any} request result
*/ async request(options, isExtendedTimeout) {
options.timeout = isExtendedTimeout ? this._extendedTimeout : this._timeout;
try {
const response = await this._makeRequest(options);
return response && response.data || undefined;
} catch (err) {
throw this._convertError(err);
}
}
/**
* Performs a request with a failover. Response errors are returned as ApiError or subclasses.
* @param {Object} options request options
* @returns {Object|String|any} request result
*/ async requestWithFailover(options, retryCounter = 0, endTime = Date.now() + this._maxRetryDelay * this._retries) {
options.timeout = this._timeout;
let retryAfterSeconds = 0;
options.callback = (e, res)=>{
if (res && res.status === 202) {
var _res_data_metadata, _res_data;
var _res_headers_retryafter;
retryAfterSeconds = (_res_headers_retryafter = res.headers["retry-after"]) !== null && _res_headers_retryafter !== void 0 ? _res_headers_retryafter : (_res_data = res.data) === null || _res_data === void 0 ? void 0 : (_res_data_metadata = _res_data.metadata) === null || _res_data_metadata === void 0 ? void 0 : _res_data_metadata.recommendedRetryTime;
if (isNaN(retryAfterSeconds)) {
retryAfterSeconds = Math.max((new Date(retryAfterSeconds).getTime() - Date.now()) / 1000, 1);
}
}
};
let body;
try {
const response = await this._makeRequest(options);
options.callback(null, response);
body = response && response.data || undefined;
} catch (err) {
retryCounter = await this._handleError(err, retryCounter, endTime);
return this.requestWithFailover(options, retryCounter, endTime);
}
if (retryAfterSeconds) {
await this._handleRetry(endTime, retryAfterSeconds * 1000);
body = await this.requestWithFailover(options, retryCounter, endTime);
}
return body;
}
_makeRequest(options) {
return axios({
transitional: {
clarifyTimeoutError: true
},
...options
});
}
async _wait(pause) {
await new Promise((res)=>setTimeout(res, pause));
}
async _handleRetry(endTime, retryAfter) {
if (endTime > Date.now() + retryAfter) {
await this._wait(retryAfter);
} else {
throw new _timeoutError.default("Timed out waiting for the response");
}
}
async _handleError(err, retryCounter, endTime) {
const error = this._convertError(err);
if ([
"ConflictError",
"InternalError",
"ApiError",
"TimeoutError"
].includes(error.name) && retryCounter < this._retries) {
const pause = Math.min(Math.pow(2, retryCounter) * this._minRetryDelay, this._maxRetryDelay);
await this._wait(pause);
return retryCounter + 1;
} else if (error.name === "TooManyRequestsError") {
const retryTime = new Date(error.metadata.recommendedRetryTime);
if (retryTime < endTime) {
await this._wait(retryTime.getTime() - Date.now());
return retryCounter;
}
}
throw error;
}
// eslint-disable-next-line complexity
_convertError(err) {
var _err_config;
const errorResponse = err.response || {};
const errorData = errorResponse.data || {};
const status = errorResponse.status || err.status;
const url = err === null || err === void 0 ? void 0 : (_err_config = err.config) === null || _err_config === void 0 ? void 0 : _err_config.url;
const errMsgDefault = errorData.message || err.code || err.message;
const errMsg = errorData.message || err.message;
switch(status){
case 400:
return new _errorHandler.ValidationError(errMsg, errorData.details || err.details, url);
case 401:
return new _errorHandler.UnauthorizedError(errMsg, url);
case 403:
return new _errorHandler.ForbiddenError(errMsg, url);
case 404:
return new _errorHandler.NotFoundError(errMsg, url);
case 409:
return new _errorHandler.ConflictError(errMsg, url);
case 429:
return new _errorHandler.TooManyRequestsError(errMsg, errorData.metadata || err.metadata, url);
case 500:
return new _errorHandler.InternalError(errMsg, url);
default:
return new _errorHandler.ApiError(_errorHandler.ApiError, errMsgDefault, status, url);
}
}
/**
* @typedef {Object} RetryOptions retry options
* @property {Number} [retries] the number of attempts to retry failed request, default 5
* @property {Number} [minDelayInSeconds] minimum delay in seconds before retrying, default 1
* @property {Number} [maxDelayInSeconds] maximum delay in seconds before retrying, default 30
*/ /**
* Constructs HttpClient class instance
* @param {Number} [timeout] request timeout in seconds
* @param {Number} [extendedTimeout] request timeout in seconds
* @param {RetryOptions} [retryOpts] retry options
*/ constructor(timeout = 10, extendedTimeout = 70, retryOpts = {}){
_define_property(this, "_timeout", void 0);
_define_property(this, "_extendedTimeout", void 0);
_define_property(this, "_retries", void 0);
_define_property(this, "_minRetryDelay", void 0);
_define_property(this, "_maxRetryDelay", void 0);
this._timeout = timeout * 1000;
this._extendedTimeout = extendedTimeout * 1000;
this._retries = retryOpts.retries || 5;
this._minRetryDelay = (retryOpts.minDelayInSeconds || 1) * 1000;
this._maxRetryDelay = (retryOpts.maxDelayInSeconds || 30) * 1000;
}
};
let HttpClientMock = class HttpClientMock extends HttpClient {
_makeRequest(...args) {
return this._requestFn(...args);
}
/**
* Constructs HTTP client mock
* @param {Function(options:Object):Promise} requestFn mocked request function
* @param {Number} timeout request timeout in seconds
* @param {RetryOptions} retryOpts retry options
*/ constructor(requestFn, timeout, extendedTimeout, retryOpts){
super(timeout, extendedTimeout, retryOpts);
_define_property(this, "_requestFn", void 0);
this._requestFn = requestFn;
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmNvbnN0IGF4aW9zID0gcmVxdWlyZSgnYXhpb3MnKTtcbmltcG9ydCB7XG4gIFVuYXV0aG9yaXplZEVycm9yLCBGb3JiaWRkZW5FcnJvciwgQXBpRXJyb3IsIFZhbGlkYXRpb25FcnJvciwgSW50ZXJuYWxFcnJvciwgXG4gIE5vdEZvdW5kRXJyb3IsIFRvb01hbnlSZXF1ZXN0c0Vycm9yLCBDb25mbGljdEVycm9yXG59IGZyb20gJy4uLy4uL2NsaWVudHMvZXJyb3JIYW5kbGVyJztcbmltcG9ydCBUaW1lb3V0RXJyb3IgZnJvbSAnLi4vLi4vY2xpZW50cy90aW1lb3V0RXJyb3InO1xuXG4vKipcbiAqIEhUVFAgY2xpZW50IGxpYnJhcnkgYmFzZWQgb24gcmVxdWVzdC1wcm9taXNlXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEh0dHBDbGllbnQge1xuICBcbiAgcHJpdmF0ZSBfdGltZW91dDogbnVtYmVyO1xuICBwcml2YXRlIF9leHRlbmRlZFRpbWVvdXQ6IG51bWJlcjtcbiAgcHJpdmF0ZSBfcmV0cmllczogYW55O1xuICBwcml2YXRlIF9taW5SZXRyeURlbGF5OiBudW1iZXI7XG4gIHByaXZhdGUgX21heFJldHJ5RGVsYXk6IG51bWJlcjtcblxuICAvKipcbiAgICogQHR5cGVkZWYge09iamVjdH0gUmV0cnlPcHRpb25zIHJldHJ5IG9wdGlvbnNcbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFtyZXRyaWVzXSB0aGUgbnVtYmVyIG9mIGF0dGVtcHRzIHRvIHJldHJ5IGZhaWxlZCByZXF1ZXN0LCBkZWZhdWx0IDVcbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFttaW5EZWxheUluU2Vjb25kc10gbWluaW11bSBkZWxheSBpbiBzZWNvbmRzIGJlZm9yZSByZXRyeWluZywgZGVmYXVsdCAxXG4gICAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbbWF4RGVsYXlJblNlY29uZHNdIG1heGltdW0gZGVsYXkgaW4gc2Vjb25kcyBiZWZvcmUgcmV0cnlpbmcsIGRlZmF1bHQgMzBcbiAgICovXG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgSHR0cENsaWVudCBjbGFzcyBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge051bWJlcn0gW3RpbWVvdXRdIHJlcXVlc3QgdGltZW91dCBpbiBzZWNvbmRzXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBbZXh0ZW5kZWRUaW1lb3V0XSByZXF1ZXN0IHRpbWVvdXQgaW4gc2Vjb25kc1xuICAgKiBAcGFyYW0ge1JldHJ5T3B0aW9uc30gW3JldHJ5T3B0c10gcmV0cnkgb3B0aW9uc1xuICAgKi9cbiAgY29uc3RydWN0b3IodGltZW91dCA9IDEwLCBleHRlbmRlZFRpbWVvdXQgPSA3MCwgcmV0cnlPcHRzOiBSZXRyeU9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX3RpbWVvdXQgPSB0aW1lb3V0ICogMTAwMDtcbiAgICB0aGlzLl9leHRlbmRlZFRpbWVvdXQgPSBleHRlbmRlZFRpbWVvdXQgKiAxMDAwO1xuICAgIHRoaXMuX3JldHJpZXMgPSByZXRyeU9wdHMucmV0cmllcyB8fCA1O1xuICAgIHRoaXMuX21pblJldHJ5RGVsYXkgPSAocmV0cnlPcHRzLm1pbkRlbGF5SW5TZWNvbmRzIHx8IDEpICogMTAwMDtcbiAgICB0aGlzLl9tYXhSZXRyeURlbGF5ID0gKHJldHJ5T3B0cy5tYXhEZWxheUluU2Vjb25kcyB8fCAzMCkgKiAxMDAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGEgcmVxdWVzdC4gUmVzcG9uc2UgZXJyb3JzIGFyZSByZXR1cm5lZCBhcyBBcGlFcnJvciBvciBzdWJjbGFzc2VzLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyByZXF1ZXN0IG9wdGlvbnNcbiAgICogQHBhcmFtIHtCb29sZWFufSBpc0V4dGVuZGVkVGltZW91dCB3aGV0aGVyIHRvIHJ1biB0aGUgcmVxdWVzdCB3aXRoIGFuIGV4dGVuZGVkIHRpbWVvdXRcbiAgICogQHJldHVybnMge09iamVjdHxTdHJpbmd8YW55fSByZXF1ZXN0IHJlc3VsdFxuICAgKi9cbiAgYXN5bmMgcmVxdWVzdChvcHRpb25zLCBpc0V4dGVuZGVkVGltZW91dD8pIHtcbiAgICBvcHRpb25zLnRpbWVvdXQgPSBpc0V4dGVuZGVkVGltZW91dCA/IHRoaXMuX2V4dGVuZGVkVGltZW91dCA6IHRoaXMuX3RpbWVvdXQ7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fbWFrZVJlcXVlc3Qob3B0aW9ucyk7XG4gICAgICByZXR1cm4gKHJlc3BvbnNlICYmIHJlc3BvbnNlLmRhdGEpIHx8IHVuZGVmaW5lZDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IHRoaXMuX2NvbnZlcnRFcnJvcihlcnIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIHJlcXVlc3Qgd2l0aCBhIGZhaWxvdmVyLiBSZXNwb25zZSBlcnJvcnMgYXJlIHJldHVybmVkIGFzIEFwaUVycm9yIG9yIHN1YmNsYXNzZXMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIHJlcXVlc3Qgb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7T2JqZWN0fFN0cmluZ3xhbnl9IHJlcXVlc3QgcmVzdWx0XG4gICAqL1xuICBhc3luYyByZXF1ZXN0V2l0aEZhaWxvdmVyKG9wdGlvbnMsIHJldHJ5Q291bnRlciA9IDAsIGVuZFRpbWUgPSBEYXRlLm5vdygpICsgdGhpcy5fbWF4UmV0cnlEZWxheSAqIHRoaXMuX3JldHJpZXMpIHtcbiAgICBvcHRpb25zLnRpbWVvdXQgPSB0aGlzLl90aW1lb3V0O1xuICAgIGxldCByZXRyeUFmdGVyU2Vjb25kcyA9IDA7XG5cbiAgICBvcHRpb25zLmNhbGxiYWNrID0gKGUsIHJlcykgPT4ge1xuICAgICAgaWYgKHJlcyAmJiByZXMuc3RhdHVzID09PSAyMDIpIHtcbiAgICAgICAgcmV0cnlBZnRlclNlY29uZHMgPSByZXMuaGVhZGVyc1sncmV0cnktYWZ0ZXInXSA/PyByZXMuZGF0YT8ubWV0YWRhdGE/LnJlY29tbWVuZGVkUmV0cnlUaW1lO1xuICAgICAgICBpZiAoaXNOYU4ocmV0cnlBZnRlclNlY29uZHMpKSB7XG4gICAgICAgICAgcmV0cnlBZnRlclNlY29uZHMgPSBNYXRoLm1heCgobmV3IERhdGUocmV0cnlBZnRlclNlY29uZHMpLmdldFRpbWUoKSAtIERhdGUubm93KCkpIC8gMTAwMCwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICAgIFxuICAgIGxldCBib2R5O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX21ha2VSZXF1ZXN0KG9wdGlvbnMpO1xuICAgICAgb3B0aW9ucy5jYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICBib2R5ID0gKHJlc3BvbnNlICYmIHJlc3BvbnNlLmRhdGEpIHx8IHVuZGVmaW5lZDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHJ5Q291bnRlciA9IGF3YWl0IHRoaXMuX2hhbmRsZUVycm9yKGVyciwgcmV0cnlDb3VudGVyLCBlbmRUaW1lKTtcbiAgICAgIHJldHVybiB0aGlzLnJlcXVlc3RXaXRoRmFpbG92ZXIob3B0aW9ucywgcmV0cnlDb3VudGVyLCBlbmRUaW1lKTtcbiAgICB9XG5cbiAgICBpZiAocmV0cnlBZnRlclNlY29uZHMpIHtcbiAgICAgIGF3YWl0IHRoaXMuX2hhbmRsZVJldHJ5KGVuZFRpbWUsIHJldHJ5QWZ0ZXJTZWNvbmRzICogMTAwMCk7XG4gICAgICBib2R5ID0gYXdhaXQgdGhpcy5yZXF1ZXN0V2l0aEZhaWxvdmVyKG9wdGlvbnMsIHJldHJ5Q291bnRlciwgZW5kVGltZSk7XG4gICAgfVxuICAgIHJldHVybiBib2R5O1xuICB9XG5cbiAgX21ha2VSZXF1ZXN0KG9wdGlvbnMpIHtcbiAgICByZXR1cm4gYXhpb3Moe1xuICAgICAgdHJhbnNpdGlvbmFsOiB7XG4gICAgICAgIGNsYXJpZnlUaW1lb3V0RXJyb3I6IHRydWVcbiAgICAgIH0sXG4gICAgICAuLi5vcHRpb25zXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBfd2FpdChwYXVzZSkge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlcyA9PiBzZXRUaW1lb3V0KHJlcywgcGF1c2UpKTtcbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVSZXRyeShlbmRUaW1lLCByZXRyeUFmdGVyKSB7XG4gICAgaWYgKGVuZFRpbWUgPiBEYXRlLm5vdygpICsgcmV0cnlBZnRlcikge1xuICAgICAgYXdhaXQgdGhpcy5fd2FpdChyZXRyeUFmdGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFRpbWVvdXRFcnJvcignVGltZWQgb3V0IHdhaXRpbmcgZm9yIHRoZSByZXNwb25zZScpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVFcnJvcihlcnIsIHJldHJ5Q291bnRlciwgZW5kVGltZSkge1xuICAgIGNvbnN0IGVycm9yID0gdGhpcy5fY29udmVydEVycm9yKGVycik7XG4gICAgaWYgKFsnQ29uZmxpY3RFcnJvcicsICdJbnRlcm5hbEVycm9yJywgJ0FwaUVycm9yJywgJ1RpbWVvdXRFcnJvciddLmluY2x1ZGVzKGVycm9yLm5hbWUpXG4gICAgICAmJiByZXRyeUNvdW50ZXIgPCB0aGlzLl9yZXRyaWVzKSB7XG4gICAgICBjb25zdCBwYXVzZSA9IE1hdGgubWluKE1hdGgucG93KDIsIHJldHJ5Q291bnRlcikgKiB0aGlzLl9taW5SZXRyeURlbGF5LCB0aGlzLl9tYXhSZXRyeURlbGF5KTtcbiAgICAgIGF3YWl0IHRoaXMuX3dhaXQocGF1c2UpO1xuICAgICAgcmV0dXJuIHJldHJ5Q291bnRlciArIDE7XG4gICAgfSBlbHNlIGlmIChlcnJvci5uYW1lID09PSAnVG9vTWFueVJlcXVlc3RzRXJyb3InKSB7XG4gICAgICBjb25zdCByZXRyeVRpbWUgPSBuZXcgRGF0ZSgoZXJyb3IgYXMgVG9vTWFueVJlcXVlc3RzRXJyb3IpLm1ldGFkYXRhLnJlY29tbWVuZGVkUmV0cnlUaW1lKTtcbiAgICAgIGlmIChyZXRyeVRpbWUgPCBlbmRUaW1lKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX3dhaXQocmV0cnlUaW1lLmdldFRpbWUoKSAtIERhdGUubm93KCkpO1xuICAgICAgICByZXR1cm4gcmV0cnlDb3VudGVyO1xuICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG4gIF9jb252ZXJ0RXJyb3IoZXJyKSB7XG4gICAgY29uc3QgZXJyb3JSZXNwb25zZSA9IGVyci5yZXNwb25zZSB8fCB7fTtcbiAgICBjb25zdCBlcnJvckRhdGEgPSBlcnJvclJlc3BvbnNlLmRhdGEgfHwge307XG4gICAgY29uc3Qgc3RhdHVzID0gZXJyb3JSZXNwb25zZS5zdGF0dXMgfHwgZXJyLnN0YXR1cztcbiAgICBjb25zdCB1cmwgPSBlcnI/LmNvbmZpZz8udXJsO1xuXG4gICAgY29uc3QgZXJyTXNnRGVmYXVsdCA9IGVycm9yRGF0YS5tZXNzYWdlIHx8IGVyci5jb2RlIHx8IGVyci5tZXNzYWdlO1xuICAgIGNvbnN0IGVyck1zZyA9IGVycm9yRGF0YS5tZXNzYWdlIHx8IGVyci5tZXNzYWdlO1xuXG4gICAgc3dpdGNoIChzdGF0dXMpIHtcbiAgICBjYXNlIDQwMDpcbiAgICAgIHJldHVybiBuZXcgVmFsaWRhdGlvbkVycm9yKGVyck1zZywgZXJyb3JEYXRhLmRldGFpbHMgfHwgZXJyLmRldGFpbHMsIHVybCk7XG4gICAgY2FzZSA0MDE6XG4gICAgICByZXR1cm4gbmV3IFVuYXV0aG9yaXplZEVycm9yKGVyck1zZywgdXJsKTtcbiAgICBjYXNlIDQwMzpcbiAgICAgIHJldHVybiBuZXcgRm9yYmlkZGVuRXJyb3IoZXJyTXNnLCB1cmwpO1xuICAgIGNhc2UgNDA0OlxuICAgICAgcmV0dXJuIG5ldyBOb3RGb3VuZEVycm9yKGVyck1zZywgdXJsKTtcbiAgICBjYXNlIDQwOTpcbiAgICAgIHJldHVybiBuZXcgQ29uZmxpY3RFcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0Mjk6XG4gICAgICByZXR1cm4gbmV3IFRvb01hbnlSZXF1ZXN0c0Vycm9yKGVyck1zZywgZXJyb3JEYXRhLm1ldGFkYXRhIHx8IGVyci5tZXRhZGF0YSwgdXJsKTtcbiAgICBjYXNlIDUwMDpcbiAgICAgIHJldHVybiBuZXcgSW50ZXJuYWxFcnJvcihlcnJNc2csIHVybCk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBuZXcgQXBpRXJyb3IoQXBpRXJyb3IsIGVyck1zZ0RlZmF1bHQsIHN0YXR1cywgdXJsKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBIVFRQIGNsaWVudCBzZXJ2aWNlIG1vY2sgZm9yIHRlc3RzXG4gKi9cbmV4cG9ydCBjbGFzcyBIdHRwQ2xpZW50TW9jayBleHRlbmRzIEh0dHBDbGllbnQge1xuICBfcmVxdWVzdEZuOiBhbnk7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIEhUVFAgY2xpZW50IG1vY2tcbiAgICogQHBhcmFtIHtGdW5jdGlvbihvcHRpb25zOk9iamVjdCk6UHJvbWlzZX0gcmVxdWVzdEZuIG1vY2tlZCByZXF1ZXN0IGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lb3V0IHJlcXVlc3QgdGltZW91dCBpbiBzZWNvbmRzXG4gICAqIEBwYXJhbSB7UmV0cnlPcHRpb25zfSByZXRyeU9wdHMgcmV0cnkgb3B0aW9uc1xuICAgKi9cbiAgY29uc3RydWN0b3IocmVxdWVzdEZuLCB0aW1lb3V0PywgZXh0ZW5kZWRUaW1lb3V0PywgcmV0cnlPcHRzPykge1xuICAgIHN1cGVyKHRpbWVvdXQsIGV4dGVuZGVkVGltZW91dCwgcmV0cnlPcHRzKTtcbiAgICB0aGlzLl9yZXF1ZXN0Rm4gPSByZXF1ZXN0Rm47XG4gIH1cblxuICBfbWFrZVJlcXVlc3QoLi4uYXJnczogYW55W10pIHtcbiAgICByZXR1cm4gdGhpcy5fcmVxdWVzdEZuKC4uLmFyZ3MpO1xuICB9XG5cbn1cblxuLyoqXG4gKiByZXRyeSBvcHRpb25zXG4gKi9cbmV4cG9ydCBkZWNsYXJlIHR5cGUgUmV0cnlPcHRpb25zID0ge1xuXG4gIC8qKlxuICAgKiB0aGUgbnVtYmVyIG9mIGF0dGVtcHRzIHRvIHJldHJ5IGZhaWxlZCByZXF1ZXN0LCBkZWZhdWx0IDVcbiAgICovXG4gIHJldHJpZXM/OiBudW1iZXIsXG5cbiAgLyoqXG4gICAqIG1pbmltdW0gZGVsYXkgaW4gc2Vjb25kcyBiZWZvcmUgcmV0cnlpbmcsIGRlZmF1bHQgMVxuICAgKi9cbiAgbWluRGVsYXlJblNlY29uZHM/OiBudW1iZXIsXG5cbiAgLyoqXG4gICAqIG1heGltdW0gZGVsYXkgaW4gc2Vjb25kcyBiZWZvcmUgcmV0cnlpbmcsIGRlZmF1bHQgMzBcbiAgICovXG4gIG1heERlbGF5SW5TZWNvbmRzPzogbnVtYmVyXG59XG4iXSwibmFtZXMiOlsiSHR0cENsaWVudE1vY2siLCJIdHRwQ2xpZW50IiwiYXhpb3MiLCJyZXF1aXJlIiwicmVxdWVzdCIsIm9wdGlvbnMiLCJpc0V4dGVuZGVkVGltZW91dCIsInRpbWVvdXQiLCJfZXh0ZW5kZWRUaW1lb3V0IiwiX3RpbWVvdXQiLCJyZXNwb25zZSIsIl9tYWtlUmVxdWVzdCIsImRhdGEiLCJ1bmRlZmluZWQiLCJlcnIiLCJfY29udmVydEVycm9yIiwicmVxdWVzdFdpdGhGYWlsb3ZlciIsInJldHJ5Q291bnRlciIsImVuZFRpbWUiLCJEYXRlIiwibm93IiwiX21heFJldHJ5RGVsYXkiLCJfcmV0cmllcyIsInJldHJ5QWZ0ZXJTZWNvbmRzIiwiY2FsbGJhY2siLCJlIiwicmVzIiwic3RhdHVzIiwiaGVhZGVycyIsIm1ldGFkYXRhIiwicmVjb21tZW5kZWRSZXRyeVRpbWUiLCJpc05hTiIsIk1hdGgiLCJtYXgiLCJnZXRUaW1lIiwiYm9keSIsIl9oYW5kbGVFcnJvciIsIl9oYW5kbGVSZXRyeSIsInRyYW5zaXRpb25hbCIsImNsYXJpZnlUaW1lb3V0RXJyb3IiLCJfd2FpdCIsInBhdXNlIiwiUHJvbWlzZSIsInNldFRpbWVvdXQiLCJyZXRyeUFmdGVyIiwiVGltZW91dEVycm9yIiwiZXJyb3IiLCJpbmNsdWRlcyIsIm5hbWUiLCJtaW4iLCJwb3ciLCJfbWluUmV0cnlEZWxheSIsInJldHJ5VGltZSIsImVycm9yUmVzcG9uc2UiLCJlcnJvckRhdGEiLCJ1cmwiLCJjb25maWciLCJlcnJNc2dEZWZhdWx0IiwibWVzc2FnZSIsImNvZGUiLCJlcnJNc2ciLCJWYWxpZGF0aW9uRXJyb3IiLCJkZXRhaWxzIiwiVW5hdXRob3JpemVkRXJyb3IiLCJGb3JiaWRkZW5FcnJvciIsIk5vdEZvdW5kRXJyb3IiLCJDb25mbGljdEVycm9yIiwiVG9vTWFueVJlcXVlc3RzRXJyb3IiLCJJbnRlcm5hbEVycm9yIiwiQXBpRXJyb3IiLCJjb25zdHJ1Y3RvciIsImV4dGVuZGVkVGltZW91dCIsInJldHJ5T3B0cyIsInJldHJpZXMiLCJtaW5EZWxheUluU2Vjb25kcyIsIm1heERlbGF5SW5TZWNvbmRzIiwiYXJncyIsIl9yZXF1ZXN0Rm4iLCJyZXF1ZXN0Rm4iXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7OztJQW9LYUEsY0FBYztlQUFkQTs7O2VBeEpRQzs7OzhCQU5kO3FFQUNrQjs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUx6QixNQUFNQyxRQUFRQyxRQUFRO0FBVVAsSUFBQSxBQUFNRixhQUFOLE1BQU1BO0lBNkJuQjs7Ozs7R0FLQyxHQUNELE1BQU1HLFFBQVFDLE9BQU8sRUFBRUMsaUJBQWtCLEVBQUU7UUFDekNELFFBQVFFLE9BQU8sR0FBR0Qsb0JBQW9CLElBQUksQ0FBQ0UsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDQyxRQUFRO1FBQzNFLElBQUk7WUFDRixNQUFNQyxXQUFXLE1BQU0sSUFBSSxDQUFDQyxZQUFZLENBQUNOO1lBQ3pDLE9BQU8sQUFBQ0ssWUFBWUEsU0FBU0UsSUFBSSxJQUFLQztRQUN4QyxFQUFFLE9BQU9DLEtBQUs7WUFDWixNQUFNLElBQUksQ0FBQ0MsYUFBYSxDQUFDRDtRQUMzQjtJQUNGO0lBRUE7Ozs7R0FJQyxHQUNELE1B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