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)
205 lines (204 loc) • 21.8 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 SynchronizationListener from '../clients/metaApi/synchronizationListener';
let HistoryStorage = class HistoryStorage extends SynchronizationListener {
/**
* Initializes the storage and loads required data from a persistent storage
* @param {string} accountId account id
* @param {string} application application
* @returns {Promise} promise resolving when history storage is initialized
*/ initialize(accountId, application) {
var _this = this;
return _async_to_generator(function*() {
_this._accountId = accountId;
_this._application = application;
})();
}
/**
* Returns flag indicating whether order history synchronization have finished
* @return {Boolean} flag indicating whether order history synchronization have finished
*/ get orderSynchronizationFinished() {
return Object.values(this._orderSynchronizationFinished).reduce((acc, r)=>acc || r, false);
}
/**
* Returns flag indicating whether deal history synchronization have finished
* @return {Boolean} flag indicating whether deal history synchronization have finished
*/ get dealSynchronizationFinished() {
return Object.values(this._dealSynchronizationFinished).reduce((acc, r)=>acc || r, false);
}
/**
* Clears the storage and deletes persistent data
* @returns {Promise} promise resolving when history storage is cleared
*/ clear() {
return _async_to_generator(function*() {
throw Error('Abstract method clear has no implementation');
})();
}
/**
* Returns the time of the last history order record stored in the history storage
* @param {String} [instanceIndex] index of an account instance connected
* @returns {Promise<Date>} the time of the last history order record stored in the history storage
*/ lastHistoryOrderTime(instanceIndex) {
return _async_to_generator(function*() {
throw Error('Abstract method lastHistoryOrderTime has no implementation');
})();
}
/**
* Returns the time of the last history deal record stored in the history storage
* @param {String} [instanceIndex] index of an account instance connected
* @returns {Promise<Date>} the time of the last history deal record stored in the history storage
*/ lastDealTime(instanceIndex) {
return _async_to_generator(function*() {
throw Error('Abstract method lastDealTime has no implementation');
})();
}
/**
* Invoked when a new MetaTrader history order is added
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderOrder} historyOrder new MetaTrader history order
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ onHistoryOrderAdded(instanceIndex, historyOrder) {
return _async_to_generator(function*() {
throw Error('Abstract method onHistoryOrderAdded has no implementation');
})();
}
/**
* Invoked when a new MetaTrader history deal is added
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderDeal} deal new MetaTrader history deal
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ onDealAdded(instanceIndex, deal) {
return _async_to_generator(function*() {
throw Error('Abstract method onDealAdded has no implementation');
})();
}
/**
* Invoked when a synchronization of history deals on a MetaTrader account have finished to indicate progress of an
* initial terminal state synchronization
* @param {String} instanceIndex index of an account instance connected
* @param {String} synchronizationId synchronization request id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ onDealsSynchronized(instanceIndex, synchronizationId) {
var _this = this;
return _async_to_generator(function*() {
const instance = _this.getInstanceNumber(instanceIndex);
_this._dealSynchronizationFinished['' + instance] = true;
})();
}
/**
* Invoked when a synchronization of history orders on a MetaTrader account have finished to indicate progress of an
* initial terminal state synchronization
* @param {String} instanceIndex index of an account instance connected
* @param {String} synchronizationId synchronization request id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ onHistoryOrdersSynchronized(instanceIndex, synchronizationId) {
var _this = this;
return _async_to_generator(function*() {
const instance = _this.getInstanceNumber(instanceIndex);
_this._orderSynchronizationFinished['' + instance] = true;
})();
}
/**
* Invoked when connection to MetaTrader terminal established
* @param {String} instanceIndex index of an account instance connected
*/ onConnected(instanceIndex) {
const instance = this.getInstanceNumber(instanceIndex);
this._orderSynchronizationFinished['' + instance] = false;
this._dealSynchronizationFinished['' + instance] = false;
}
/**
* Returns all deals
* @returns {Array<MetatraderDeal>} all deals
*/ get deals() {
throw Error('Abstract property deals has no implementation');
}
/**
* Returns deals by ticket id
* @param {string} id ticket id
* @returns {Array<MetatraderDeal>} deals found
*/ getDealsByTicket(id) {
throw Error('Abstract method getDealsByTicket has no implementation');
}
/**
* Returns deals by position id
* @param {string} positionId position id
* @returns {Array<MetatraderDeal>} deals found
*/ getDealsByPosition(positionId) {
throw Error('Abstract method getDealsByPosition has no implementation');
}
/**
* Returns deals by time range
* @param startTime start time, inclusive
* @param endTime end time, inclusive
* @returns {Array<MetatraderDeal>} deals found
*/ getDealsByTimeRange(startTime, endTime) {
throw Error('Abstract method getDealsByTimeRange has no implementation');
}
/**
* Returns all history orders
* @returns {Array<MetatraderOrder>} all history orders
*/ get historyOrders() {
throw Error('Abstract property historyOrders has no implementation');
}
/**
* Returns history orders by ticket id
* @param {string} id ticket id
* @returns {Array<MetatraderOrder>} history orders found
*/ getHistoryOrdersByTicket(id) {
throw Error('Abstract method getHistoryOrdersByTicket has no implementation');
}
/**
* Returns history orders by position id
* @param {string} positionId position id
* @returns {Array<MetatraderOrder>} history orders found
*/ getHistoryOrdersByPosition(positionId) {
throw Error('Abstract method getHistoryOrdersByPosition has no implementation');
}
/**
* Returns history orders by time range
* @param startTime start time, inclusive
* @param endTime end time, inclusive
* @returns {Array<MetatraderOrder>} hisotry orders found
*/ getHistoryOrdersByTimeRange(startTime, endTime) {
throw Error('Abstract method getHistoryOrdersByTimeRange has no implementation');
}
/**
* Constructs the history storage
*/ constructor(){
super();
this._orderSynchronizationFinished = {};
this._dealSynchronizationFinished = {};
}
};
/**
* Abstract class which defines MetaTrader history storage interface.
*/ export { HistoryStorage as default };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBTeW5jaHJvbml6YXRpb25MaXN0ZW5lciBmcm9tICcuLi9jbGllbnRzL21ldGFBcGkvc3luY2hyb25pemF0aW9uTGlzdGVuZXInO1xuXG4vKipcbiAqIEFic3RyYWN0IGNsYXNzIHdoaWNoIGRlZmluZXMgTWV0YVRyYWRlciBoaXN0b3J5IHN0b3JhZ2UgaW50ZXJmYWNlLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBIaXN0b3J5U3RvcmFnZSBleHRlbmRzIFN5bmNocm9uaXphdGlvbkxpc3RlbmVyIHtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyB0aGUgaGlzdG9yeSBzdG9yYWdlXG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuX29yZGVyU3luY2hyb25pemF0aW9uRmluaXNoZWQgPSB7fTtcbiAgICB0aGlzLl9kZWFsU3luY2hyb25pemF0aW9uRmluaXNoZWQgPSB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplcyB0aGUgc3RvcmFnZSBhbmQgbG9hZHMgcmVxdWlyZWQgZGF0YSBmcm9tIGEgcGVyc2lzdGVudCBzdG9yYWdlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhY2NvdW50SWQgYWNjb3VudCBpZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXBwbGljYXRpb24gYXBwbGljYXRpb25cbiAgICogQHJldHVybnMge1Byb21pc2V9IHByb21pc2UgcmVzb2x2aW5nIHdoZW4gaGlzdG9yeSBzdG9yYWdlIGlzIGluaXRpYWxpemVkXG4gICAqL1xuICBhc3luYyBpbml0aWFsaXplKGFjY291bnRJZCwgYXBwbGljYXRpb24pIHtcbiAgICB0aGlzLl9hY2NvdW50SWQgPSBhY2NvdW50SWQ7XG4gICAgdGhpcy5fYXBwbGljYXRpb24gPSBhcHBsaWNhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIG9yZGVyIGhpc3Rvcnkgc3luY2hyb25pemF0aW9uIGhhdmUgZmluaXNoZWRcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gZmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgb3JkZXIgaGlzdG9yeSBzeW5jaHJvbml6YXRpb24gaGF2ZSBmaW5pc2hlZFxuICAgKi9cbiAgZ2V0IG9yZGVyU3luY2hyb25pemF0aW9uRmluaXNoZWQoKSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5fb3JkZXJTeW5jaHJvbml6YXRpb25GaW5pc2hlZCkucmVkdWNlKChhY2MsIHIpID0+IGFjYyB8fCByLCBmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBmbGFnIGluZGljYXRpbmcgd2hldGhlciBkZWFsIGhpc3Rvcnkgc3luY2hyb25pemF0aW9uIGhhdmUgZmluaXNoZWRcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gZmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgZGVhbCBoaXN0b3J5IHN5bmNocm9uaXphdGlvbiBoYXZlIGZpbmlzaGVkXG4gICAqL1xuICBnZXQgZGVhbFN5bmNocm9uaXphdGlvbkZpbmlzaGVkKCkge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuX2RlYWxTeW5jaHJvbml6YXRpb25GaW5pc2hlZCkucmVkdWNlKChhY2MsIHIpID0+IGFjYyB8fCByLCBmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXJzIHRoZSBzdG9yYWdlIGFuZCBkZWxldGVzIHBlcnNpc3RlbnQgZGF0YVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBoaXN0b3J5IHN0b3JhZ2UgaXMgY2xlYXJlZFxuICAgKi9cbiAgYXN5bmMgY2xlYXIoKSB7XG4gICAgdGhyb3cgRXJyb3IoJ0Fic3RyYWN0IG1ldGhvZCBjbGVhciBoYXMgbm8gaW1wbGVtZW50YXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0aW1lIG9mIHRoZSBsYXN0IGhpc3Rvcnkgb3JkZXIgcmVjb3JkIHN0b3JlZCBpbiB0aGUgaGlzdG9yeSBzdG9yYWdlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbaW5zdGFuY2VJbmRleF0gaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHJldHVybnMge1Byb21pc2U8RGF0ZT59IHRoZSB0aW1lIG9mIHRoZSBsYXN0IGhpc3Rvcnkgb3JkZXIgcmVjb3JkIHN0b3JlZCBpbiB0aGUgaGlzdG9yeSBzdG9yYWdlXG4gICAqL1xuICBhc3luYyBsYXN0SGlzdG9yeU9yZGVyVGltZShpbnN0YW5jZUluZGV4KSB7XG4gICAgdGhyb3cgRXJyb3IoJ0Fic3RyYWN0IG1ldGhvZCBsYXN0SGlzdG9yeU9yZGVyVGltZSBoYXMgbm8gaW1wbGVtZW50YXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0aW1lIG9mIHRoZSBsYXN0IGhpc3RvcnkgZGVhbCByZWNvcmQgc3RvcmVkIGluIHRoZSBoaXN0b3J5IHN0b3JhZ2VcbiAgICogQHBhcmFtIHtTdHJpbmd9IFtpbnN0YW5jZUluZGV4XSBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxEYXRlPn0gdGhlIHRpbWUgb2YgdGhlIGxhc3QgaGlzdG9yeSBkZWFsIHJlY29yZCBzdG9yZWQgaW4gdGhlIGhpc3Rvcnkgc3RvcmFnZVxuICAgKi9cbiAgYXN5bmMgbGFzdERlYWxUaW1lKGluc3RhbmNlSW5kZXgpIHtcbiAgICB0aHJvdyBFcnJvcignQWJzdHJhY3QgbWV0aG9kIGxhc3REZWFsVGltZSBoYXMgbm8gaW1wbGVtZW50YXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYSBuZXcgTWV0YVRyYWRlciBoaXN0b3J5IG9yZGVyIGlzIGFkZGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7TWV0YXRyYWRlck9yZGVyfSBoaXN0b3J5T3JkZXIgbmV3IE1ldGFUcmFkZXIgaGlzdG9yeSBvcmRlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uSGlzdG9yeU9yZGVyQWRkZWQoaW5zdGFuY2VJbmRleCwgaGlzdG9yeU9yZGVyKSB7XG4gICAgdGhyb3cgRXJyb3IoJ0Fic3RyYWN0IG1ldGhvZCBvbkhpc3RvcnlPcmRlckFkZGVkIGhhcyBubyBpbXBsZW1lbnRhdGlvbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBhIG5ldyBNZXRhVHJhZGVyIGhpc3RvcnkgZGVhbCBpcyBhZGRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge01ldGF0cmFkZXJEZWFsfSBkZWFsIG5ldyBNZXRhVHJhZGVyIGhpc3RvcnkgZGVhbFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uRGVhbEFkZGVkKGluc3RhbmNlSW5kZXgsIGRlYWwpIHtcbiAgICB0aHJvdyBFcnJvcignQWJzdHJhY3QgbWV0aG9kIG9uRGVhbEFkZGVkIGhhcyBubyBpbXBsZW1lbnRhdGlvbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBhIHN5bmNocm9uaXphdGlvbiBvZiBoaXN0b3J5IGRlYWxzIG9uIGEgTWV0YVRyYWRlciBhY2NvdW50IGhhdmUgZmluaXNoZWQgdG8gaW5kaWNhdGUgcHJvZ3Jlc3Mgb2YgYW5cbiAgICogaW5pdGlhbCB0ZXJtaW5hbCBzdGF0ZSBzeW5jaHJvbml6YXRpb25cbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bmNocm9uaXphdGlvbklkIHN5bmNocm9uaXphdGlvbiByZXF1ZXN0IGlkXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25EZWFsc1N5bmNocm9uaXplZChpbnN0YW5jZUluZGV4LCBzeW5jaHJvbml6YXRpb25JZCkge1xuICAgIGNvbnN0IGluc3RhbmNlID0gdGhpcy5nZXRJbnN0YW5jZU51bWJlcihpbnN0YW5jZUluZGV4KTtcbiAgICB0aGlzLl9kZWFsU3luY2hyb25pemF0aW9uRmluaXNoZWRbJycgKyBpbnN0YW5jZV0gPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBhIHN5bmNocm9uaXphdGlvbiBvZiBoaXN0b3J5IG9yZGVycyBvbiBhIE1ldGFUcmFkZXIgYWNjb3VudCBoYXZlIGZpbmlzaGVkIHRvIGluZGljYXRlIHByb2dyZXNzIG9mIGFuXG4gICAqIGluaXRpYWwgdGVybWluYWwgc3RhdGUgc3luY2hyb25pemF0aW9uXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzeW5jaHJvbml6YXRpb25JZCBzeW5jaHJvbml6YXRpb24gcmVxdWVzdCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uSGlzdG9yeU9yZGVyc1N5bmNocm9uaXplZChpbnN0YW5jZUluZGV4LCBzeW5jaHJvbml6YXRpb25JZCkge1xuICAgIGNvbnN0IGluc3RhbmNlID0gdGhpcy5nZXRJbnN0YW5jZU51bWJlcihpbnN0YW5jZUluZGV4KTtcbiAgICB0aGlzLl9vcmRlclN5bmNocm9uaXphdGlvbkZpbmlzaGVkWycnICsgaW5zdGFuY2VdID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gY29ubmVjdGlvbiB0byBNZXRhVHJhZGVyIHRlcm1pbmFsIGVzdGFibGlzaGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqL1xuICBvbkNvbm5lY3RlZChpbnN0YW5jZUluZGV4KSB7XG4gICAgY29uc3QgaW5zdGFuY2UgPSB0aGlzLmdldEluc3RhbmNlTnVtYmVyKGluc3RhbmNlSW5kZXgpO1xuICAgIHRoaXMuX29yZGVyU3luY2hyb25pemF0aW9uRmluaXNoZWRbJycgKyBpbnN0YW5jZV0gPSBmYWxzZTtcbiAgICB0aGlzLl9kZWFsU3luY2hyb25pemF0aW9uRmluaXNoZWRbJycgKyBpbnN0YW5jZV0gPSBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBkZWFsc1xuICAgKiBAcmV0dXJucyB7QXJyYXk8TWV0YXRyYWRlckRlYWw+fSBhbGwgZGVhbHNcbiAgICovXG4gIGdldCBkZWFscygpIHtcbiAgICB0aHJvdyBFcnJvcignQWJzdHJhY3QgcHJvcGVydHkgZGVhbHMgaGFzIG5vIGltcGxlbWVudGF0aW9uJyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBkZWFscyBieSB0aWNrZXQgaWRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIHRpY2tldCBpZFxuICAgKiBAcmV0dXJucyB7QXJyYXk8TWV0YXRyYWRlckRlYWw+fSBkZWFscyBmb3VuZFxuICAgKi9cbiAgZ2V0RGVhbHNCeVRpY2tldChpZCkge1xuICAgIHRocm93IEVycm9yKCdBYnN0cmFjdCBtZXRob2QgZ2V0RGVhbHNCeVRpY2tldCBoYXMgbm8gaW1wbGVtZW50YXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGRlYWxzIGJ5IHBvc2l0aW9uIGlkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwb3NpdGlvbklkIHBvc2l0aW9uIGlkXG4gICAqIEByZXR1cm5zIHtBcnJheTxNZXRhdHJhZGVyRGVhbD59IGRlYWxzIGZvdW5kXG4gICAqL1xuICBnZXREZWFsc0J5UG9zaXRpb24ocG9zaXRpb25JZCkge1xuICAgIHRocm93IEVycm9yKCdBYnN0cmFjdCBtZXRob2QgZ2V0RGVhbHNCeVBvc2l0aW9uIGhhcyBubyBpbXBsZW1lbnRhdGlvbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZGVhbHMgYnkgdGltZSByYW5nZVxuICAgKiBAcGFyYW0gc3RhcnRUaW1lIHN0YXJ0IHRpbWUsIGluY2x1c2l2ZVxuICAgKiBAcGFyYW0gZW5kVGltZSBlbmQgdGltZSwgaW5jbHVzaXZlXG4gICAqIEByZXR1cm5zIHtBcnJheTxNZXRhdHJhZGVyRGVhbD59IGRlYWxzIGZvdW5kXG4gICAqL1xuICBnZXREZWFsc0J5VGltZVJhbmdlKHN0YXJ0VGltZSwgZW5kVGltZSkge1xuICAgIHRocm93IEVycm9yKCdBYnN0cmFjdCBtZXRob2QgZ2V0RGVhbHNCeVRpbWVSYW5nZSBoYXMgbm8gaW1wbGVtZW50YXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBoaXN0b3J5IG9yZGVyc1xuICAgKiBAcmV0dXJucyB7QXJyYXk8TWV0YXRyYWRlck9yZGVyPn0gYWxsIGhpc3Rvcnkgb3JkZXJzXG4gICAqL1xuICBnZXQgaGlzdG9yeU9yZGVycygpIHtcbiAgICB0aHJvdyBFcnJvcignQWJzdHJhY3QgcHJvcGVydHkgaGlzdG9yeU9yZGVycyBoYXMgbm8gaW1wbGVtZW50YXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGhpc3Rvcnkgb3JkZXJzIGJ5IHRpY2tldCBpZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgdGlja2V0IGlkXG4gICAqIEByZXR1cm5zIHtBcnJheTxNZXRhdHJhZGVyT3JkZXI+fSBoaXN0b3J5IG9yZGVycyBmb3VuZFxuICAgKi9cbiAgZ2V0SGlzdG9yeU9yZGVyc0J5VGlja2V0KGlkKSB7XG4gICAgdGhyb3cgRXJyb3IoJ0Fic3RyYWN0IG1ldGhvZCBnZXRIaXN0b3J5T3JkZXJzQnlUaWNrZXQgaGFzIG5vIGltcGxlbWVudGF0aW9uJyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBoaXN0b3J5IG9yZGVycyBieSBwb3NpdGlvbiBpZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcG9zaXRpb25JZCBwb3NpdGlvbiBpZFxuICAgKiBAcmV0dXJucyB7QXJyYXk8TWV0YXRyYWRlck9yZGVyPn0gaGlzdG9yeSBvcmRlcnMgZm91bmRcbiAgICovXG4gIGdldEhpc3RvcnlPcmRlcnNCeVBvc2l0aW9uKHBvc2l0aW9uSWQpIHtcbiAgICB0aHJvdyBFcnJvcignQWJzdHJhY3QgbWV0aG9kIGdldEhpc3RvcnlPcmRlcnNCeVBvc2l0aW9uIGhhcyBubyBpbXBsZW1lbnRhdGlvbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgaGlzdG9yeSBvcmRlcnMgYnkgdGltZSByYW5nZVxuICAgKiBAcGFyYW0gc3RhcnRUaW1lIHN0YXJ0IHRpbWUsIGluY2x1c2l2ZVxuICAgKiBAcGFyYW0gZW5kVGltZSBlbmQgdGltZSwgaW5jbHVzaXZlXG4gICAqIEByZXR1cm5zIHtBcnJheTxNZXRhdHJhZGVyT3JkZXI+fSBoaXNvdHJ5IG9yZGVycyBmb3VuZFxuICAgKi9cbiAgZ2V0SGlzdG9yeU9yZGVyc0J5VGltZVJhbmdlKHN0YXJ0VGltZSwgZW5kVGltZSkge1xuICAgIHRocm93IEVycm9yKCdBYnN0cmFjdCBtZXRob2QgZ2V0SGlzdG9yeU9yZGVyc0J5VGltZVJhbmdlIGhhcyBubyBpbXBsZW1lbnRhdGlvbicpO1xuICB9XG5cbn1cbiJdLCJuYW1lcyI6WyJTeW5jaHJvbml6YXRpb25MaXN0ZW5lciIsIkhpc3RvcnlTdG9yYWdlIiwiaW5pdGlhbGl6ZSIsImFjY291bnRJZCIsImFwcGxpY2F0aW9uIiwiX2FjY291bnRJZCIsIl9hcHBsaWNhdGlvbiIsIm9yZGVyU3luY2hyb25pemF0aW9uRmluaXNoZWQiLCJPYmplY3QiLCJ2YWx1ZXMiLCJfb3JkZXJTeW5jaHJvbml6YXRpb25GaW5pc2hlZCIsInJlZHVjZSIsImFjYyIsInIiLCJkZWFsU3luY2hyb25pemF0aW9uRmluaXNoZWQiLCJfZGVhbFN5bmNocm9uaXphdGlvbkZpbmlzaGVkIiwiY2xlYXIiLCJFcnJvciIsImxhc3RIaXN0b3J5T3JkZXJUaW1lIiwiaW5zdGFuY2VJbmRleCIsImxhc3REZWFsVGltZSIsIm9uSGlzdG9yeU9yZGVyQWRkZWQiLCJoaXN0b3J5T3JkZXIiLCJvbkRlYWxBZGRlZCIsImRlYWwiLCJvbkRlYWxzU3luY2hyb25pemVkIiwic3luY2hyb25pemF0aW9uSWQiLCJpbnN0YW5jZSIsImdldEluc3RhbmNlTnVtYmVyIiwib25IaXN0b3J5T3JkZXJzU3luY2hyb25pemVkIiwib25Db25uZWN0ZWQiLCJkZWFscyIsImdldERlYWxzQnlUaWNrZXQiLCJpZCIsImdldERlYWxzQnlQb3NpdGlvbiIsInBvc2l0aW9uSWQiLCJnZXREZWFsc0J5VGltZVJhbmdlIiwic3RhcnRUaW1lIiwiZW5kVGltZSIsImhpc3RvcnlPcmRlcnMiLCJnZXRIaXN0b3J5T3JkZXJzQnlUaWNrZXQiLCJnZXRIaXN0b3J5T3JkZXJzQnlQb3NpdGlvbiIsImdldEhpc3RvcnlPcmRlcnNCeVRpbWVSYW5nZSIsImNvbnN0cnVjdG9yIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsT0FBT0EsNkJBQTZCLDZDQUE2QztBQUtsRSxJQUFBLEFBQU1DLGlCQUFOLE1BQU1BLHVCQUF1QkQ7SUFXMUM7Ozs7O0dBS0MsR0FDRCxBQUFNRSxXQUFXQyxT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