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)
152 lines (151 loc) • 13.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;
}
import LoggerManager from '../logger';
/**
* Custom event emitter implementation for use
*/ let EventEmitter = class EventEmitter {
/**
* Subscribes a listener to event
* @param event Event to subscribe to
* @param callback Listener function to subscribe
*/ on(event, callback) {
if (!event) {
throw new Error('Event name is empty or undefined');
}
this._listeners[event] = this._listeners[event] || new Set();
this._listeners[event].add(callback);
}
/**
* Unsubscribes a listener from event
* @param event Event to unsubscribe from
* @param callback Callback to unsubscribe
*/ off(event, callback) {
if (this._listeners[event]) {
this._listeners[event].delete(callback);
if (!this._listeners[event].size) {
delete this._listeners[event];
}
}
}
/**
* Subscribes a listener to event once
* @param event Event to subscribe to
* @param callback Listener function to subscribe
* @param options Additional options
*/ once(event, callback, options) {
let listener = (...args)=>{
if (!(options === null || options === void 0 ? void 0 : options.ifArgs) || (options === null || options === void 0 ? void 0 : options.ifArgs(...args))) {
this.off(event, listener);
return callback(...args);
}
};
this.on(event, listener);
}
/**
* Emits an event
* @param event Event to emit
* @param data Event payload
* @returns Promise resolving when all listeners calls completed. Usually async version is useful if listeners may
* return promises and the call should wait for them. If one of listener rejects or throws an error, it will be
* logged. Async listeners called all at once
*/ emit(event, ...args) {
var _this = this;
return _async_to_generator(function*() {
var _this__listeners_event;
if (!((_this__listeners_event = _this._listeners[event]) === null || _this__listeners_event === void 0 ? void 0 : _this__listeners_event.size)) {
return;
}
let results = [];
for (let listener of _this._listeners[event]){
results.push(_this._callListener(event, listener, args));
}
return Promise.all(results);
})();
}
/**
* Returns subscribed events
* @returns subscribed events
*/ getSubscriptions() {
return Object.keys(this._listeners);
}
/**
* Returns subscribed event listeners
* @param event Event
* @returns Listeners
*/ getListeners(event) {
var _this__listeners_event;
if (!((_this__listeners_event = this._listeners[event]) === null || _this__listeners_event === void 0 ? void 0 : _this__listeners_event.size)) {
return [];
}
return [
...this._listeners[event].values()
];
}
/**
* Returns whether has listeners on specific event
* @param event Event
* @returns Whether has listeners
*/ hasListeners(event) {
return !!this._listeners[event];
}
_callListener(event, listener, args) {
var _this = this;
return _async_to_generator(function*() {
try {
yield listener(...args);
} catch (err) {
_this._eventEmitterLogger.error(`${event}: listener failed with error`, err);
}
})();
}
/**
* Constructs instance
*/ constructor(){
_define_property(this, "_listeners", void 0);
_define_property(this, "_eventEmitterLogger", LoggerManager.getLogger('EventEmitter'));
this._listeners = {};
}
};
export default EventEmitter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBMb2dnZXJNYW5hZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5cbi8qKlxuICogQ3VzdG9tIGV2ZW50IGVtaXR0ZXIgaW1wbGVtZW50YXRpb24gZm9yIHVzZVxuICovXG5jbGFzcyBFdmVudEVtaXR0ZXI8TCBleHRlbmRzIExpc3RlbmVyU2lnbmF0dXJlPEw+ID0gRGVmYXVsdExpc3RlbmVyPiB7XG5cbiAgcHJpdmF0ZSBfbGlzdGVuZXJzOiB7W0UgaW4ga2V5b2YgTF0/OiBTZXQ8TFtFXT59O1xuICBwcml2YXRlIF9ldmVudEVtaXR0ZXJMb2dnZXIgPSBMb2dnZXJNYW5hZ2VyLmdldExvZ2dlcignRXZlbnRFbWl0dGVyJyk7XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgaW5zdGFuY2VcbiAgICovXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuX2xpc3RlbmVycyA9IHt9O1xuICB9XG5cbiAgLyoqXG4gICAqIFN1YnNjcmliZXMgYSBsaXN0ZW5lciB0byBldmVudFxuICAgKiBAcGFyYW0gZXZlbnQgRXZlbnQgdG8gc3Vic2NyaWJlIHRvXG4gICAqIEBwYXJhbSBjYWxsYmFjayBMaXN0ZW5lciBmdW5jdGlvbiB0byBzdWJzY3JpYmVcbiAgICovXG4gIG9uPFUgZXh0ZW5kcyBFdmVudEVtaXR0ZXIuRXZlbnQ8TD4+KGV2ZW50OiBVLCBjYWxsYmFjazogTFtVXSkge1xuICAgIGlmICghZXZlbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXZlbnQgbmFtZSBpcyBlbXB0eSBvciB1bmRlZmluZWQnKTtcbiAgICB9XG4gICAgdGhpcy5fbGlzdGVuZXJzW2V2ZW50XSA9IHRoaXMuX2xpc3RlbmVyc1tldmVudF0gfHwgbmV3IFNldCgpO1xuICAgIHRoaXMuX2xpc3RlbmVyc1tldmVudF0uYWRkKGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnN1YnNjcmliZXMgYSBsaXN0ZW5lciBmcm9tIGV2ZW50XG4gICAqIEBwYXJhbSBldmVudCBFdmVudCB0byB1bnN1YnNjcmliZSBmcm9tXG4gICAqIEBwYXJhbSBjYWxsYmFjayBDYWxsYmFjayB0byB1bnN1YnNjcmliZVxuICAgKi9cbiAgb2ZmPFUgZXh0ZW5kcyBFdmVudEVtaXR0ZXIuRXZlbnQ8TD4+KGV2ZW50OiBVLCBjYWxsYmFjazogTFtVXSkge1xuICAgIGlmICh0aGlzLl9saXN0ZW5lcnNbZXZlbnRdKSB7XG4gICAgICB0aGlzLl9saXN0ZW5lcnNbZXZlbnRdLmRlbGV0ZShjYWxsYmFjayk7XG4gICAgICBpZiAoIXRoaXMuX2xpc3RlbmVyc1tldmVudF0uc2l6ZSkge1xuICAgICAgICBkZWxldGUgdGhpcy5fbGlzdGVuZXJzW2V2ZW50XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlcyBhIGxpc3RlbmVyIHRvIGV2ZW50IG9uY2VcbiAgICogQHBhcmFtIGV2ZW50IEV2ZW50IHRvIHN1YnNjcmliZSB0b1xuICAgKiBAcGFyYW0gY2FsbGJhY2sgTGlzdGVuZXIgZnVuY3Rpb24gdG8gc3Vic2NyaWJlXG4gICAqIEBwYXJhbSBvcHRpb25zIEFkZGl0aW9uYWwgb3B0aW9uc1xuICAgKi9cbiAgb25jZTxVIGV4dGVuZHMgRXZlbnRFbWl0dGVyLkV2ZW50PEw+PihldmVudDogVSwgY2FsbGJhY2s6IExbVV0sIG9wdGlvbnM/OiBFdmVudEVtaXR0ZXIuT25jZU9wdGlvbnM8TFtVXT4pIHtcbiAgICBsZXQgbGlzdGVuZXI6IGFueSA9ICgoLi4uYXJnczogUGFyYW1ldGVyczxMW1VdPikgPT4ge1xuICAgICAgaWYgKCFvcHRpb25zPy5pZkFyZ3MgfHwgb3B0aW9ucz8uaWZBcmdzKC4uLmFyZ3MpKSB7XG4gICAgICAgIHRoaXMub2ZmKGV2ZW50LCBsaXN0ZW5lcik7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayguLi5hcmdzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLm9uKGV2ZW50LCBsaXN0ZW5lcik7XG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgYW4gZXZlbnRcbiAgICogQHBhcmFtIGV2ZW50IEV2ZW50IHRvIGVtaXRcbiAgICogQHBhcmFtIGRhdGEgRXZlbnQgcGF5bG9hZFxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB3aGVuIGFsbCBsaXN0ZW5lcnMgY2FsbHMgY29tcGxldGVkLiBVc3VhbGx5IGFzeW5jIHZlcnNpb24gaXMgdXNlZnVsIGlmIGxpc3RlbmVycyBtYXlcbiAgICogcmV0dXJuIHByb21pc2VzIGFuZCB0aGUgY2FsbCBzaG91bGQgd2FpdCBmb3IgdGhlbS4gSWYgb25lIG9mIGxpc3RlbmVyIHJlamVjdHMgb3IgdGhyb3dzIGFuIGVycm9yLCBpdCB3aWxsIGJlXG4gICAqIGxvZ2dlZC4gQXN5bmMgbGlzdGVuZXJzIGNhbGxlZCBhbGwgYXQgb25jZVxuICAgKi9cbiAgYXN5bmMgZW1pdDxVIGV4dGVuZHMgRXZlbnRFbWl0dGVyLkV2ZW50PEw+PihldmVudDogVSwgLi4uYXJnczogUGFyYW1ldGVyczxMW1VdPik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5fbGlzdGVuZXJzW2V2ZW50XT8uc2l6ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgcmVzdWx0cyA9IFtdO1xuICAgIGZvciAobGV0IGxpc3RlbmVyIG9mIHRoaXMuX2xpc3RlbmVyc1tldmVudF0pIHtcbiAgICAgIHJlc3VsdHMucHVzaCh0aGlzLl9jYWxsTGlzdGVuZXIoZXZlbnQgYXMgc3RyaW5nLCBsaXN0ZW5lciwgYXJncykpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVzdWx0cykgYXMgYW55O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3Vic2NyaWJlZCBldmVudHNcbiAgICogQHJldHVybnMgc3Vic2NyaWJlZCBldmVudHNcbiAgICovXG4gIGdldFN1YnNjcmlwdGlvbnMoKTogRXZlbnRFbWl0dGVyLkV2ZW50PEw+W10ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9saXN0ZW5lcnMpIGFzIEV2ZW50RW1pdHRlci5FdmVudDxMPltdO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3Vic2NyaWJlZCBldmVudCBsaXN0ZW5lcnNcbiAgICogQHBhcmFtIGV2ZW50IEV2ZW50XG4gICAqIEByZXR1cm5zIExpc3RlbmVyc1xuICAgKi9cbiAgZ2V0TGlzdGVuZXJzPFUgZXh0ZW5kcyBFdmVudEVtaXR0ZXIuRXZlbnQ8TD4+KGV2ZW50OiBVKTogTFtVXVtdIHtcbiAgICBpZiAoIXRoaXMuX2xpc3RlbmVyc1tldmVudF0/LnNpemUpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgcmV0dXJuIFsuLi50aGlzLl9saXN0ZW5lcnNbZXZlbnRdLnZhbHVlcygpXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgaGFzIGxpc3RlbmVycyBvbiBzcGVjaWZpYyBldmVudFxuICAgKiBAcGFyYW0gZXZlbnQgRXZlbnRcbiAgICogQHJldHVybnMgV2hldGhlciBoYXMgbGlzdGVuZXJzXG4gICAqL1xuICBoYXNMaXN0ZW5lcnM8VSBleHRlbmRzIEV2ZW50RW1pdHRlci5FdmVudDxMPj4oZXZlbnQ6IFUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLl9saXN0ZW5lcnNbZXZlbnRdO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfY2FsbExpc3RlbmVyKGV2ZW50OiBzdHJpbmcsIGxpc3RlbmVyOiAoLi4uYXJnczogYW55KSA9PiBhbnksIGFyZ3M6IGFueVtdKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGxpc3RlbmVyKC4uLmFyZ3MpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyTG9nZ2VyLmVycm9yKGAke2V2ZW50fTogbGlzdGVuZXIgZmFpbGVkIHdpdGggZXJyb3JgLCBlcnIpO1xuICAgIH1cbiAgfVxufVxuXG5uYW1lc3BhY2UgRXZlbnRFbWl0dGVyIHtcblxuICAvKiogTWV0aG9kIG9wdGlvbnMgKi9cbiAgZXhwb3J0IHR5cGUgT25jZU9wdGlvbnM8TGlzdGVuZXIgZXh0ZW5kcyAoLi4uYXJnczogYW55W10pID0+IGFueT4gPSB7XG4gICAgLyoqXG4gICAgICogSWYgc3BlY2lmaWVkLCB0aGUgbGlzdGVuZXIgd2lsbCBiZSBjYWxsZWQgb25seSBpZiB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVlLiBPdGhlcndpc2UsIHRoZSBsaXN0ZW5lciB3aWxsIHdhaXRcbiAgICAgKiBmb3IgdGhlIG5leHQgbWF0Y2hpbmcgY2FsbFxuICAgICAqL1xuICAgIGlmQXJncz86ICguLi5hcmdzOiBQYXJhbWV0ZXJzPExpc3RlbmVyPikgPT4gYm9vbGVhbjtcbiAgfTtcblxuICAvKiogSW5mZXJzIGV2ZW50IHR5cGUgb2YgYSBsaXN0ZW5lciAqL1xuICBleHBvcnQgdHlwZSBFdmVudDxMIGV4dGVuZHMgTGlzdGVuZXJTaWduYXR1cmU8TD4+ID0gRXh0cmFjdDxrZXlvZiBMLCBzdHJpbmc+O1xufVxuXG5leHBvcnQgZGVmYXVsdCBFdmVudEVtaXR0ZXI7XG5cbi8qKlxuICogRXZlbnQgZW1pdHRlciBsaXN0ZW5lciB0eXBlXG4gKi9cbmV4cG9ydCB0eXBlIExpc3RlbmVyU2lnbmF0dXJlPExpc3RlbmVycz4gPSB7XG4gIFtFdmVudE5hbWUgaW4ga2V5b2YgTGlzdGVuZXJzXTogKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnk7XG59O1xuXG4vKipcbiAqIERlZmF1bHQgZXZlbnQgZW1pdHRlciBsaXN0ZW5lciB0eXBlXG4gKi9cbmV4cG9ydCB0eXBlIERlZmF1bHRMaXN0ZW5lciA9IHtcbiAgW2s6IHN0cmluZ106ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55O1xufTtcbiJdLCJuYW1lcyI6WyJMb2dnZXJNYW5hZ2VyIiwiRXZlbnRFbWl0dGVyIiwib24iLCJldmVudCIsImNhbGxiYWNrIiwiRXJyb3IiLCJfbGlzdGVuZXJzIiwiU2V0IiwiYWRkIiwib2ZmIiwiZGVsZXRlIiwic2l6ZSIsIm9uY2UiLCJvcHRpb25zIiwibGlzdGVuZXIiLCJhcmdzIiwiaWZBcmdzIiwiZW1pdCIsInJlc3VsdHMiLCJwdXNoIiwiX2NhbGxMaXN0ZW5lciIsIlByb21pc2UiLCJhbGwiLCJnZXRTdWJzY3JpcHRpb25zIiwiT2JqZWN0Iiwia2V5cyIsImdldExpc3RlbmVycyIsInZhbHVlcyIsImhhc0xpc3RlbmVycyIsImVyciIsIl9ldmVudEVtaXR0ZXJMb2dnZXIiLCJlcnJvciIsImNvbnN0cnVjdG9yIiwiZ2V0TG9nZ2VyIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLE9BQU9BLG1CQUFtQixZQUFZO0FBRXRDOztDQUVDLEdBQ0QsSUFBQSxBQUFNQyxlQUFOLE1BQU1BO0lBWUo7Ozs7R0FJQyxHQUNEQyxHQUFvQ0MsS0FBUSxFQUFFQyxRQUFjLEVBQUU7UUFDNUQsSUFBSSxDQUFDRCxPQUFPO1lBQ1YsTUFBTSxJQUFJRSxNQUFNO1FBQ2xCO1FBQ0EsSUFBSSxDQUFDQyxVQUFVLENBQUNILE1BQU0sR0FBRyxJQUFJLENBQUNHLFVBQVUsQ0FBQ0gsTUFBTSxJQUFJLElBQUlJO1FBQ3ZELElBQUksQ0FBQ0QsVUFBVSxDQUFDSCxNQUFNLENBQUNLLEdBQUcsQ0FBQ0o7SUFDN0I7SUFFQTs7OztHQUlDLEdBQ0RLLElBQXFDTixLQUFRLEVBQUVDLFFBQWMsRUFBRTtRQUM3RCxJQUFJLElBQUksQ0FBQ0UsVUFBVSxDQUFDSCxNQUFNLEVBQUU7WUFDMUIsSUFBSSxDQUFDRyxVQUFVLENBQUNILE1BQU0sQ0FBQ08sTUFBTSxDQUFDTjtZQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDRSxVQUFVLENBQUNILE1BQU0sQ0FBQ1EsSUFBSSxFQUFFO2dCQUNoQyxPQUFPLElBQUksQ0FBQ0wsVUFBVSxDQUFDSCxNQUFNO1lBQy9CO1FBQ0Y7SUFDRjtJQUVBOzs7OztHQUtDLEdBQ0RTLEtBQXNDVCxLQUFRLEVBQUVDLFFBQWMsRUFBRVMsT0FBd0MsRUFBRTtRQUN4RyxJQUFJQyxXQUFpQixDQUFDLEdBQUdDO1lBQ3ZCLElBQUksRUFBQ0Ysb0JBQUFBLDhCQUFBQSxRQUFTRyxNQUFNLE1BQUlILG9CQUFBQSw4QkFBQUEsUUFBU0csTUFBTSxJQUFJRCxRQUFPO2dCQUNoRCxJQUFJLENBQUNOLEdBQUcsQ0FBQ04sT0FBT1c7Z0JBQ2hCLE9BQU9WLFlBQVlXO1lBQ3JCO1FBQ0Y7UUFDQSxJQUFJLENBQUNiLEVBQUUsQ0FBQ0MsT0FBT1c7SUFDakI7SUFFQTs7Ozs7OztHQU9DLEdBQ0QsQUFBTUcsS0FBc0NkLEtBQVEsRUFBRSxHQUFHWSxJQUFzQjs7ZUFBL0Usb0JBQUE7Z0JBQ087WUFBTCxJQUFJLEdBQUMseUJBQUEsTUFBS1QsVUFBVSxDQUFDSCxNQUFNLGNBQXRCLDZDQUFBLHVCQUF3QlEsSUFBSSxHQUFFO2dCQUNqQztZQUNGO1lBQ0EsSUFBSU8sVUFBVSxFQUFFO1lBQ2hCLEtBQUssSUFBSUosWUFBWSxNQUFLUixVQUFVLENBQUNILE1BQU0sQ0FBRTtnQkFDM0NlLFFBQVFDLElBQUksQ0FBQyxNQUFLQyxhQUFhLENBQUNqQixPQUFpQlcsVUFBVUM7WUFDN0Q7WUFDQSxPQUFPTSxRQUFRQyxHQUFHLENBQUNKO1FBQ3JCOztJQUVBOzs7R0FHQyxHQUNESyxtQkFBNEM7UUFDMUMsT0FBT0MsT0FBT0MsSUFBSSxDQUFDLElBQUksQ0FBQ25CLFVBQVU7SUFDcEM7SUFFQTs7OztHQUlDLEdBQ0RvQixhQUE4Q3ZCLEtBQVEsRUFBVTtZQUN6RDtRQUFMLElBQUksR0FBQyx5QkFBQSxJQUFJLENBQUNHLFVBQVUsQ0FBQ0gsTUFBTSxjQUF0Qiw2Q0FBQSx1QkFBd0JRLElBQUksR0FBRTtZQUNqQyxPQUFPLEVBQUU7UUFDWDtRQUNBLE9BQU87ZUFBSSxJQUFJLENBQUNMLFVBQVUsQ0FBQ0gsTUFBTSxDQUFDd0IsTUFBTTtTQUFHO0lBQzdDO0lBRUE7Ozs7R0FJQyxHQUNEQyxhQUE4Q3pCLEtBQVEsRUFBVztRQUMvRCxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUNHLFVBQVUsQ0FBQ0gsTUFBTTtJQUNqQztJQUVjaUIsY0FBY2pCLEtBQWEsRUFBRVcsUUFBK0IsRUFBRUMsSUFBVzs7ZUFBdkYsb0JBQUE7WUFDRSxJQUFJO2dCQUNGLE1BQU1ELFlBQVlDO1lBQ3BCLEVBQUUsT0FBT2MsS0FBSztnQkFDWixNQUFLQyxtQkFBbUIsQ0FBQ0MsS0FBSyxDQUFDLENBQUMsRUFBRTVCLE1BQU0sNEJBQTRCLENBQUMsRUFBRTBCO1lBQ3pFO1FBQ0Y7O0lBeEdBOztHQUVDLEdBQ0RHLGFBQWM7UUFOZCx1QkFBUTFCLGNBQVIsS0FBQTtRQUNBLHVCQUFRd0IsdUJBQXNCOUIsY0FBY2lDLFNBQVMsQ0FBQztRQU1wRCxJQUFJLENBQUMzQixVQUFVLEdBQUcsQ0FBQztJQUNyQjtBQW9HRjtBQWlCQSxlQUFlTCxhQUFhIn0=