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)
226 lines (225 loc) • 23.9 kB
JavaScript
;
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);
});
};
}
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 _object_spread(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === "function") {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_define_property(target, key, source[key]);
});
}
return target;
}
import axios from 'axios';
import { UnauthorizedError, ForbiddenError, ApiError, ValidationError, InternalError, NotFoundError, TooManyRequestsError, ConflictError } from '../../clients/errorHandler';
import TimeoutError from '../../clients/timeoutError';
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
*/ request(options, isExtendedTimeout) {
var _this = this;
return _async_to_generator(function*() {
options.timeout = isExtendedTimeout ? _this._extendedTimeout : _this._timeout;
try {
const response = yield _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
*/ requestWithFailover(options, retryCounter = 0, endTime = Date.now() + this._maxRetryDelay * this._retries) {
var _this = this;
return _async_to_generator(function*() {
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 = yield _this._makeRequest(options);
options.callback(null, response);
body = response && response.data || undefined;
} catch (err) {
retryCounter = yield _this._handleError(err, retryCounter, endTime);
return _this.requestWithFailover(options, retryCounter, endTime);
}
if (retryAfterSeconds) {
yield _this._handleRetry(endTime, retryAfterSeconds * 1000);
body = yield _this.requestWithFailover(options, retryCounter, endTime);
}
return body;
})();
}
_makeRequest(options) {
return axios(_object_spread({
transitional: {
clarifyTimeoutError: true
}
}, options));
}
_wait(pause) {
return _async_to_generator(function*() {
yield new Promise((res)=>setTimeout(res, pause));
})();
}
_handleRetry(endTime, retryAfter) {
var _this = this;
return _async_to_generator(function*() {
if (endTime > Date.now() + retryAfter) {
yield _this._wait(retryAfter);
} else {
throw new TimeoutError('Timed out waiting for the response');
}
})();
}
_handleError(err, retryCounter, endTime) {
var _this = this;
return _async_to_generator(function*() {
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);
yield _this._wait(pause);
return retryCounter + 1;
} else if (error.name === 'TooManyRequestsError') {
const retryTime = Date.parse(error.metadata.recommendedRetryTime);
if (retryTime < endTime) {
yield _this._wait(retryTime - 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 ValidationError(errMsg, errorData.details || err.details, url);
case 401:
return new UnauthorizedError(errMsg, url);
case 403:
return new ForbiddenError(errMsg, url);
case 404:
return new NotFoundError(errMsg, url);
case 409:
return new ConflictError(errMsg, url);
case 429:
return new TooManyRequestsError(errMsg, errorData.metadata || err.metadata, url);
case 500:
return new InternalError(errMsg, url);
default:
return new ApiError(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 = {}){
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;
}
};
/**
* HTTP client library based on request-promise
*/ export { HttpClient as default };
/**
* HTTP client service mock for tests
*/ export class HttpClientMock extends HttpClient {
_makeRequest() {
return this._requestFn.apply(this, arguments);
}
/**
* 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);
this._requestFn = requestFn;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBheGlvcyBmcm9tICdheGlvcyc7XG5pbXBvcnQge1xuICBVbmF1dGhvcml6ZWRFcnJvciwgRm9yYmlkZGVuRXJyb3IsIEFwaUVycm9yLCBWYWxpZGF0aW9uRXJyb3IsIEludGVybmFsRXJyb3IsIFxuICBOb3RGb3VuZEVycm9yLCBUb29NYW55UmVxdWVzdHNFcnJvciwgQ29uZmxpY3RFcnJvclxufSBmcm9tICcuLi8uLi9jbGllbnRzL2Vycm9ySGFuZGxlcic7XG5pbXBvcnQgVGltZW91dEVycm9yIGZyb20gJy4uLy4uL2NsaWVudHMvdGltZW91dEVycm9yJztcblxuLyoqXG4gKiBIVFRQIGNsaWVudCBsaWJyYXJ5IGJhc2VkIG9uIHJlcXVlc3QtcHJvbWlzZVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBIdHRwQ2xpZW50IHtcblxuICAvKipcbiAgICogQHR5cGVkZWYge09iamVjdH0gUmV0cnlPcHRpb25zIHJldHJ5IG9wdGlvbnNcbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFtyZXRyaWVzXSB0aGUgbnVtYmVyIG9mIGF0dGVtcHRzIHRvIHJldHJ5IGZhaWxlZCByZXF1ZXN0LCBkZWZhdWx0IDVcbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFttaW5EZWxheUluU2Vjb25kc10gbWluaW11bSBkZWxheSBpbiBzZWNvbmRzIGJlZm9yZSByZXRyeWluZywgZGVmYXVsdCAxXG4gICAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBbbWF4RGVsYXlJblNlY29uZHNdIG1heGltdW0gZGVsYXkgaW4gc2Vjb25kcyBiZWZvcmUgcmV0cnlpbmcsIGRlZmF1bHQgMzBcbiAgICovXG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgSHR0cENsaWVudCBjbGFzcyBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge051bWJlcn0gW3RpbWVvdXRdIHJlcXVlc3QgdGltZW91dCBpbiBzZWNvbmRzXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBbZXh0ZW5kZWRUaW1lb3V0XSByZXF1ZXN0IHRpbWVvdXQgaW4gc2Vjb25kc1xuICAgKiBAcGFyYW0ge1JldHJ5T3B0aW9uc30gW3JldHJ5T3B0c10gcmV0cnkgb3B0aW9uc1xuICAgKi9cbiAgY29uc3RydWN0b3IodGltZW91dCA9IDEwLCBleHRlbmRlZFRpbWVvdXQgPSA3MCwgcmV0cnlPcHRzID0ge30pIHtcbiAgICB0aGlzLl90aW1lb3V0ID0gdGltZW91dCAqIDEwMDA7XG4gICAgdGhpcy5fZXh0ZW5kZWRUaW1lb3V0ID0gZXh0ZW5kZWRUaW1lb3V0ICogMTAwMDtcbiAgICB0aGlzLl9yZXRyaWVzID0gcmV0cnlPcHRzLnJldHJpZXMgfHwgNTtcbiAgICB0aGlzLl9taW5SZXRyeURlbGF5ID0gKHJldHJ5T3B0cy5taW5EZWxheUluU2Vjb25kcyB8fCAxKSAqIDEwMDA7XG4gICAgdGhpcy5fbWF4UmV0cnlEZWxheSA9IChyZXRyeU9wdHMubWF4RGVsYXlJblNlY29uZHMgfHwgMzApICogMTAwMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIHJlcXVlc3QuIFJlc3BvbnNlIGVycm9ycyBhcmUgcmV0dXJuZWQgYXMgQXBpRXJyb3Igb3Igc3ViY2xhc3Nlcy5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgcmVxdWVzdCBvcHRpb25zXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gaXNFeHRlbmRlZFRpbWVvdXQgd2hldGhlciB0byBydW4gdGhlIHJlcXVlc3Qgd2l0aCBhbiBleHRlbmRlZCB0aW1lb3V0XG4gICAqIEByZXR1cm5zIHtPYmplY3R8U3RyaW5nfGFueX0gcmVxdWVzdCByZXN1bHRcbiAgICovXG4gIGFzeW5jIHJlcXVlc3Qob3B0aW9ucywgaXNFeHRlbmRlZFRpbWVvdXQpIHtcbiAgICBvcHRpb25zLnRpbWVvdXQgPSBpc0V4dGVuZGVkVGltZW91dCA/IHRoaXMuX2V4dGVuZGVkVGltZW91dCA6IHRoaXMuX3RpbWVvdXQ7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fbWFrZVJlcXVlc3Qob3B0aW9ucyk7XG4gICAgICByZXR1cm4gKHJlc3BvbnNlICYmIHJlc3BvbnNlLmRhdGEpIHx8IHVuZGVmaW5lZDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IHRoaXMuX2NvbnZlcnRFcnJvcihlcnIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIHJlcXVlc3Qgd2l0aCBhIGZhaWxvdmVyLiBSZXNwb25zZSBlcnJvcnMgYXJlIHJldHVybmVkIGFzIEFwaUVycm9yIG9yIHN1YmNsYXNzZXMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIHJlcXVlc3Qgb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7T2JqZWN0fFN0cmluZ3xhbnl9IHJlcXVlc3QgcmVzdWx0XG4gICAqL1xuICBhc3luYyByZXF1ZXN0V2l0aEZhaWxvdmVyKG9wdGlvbnMsIHJldHJ5Q291bnRlciA9IDAsIGVuZFRpbWUgPSBEYXRlLm5vdygpICsgdGhpcy5fbWF4UmV0cnlEZWxheSAqIHRoaXMuX3JldHJpZXMpIHtcbiAgICBvcHRpb25zLnRpbWVvdXQgPSB0aGlzLl90aW1lb3V0O1xuICAgIGxldCByZXRyeUFmdGVyU2Vjb25kcyA9IDA7XG5cbiAgICBvcHRpb25zLmNhbGxiYWNrID0gKGUsIHJlcykgPT4ge1xuICAgICAgaWYgKHJlcyAmJiByZXMuc3RhdHVzID09PSAyMDIpIHtcbiAgICAgICAgcmV0cnlBZnRlclNlY29uZHMgPSByZXMuaGVhZGVyc1sncmV0cnktYWZ0ZXInXSA/PyByZXMuZGF0YT8ubWV0YWRhdGE/LnJlY29tbWVuZGVkUmV0cnlUaW1lO1xuICAgICAgICBpZiAoaXNOYU4ocmV0cnlBZnRlclNlY29uZHMpKSB7XG4gICAgICAgICAgcmV0cnlBZnRlclNlY29uZHMgPSBNYXRoLm1heCgobmV3IERhdGUocmV0cnlBZnRlclNlY29uZHMpLmdldFRpbWUoKSAtIERhdGUubm93KCkpIC8gMTAwMCwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICAgIFxuICAgIGxldCBib2R5O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX21ha2VSZXF1ZXN0KG9wdGlvbnMpO1xuICAgICAgb3B0aW9ucy5jYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICBib2R5ID0gKHJlc3BvbnNlICYmIHJlc3BvbnNlLmRhdGEpIHx8IHVuZGVmaW5lZDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHJ5Q291bnRlciA9IGF3YWl0IHRoaXMuX2hhbmRsZUVycm9yKGVyciwgcmV0cnlDb3VudGVyLCBlbmRUaW1lKTtcbiAgICAgIHJldHVybiB0aGlzLnJlcXVlc3RXaXRoRmFpbG92ZXIob3B0aW9ucywgcmV0cnlDb3VudGVyLCBlbmRUaW1lKTtcbiAgICB9XG5cbiAgICBpZiAocmV0cnlBZnRlclNlY29uZHMpIHtcbiAgICAgIGF3YWl0IHRoaXMuX2hhbmRsZVJldHJ5KGVuZFRpbWUsIHJldHJ5QWZ0ZXJTZWNvbmRzICogMTAwMCk7XG4gICAgICBib2R5ID0gYXdhaXQgdGhpcy5yZXF1ZXN0V2l0aEZhaWxvdmVyKG9wdGlvbnMsIHJldHJ5Q291bnRlciwgZW5kVGltZSk7XG4gICAgfVxuICAgIHJldHVybiBib2R5O1xuICB9XG5cbiAgX21ha2VSZXF1ZXN0KG9wdGlvbnMpIHtcbiAgICByZXR1cm4gYXhpb3Moe1xuICAgICAgdHJhbnNpdGlvbmFsOiB7XG4gICAgICAgIGNsYXJpZnlUaW1lb3V0RXJyb3I6IHRydWVcbiAgICAgIH0sXG4gICAgICAuLi5vcHRpb25zXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBfd2FpdChwYXVzZSkge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlcyA9PiBzZXRUaW1lb3V0KHJlcywgcGF1c2UpKTtcbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVSZXRyeShlbmRUaW1lLCByZXRyeUFmdGVyKSB7XG4gICAgaWYgKGVuZFRpbWUgPiBEYXRlLm5vdygpICsgcmV0cnlBZnRlcikge1xuICAgICAgYXdhaXQgdGhpcy5fd2FpdChyZXRyeUFmdGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFRpbWVvdXRFcnJvcignVGltZWQgb3V0IHdhaXRpbmcgZm9yIHRoZSByZXNwb25zZScpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIF9oYW5kbGVFcnJvcihlcnIsIHJldHJ5Q291bnRlciwgZW5kVGltZSkge1xuICAgIGNvbnN0IGVycm9yID0gdGhpcy5fY29udmVydEVycm9yKGVycik7XG4gICAgaWYgKFsnQ29uZmxpY3RFcnJvcicsICdJbnRlcm5hbEVycm9yJywgJ0FwaUVycm9yJywgJ1RpbWVvdXRFcnJvciddLmluY2x1ZGVzKGVycm9yLm5hbWUpXG4gICAgICAmJiByZXRyeUNvdW50ZXIgPCB0aGlzLl9yZXRyaWVzKSB7XG4gICAgICBjb25zdCBwYXVzZSA9IE1hdGgubWluKE1hdGgucG93KDIsIHJldHJ5Q291bnRlcikgKiB0aGlzLl9taW5SZXRyeURlbGF5LCB0aGlzLl9tYXhSZXRyeURlbGF5KTtcbiAgICAgIGF3YWl0IHRoaXMuX3dhaXQocGF1c2UpO1xuICAgICAgcmV0dXJuIHJldHJ5Q291bnRlciArIDE7XG4gICAgfSBlbHNlIGlmIChlcnJvci5uYW1lID09PSAnVG9vTWFueVJlcXVlc3RzRXJyb3InKSB7XG4gICAgICBjb25zdCByZXRyeVRpbWUgPSBEYXRlLnBhcnNlKGVycm9yLm1ldGFkYXRhLnJlY29tbWVuZGVkUmV0cnlUaW1lKTtcbiAgICAgIGlmIChyZXRyeVRpbWUgPCBlbmRUaW1lKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX3dhaXQocmV0cnlUaW1lIC0gRGF0ZS5ub3coKSk7XG4gICAgICAgIHJldHVybiByZXRyeUNvdW50ZXI7XG4gICAgICB9XG4gICAgfVxuICAgIHRocm93IGVycm9yO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbiAgX2NvbnZlcnRFcnJvcihlcnIpIHtcbiAgICBjb25zdCBlcnJvclJlc3BvbnNlID0gZXJyLnJlc3BvbnNlIHx8IHt9O1xuICAgIGNvbnN0IGVycm9yRGF0YSA9IGVycm9yUmVzcG9uc2UuZGF0YSB8fCB7fTtcbiAgICBjb25zdCBzdGF0dXMgPSBlcnJvclJlc3BvbnNlLnN0YXR1cyB8fCBlcnIuc3RhdHVzO1xuICAgIGNvbnN0IHVybCA9IGVycj8uY29uZmlnPy51cmw7XG5cbiAgICBjb25zdCBlcnJNc2dEZWZhdWx0ID0gZXJyb3JEYXRhLm1lc3NhZ2UgfHwgZXJyLmNvZGUgfHwgZXJyLm1lc3NhZ2U7XG4gICAgY29uc3QgZXJyTXNnID0gZXJyb3JEYXRhLm1lc3NhZ2UgfHwgZXJyLm1lc3NhZ2U7XG5cbiAgICBzd2l0Y2ggKHN0YXR1cykge1xuICAgIGNhc2UgNDAwOlxuICAgICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uRXJyb3IoZXJyTXNnLCBlcnJvckRhdGEuZGV0YWlscyB8fCBlcnIuZGV0YWlscywgdXJsKTtcbiAgICBjYXNlIDQwMTpcbiAgICAgIHJldHVybiBuZXcgVW5hdXRob3JpemVkRXJyb3IoZXJyTXNnLCB1cmwpO1xuICAgIGNhc2UgNDAzOlxuICAgICAgcmV0dXJuIG5ldyBGb3JiaWRkZW5FcnJvcihlcnJNc2csIHVybCk7XG4gICAgY2FzZSA0MDQ6XG4gICAgICByZXR1cm4gbmV3IE5vdEZvdW5kRXJyb3IoZXJyTXNnLCB1cmwpO1xuICAgIGNhc2UgNDA5OlxuICAgICAgcmV0dXJuIG5ldyBDb25mbGljdEVycm9yKGVyck1zZywgdXJsKTtcbiAgICBjYXNlIDQyOTpcbiAgICAgIHJldHVybiBuZXcgVG9vTWFueVJlcXVlc3RzRXJyb3IoZXJyTXNnLCBlcnJvckRhdGEubWV0YWRhdGEgfHwgZXJyLm1ldGFkYXRhLCB1cmwpO1xuICAgIGNhc2UgNTAwOlxuICAgICAgcmV0dXJuIG5ldyBJbnRlcm5hbEVycm9yKGVyck1zZywgdXJsKTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIG5ldyBBcGlFcnJvcihBcGlFcnJvciwgZXJyTXNnRGVmYXVsdCwgc3RhdHVzLCB1cmwpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEhUVFAgY2xpZW50IHNlcnZpY2UgbW9jayBmb3IgdGVzdHNcbiAqL1xuZXhwb3J0IGNsYXNzIEh0dHBDbGllbnRNb2NrIGV4dGVuZHMgSHR0cENsaWVudCB7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIEhUVFAgY2xpZW50IG1vY2tcbiAgICogQHBhcmFtIHtGdW5jdGlvbihvcHRpb25zOk9iamVjdCk6UHJvbWlzZX0gcmVxdWVzdEZuIG1vY2tlZCByZXF1ZXN0IGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lb3V0IHJlcXVlc3QgdGltZW91dCBpbiBzZWNvbmRzXG4gICAqIEBwYXJhbSB7UmV0cnlPcHRpb25zfSByZXRyeU9wdHMgcmV0cnkgb3B0aW9uc1xuICAgKi9cbiAgY29uc3RydWN0b3IocmVxdWVzdEZuLCB0aW1lb3V0LCBleHRlbmRlZFRpbWVvdXQsIHJldHJ5T3B0cykge1xuICAgIHN1cGVyKHRpbWVvdXQsIGV4dGVuZGVkVGltZW91dCwgcmV0cnlPcHRzKTtcbiAgICB0aGlzLl9yZXF1ZXN0Rm4gPSByZXF1ZXN0Rm47XG4gIH1cblxuICBfbWFrZVJlcXVlc3QoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JlcXVlc3RGbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9XG5cbn1cbiJdLCJuYW1lcyI6WyJheGlvcyIsIlVuYXV0aG9yaXplZEVycm9yIiwiRm9yYmlkZGVuRXJyb3IiLCJBcGlFcnJvciIsIlZhbGlkYXRpb25FcnJvciIsIkludGVybmFsRXJyb3IiLCJOb3RGb3VuZEVycm9yIiwiVG9vTWFueVJlcXVlc3RzRXJyb3IiLCJDb25mbGljdEVycm9yIiwiVGltZW91dEVycm9yIiwiSHR0cENsaWVudCIsInJlcXVlc3QiLCJvcHRpb25zIiwiaXNFeHRlbmRlZFRpbWVvdXQiLCJ0aW1lb3V0IiwiX2V4dGVuZGVkVGltZW91dCIsIl90aW1lb3V0IiwicmVzcG9uc2UiLCJfbWFrZVJlcXVlc3QiLCJkYXRhIiwidW5kZWZpbmVkIiwiZXJyIiwiX2NvbnZlcnRFcnJvciIsInJlcXVlc3RXaXRoRmFpbG92ZXIiLCJyZXRyeUNvdW50ZXIiLCJlbmRUaW1lIiwiRGF0ZSIsIm5vdyIsIl9tYXhSZXRyeURlbGF5IiwiX3JldHJpZXMiLCJyZXRyeUFmdGVyU2Vjb25kcyIsImNhbGxiYWNrIiwiZSIsInJlcyIsInN0YXR1cyIsImhlYWRlcnMiLCJtZXRhZGF0YSIsInJlY29tbWVuZGVkUmV0cnlUaW1lIiwiaXNOYU4iLCJNYXRoIiwibWF4IiwiZ2V0VGltZSIsImJvZHkiLCJfaGFuZGxlRXJyb3IiLCJfaGFuZGxlUmV0cnkiLCJ0cmFuc2l0aW9uYWwiLCJjbGFyaWZ5VGltZW91dEVycm9yIiwiX3dhaXQiLCJwYXVzZSIsIlByb21pc2UiLCJzZXRUaW1lb3V0IiwicmV0cnlBZnRlciIsImVycm9yIiwiaW5jbHVkZXMiLCJuYW1lIiwibWluIiwicG93IiwiX21pblJldHJ5RGVsYXkiLCJyZXRyeVRpbWUiLCJwYXJzZSIsImVycm9yUmVzcG9uc2UiLCJlcnJvckRhdGEiLCJ1cmwiLCJjb25maWciLCJlcnJNc2dEZWZhdWx0IiwibWVzc2FnZSIsImNvZGUiLCJlcnJNc2ciLCJkZXRhaWxzIiwiY29uc3RydWN0b3IiLCJleHRlbmRlZFRpbWVvdXQiLCJyZXRyeU9wdHMiLCJyZXRyaWVzIiwibWluRGVsYXlJblNlY29uZHMiLCJtYXhEZWxheUluU2Vjb25kcyIsIkh0dHBDbGllbnRNb2NrIiwiX3JlcXVlc3RGbiIsImFwcGx5IiwiYXJndW1lbnRzIiwicmVxdWVzdEZuIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLE9BQU9BLFdBQVcsUUFBUTtBQUMxQixTQUNFQyxpQkFBaUIsRUFBRUMsY0FBYyxFQUFFQyxRQUFRLEVBQUVDLGVBQWUsRUFBRUMsYUFBYSxFQUMzRUMsYUFBYSxFQUFFQyxvQkFBb0IsRUFBRUMsYUFBYSxRQUM3Qyw2QkFBNkI7QUFDcEMsT0FBT0Msa0JBQWtCLDZCQUE2QjtBQUt2QyxJQUFBLEFBQU1DLGFBQU4sTUFBTUE7SUF1Qm5COzs7OztHQUtDLEdBQ0QsQUFBTUMsUUFBUUMsT0FBTyxFQUFFQyxpQkFBaUI7O2VBQXhDLG9CQUFBO1lBQ0VELFFBQVFFLE9BQU8sR0FBR0Qsb0JBQW9CLE1BQUtFLGdCQUFnQixHQUFHLE1BQUtDLFFBQVE7WUFDM0UsSUFBSTtnQkFDRixNQUFNQyxXQUFXLE1BQU0sTUFBS0MsWUFBWSxDQUFDTjtnQkFDekMsT0FBTyxBQUFDSyxZQUFZQSxTQUFTRSxJQUFJLElBQUtDO1lBQ3hDLEVBQUUsT0FBT0MsS0FBSztnQkFDWixNQUFNLE1BQUtDLGFBQWEsQ0FBQ0Q7WUFDM0I7UUFDRjs7SUFFQTs7OztHQUlDLEdBQ0QsQUFBTUUsb0JBQW9CWCxPQUFPLEVBQUVZLGVBQWUsQ0FBQyxFQUFFQyxVQUFVQyxLQUFLQyxHQUFHLEtBQUssSUFBSSxDQUFDQyxjQUFjLEdBQUcsSUFBSSxDQUFDQyxRQUFROztlQUEvRyxvQkFBQTtZQUNFakIsUUFBUUUsT0FBTyxHQUFHLE1BQUtFLFFBQVE7WUFDL0IsSUFBSWMsb0JBQW9CO1lBRXhCbEIsUUFBUW1CLFFBQVEsR0FBRyxDQUFDQyxHQUFHQztnQkFDckIsSUFBSUEsT0FBT0EsSUFBSUMsTUFBTSxLQUFLLEtBQUs7d0JBQ3FCRCxvQkFBQUE7d0JBQTlCQTtvQkFBcEJILG9CQUFvQkcsQ0FBQUEsMEJBQUFBLElBQUlFLE9BQU8sQ0FBQyxjQUFjLGNBQTFCRixxQ0FBQUEsMkJBQThCQSxZQUFBQSxJQUFJZCxJQUFJLGNBQVJjLGlDQUFBQSxxQkFBQUEsVUFBVUcsUUFBUSxjQUFsQkgseUNBQUFBLG1CQUFvQkksb0JBQW9CO29CQUMxRixJQUFJQyxNQUFNUixvQkFBb0I7d0JBQzVCQSxvQkFBb0JTLEtBQUtDLEdBQUcsQ0FBQyxBQUFDLENBQUEsSUFBSWQsS0FBS0ksbUJBQW1CVyxPQUFPLEtBQUtmLEtBQUtDLEdBQUcsRUFBQyxJQUFLLE1BQU07b0JBQzVGO2dCQUNGO1lBQ0Y7WUFFQSxJQUFJZTtZQUNKLElBQUk7Z0JBQ0YsTUFBTXpCLFdBQVcsTUFBTSxNQUFLQyxZQUFZLENBQUNOO2dCQUN6Q0EsUUFBUW1CLFFBQVEsQ0FBQyxNQUFNZDtnQkFDdkJ5QixPQUFPLEFBQUN6QixZQUFZQSxTQUFTRSxJQUFJLElBQUtDO1lBQ3hDLEVBQUUsT0FBT0MsS0FBSztnQkFDWkcsZUFBZSxNQUFNLE1BQUttQixZQUFZLENBQUN0QixLQUFLRyxjQUFjQztnQkFDMUQsT0FBTyxNQUFLRixtQkFBbUIsQ0FBQ1gsU0FBU1ksY0FBY0M7WUFDekQ7WUFFQSxJQUFJSyxtQkFBbUI7Z0JBQ3JCLE1BQU0sTUFBS2MsWUFBWSxDQUFDbkIsU0FBU0ssb0JBQW9CO2dCQUNyRFksT0FBTyxNQUFNLE1BQUtuQixtQkFBbUIsQ0FBQ1gsU0FBU1ksY0FBY0M7WUFDL0Q7WUFDQSxPQUFPaUI7UUFDVDs7SUFFQXhCLGFBQWFOLE9BQU8sRUFBRTtRQUNwQixPQUFPWixNQUFNO1lBQ1g2QyxjQUFjO2dCQUNaQyxxQkFBcUI7WUFDdkI7V0FDR2xDO0lBRVA7SUFFTW1DLE1BQU1DLEtBQUs7ZUFBakIsb0JBQUE7WUFDRSxNQUFNLElBQUlDLFFBQVFoQixDQUFBQSxNQUFPaUIsV0FBV2pCLEtBQUtlO1FBQzNDOztJQUVNSixhQUFhbkIsT0FBTyxFQUFFMEIsVUFBVTs7ZUFBdEMsb0JBQUE7WUFDRSxJQUFJMUIsVUFBVUMsS0FBS0MsR0FBRyxLQUFLd0IsWUFBWTtnQkFDckMsTUFBTSxNQUFLSixLQUFLLENBQUNJO1lBQ25CLE9BQU87Z0JBQ0wsTUFBTSxJQUFJMUMsYUFBYTtZQUN6QjtRQUNGOztJQUVNa0MsYUFBYXRCLEdBQUcsRUFBRUcsWUFBWSxFQUFFQyxPQUFPOztlQUE3QyxvQkFBQTtZQUNFLE1BQU0yQixRQUFRLE1BQUs5QixhQUFhLENBQUNEO1lBQ2pDLElBQUk7Z0JBQUM7Z0JBQWlCO2dCQUFpQjtnQkFBWTthQUFlLENBQUNnQyxRQUFRLENBQUNELE1BQU1FLElBQUksS0FDakY5QixlQUFlLE1BQUtLLFFBQVEsRUFBRTtnQkFDakMsTUFBTW1CLFFBQVFULEtBQUtnQixHQUFHLENBQUNoQixLQUFLaUIsR0FBRyxDQUFDLEdBQUdoQyxnQkFBZ0IsTUFBS2lDLGNBQWMsRUFBRSxNQUFLN0IsY0FBYztnQkFDM0YsTUFBTSxNQUFLbUIsS0FBSyxDQUFDQztnQkFDakIsT0FBT3hCLGVBQWU7WUFDeEIsT0FBTyxJQUFJNEIsTUFBTUUsSUFBSSxLQUFLLHdCQUF3QjtnQkFDaEQsTUFBTUksWUFBWWhDLEtBQUtpQyxLQUFLLENBQUNQLE1BQU1oQixRQUFRLENBQUNDLG9CQUFvQjtnQkFDaEUsSUFBSXFCLFlBQVlqQyxTQUFTO29CQUN2QixNQUFNLE1BQUtzQixLQUFLLENBQUNXLFlBQVloQyxLQUFLQyxHQUFHO29CQUNyQyxPQUFPSDtnQkFDVDtZQUNGO1lBQ0EsTUFBTTRCO1FBQ1I7O0lBRUEsc0NBQXNDO0lBQ3RDOUIsY0FBY0QsR0FBRyxFQUFFO1lBSUxBO1FBSFosTUFBTXVDLGdCQUFnQnZDLElBQUlKLFFBQVEsSUFBSSxDQUFDO1FBQ3ZDLE1BQU00QyxZQUFZRCxjQUFjekMsSUFBSSxJQUFJLENBQUM7UUFDekMsTUFBTWUsU0FBUzBCLGNBQWMxQixNQUFNLElBQUliLElBQUlhLE1BQU07UUFDakQsTUFBTTRCLE1BQU16QyxnQkFBQUEsMkJBQUFBLGNBQUFBLElBQUswQyxNQUFNLGNBQVgxQyxrQ0FBQUEsWUFBYXlDLEdBQUc7UUFFNUIsTUFBTUUsZ0JBQWdCSCxVQUFVSSxPQUFPLElBQUk1QyxJQUFJNkMsSUFBSSxJQUFJN0MsSUFBSTRDLE9BQU87UUFDbEUsTUFBTUUsU0FBU04sVUFBVUksT0FBTyxJQUFJNUMsSUFBSTRDLE9BQU87UUFFL0MsT0FBUS9CO1lBQ1IsS0FBSztnQkFDSCxPQUFPLElBQUk5QixnQkFBZ0IrRCxRQUFRTixVQUFVTyxPQUFPLElBQUkvQyxJQUFJK0MsT0FBTyxFQUFFTjtZQUN2RSxLQUFLO2dCQUNILE9BQU8sSUFBSTdELGtCQUFrQmtFLFFBQVFMO1lBQ3ZDLEtBQUs7Z0JBQ0gsT0FBTyxJQUFJNUQsZUFBZWlFLFFBQVFMO1lBQ3BDLEtBQUs7Z0JBQ0gsT0FBTyxJQUFJeEQsY0FBYzZELFFBQVFMO1lBQ25DLEtBQUs7Z0JBQ0gsT0FBTyxJQUFJdEQsY0FBYzJELFFBQVFMO1lBQ25DLEtBQUs7Z0JBQ0gsT0FBTyxJQUFJdkQscUJBQXFCNEQsUUFBUU4sVUFBVXpCLFFBQVEsSUFBSWYsSUFBSWUsUUFBUSxFQUFFMEI7WUFDOUUsS0FBSztnQkFDSCxPQUFPLElBQUl6RCxjQUFjOEQsUUFBUUw7WUFDbkM7Z0JBQ0UsT0FBTyxJQUFJM0QsU0FBU0EsVUFBVTZELGVBQWU5QixRQUFRNEI7UUFDdkQ7SUFDRjtJQTFJQTs7Ozs7R0FLQyxHQUVEOzs7OztHQUtDLEdBQ0RPLFlBQVl2RCxVQUFVLEVBQUUsRUFBRXdELGtCQUFrQixFQUFFLEVBQUVDLFlBQVksQ0FBQyxDQUFDLENBQUU7UUFDOUQsSUFBSSxDQUFDdkQsUUFBUSxHQUFHRixVQUFVO1FBQzFCLElBQUksQ0FBQ0MsZ0JBQWdCLEdBQUd1RCxrQkFBa0I7UUFDMUMsSUFBSSxDQUFDekMsUUFBUSxHQUFHMEMsVUFBVUMsT0FBTyxJQUFJO1FBQ3JDLElBQUksQ0FBQ2YsY0FBYyxHQUFHLEFBQUNjLENBQUFBLFVBQVVFLGlCQUFpQixJQUFJLENBQUEsSUFBSztRQUMzRCxJQUFJLENBQUM3QyxjQUFjLEdBQUcsQUFBQzJDLENBQUFBLFVBQVVHLGlCQUFpQixJQUFJLEVBQUMsSUFBSztJQUM5RDtBQXdIRjtBQWhKQTs7Q0FFQyxHQUNELFNBQXFCaEUsd0JBNklwQjtBQUVEOztDQUVDLEdBQ0QsT0FBTyxNQUFNaUUsdUJBQXVCakU7SUFZbENRLGVBQWU7UUFDYixPQUFPLElBQUksQ0FBQzBELFVBQVUsQ0FBQ0MsS0FBSyxDQUFDLElBQUksRUFBRUM7SUFDckM7SUFiQTs7Ozs7R0FLQyxHQUNEVCxZQUFZVSxTQUFTLEVBQUVqRSxPQUFPLEVBQUV3RCxlQUFlLEVBQUVDLFNBQVMsQ0FBRTtRQUMxRCxLQUFLLENBQUN6RCxTQUFTd0QsaUJBQWlCQztRQUNoQyxJQUFJLENBQUNLLFVBQVUsR0FBR0c7SUFDcEI7QUFNRiJ9