metaapi.cloud-copyfactory-sdk
Version:
Javascript SDK for SDK for CopyFactory trade copying API. Can copy trades both between MetaTrader 5 (MT5) and MetaTrader 4 (MT4). (https://metaapi.cloud)
242 lines (241 loc) • 23 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);
});
};
}
import any from 'promise.any';
let DomainClient = class DomainClient {
/**
* Returns domain client domain
* @returns {String} client domain
*/ get domain() {
return this._domain;
}
/**
* Returns domain client token
* @returns {String} client token
*/ get token() {
return this._token;
}
/**
* Sends a CopyFactory API request
* @param {Object} opts options request options
* @param {Boolean} isExtendedTimeout whether to run the request with an extended timeout
* @returns {Object|String|any} request result
*/ requestCopyFactory(opts, isExtendedTimeout = false) {
var _this = this;
return _async_to_generator(function*() {
yield _this._updateHost();
const regionIndex = _this._regionIndex;
try {
return yield _this._httpClient.request(Object.assign({}, opts, {
url: _this._urlCache.url + opts.url
}), isExtendedTimeout);
} catch (err) {
if (![
'ConflictError',
'InternalError',
'ApiError',
'TimeoutError'
].includes(err.name)) {
throw err;
} else {
if (_this._regionCache.length === _this._regionIndex + 1) {
_this._regionIndex = 0;
throw err;
} else {
if (_this._regionIndex === regionIndex) {
_this._regionIndex++;
}
return yield _this.requestCopyFactory(opts, isExtendedTimeout);
}
}
}
})();
}
/**
* Sends an http request
* @param {Object} opts options request options
* @returns {Object|String|any} request result
*/ request(opts) {
return this._httpClient.request(opts);
}
/**
* Sends a signal client request
* @param {Object} opts options request options
* @param {Object} host signal client host data
* @param {String} accountId account id
* @returns {Object|String|any} request result
*/ requestSignal(opts, host, accountId) {
var _this = this;
return _async_to_generator(function*() {
_this._updateAccountRegions(host, accountId);
try {
return yield any(host.regions.map((region)=>{
return _this._httpClient.requestWithFailover(Object.assign({}, opts, {
url: `${host.host}.${region}.${host.domain}` + opts.url,
headers: {
'auth-token': _this._token
}
}));
}));
} catch (error) {
throw error.errors[0];
}
})();
}
/**
* Returns CopyFactory host for signal client requests
* @param {String[]} regions subscriber regions
* @returns {String} signal client CopyFactory host
*/ getSignalClientHost(regions) {
var _this = this;
return _async_to_generator(function*() {
yield _this._updateHost();
return {
host: 'https://copyfactory-api-v1',
regions,
lastUpdated: Date.now(),
domain: _this._urlCache.domain
};
})();
}
/**
* Account request info
* @typedef {Object} AccountInfo
* @property {String} id primary account id
* @property {String[]} regions account available regions
*/ /**
* Returns account data by id
* @param {String} accountId account id
* @returns {AccountInfo} account data
*/ getAccountInfo(accountId) {
var _this = this;
return _async_to_generator(function*() {
const getAccount = function() {
var _ref = _async_to_generator(function*(id) {
const accountOpts = {
url: `https://mt-provisioning-api-v1.${_this.domain}/users/current/accounts/${id}`,
method: 'GET',
headers: {
'auth-token': _this.token
},
json: true
};
return yield _this._httpClient.requestWithFailover(accountOpts);
});
return function getAccount(id) {
return _ref.apply(this, arguments);
};
}();
let accountData = yield getAccount(accountId);
let primaryAccountId = '';
if (accountData.primaryAccountId) {
primaryAccountId = accountData.primaryAccountId;
accountData = yield getAccount(primaryAccountId);
} else {
primaryAccountId = accountData._id;
}
let regions = [
accountData.region
].concat(accountData.accountReplicas && accountData.accountReplicas.map((replica)=>replica.region) || []);
return {
id: primaryAccountId,
regions
};
})();
}
_updateHost() {
var _this = this;
return _async_to_generator(function*() {
if (!_this._urlCache || _this._urlCache.lastUpdated < Date.now() - 1000 * 60 * 10) {
yield _this._updateRegions();
const urlSettings = yield _this._httpClient.request({
url: `https://mt-provisioning-api-v1.${_this._domain}/users/current/servers/mt-client-api`,
method: 'GET',
headers: {
'auth-token': _this._token
},
json: true
});
_this._urlCache = {
url: `https://copyfactory-api-v1.${_this._regionCache[_this._regionIndex]}.${urlSettings.domain}`,
domain: urlSettings.domain,
lastUpdated: Date.now()
};
} else {
_this._urlCache = {
url: `https://copyfactory-api-v1.${_this._regionCache[_this._regionIndex]}.${_this._urlCache.domain}`,
domain: _this._urlCache.domain,
lastUpdated: Date.now()
};
}
})();
}
_updateRegions() {
var _this = this;
return _async_to_generator(function*() {
_this._regionCache = yield _this._httpClient.request({
url: `https://mt-provisioning-api-v1.${_this._domain}/users/current/regions`,
method: 'GET',
headers: {
'auth-token': _this._token
},
json: true
});
_this._regionIndex = 0;
})();
}
_updateAccountRegions(host, accountId) {
var _this = this;
return _async_to_generator(function*() {
if (host.lastUpdated < Date.now() - 1000 * 60 * 10) {
const accountData = yield _this.getAccountInfo(accountId);
host.lastUpdated = Date.now();
host.regions = accountData.regions;
}
})();
}
/**
* Constructs domain client instance
* @param {HttpClient} httpClient HTTP client
* @param {String} token authorization token
* @param {String} domain domain to connect to, default is agiliumtrade.agiliumtrade.ai
*/ constructor(httpClient, token, domain = 'agiliumtrade.agiliumtrade.ai'){
this._httpClient = httpClient;
this._domain = domain;
this._token = token;
this._urlCache = null;
this._regionCache = [];
this._regionIndex = 0;
}
};
/**
* Connection URL and request managing client
*/ export { DomainClient as default };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBhbnkgZnJvbSAncHJvbWlzZS5hbnknO1xuXG4vKipcbiAqIENvbm5lY3Rpb24gVVJMIGFuZCByZXF1ZXN0IG1hbmFnaW5nIGNsaWVudFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEb21haW5DbGllbnQge1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGRvbWFpbiBjbGllbnQgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtIdHRwQ2xpZW50fSBodHRwQ2xpZW50IEhUVFAgY2xpZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0b2tlbiBhdXRob3JpemF0aW9uIHRva2VuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkb21haW4gZG9tYWluIHRvIGNvbm5lY3QgdG8sIGRlZmF1bHQgaXMgYWdpbGl1bXRyYWRlLmFnaWxpdW10cmFkZS5haVxuICAgKi9cbiAgY29uc3RydWN0b3IoaHR0cENsaWVudCwgdG9rZW4sIGRvbWFpbiA9ICdhZ2lsaXVtdHJhZGUuYWdpbGl1bXRyYWRlLmFpJykge1xuICAgIHRoaXMuX2h0dHBDbGllbnQgPSBodHRwQ2xpZW50O1xuICAgIHRoaXMuX2RvbWFpbiA9IGRvbWFpbjtcbiAgICB0aGlzLl90b2tlbiA9IHRva2VuO1xuICAgIHRoaXMuX3VybENhY2hlID0gbnVsbDtcbiAgICB0aGlzLl9yZWdpb25DYWNoZSA9IFtdO1xuICAgIHRoaXMuX3JlZ2lvbkluZGV4ID0gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGRvbWFpbiBjbGllbnQgZG9tYWluXG4gICAqIEByZXR1cm5zIHtTdHJpbmd9IGNsaWVudCBkb21haW5cbiAgICovXG4gIGdldCBkb21haW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2RvbWFpbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGRvbWFpbiBjbGllbnQgdG9rZW5cbiAgICogQHJldHVybnMge1N0cmluZ30gY2xpZW50IHRva2VuXG4gICAqL1xuICBnZXQgdG9rZW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Rva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGEgQ29weUZhY3RvcnkgQVBJIHJlcXVlc3RcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgb3B0aW9ucyByZXF1ZXN0IG9wdGlvbnNcbiAgICogQHBhcmFtIHtCb29sZWFufSBpc0V4dGVuZGVkVGltZW91dCB3aGV0aGVyIHRvIHJ1biB0aGUgcmVxdWVzdCB3aXRoIGFuIGV4dGVuZGVkIHRpbWVvdXRcbiAgICogQHJldHVybnMge09iamVjdHxTdHJpbmd8YW55fSByZXF1ZXN0IHJlc3VsdFxuICAgKi9cbiAgYXN5bmMgcmVxdWVzdENvcHlGYWN0b3J5KG9wdHMsIGlzRXh0ZW5kZWRUaW1lb3V0ID0gZmFsc2UpIHtcbiAgICBhd2FpdCB0aGlzLl91cGRhdGVIb3N0KCk7XG4gICAgY29uc3QgcmVnaW9uSW5kZXggPSB0aGlzLl9yZWdpb25JbmRleDtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChPYmplY3QuYXNzaWduKHt9LCBvcHRzLCB7XG4gICAgICAgIHVybDogdGhpcy5fdXJsQ2FjaGUudXJsICsgb3B0cy51cmxcbiAgICAgIH0pLCBpc0V4dGVuZGVkVGltZW91dCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZighWydDb25mbGljdEVycm9yJywgJ0ludGVybmFsRXJyb3InLCAnQXBpRXJyb3InLCAnVGltZW91dEVycm9yJ10uaW5jbHVkZXMoZXJyLm5hbWUpKSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKHRoaXMuX3JlZ2lvbkNhY2hlLmxlbmd0aCA9PT0gdGhpcy5fcmVnaW9uSW5kZXggKyAxKSB7XG4gICAgICAgICAgdGhpcy5fcmVnaW9uSW5kZXggPSAwO1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZih0aGlzLl9yZWdpb25JbmRleCA9PT0gcmVnaW9uSW5kZXgpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlZ2lvbkluZGV4Kys7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJlcXVlc3RDb3B5RmFjdG9yeShvcHRzLCBpc0V4dGVuZGVkVGltZW91dCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kcyBhbiBodHRwIHJlcXVlc3RcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgb3B0aW9ucyByZXF1ZXN0IG9wdGlvbnNcbiAgICogQHJldHVybnMge09iamVjdHxTdHJpbmd8YW55fSByZXF1ZXN0IHJlc3VsdFxuICAgKi9cbiAgcmVxdWVzdChvcHRzKSB7XG4gICAgcmV0dXJuIHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChvcHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kcyBhIHNpZ25hbCBjbGllbnQgcmVxdWVzdFxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyBvcHRpb25zIHJlcXVlc3Qgb3B0aW9ucyBcbiAgICogQHBhcmFtIHtPYmplY3R9IGhvc3Qgc2lnbmFsIGNsaWVudCBob3N0IGRhdGFcbiAgICogQHBhcmFtIHtTdHJpbmd9IGFjY291bnRJZCBhY2NvdW50IGlkXG4gICAqIEByZXR1cm5zIHtPYmplY3R8U3RyaW5nfGFueX0gcmVxdWVzdCByZXN1bHRcbiAgICovXG4gIGFzeW5jIHJlcXVlc3RTaWduYWwob3B0cywgaG9zdCwgYWNjb3VudElkKSB7XG4gICAgdGhpcy5fdXBkYXRlQWNjb3VudFJlZ2lvbnMoaG9zdCwgYWNjb3VudElkKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGFueShob3N0LnJlZ2lvbnMubWFwKHJlZ2lvbiA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3RXaXRoRmFpbG92ZXIoT2JqZWN0LmFzc2lnbih7fSwgb3B0cywge1xuICAgICAgICAgIHVybDogYCR7aG9zdC5ob3N0fS4ke3JlZ2lvbn0uJHtob3N0LmRvbWFpbn1gICsgb3B0cy51cmwsXG4gICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgICAgIH0sXG4gICAgICAgIH0pKTtcbiAgICAgIH0pKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgZXJyb3IuZXJyb3JzWzBdOyBcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBDb3B5RmFjdG9yeSBob3N0IGZvciBzaWduYWwgY2xpZW50IHJlcXVlc3RzXG4gICAqIEBwYXJhbSB7U3RyaW5nW119IHJlZ2lvbnMgc3Vic2NyaWJlciByZWdpb25zXG4gICAqIEByZXR1cm5zIHtTdHJpbmd9IHNpZ25hbCBjbGllbnQgQ29weUZhY3RvcnkgaG9zdFxuICAgKi9cbiAgYXN5bmMgZ2V0U2lnbmFsQ2xpZW50SG9zdChyZWdpb25zKSB7XG4gICAgYXdhaXQgdGhpcy5fdXBkYXRlSG9zdCgpO1xuICAgIHJldHVybiB7XG4gICAgICBob3N0OiAnaHR0cHM6Ly9jb3B5ZmFjdG9yeS1hcGktdjEnLFxuICAgICAgcmVnaW9ucyxcbiAgICAgIGxhc3RVcGRhdGVkOiBEYXRlLm5vdygpLFxuICAgICAgZG9tYWluOiB0aGlzLl91cmxDYWNoZS5kb21haW5cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFjY291bnQgcmVxdWVzdCBpbmZvXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IEFjY291bnRJbmZvXG4gICAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBpZCBwcmltYXJ5IGFjY291bnQgaWRcbiAgICogQHByb3BlcnR5IHtTdHJpbmdbXX0gcmVnaW9ucyBhY2NvdW50IGF2YWlsYWJsZSByZWdpb25zXG4gICAqL1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFjY291bnQgZGF0YSBieSBpZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gYWNjb3VudElkIGFjY291bnQgaWRcbiAgICogQHJldHVybnMge0FjY291bnRJbmZvfSBhY2NvdW50IGRhdGFcbiAgICovXG4gIGFzeW5jIGdldEFjY291bnRJbmZvKGFjY291bnRJZCkge1xuICAgIGNvbnN0IGdldEFjY291bnQgPSBhc3luYyAoaWQpID0+IHtcbiAgICAgIGNvbnN0IGFjY291bnRPcHRzID0ge1xuICAgICAgICB1cmw6IGBodHRwczovL210LXByb3Zpc2lvbmluZy1hcGktdjEuJHt0aGlzLmRvbWFpbn0vdXNlcnMvY3VycmVudC9hY2NvdW50cy8ke2lkfWAsXG4gICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAnYXV0aC10b2tlbic6IHRoaXMudG9rZW5cbiAgICAgICAgfSxcbiAgICAgICAganNvbjogdHJ1ZVxuICAgICAgfTtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3RXaXRoRmFpbG92ZXIoYWNjb3VudE9wdHMpO1xuICAgIH07XG5cbiAgICBsZXQgYWNjb3VudERhdGEgPSBhd2FpdCBnZXRBY2NvdW50KGFjY291bnRJZCk7XG4gICAgbGV0IHByaW1hcnlBY2NvdW50SWQgPSAnJztcbiAgICBpZihhY2NvdW50RGF0YS5wcmltYXJ5QWNjb3VudElkKSB7XG4gICAgICBwcmltYXJ5QWNjb3VudElkID0gYWNjb3VudERhdGEucHJpbWFyeUFjY291bnRJZDtcbiAgICAgIGFjY291bnREYXRhID0gYXdhaXQgZ2V0QWNjb3VudChwcmltYXJ5QWNjb3VudElkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJpbWFyeUFjY291bnRJZCA9IGFjY291bnREYXRhLl9pZDtcbiAgICB9XG5cbiAgICBsZXQgcmVnaW9ucyA9IFthY2NvdW50RGF0YS5yZWdpb25dLmNvbmNhdChhY2NvdW50RGF0YS5hY2NvdW50UmVwbGljYXMgJiYgXG4gICAgICBhY2NvdW50RGF0YS5hY2NvdW50UmVwbGljYXMubWFwKHJlcGxpY2EgPT4gcmVwbGljYS5yZWdpb24pIHx8IFtdKTtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IHByaW1hcnlBY2NvdW50SWQsXG4gICAgICByZWdpb25zXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIF91cGRhdGVIb3N0KCkge1xuICAgIGlmKCF0aGlzLl91cmxDYWNoZSB8fCB0aGlzLl91cmxDYWNoZS5sYXN0VXBkYXRlZCA8IERhdGUubm93KCkgLSAxMDAwICogNjAgKiAxMCkge1xuICAgICAgYXdhaXQgdGhpcy5fdXBkYXRlUmVnaW9ucygpO1xuICAgICAgY29uc3QgdXJsU2V0dGluZ3MgPSBhd2FpdCB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3Qoe1xuICAgICAgICB1cmw6IGBodHRwczovL210LXByb3Zpc2lvbmluZy1hcGktdjEuJHt0aGlzLl9kb21haW59L3VzZXJzL2N1cnJlbnQvc2VydmVycy9tdC1jbGllbnQtYXBpYCxcbiAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW5cbiAgICAgICAgfSxcbiAgICAgICAganNvbjogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fdXJsQ2FjaGUgPSB7XG4gICAgICAgIHVybDogYGh0dHBzOi8vY29weWZhY3RvcnktYXBpLXYxLiR7dGhpcy5fcmVnaW9uQ2FjaGVbdGhpcy5fcmVnaW9uSW5kZXhdfS4ke3VybFNldHRpbmdzLmRvbWFpbn1gLFxuICAgICAgICBkb21haW46IHVybFNldHRpbmdzLmRvbWFpbixcbiAgICAgICAgbGFzdFVwZGF0ZWQ6IERhdGUubm93KClcbiAgICAgIH07IFxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl91cmxDYWNoZSA9IHtcbiAgICAgICAgdXJsOiBgaHR0cHM6Ly9jb3B5ZmFjdG9yeS1hcGktdjEuJHt0aGlzLl9yZWdpb25DYWNoZVt0aGlzLl9yZWdpb25JbmRleF19LiR7dGhpcy5fdXJsQ2FjaGUuZG9tYWlufWAsXG4gICAgICAgIGRvbWFpbjogdGhpcy5fdXJsQ2FjaGUuZG9tYWluLFxuICAgICAgICBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKVxuICAgICAgfTsgXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX3VwZGF0ZVJlZ2lvbnMoKSB7XG4gICAgdGhpcy5fcmVnaW9uQ2FjaGUgPSBhd2FpdCB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3Qoe1xuICAgICAgdXJsOiBgaHR0cHM6Ly9tdC1wcm92aXNpb25pbmctYXBpLXYxLiR7dGhpcy5fZG9tYWlufS91c2Vycy9jdXJyZW50L3JlZ2lvbnNgLFxuICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWUsXG4gICAgfSk7XG4gICAgdGhpcy5fcmVnaW9uSW5kZXggPSAwO1xuICB9XG5cbiAgYXN5bmMgX3VwZGF0ZUFjY291bnRSZWdpb25zKGhvc3QsIGFjY291bnRJZCkge1xuICAgIGlmKGhvc3QubGFzdFVwZGF0ZWQgPCBEYXRlLm5vdygpIC0gMTAwMCAqIDYwICogMTApIHtcbiAgICAgIGNvbnN0IGFjY291bnREYXRhID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50SW5mbyhhY2NvdW50SWQpO1xuICAgICAgaG9zdC5sYXN0VXBkYXRlZCA9IERhdGUubm93KCk7XG4gICAgICBob3N0LnJlZ2lvbnMgPSBhY2NvdW50RGF0YS5yZWdpb25zO1xuICAgIH1cbiAgfVxuXG59Il0sIm5hbWVzIjpbImFueSIsIkRvbWFpbkNsaWVudCIsImRvbWFpbiIsIl9kb21haW4iLCJ0b2tlbiIsIl90b2tlbiIsInJlcXVlc3RDb3B5RmFjdG9yeSIsIm9wdHMiLCJpc0V4dGVuZGVkVGltZW91dCIsIl91cGRhdGVIb3N0IiwicmVnaW9uSW5kZXgiLCJfcmVnaW9uSW5kZXgiLCJfaHR0cENsaWVudCIsInJlcXVlc3QiLCJPYmplY3QiLCJhc3NpZ24iLCJ1cmwiLCJfdXJsQ2FjaGUiLCJlcnIiLCJpbmNsdWRlcyIsIm5hbWUiLCJfcmVnaW9uQ2FjaGUiLCJsZW5ndGgiLCJyZXF1ZXN0U2lnbmFsIiwiaG9zdCIsImFjY291bnRJZCIsIl91cGRhdGVBY2NvdW50UmVnaW9ucyIsInJlZ2lvbnMiLCJtYXAiLCJyZWdpb24iLCJyZXF1ZXN0V2l0aEZhaWxvdmVyIiwiaGVhZGVycyIsImVycm9yIiwiZXJyb3JzIiwiZ2V0U2lnbmFsQ2xpZW50SG9zdCIsImxhc3RVcGRhdGVkIiwiRGF0ZSIsIm5vdyIsImdldEFjY291bnRJbmZvIiwiZ2V0QWNjb3VudCIsImlkIiwiYWNjb3VudE9wdHMiLCJtZXRob2QiLCJqc29uIiwiYWNjb3VudERhdGEiLCJwcmltYXJ5QWNjb3VudElkIiwiX2lkIiwiY29uY2F0IiwiYWNjb3VudFJlcGxpY2FzIiwicmVwbGljYSIsIl91cGRhdGVSZWdpb25zIiwidXJsU2V0dGluZ3MiLCJjb25zdHJ1Y3RvciIsImh0dHBDbGllbnQiXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxPQUFPQSxTQUFTLGNBQWM7QUFLZixJQUFBLEFBQU1DLGVBQU4sTUFBTUE7SUFpQm5COzs7R0FHQyxHQUNELElBQUlDLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQ0MsT0FBTztJQUNyQjtJQUVBOzs7R0FHQyxHQUNELElBQUlDLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQ0MsTUFBTTtJQUNwQjtJQUVBOzs7OztHQUtDLEdBQ0QsQUFBTUMsbUJBQW1CQyxJQUFJLEVBQUVDLG9CQUFvQixLQUFLOztlQUF4RCxvQkFBQSxZQUEwRDtZQUN4RCxNQUFNLE1BQUtDLFdBQVc7WUFDdEIsTUFBTUMsY0FBYyxNQUFLQyxZQUFZO1lBQ3JDLElBQUk7Z0JBQ0YsT0FBTyxNQUFNLE1BQUtDLFdBQVcsQ0FBQ0MsT0FBTyxDQUFDQyxPQUFPQyxNQUFNLENBQUMsQ0FBQyxHQUFHUixNQUFNO29CQUM1RFMsS0FBSyxNQUFLQyxTQUFTLENBQUNELEdBQUcs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