UNPKG

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)

222 lines (221 loc) 33.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "default", { enumerable: true, get: function() { return RpcMetaApiConnectionInstance; } }); const _logger = /*#__PURE__*/ _interop_require_default(require("../logger")); const _metaApiConnectionInstance = /*#__PURE__*/ _interop_require_default(require("./metaApiConnectionInstance")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } let RpcMetaApiConnectionInstance = class RpcMetaApiConnectionInstance extends _metaApiConnectionInstance.default { /** * Opens the connection. Can only be called the first time, next calls will be ignored. * @return {Promise} promise resolving when the connection is opened */ async connect() { if (!this._opened) { this._opened = true; this._metaApiConnection.connect(this.instanceId); } } /** * Closes the connection. The instance of the class should no longer be used after this method is invoked. */ async close() { if (!this._closed) { this._metaApiConnection.close(this.instanceId); this._closed = true; } } /** * Returns account information * @param {GetAccountInformationOptions} [options] additional request options * @returns {Promise<MetatraderAccountInformation>} promise resolving with account information */ getAccountInformation(options) { this._checkIsConnectionActive(); return this._websocketClient.getAccountInformation(this._metaApiConnection.account.id, options); } /** * Returns positions * @param {GetPositionsOptions} [options] additional request options * @returns {Promise<Array<MetatraderPosition>} promise resolving with array of open positions */ getPositions(options) { this._checkIsConnectionActive(); return this._websocketClient.getPositions(this._metaApiConnection.account.id, options); } /** * Returns specific position * @param {String} positionId position id * @param {GetPositionOptions} [options] additional request options * @return {Promise<MetatraderPosition>} promise resolving with MetaTrader position found */ getPosition(positionId, options) { this._checkIsConnectionActive(); return this._websocketClient.getPosition(this._metaApiConnection.account.id, positionId, options); } /** * Returns open orders * @param {GetOrdersOptions} [options] additional request options * @return {Promise<Array<MetatraderOrder>>} promise resolving with open MetaTrader orders */ getOrders(options) { this._checkIsConnectionActive(); return this._websocketClient.getOrders(this._metaApiConnection.account.id, options); } /** * Returns specific open order * @param {String} orderId order id (ticket number) * @param {GetOrderOptions} [options] additional request options * @return {Promise<MetatraderOrder>} promise resolving with metatrader order found */ getOrder(orderId, options) { this._checkIsConnectionActive(); return this._websocketClient.getOrder(this._metaApiConnection.account.id, orderId, options); } /** * Returns the history of completed orders for a specific ticket number * @param {String} ticket ticket number (order id) * @returns {Promise<MetatraderHistoryOrders>} promise resolving with request results containing history orders found */ getHistoryOrdersByTicket(ticket) { this._checkIsConnectionActive(); return this._websocketClient.getHistoryOrdersByTicket(this._metaApiConnection.account.id, ticket); } /** * Returns the history of completed orders for a specific position id * @param {String} positionId position id * @returns {Promise<MetatraderHistoryOrders>} promise resolving with request results containing history orders found */ getHistoryOrdersByPosition(positionId) { this._checkIsConnectionActive(); return this._websocketClient.getHistoryOrdersByPosition(this._metaApiConnection.account.id, positionId); } /** * Returns the history of completed orders for a specific time range * @param {Date} startTime start of time range, inclusive * @param {Date} endTime end of time range, exclusive * @param {Number} offset pagination offset, default is 0 * @param {Number} limit pagination limit, default is 1000 * @returns {Promise<MetatraderHistoryOrders>} promise resolving with request results containing history orders found */ getHistoryOrdersByTimeRange(startTime, endTime, offset = 0, limit = 1000) { this._checkIsConnectionActive(); return this._websocketClient.getHistoryOrdersByTimeRange(this._metaApiConnection.account.id, startTime, endTime, offset, limit); } /** * Returns history deals with a specific ticket number * @param {String} ticket ticket number (deal id for MT5 or order id for MT4) * @returns {Promise<MetatraderDeals>} promise resolving with request results containing deals found */ getDealsByTicket(ticket) { this._checkIsConnectionActive(); return this._websocketClient.getDealsByTicket(this._metaApiConnection.account.id, ticket); } /** * Returns history deals for a specific position id * @param {String} positionId position id * @returns {Promise<MetatraderDeals>} promise resolving with request results containing deals found */ getDealsByPosition(positionId) { this._checkIsConnectionActive(); return this._websocketClient.getDealsByPosition(this._metaApiConnection.account.id, positionId); } /** * Returns history deals with for a specific time range * @param {Date} startTime start of time range, inclusive * @param {Date} endTime end of time range, exclusive * @param {Number} offset pagination offset, default is 0 * @param {Number} limit pagination limit, default is 1000 * @returns {Promise<MetatraderDeals>} promise resolving with request results containing deals found */ getDealsByTimeRange(startTime, endTime, offset = 0, limit = 1000) { this._checkIsConnectionActive(); return this._websocketClient.getDealsByTimeRange(this._metaApiConnection.account.id, startTime, endTime, offset, limit); } /** * Retrieves available symbols for an account * @param {String} symbol symbol to retrieve symbols for * @returns {Promise<Array<string>>} promise which resolves when symbols are retrieved */ getSymbols() { this._checkIsConnectionActive(); return this._websocketClient.getSymbols(this._metaApiConnection.account.id); } /** * Retrieves specification for a symbol * @param {String} symbol symbol to retrieve specification for * @returns {Promise<MetatraderSymbolSpecification>} promise which resolves when specification is retrieved */ getSymbolSpecification(symbol) { this._checkIsConnectionActive(); return this._websocketClient.getSymbolSpecification(this._metaApiConnection.account.id, symbol); } /** * Retrieves latest price for a symbol * @param {String} symbol symbol to retrieve price for * @param {boolean} keepSubscription if set to true, the account will get a long-term subscription to symbol market * data. Long-term subscription means that on subsequent calls you will get updated value faster. If set to false or * not set, the subscription will be set to expire in 12 minutes. * @returns {Promise<MetatraderSymbolPrice>} promise which resolves when price is retrieved */ getSymbolPrice(symbol, keepSubscription) { this._checkIsConnectionActive(); return this._websocketClient.getSymbolPrice(this._metaApiConnection.account.id, symbol, keepSubscription); } /** * Retrieves latest candle for a symbol and timeframe * @param {String} symbol symbol to retrieve candle for * @param {string} timeframe defines the timeframe according to which the candle must be generated. Allowed values for * MT5 are 1m, 2m, 3m, 4m, 5m, 6m, 10m, 12m, 15m, 20m, 30m, 1h, 2h, 3h, 4h, 6h, 8h, 12h, 1d, 1w, 1mn. Allowed values * for MT4 are 1m, 5m, 15m 30m, 1h, 4h, 1d, 1w, 1mn * @param {boolean} keepSubscription if set to true, the account will get a long-term subscription to symbol market * data. Long-term subscription means that on subsequent calls you will get updated value faster. If set to false or * not set, the subscription will be set to expire in 12 minutes. * @returns {Promise<MetatraderCandle>} promise which resolves when candle is retrieved */ getCandle(symbol, timeframe, keepSubscription = false) { this._checkIsConnectionActive(); return this._websocketClient.getCandle(this._metaApiConnection.account.id, symbol, timeframe, keepSubscription); } /** * Retrieves latest tick for a symbol. MT4 G1 accounts do not support this API * @param {String} symbol symbol to retrieve tick for * @param {boolean} keepSubscription if set to true, the account will get a long-term subscription to symbol market * data. Long-term subscription means that on subsequent calls you will get updated value faster. If set to false or * not set, the subscription will be set to expire in 12 minutes. * @returns {Promise<MetatraderTick>} promise which resolves when tick is retrieved */ getTick(symbol, keepSubscription = false) { this._checkIsConnectionActive(); return this._websocketClient.getTick(this._metaApiConnection.account.id, symbol, keepSubscription); } /** * Retrieves latest order book for a symbol. MT4 accounts do not support this API * @param {string} symbol symbol to retrieve order book for * @param {boolean} keepSubscription if set to true, the account will get a long-term subscription to symbol market * data. Long-term subscription means that on subsequent calls you will get updated value faster. If set to false or * not set, the subscription will be set to expire in 12 minutes. * @returns {Promise<MetatraderTick>} promise which resolves when order book is retrieved */ getBook(symbol, keepSubscription = false) { this._checkIsConnectionActive(); return this._websocketClient.getBook(this._metaApiConnection.account.id, symbol, keepSubscription); } /** * Returns server time for a specified MetaTrader account * @returns {Promise<ServerTime>} promise resolving with server time */ async getServerTime() { this._checkIsConnectionActive(); return this._websocketClient.getServerTime(this._metaApiConnection.account.id); } /** * Waits until synchronization to RPC application is completed * @param {Number} timeoutInSeconds synchronization timeout in seconds * @return {Promise} promise which resolves when synchronization to RPC application is completed * @throws {TimeoutError} if application failed to synchronize with the teminal within timeout allowed */ async waitSynchronized(timeoutInSeconds = 300) { this._checkIsConnectionActive(); return this._metaApiConnection.waitSynchronized(timeoutInSeconds); } /** * Constructs MetaApi MetaTrader RPC Api connection instance * @param {MetaApiWebsocketClient} websocketClient MetaApi websocket client * @param {StreamingMetaApiConnection} metaApiConnection RPC MetaApi connection */ constructor(websocketClient, metaApiConnection){ super(websocketClient, metaApiConnection); this._metaApiConnection = metaApiConnection; this._logger = _logger.default.getLogger("RpcMetaApiConnectionInstance"); } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBMb2dnZXJNYW5hZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQgTWV0YUFwaUNvbm5lY3Rpb25JbnN0YW5jZSBmcm9tICcuL21ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UnO1xuXG4vKipcbiAqIEV4cG9zZXMgTWV0YUFwaSBNZXRhVHJhZGVyIFJQQyBBUEkgY29ubmVjdGlvbiBpbnN0YW5jZSB0byBjb25zdW1lcnNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUnBjTWV0YUFwaUNvbm5lY3Rpb25JbnN0YW5jZSBleHRlbmRzIE1ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2Uge1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIE1ldGFBcGkgTWV0YVRyYWRlciBSUEMgQXBpIGNvbm5lY3Rpb24gaW5zdGFuY2VcbiAgICogQHBhcmFtIHtNZXRhQXBpV2Vic29ja2V0Q2xpZW50fSB3ZWJzb2NrZXRDbGllbnQgTWV0YUFwaSB3ZWJzb2NrZXQgY2xpZW50XG4gICAqIEBwYXJhbSB7U3RyZWFtaW5nTWV0YUFwaUNvbm5lY3Rpb259IG1ldGFBcGlDb25uZWN0aW9uIFJQQyBNZXRhQXBpIGNvbm5lY3Rpb25cbiAgICovXG4gIGNvbnN0cnVjdG9yKHdlYnNvY2tldENsaWVudCwgbWV0YUFwaUNvbm5lY3Rpb24pIHtcbiAgICBzdXBlcih3ZWJzb2NrZXRDbGllbnQsIG1ldGFBcGlDb25uZWN0aW9uKTtcbiAgICB0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbiA9IG1ldGFBcGlDb25uZWN0aW9uO1xuICAgIHRoaXMuX2xvZ2dlciA9IExvZ2dlck1hbmFnZXIuZ2V0TG9nZ2VyKCdScGNNZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlJyk7XG4gIH1cblxuICAvKipcbiAgICogT3BlbnMgdGhlIGNvbm5lY3Rpb24uIENhbiBvbmx5IGJlIGNhbGxlZCB0aGUgZmlyc3QgdGltZSwgbmV4dCBjYWxscyB3aWxsIGJlIGlnbm9yZWQuXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgcmVzb2x2aW5nIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgb3BlbmVkXG4gICAqL1xuICBhc3luYyBjb25uZWN0KCkge1xuICAgIGlmICghdGhpcy5fb3BlbmVkKSB7XG4gICAgICB0aGlzLl9vcGVuZWQgPSB0cnVlO1xuICAgICAgdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uY29ubmVjdCh0aGlzLmluc3RhbmNlSWQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24uIFRoZSBpbnN0YW5jZSBvZiB0aGUgY2xhc3Mgc2hvdWxkIG5vIGxvbmdlciBiZSB1c2VkIGFmdGVyIHRoaXMgbWV0aG9kIGlzIGludm9rZWQuXG4gICAqL1xuICBhc3luYyBjbG9zZSgpIHtcbiAgICBpZiAoIXRoaXMuX2Nsb3NlZCkge1xuICAgICAgdGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uY2xvc2UodGhpcy5pbnN0YW5jZUlkKTtcbiAgICAgIHRoaXMuX2Nsb3NlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWNjb3VudCBpbmZvcm1hdGlvblxuICAgKiBAcGFyYW0ge0dldEFjY291bnRJbmZvcm1hdGlvbk9wdGlvbnN9IFtvcHRpb25zXSBhZGRpdGlvbmFsIHJlcXVlc3Qgb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxNZXRhdHJhZGVyQWNjb3VudEluZm9ybWF0aW9uPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBhY2NvdW50IGluZm9ybWF0aW9uXG4gICAqL1xuICBnZXRBY2NvdW50SW5mb3JtYXRpb24ob3B0aW9ucykge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXRBY2NvdW50SW5mb3JtYXRpb24odGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uYWNjb3VudC5pZCwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwb3NpdGlvbnNcbiAgICogQHBhcmFtIHtHZXRQb3NpdGlvbnNPcHRpb25zfSBbb3B0aW9uc10gYWRkaXRpb25hbCByZXF1ZXN0IG9wdGlvbnNcbiAgICogQHJldHVybnMge1Byb21pc2U8QXJyYXk8TWV0YXRyYWRlclBvc2l0aW9uPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBhcnJheSBvZiBvcGVuIHBvc2l0aW9uc1xuICAgKi9cbiAgZ2V0UG9zaXRpb25zKG9wdGlvbnMpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0UG9zaXRpb25zKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3BlY2lmaWMgcG9zaXRpb25cbiAgICogQHBhcmFtIHtTdHJpbmd9IHBvc2l0aW9uSWQgcG9zaXRpb24gaWRcbiAgICogQHBhcmFtIHtHZXRQb3NpdGlvbk9wdGlvbnN9IFtvcHRpb25zXSBhZGRpdGlvbmFsIHJlcXVlc3Qgb3B0aW9uc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1ldGF0cmFkZXJQb3NpdGlvbj59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggTWV0YVRyYWRlciBwb3NpdGlvbiBmb3VuZFxuICAgKi9cbiAgZ2V0UG9zaXRpb24ocG9zaXRpb25JZCwgb3B0aW9ucykge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXRQb3NpdGlvbih0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkLCBwb3NpdGlvbklkLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG9wZW4gb3JkZXJzXG4gICAqIEBwYXJhbSB7R2V0T3JkZXJzT3B0aW9uc30gW29wdGlvbnNdIGFkZGl0aW9uYWwgcmVxdWVzdCBvcHRpb25zXG4gICAqIEByZXR1cm4ge1Byb21pc2U8QXJyYXk8TWV0YXRyYWRlck9yZGVyPj59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggb3BlbiBNZXRhVHJhZGVyIG9yZGVyc1xuICAgKi9cbiAgZ2V0T3JkZXJzKG9wdGlvbnMpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0T3JkZXJzKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3BlY2lmaWMgb3BlbiBvcmRlclxuICAgKiBAcGFyYW0ge1N0cmluZ30gb3JkZXJJZCBvcmRlciBpZCAodGlja2V0IG51bWJlcilcbiAgICogQHBhcmFtIHtHZXRPcmRlck9wdGlvbnN9IFtvcHRpb25zXSBhZGRpdGlvbmFsIHJlcXVlc3Qgb3B0aW9uc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1ldGF0cmFkZXJPcmRlcj59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggbWV0YXRyYWRlciBvcmRlciBmb3VuZFxuICAgKi9cbiAgZ2V0T3JkZXIob3JkZXJJZCwgb3B0aW9ucykge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXRPcmRlcih0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkLCBvcmRlcklkLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBoaXN0b3J5IG9mIGNvbXBsZXRlZCBvcmRlcnMgZm9yIGEgc3BlY2lmaWMgdGlja2V0IG51bWJlclxuICAgKiBAcGFyYW0ge1N0cmluZ30gdGlja2V0IHRpY2tldCBudW1iZXIgKG9yZGVyIGlkKVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxNZXRhdHJhZGVySGlzdG9yeU9yZGVycz59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggcmVxdWVzdCByZXN1bHRzIGNvbnRhaW5pbmcgaGlzdG9yeSBvcmRlcnMgZm91bmRcbiAgICovXG4gIGdldEhpc3RvcnlPcmRlcnNCeVRpY2tldCh0aWNrZXQpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0SGlzdG9yeU9yZGVyc0J5VGlja2V0KHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIHRpY2tldCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaGlzdG9yeSBvZiBjb21wbGV0ZWQgb3JkZXJzIGZvciBhIHNwZWNpZmljIHBvc2l0aW9uIGlkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwb3NpdGlvbklkIHBvc2l0aW9uIGlkXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPE1ldGF0cmFkZXJIaXN0b3J5T3JkZXJzPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCByZXF1ZXN0IHJlc3VsdHMgY29udGFpbmluZyBoaXN0b3J5IG9yZGVycyBmb3VuZFxuICAgKi9cbiAgZ2V0SGlzdG9yeU9yZGVyc0J5UG9zaXRpb24ocG9zaXRpb25JZCkge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXRIaXN0b3J5T3JkZXJzQnlQb3NpdGlvbih0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkLCBwb3NpdGlvbklkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBoaXN0b3J5IG9mIGNvbXBsZXRlZCBvcmRlcnMgZm9yIGEgc3BlY2lmaWMgdGltZSByYW5nZVxuICAgKiBAcGFyYW0ge0RhdGV9IHN0YXJ0VGltZSBzdGFydCBvZiB0aW1lIHJhbmdlLCBpbmNsdXNpdmVcbiAgICogQHBhcmFtIHtEYXRlfSBlbmRUaW1lIGVuZCBvZiB0aW1lIHJhbmdlLCBleGNsdXNpdmVcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9mZnNldCBwYWdpbmF0aW9uIG9mZnNldCwgZGVmYXVsdCBpcyAwXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBsaW1pdCBwYWdpbmF0aW9uIGxpbWl0LCBkZWZhdWx0IGlzIDEwMDBcbiAgICogQHJldHVybnMge1Byb21pc2U8TWV0YXRyYWRlckhpc3RvcnlPcmRlcnM+fSBwcm9taXNlIHJlc29sdmluZyB3aXRoIHJlcXVlc3QgcmVzdWx0cyBjb250YWluaW5nIGhpc3Rvcnkgb3JkZXJzIGZvdW5kXG4gICAqL1xuICBnZXRIaXN0b3J5T3JkZXJzQnlUaW1lUmFuZ2Uoc3RhcnRUaW1lLCBlbmRUaW1lLCBvZmZzZXQgPSAwLCBsaW1pdCA9IDEwMDApIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0SGlzdG9yeU9yZGVyc0J5VGltZVJhbmdlKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIFxuICAgICAgc3RhcnRUaW1lLCBlbmRUaW1lLCBvZmZzZXQsIGxpbWl0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGhpc3RvcnkgZGVhbHMgd2l0aCBhIHNwZWNpZmljIHRpY2tldCBudW1iZXJcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRpY2tldCB0aWNrZXQgbnVtYmVyIChkZWFsIGlkIGZvciBNVDUgb3Igb3JkZXIgaWQgZm9yIE1UNClcbiAgICogQHJldHVybnMge1Byb21pc2U8TWV0YXRyYWRlckRlYWxzPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCByZXF1ZXN0IHJlc3VsdHMgY29udGFpbmluZyBkZWFscyBmb3VuZFxuICAgKi9cbiAgZ2V0RGVhbHNCeVRpY2tldCh0aWNrZXQpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0RGVhbHNCeVRpY2tldCh0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkLCB0aWNrZXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgaGlzdG9yeSBkZWFscyBmb3IgYSBzcGVjaWZpYyBwb3NpdGlvbiBpZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcG9zaXRpb25JZCBwb3NpdGlvbiBpZFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxNZXRhdHJhZGVyRGVhbHM+fSBwcm9taXNlIHJlc29sdmluZyB3aXRoIHJlcXVlc3QgcmVzdWx0cyBjb250YWluaW5nIGRlYWxzIGZvdW5kXG4gICAqL1xuICBnZXREZWFsc0J5UG9zaXRpb24ocG9zaXRpb25JZCkge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXREZWFsc0J5UG9zaXRpb24odGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uYWNjb3VudC5pZCwgcG9zaXRpb25JZCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBoaXN0b3J5IGRlYWxzIHdpdGggZm9yIGEgc3BlY2lmaWMgdGltZSByYW5nZVxuICAgKiBAcGFyYW0ge0RhdGV9IHN0YXJ0VGltZSBzdGFydCBvZiB0aW1lIHJhbmdlLCBpbmNsdXNpdmVcbiAgICogQHBhcmFtIHtEYXRlfSBlbmRUaW1lIGVuZCBvZiB0aW1lIHJhbmdlLCBleGNsdXNpdmVcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9mZnNldCBwYWdpbmF0aW9uIG9mZnNldCwgZGVmYXVsdCBpcyAwXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBsaW1pdCBwYWdpbmF0aW9uIGxpbWl0LCBkZWZhdWx0IGlzIDEwMDBcbiAgICogQHJldHVybnMge1Byb21pc2U8TWV0YXRyYWRlckRlYWxzPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCByZXF1ZXN0IHJlc3VsdHMgY29udGFpbmluZyBkZWFscyBmb3VuZFxuICAgKi9cbiAgZ2V0RGVhbHNCeVRpbWVSYW5nZShzdGFydFRpbWUsIGVuZFRpbWUsIG9mZnNldCA9IDAsIGxpbWl0ID0gMTAwMCkge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXREZWFsc0J5VGltZVJhbmdlKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIFxuICAgICAgc3RhcnRUaW1lLCBlbmRUaW1lLCBvZmZzZXQsIGxpbWl0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYXZhaWxhYmxlIHN5bWJvbHMgZm9yIGFuIGFjY291bnRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bWJvbCBzeW1ib2wgdG8gcmV0cmlldmUgc3ltYm9scyBmb3JcbiAgICogQHJldHVybnMge1Byb21pc2U8QXJyYXk8c3RyaW5nPj59IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiBzeW1ib2xzIGFyZSByZXRyaWV2ZWRcbiAgICovXG4gIGdldFN5bWJvbHMoKSB7XG4gICAgdGhpcy5fY2hlY2tJc0Nvbm5lY3Rpb25BY3RpdmUoKTtcbiAgICByZXR1cm4gdGhpcy5fd2Vic29ja2V0Q2xpZW50LmdldFN5bWJvbHModGhpcy5fbWV0YUFwaUNvbm5lY3Rpb24uYWNjb3VudC5pZCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHNwZWNpZmljYXRpb24gZm9yIGEgc3ltYm9sXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzeW1ib2wgc3ltYm9sIHRvIHJldHJpZXZlIHNwZWNpZmljYXRpb24gZm9yXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPE1ldGF0cmFkZXJTeW1ib2xTcGVjaWZpY2F0aW9uPn0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHNwZWNpZmljYXRpb24gaXMgcmV0cmlldmVkXG4gICAqL1xuICBnZXRTeW1ib2xTcGVjaWZpY2F0aW9uKHN5bWJvbCkge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXRTeW1ib2xTcGVjaWZpY2F0aW9uKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIHN5bWJvbCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGxhdGVzdCBwcmljZSBmb3IgYSBzeW1ib2xcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bWJvbCBzeW1ib2wgdG8gcmV0cmlldmUgcHJpY2UgZm9yXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0ga2VlcFN1YnNjcmlwdGlvbiBpZiBzZXQgdG8gdHJ1ZSwgdGhlIGFjY291bnQgd2lsbCBnZXQgYSBsb25nLXRlcm0gc3Vic2NyaXB0aW9uIHRvIHN5bWJvbCBtYXJrZXRcbiAgICogZGF0YS4gTG9uZy10ZXJtIHN1YnNjcmlwdGlvbiBtZWFucyB0aGF0IG9uIHN1YnNlcXVlbnQgY2FsbHMgeW91IHdpbGwgZ2V0IHVwZGF0ZWQgdmFsdWUgZmFzdGVyLiBJZiBzZXQgdG8gZmFsc2Ugb3JcbiAgICogbm90IHNldCwgdGhlIHN1YnNjcmlwdGlvbiB3aWxsIGJlIHNldCB0byBleHBpcmUgaW4gMTIgbWludXRlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8TWV0YXRyYWRlclN5bWJvbFByaWNlPn0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHByaWNlIGlzIHJldHJpZXZlZFxuICAgKi9cbiAgZ2V0U3ltYm9sUHJpY2Uoc3ltYm9sLCBrZWVwU3Vic2NyaXB0aW9uKSB7XG4gICAgdGhpcy5fY2hlY2tJc0Nvbm5lY3Rpb25BY3RpdmUoKTtcbiAgICByZXR1cm4gdGhpcy5fd2Vic29ja2V0Q2xpZW50LmdldFN5bWJvbFByaWNlKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIHN5bWJvbCwga2VlcFN1YnNjcmlwdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGxhdGVzdCBjYW5kbGUgZm9yIGEgc3ltYm9sIGFuZCB0aW1lZnJhbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bWJvbCBzeW1ib2wgdG8gcmV0cmlldmUgY2FuZGxlIGZvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGltZWZyYW1lIGRlZmluZXMgdGhlIHRpbWVmcmFtZSBhY2NvcmRpbmcgdG8gd2hpY2ggdGhlIGNhbmRsZSBtdXN0IGJlIGdlbmVyYXRlZC4gQWxsb3dlZCB2YWx1ZXMgZm9yXG4gICAqIE1UNSBhcmUgMW0sIDJtLCAzbSwgNG0sIDVtLCA2bSwgMTBtLCAxMm0sIDE1bSwgMjBtLCAzMG0sIDFoLCAyaCwgM2gsIDRoLCA2aCwgOGgsIDEyaCwgMWQsIDF3LCAxbW4uIEFsbG93ZWQgdmFsdWVzXG4gICAqIGZvciBNVDQgYXJlIDFtLCA1bSwgMTVtIDMwbSwgMWgsIDRoLCAxZCwgMXcsIDFtblxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGtlZXBTdWJzY3JpcHRpb24gaWYgc2V0IHRvIHRydWUsIHRoZSBhY2NvdW50IHdpbGwgZ2V0IGEgbG9uZy10ZXJtIHN1YnNjcmlwdGlvbiB0byBzeW1ib2wgbWFya2V0XG4gICAqIGRhdGEuIExvbmctdGVybSBzdWJzY3JpcHRpb24gbWVhbnMgdGhhdCBvbiBzdWJzZXF1ZW50IGNhbGxzIHlvdSB3aWxsIGdldCB1cGRhdGVkIHZhbHVlIGZhc3Rlci4gSWYgc2V0IHRvIGZhbHNlIG9yXG4gICAqIG5vdCBzZXQsIHRoZSBzdWJzY3JpcHRpb24gd2lsbCBiZSBzZXQgdG8gZXhwaXJlIGluIDEyIG1pbnV0ZXMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPE1ldGF0cmFkZXJDYW5kbGU+fSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gY2FuZGxlIGlzIHJldHJpZXZlZFxuICAgKi9cbiAgZ2V0Q2FuZGxlKHN5bWJvbCwgdGltZWZyYW1lLCBrZWVwU3Vic2NyaXB0aW9uID0gZmFsc2UpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0Q2FuZGxlKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIHN5bWJvbCwgdGltZWZyYW1lLCBrZWVwU3Vic2NyaXB0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgbGF0ZXN0IHRpY2sgZm9yIGEgc3ltYm9sLiBNVDQgRzEgYWNjb3VudHMgZG8gbm90IHN1cHBvcnQgdGhpcyBBUElcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bWJvbCBzeW1ib2wgdG8gcmV0cmlldmUgdGljayBmb3JcbiAgICogQHBhcmFtIHtib29sZWFufSBrZWVwU3Vic2NyaXB0aW9uIGlmIHNldCB0byB0cnVlLCB0aGUgYWNjb3VudCB3aWxsIGdldCBhIGxvbmctdGVybSBzdWJzY3JpcHRpb24gdG8gc3ltYm9sIG1hcmtldFxuICAgKiBkYXRhLiBMb25nLXRlcm0gc3Vic2NyaXB0aW9uIG1lYW5zIHRoYXQgb24gc3Vic2VxdWVudCBjYWxscyB5b3Ugd2lsbCBnZXQgdXBkYXRlZCB2YWx1ZSBmYXN0ZXIuIElmIHNldCB0byBmYWxzZSBvclxuICAgKiBub3Qgc2V0LCB0aGUgc3Vic2NyaXB0aW9uIHdpbGwgYmUgc2V0IHRvIGV4cGlyZSBpbiAxMiBtaW51dGVzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxNZXRhdHJhZGVyVGljaz59IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aWNrIGlzIHJldHJpZXZlZFxuICAgKi9cbiAgZ2V0VGljayhzeW1ib2wsIGtlZXBTdWJzY3JpcHRpb24gPSBmYWxzZSkge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3dlYnNvY2tldENsaWVudC5nZXRUaWNrKHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLmFjY291bnQuaWQsIHN5bWJvbCwga2VlcFN1YnNjcmlwdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGxhdGVzdCBvcmRlciBib29rIGZvciBhIHN5bWJvbC4gTVQ0IGFjY291bnRzIGRvIG5vdCBzdXBwb3J0IHRoaXMgQVBJXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzeW1ib2wgc3ltYm9sIHRvIHJldHJpZXZlIG9yZGVyIGJvb2sgZm9yXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0ga2VlcFN1YnNjcmlwdGlvbiBpZiBzZXQgdG8gdHJ1ZSwgdGhlIGFjY291bnQgd2lsbCBnZXQgYSBsb25nLXRlcm0gc3Vic2NyaXB0aW9uIHRvIHN5bWJvbCBtYXJrZXRcbiAgICogZGF0YS4gTG9uZy10ZXJtIHN1YnNjcmlwdGlvbiBtZWFucyB0aGF0IG9uIHN1YnNlcXVlbnQgY2FsbHMgeW91IHdpbGwgZ2V0IHVwZGF0ZWQgdmFsdWUgZmFzdGVyLiBJZiBzZXQgdG8gZmFsc2Ugb3JcbiAgICogbm90IHNldCwgdGhlIHN1YnNjcmlwdGlvbiB3aWxsIGJlIHNldCB0byBleHBpcmUgaW4gMTIgbWludXRlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8TWV0YXRyYWRlclRpY2s+fSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gb3JkZXIgYm9vayBpcyByZXRyaWV2ZWRcbiAgICovXG4gIGdldEJvb2soc3ltYm9sLCBrZWVwU3Vic2NyaXB0aW9uID0gZmFsc2UpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0Qm9vayh0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkLCBzeW1ib2wsIGtlZXBTdWJzY3JpcHRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc2VydmVyIHRpbWUgZm9yIGEgc3BlY2lmaWVkIE1ldGFUcmFkZXIgYWNjb3VudFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTZXJ2ZXJUaW1lPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBzZXJ2ZXIgdGltZVxuICAgKi9cbiAgYXN5bmMgZ2V0U2VydmVyVGltZSgpIHtcbiAgICB0aGlzLl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSgpO1xuICAgIHJldHVybiB0aGlzLl93ZWJzb2NrZXRDbGllbnQuZ2V0U2VydmVyVGltZSh0aGlzLl9tZXRhQXBpQ29ubmVjdGlvbi5hY2NvdW50LmlkKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFdhaXRzIHVudGlsIHN5bmNocm9uaXphdGlvbiB0byBSUEMgYXBwbGljYXRpb24gaXMgY29tcGxldGVkXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB0aW1lb3V0SW5TZWNvbmRzIHN5bmNocm9uaXphdGlvbiB0aW1lb3V0IGluIHNlY29uZHNcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHN5bmNocm9uaXphdGlvbiB0byBSUEMgYXBwbGljYXRpb24gaXMgY29tcGxldGVkXG4gICAqIEB0aHJvd3Mge1RpbWVvdXRFcnJvcn0gaWYgYXBwbGljYXRpb24gZmFpbGVkIHRvIHN5bmNocm9uaXplIHdpdGggdGhlIHRlbWluYWwgd2l0aGluIHRpbWVvdXQgYWxsb3dlZFxuICAgKi9cbiAgYXN5bmMgd2FpdFN5bmNocm9uaXplZCh0aW1lb3V0SW5TZWNvbmRzPTMwMCkge1xuICAgIHRoaXMuX2NoZWNrSXNDb25uZWN0aW9uQWN0aXZlKCk7XG4gICAgcmV0dXJuIHRoaXMuX21ldGFBcGlDb25uZWN0aW9uLndhaXRTeW5jaHJvbml6ZWQodGltZW91dEluU2Vjb25kcyk7XG4gIH1cblxufVxuIl0sIm5hbWVzIjpbIlJwY01ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UiLCJNZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlIiwiY29ubmVjdCIsIl9vcGVuZWQiLCJfbWV0YUFwaUNvbm5lY3Rpb24iLCJpbnN0YW5jZUlkIiwiY2xvc2UiLCJfY2xvc2VkIiwiZ2V0QWNjb3VudEluZm9ybWF0aW9uIiwib3B0aW9ucyIsIl9jaGVja0lzQ29ubmVjdGlvbkFjdGl2ZSIsIl93ZWJzb2NrZXRDbGllbnQiLCJhY2NvdW50IiwiaWQiLCJnZXRQb3NpdGlvbnMiLCJnZXRQb3NpdGlvbiIsInBvc2l0aW9uSWQiLCJnZXRPcmRlcnMiLCJnZXRPcmRlciIsIm9yZGVySWQiLCJnZXRIaXN0b3J5T3JkZXJzQnlUaWNrZXQiLCJ0aWNrZXQiLCJnZXRIaXN0b3J5T3JkZXJzQnlQb3NpdGlvbiIsImdldEhpc3RvcnlPcmRlcnNCeVRpbWVSYW5nZSIsInN0YXJ0VGltZSIsImVuZFRpbWUiLCJvZmZzZXQiLCJsaW1pdCIsImdldERlYWxzQnlUaWNrZXQiLCJnZXREZWFsc0J5UG9zaXRpb24iLCJnZXREZWFsc0J5VGltZVJhbmdlIiwiZ2V0U3ltYm9scyIsImdldFN5bWJvbFNwZWNpZmljYXRpb24iLCJzeW1ib2wiLCJnZXRTeW1ib2xQcmljZSIsImtlZXBTdWJzY3JpcHRpb24iLCJnZXRDYW5kbGUiLCJ0aW1lZnJhbWUiLCJnZXRUaWNrIiwiZ2V0Qm9vayIsImdldFNlcnZlclRpbWUiLCJ3YWl0U3luY2hyb25pemVkIiwidGltZW91dEluU2Vjb25kcyIsImNvbnN0cnVjdG9yIiwid2Vic29ja2V0Q2xpZW50IiwibWV0YUFwaUNvbm5lY3Rpb24iLCJfbG9nZ2VyIiwiTG9nZ2VyTWFuYWdlciIsImdldExvZ2dlciJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7ZUFRcUJBOzs7K0RBTks7a0ZBQ1k7Ozs7OztBQUt2QixJQUFBLEFBQU1BLCtCQUFOLE1BQU1BLHFDQUFxQ0Msa0NBQXlCO0lBYWpGOzs7R0FHQyxHQUNELE1BQU1DLFVBQVU7UUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDQyxPQUFPLEVBQUU7WUFDakIsSUFBSSxDQUFDQSxPQUFPLEdBQUc7WUFDZixJQUFJLENBQUNDLGtCQUFrQixDQUFDRixPQUFPLENBQUMsSUFBSSxDQUFDRyxVQUFVO1FBQ2pEO0lBQ0Y7SUFFQTs7R0FFQyxHQUNELE1BQU1DLFFBQVE7UUFDWixJQUFJLENBQUMsSUFBSSxDQUFDQyxPQUFPLEVBQUU7WUFDakIsSUFBSSxDQUFDSCxrQkFBa0IsQ0FBQ0UsS0FBSyxDQUFDLElBQUksQ0FBQ0QsVUFBVTtZQUM3QyxJQUFJLENB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