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)

128 lines (127 loc) 18.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "default", { enumerable: true, get: function() { return ConnectionRegistry; } }); const _streamingMetaApiConnection = /*#__PURE__*/ _interop_require_default(require("./streamingMetaApiConnection")); const _rpcMetaApiConnection = /*#__PURE__*/ _interop_require_default(require("./rpcMetaApiConnection")); const _streamingMetaApiConnectionInstance = /*#__PURE__*/ _interop_require_default(require("./streamingMetaApiConnectionInstance")); const _rpcMetaApiConnectionInstance = /*#__PURE__*/ _interop_require_default(require("./rpcMetaApiConnectionInstance")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } let ConnectionRegistry = class ConnectionRegistry { /** * Creates and returns a new account streaming connection if doesnt exist, otherwise returns old * @param {MetatraderAccount} account MetaTrader account id to connect to * @param {HistoryStorage} historyStorage terminal history storage * @param {Date} [historyStartTime] history start time * @return {StreamingMetaApiConnection} streaming metaapi connection */ connectStreaming(account, historyStorage, historyStartTime) { if (!this._streamingConnections[account.id]) { this._streamingConnections[account.id] = new _streamingMetaApiConnection.default(this._options, this._metaApiWebsocketClient, this._terminalHashManager, account, historyStorage, this, historyStartTime, this._refreshSubscriptionsOpts); } const instance = new _streamingMetaApiConnectionInstance.default(this._metaApiWebsocketClient, this._streamingConnections[account.id]); this._streamingConnectionInstances[account.id] = this._streamingConnectionInstances[account.id] || []; this._streamingConnectionInstances[account.id].push(instance); return instance; } /** * Removes a streaming connection from registry * @param {MetatraderAccount} account MetaTrader account to remove from registry */ async removeStreaming(account) { if (this._streamingConnections[account.id]) { delete this._streamingConnections[account.id]; delete this._streamingConnectionInstances[account.id]; } if (!this._rpcConnections[account.id]) { await this._closeLastConnection(account); } } /** * Creates and returns a new account rpc connection if doesnt exist, otherwise returns old * @param {MetatraderAccount} account MetaTrader account id to connect to * @returns {RpcMetaApiConnection} rpc metaapi connection */ connectRpc(account) { if (!this._rpcConnections[account.id]) { this._rpcConnections[account.id] = new _rpcMetaApiConnection.default(this._options, this._metaApiWebsocketClient, account, this); } const instance = new _rpcMetaApiConnectionInstance.default(this._metaApiWebsocketClient, this._rpcConnections[account.id]); this._rpcConnectionInstances[account.id] = this._rpcConnectionInstances[account.id] || []; this._rpcConnectionInstances[account.id].push(instance); return instance; } /** * Removes an RPC connection from registry * @param {MetatraderAccount} account MetaTrader account to remove from registry */ async removeRpc(account) { if (this._rpcConnections[account.id]) { delete this._rpcConnections[account.id]; delete this._rpcConnectionInstances[account.id]; } if (!this._streamingConnections[account.id]) { await this._closeLastConnection(account); } } /** * Returns application type * @return {String} application type */ get application() { return this._application; } async _closeLastConnection(account) { const accountRegions = account.accountRegions; await Promise.all(Object.values(accountRegions).map((replicaId)=>this._metaApiWebsocketClient.unsubscribe(replicaId))); } /** * Returns the dictionary of streaming connections * @returns {{[id: string]: StreamingMetaApiConnection}} */ get streamingConnections() { return this._streamingConnections; } /** * Returns the dictionary of rpc connections * @returns {{[id: string]: RpcMetaApiConnection}} */ get rpcConnections() { return this._rpcConnections; } /** * Closes all connection instances for an account * @param {string} accountId */ closeAllInstances(accountId) { if (this._rpcConnectionInstances[accountId]) { this._rpcConnectionInstances[accountId].forEach((instance)=>instance.close()); } if (this._streamingConnectionInstances[accountId]) { this._streamingConnectionInstances[accountId].forEach((instance)=>instance.close()); } } /** * Constructs a MetaTrader connection registry instance * @param {MetaApiOpts} options metaapi options * @param {MetaApiWebsocketClient} metaApiWebsocketClient MetaApi websocket client * @param {ClientApiClient} clientApiClient client API client * @param {String} application application id * @param {String} refreshSubscriptionsOpts subscriptions refresh options */ constructor(options, metaApiWebsocketClient, terminalHashManager, application = "MetaApi", refreshSubscriptionsOpts){ refreshSubscriptionsOpts = refreshSubscriptionsOpts || {}; this._metaApiWebsocketClient = metaApiWebsocketClient; this._terminalHashManager = terminalHashManager; this._application = application; this._refreshSubscriptionsOpts = refreshSubscriptionsOpts; this._rpcConnections = {}; this._rpcConnectionInstances = {}; this._streamingConnections = {}; this._streamingConnectionInstances = {}; this._connectionLocks = {}; this._options = options; } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgU3RyZWFtaW5nTWV0YUFwaUNvbm5lY3Rpb24gZnJvbSAnLi9zdHJlYW1pbmdNZXRhQXBpQ29ubmVjdGlvbic7XG5pbXBvcnQgUnBjTWV0YUFwaUNvbm5lY3Rpb24gZnJvbSAnLi9ycGNNZXRhQXBpQ29ubmVjdGlvbic7XG5pbXBvcnQgU3RyZWFtaW5nTWV0YUFwaUNvbm5lY3Rpb25JbnN0YW5jZSBmcm9tICcuL3N0cmVhbWluZ01ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UnO1xuaW1wb3J0IFJwY01ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UgZnJvbSAnLi9ycGNNZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlJztcblxuLyoqXG4gKiBNYW5hZ2VzIGFjY291bnQgY29ubmVjdGlvbnNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29ubmVjdGlvblJlZ2lzdHJ5IHtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIE1ldGFUcmFkZXIgY29ubmVjdGlvbiByZWdpc3RyeSBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge01ldGFBcGlPcHRzfSBvcHRpb25zIG1ldGFhcGkgb3B0aW9uc1xuICAgKiBAcGFyYW0ge01ldGFBcGlXZWJzb2NrZXRDbGllbnR9IG1ldGFBcGlXZWJzb2NrZXRDbGllbnQgTWV0YUFwaSB3ZWJzb2NrZXQgY2xpZW50XG4gICAqIEBwYXJhbSB7Q2xpZW50QXBpQ2xpZW50fSBjbGllbnRBcGlDbGllbnQgY2xpZW50IEFQSSBjbGllbnRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGFwcGxpY2F0aW9uIGFwcGxpY2F0aW9uIGlkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSByZWZyZXNoU3Vic2NyaXB0aW9uc09wdHMgc3Vic2NyaXB0aW9ucyByZWZyZXNoIG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMsIG1ldGFBcGlXZWJzb2NrZXRDbGllbnQsIHRlcm1pbmFsSGFzaE1hbmFnZXIsXG4gICAgYXBwbGljYXRpb24gPSAnTWV0YUFwaScsIHJlZnJlc2hTdWJzY3JpcHRpb25zT3B0cykge1xuICAgIHJlZnJlc2hTdWJzY3JpcHRpb25zT3B0cyA9IHJlZnJlc2hTdWJzY3JpcHRpb25zT3B0cyB8fCB7fTtcbiAgICB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50ID0gbWV0YUFwaVdlYnNvY2tldENsaWVudDtcbiAgICB0aGlzLl90ZXJtaW5hbEhhc2hNYW5hZ2VyID0gdGVybWluYWxIYXNoTWFuYWdlcjtcbiAgICB0aGlzLl9hcHBsaWNhdGlvbiA9IGFwcGxpY2F0aW9uO1xuICAgIHRoaXMuX3JlZnJlc2hTdWJzY3JpcHRpb25zT3B0cyA9IHJlZnJlc2hTdWJzY3JpcHRpb25zT3B0cztcbiAgICB0aGlzLl9ycGNDb25uZWN0aW9ucyA9IHt9O1xuICAgIHRoaXMuX3JwY0Nvbm5lY3Rpb25JbnN0YW5jZXMgPSB7fTtcbiAgICB0aGlzLl9zdHJlYW1pbmdDb25uZWN0aW9ucyA9IHt9O1xuICAgIHRoaXMuX3N0cmVhbWluZ0Nvbm5lY3Rpb25JbnN0YW5jZXMgPSB7fTtcbiAgICB0aGlzLl9jb25uZWN0aW9uTG9ja3MgPSB7fTtcbiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcbiAgfVxuICBcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW5kIHJldHVybnMgYSBuZXcgYWNjb3VudCBzdHJlYW1pbmcgY29ubmVjdGlvbiBpZiBkb2VzbnQgZXhpc3QsIG90aGVyd2lzZSByZXR1cm5zIG9sZFxuICAgKiBAcGFyYW0ge01ldGF0cmFkZXJBY2NvdW50fSBhY2NvdW50IE1ldGFUcmFkZXIgYWNjb3VudCBpZCB0byBjb25uZWN0IHRvXG4gICAqIEBwYXJhbSB7SGlzdG9yeVN0b3JhZ2V9IGhpc3RvcnlTdG9yYWdlIHRlcm1pbmFsIGhpc3Rvcnkgc3RvcmFnZVxuICAgKiBAcGFyYW0ge0RhdGV9IFtoaXN0b3J5U3RhcnRUaW1lXSBoaXN0b3J5IHN0YXJ0IHRpbWVcbiAgICogQHJldHVybiB7U3RyZWFtaW5nTWV0YUFwaUNvbm5lY3Rpb259IHN0cmVhbWluZyBtZXRhYXBpIGNvbm5lY3Rpb25cbiAgICovXG4gIGNvbm5lY3RTdHJlYW1pbmcoYWNjb3VudCwgaGlzdG9yeVN0b3JhZ2UsIGhpc3RvcnlTdGFydFRpbWUpIHtcbiAgICBpZiAoIXRoaXMuX3N0cmVhbWluZ0Nvbm5lY3Rpb25zW2FjY291bnQuaWRdKSB7XG4gICAgICB0aGlzLl9zdHJlYW1pbmdDb25uZWN0aW9uc1thY2NvdW50LmlkXSA9IG5ldyBTdHJlYW1pbmdNZXRhQXBpQ29ubmVjdGlvbih0aGlzLl9vcHRpb25zLFxuICAgICAgICB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LCB0aGlzLl90ZXJtaW5hbEhhc2hNYW5hZ2VyLCBhY2NvdW50LCBoaXN0b3J5U3RvcmFnZSwgdGhpcywgaGlzdG9yeVN0YXJ0VGltZSxcbiAgICAgICAgdGhpcy5fcmVmcmVzaFN1YnNjcmlwdGlvbnNPcHRzKTtcbiAgICB9XG4gICAgY29uc3QgaW5zdGFuY2UgPSBuZXcgU3RyZWFtaW5nTWV0YUFwaUNvbm5lY3Rpb25JbnN0YW5jZSh0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LCBcbiAgICAgIHRoaXMuX3N0cmVhbWluZ0Nvbm5lY3Rpb25zW2FjY291bnQuaWRdKTtcbiAgICB0aGlzLl9zdHJlYW1pbmdDb25uZWN0aW9uSW5zdGFuY2VzW2FjY291bnQuaWRdID0gdGhpcy5fc3RyZWFtaW5nQ29ubmVjdGlvbkluc3RhbmNlc1thY2NvdW50LmlkXSB8fCBbXTtcbiAgICB0aGlzLl9zdHJlYW1pbmdDb25uZWN0aW9uSW5zdGFuY2VzW2FjY291bnQuaWRdLnB1c2goaW5zdGFuY2UpO1xuICAgIHJldHVybiBpbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgc3RyZWFtaW5nIGNvbm5lY3Rpb24gZnJvbSByZWdpc3RyeVxuICAgKiBAcGFyYW0ge01ldGF0cmFkZXJBY2NvdW50fSBhY2NvdW50IE1ldGFUcmFkZXIgYWNjb3VudCB0byByZW1vdmUgZnJvbSByZWdpc3RyeVxuICAgKi9cbiAgYXN5bmMgcmVtb3ZlU3RyZWFtaW5nKGFjY291bnQpIHtcbiAgICBpZiAodGhpcy5fc3RyZWFtaW5nQ29ubmVjdGlvbnNbYWNjb3VudC5pZF0pIHtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zdHJlYW1pbmdDb25uZWN0aW9uc1thY2NvdW50LmlkXTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zdHJlYW1pbmdDb25uZWN0aW9uSW5zdGFuY2VzW2FjY291bnQuaWRdO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuX3JwY0Nvbm5lY3Rpb25zW2FjY291bnQuaWRdKSB7XG4gICAgICBhd2FpdCB0aGlzLl9jbG9zZUxhc3RDb25uZWN0aW9uKGFjY291bnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuZCByZXR1cm5zIGEgbmV3IGFjY291bnQgcnBjIGNvbm5lY3Rpb24gaWYgZG9lc250IGV4aXN0LCBvdGhlcndpc2UgcmV0dXJucyBvbGRcbiAgICogQHBhcmFtIHtNZXRhdHJhZGVyQWNjb3VudH0gYWNjb3VudCBNZXRhVHJhZGVyIGFjY291bnQgaWQgdG8gY29ubmVjdCB0b1xuICAgKiBAcmV0dXJucyB7UnBjTWV0YUFwaUNvbm5lY3Rpb259IHJwYyBtZXRhYXBpIGNvbm5lY3Rpb25cbiAgICovXG4gIGNvbm5lY3RScGMoYWNjb3VudCkge1xuICAgIGlmICghdGhpcy5fcnBjQ29ubmVjdGlvbnNbYWNjb3VudC5pZF0pIHtcbiAgICAgIHRoaXMuX3JwY0Nvbm5lY3Rpb25zW2FjY291bnQuaWRdID0gbmV3IFJwY01ldGFBcGlDb25uZWN0aW9uKHRoaXMuX29wdGlvbnMsIHRoaXMuX21ldGFBcGlXZWJzb2NrZXRDbGllbnQsIGFjY291bnQsXG4gICAgICAgIHRoaXMpO1xuICAgIH1cbiAgICBjb25zdCBpbnN0YW5jZSA9IG5ldyBScGNNZXRhQXBpQ29ubmVjdGlvbkluc3RhbmNlKHRoaXMuX21ldGFBcGlXZWJzb2NrZXRDbGllbnQsIFxuICAgICAgdGhpcy5fcnBjQ29ubmVjdGlvbnNbYWNjb3VudC5pZF0pO1xuICAgIHRoaXMuX3JwY0Nvbm5lY3Rpb25JbnN0YW5jZXNbYWNjb3VudC5pZF0gPSB0aGlzLl9ycGNDb25uZWN0aW9uSW5zdGFuY2VzW2FjY291bnQuaWRdIHx8IFtdO1xuICAgIHRoaXMuX3JwY0Nvbm5lY3Rpb25JbnN0YW5jZXNbYWNjb3VudC5pZF0ucHVzaChpbnN0YW5jZSk7XG4gICAgcmV0dXJuIGluc3RhbmNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYW4gUlBDIGNvbm5lY3Rpb24gZnJvbSByZWdpc3RyeVxuICAgKiBAcGFyYW0ge01ldGF0cmFkZXJBY2NvdW50fSBhY2NvdW50IE1ldGFUcmFkZXIgYWNjb3VudCB0byByZW1vdmUgZnJvbSByZWdpc3RyeVxuICAgKi9cbiAgYXN5bmMgcmVtb3ZlUnBjKGFjY291bnQpIHtcbiAgICBpZiAodGhpcy5fcnBjQ29ubmVjdGlvbnNbYWNjb3VudC5pZF0pIHtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ycGNDb25uZWN0aW9uc1thY2NvdW50LmlkXTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ycGNDb25uZWN0aW9uSW5zdGFuY2VzW2FjY291bnQuaWRdO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuX3N0cmVhbWluZ0Nvbm5lY3Rpb25zW2FjY291bnQuaWRdKSB7XG4gICAgICBhd2FpdCB0aGlzLl9jbG9zZUxhc3RDb25uZWN0aW9uKGFjY291bnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFwcGxpY2F0aW9uIHR5cGVcbiAgICogQHJldHVybiB7U3RyaW5nfSBhcHBsaWNhdGlvbiB0eXBlXG4gICAqL1xuICBnZXQgYXBwbGljYXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FwcGxpY2F0aW9uO1xuICB9XG5cbiAgYXN5bmMgX2Nsb3NlTGFzdENvbm5lY3Rpb24oYWNjb3VudCkge1xuICAgIGNvbnN0IGFjY291bnRSZWdpb25zID0gYWNjb3VudC5hY2NvdW50UmVnaW9ucztcbiAgICBhd2FpdCBQcm9taXNlLmFsbChPYmplY3QudmFsdWVzKGFjY291bnRSZWdpb25zKS5tYXAocmVwbGljYUlkID0+XG4gICAgICB0aGlzLl9tZXRhQXBpV2Vic29ja2V0Q2xpZW50LnVuc3Vic2NyaWJlKHJlcGxpY2FJZCkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBkaWN0aW9uYXJ5IG9mIHN0cmVhbWluZyBjb25uZWN0aW9uc1xuICAgKiBAcmV0dXJucyB7e1tpZDogc3RyaW5nXTogU3RyZWFtaW5nTWV0YUFwaUNvbm5lY3Rpb259fVxuICAgKi9cbiAgZ2V0IHN0cmVhbWluZ0Nvbm5lY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLl9zdHJlYW1pbmdDb25uZWN0aW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBkaWN0aW9uYXJ5IG9mIHJwYyBjb25uZWN0aW9uc1xuICAgKiBAcmV0dXJucyB7e1tpZDogc3RyaW5nXTogUnBjTWV0YUFwaUNvbm5lY3Rpb259fVxuICAgKi9cbiAgZ2V0IHJwY0Nvbm5lY3Rpb25zKCkge1xuICAgIHJldHVybiB0aGlzLl9ycGNDb25uZWN0aW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgYWxsIGNvbm5lY3Rpb24gaW5zdGFuY2VzIGZvciBhbiBhY2NvdW50XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhY2NvdW50SWQgXG4gICAqL1xuICBjbG9zZUFsbEluc3RhbmNlcyhhY2NvdW50SWQpIHtcbiAgICBpZiAodGhpcy5fcnBjQ29ubmVjdGlvbkluc3RhbmNlc1thY2NvdW50SWRdKSB7XG4gICAgICB0aGlzLl9ycGNDb25uZWN0aW9uSW5zdGFuY2VzW2FjY291bnRJZF0uZm9yRWFjaChpbnN0YW5jZSA9PiBpbnN0YW5jZS5jbG9zZSgpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX3N0cmVhbWluZ0Nvbm5lY3Rpb25JbnN0YW5jZXNbYWNjb3VudElkXSkge1xuICAgICAgdGhpcy5fc3RyZWFtaW5nQ29ubmVjdGlvbkluc3RhbmNlc1thY2NvdW50SWRdLmZvckVhY2goaW5zdGFuY2UgPT4gaW5zdGFuY2UuY2xvc2UoKSk7XG4gICAgfVxuICB9XG4gIFxufVxuIl0sIm5hbWVzIjpbIkNvbm5lY3Rpb25SZWdpc3RyeSIsImNvbm5lY3RTdHJlYW1pbmciLCJhY2NvdW50IiwiaGlzdG9yeVN0b3JhZ2UiLCJoaXN0b3J5U3RhcnRUaW1lIiwiX3N0cmVhbWluZ0Nvbm5lY3Rpb25zIiwiaWQiLCJTdHJlYW1pbmdNZXRhQXBpQ29ubmVjdGlvbiIsIl9vcHRpb25zIiwiX21ldGFBcGlXZWJzb2NrZXRDbGllbnQiLCJfdGVybWluYWxIYXNoTWFuYWdlciIsIl9yZWZyZXNoU3Vic2NyaXB0aW9uc09wdHMiLCJpbnN0YW5jZSIsIlN0cmVhbWluZ01ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UiLCJfc3RyZWFtaW5nQ29ubmVjdGlvbkluc3RhbmNlcyIsInB1c2giLCJyZW1vdmVTdHJlYW1pbmciLCJfcnBjQ29ubmVjdGlvbnMiLCJfY2xvc2VMYXN0Q29ubmVjdGlvbiIsImNvbm5lY3RScGMiLCJScGNNZXRhQXBpQ29ubmVjdGlvbiIsIlJwY01ldGFBcGlDb25uZWN0aW9uSW5zdGFuY2UiLCJfcnBjQ29ubmVjdGlvbkluc3RhbmNlcyIsInJlbW92ZVJwYyIsImFwcGxpY2F0aW9uIiwiX2FwcGxpY2F0aW9uIiwiYWNjb3VudFJlZ2lvbnMiLCJQcm9taXNlIiwiYWxsIiwiT2JqZWN0IiwidmFsdWVzIiwibWFwIiwicmVwbGljYUlkIiwidW5zdWJzY3JpYmUiLCJzdHJlYW1pbmdDb25uZWN0aW9ucyIsInJwY0Nvbm5lY3Rpb25zIiwiY2xvc2VBbGxJbnN0YW5jZXMiLCJhY2NvdW50SWQiLCJmb3JFYWNoIiwiY2xvc2UiLCJjb25zdHJ1Y3RvciIsIm9wdGlvbnMiLCJtZXRhQXBpV2Vic29ja2V0Q2xpZW50IiwidGVybWluYWxIYXNoTWFuYWdlciIsInJlZnJlc2hTdWJzY3JpcHRpb25zT3B0cyIsIl9jb25uZWN0aW9uTG9j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