'use strict'; import HttpClient from '../clients/httpClient'; import ProvisioningProfileClient from '../clients/metaApi/provisioningProfile.client'; import ProvisioningProfileApi from './provisioningProfileApi'; import MetaApiWebsocketClient from '../clients/metaApi/metaApiWebsocket.client'; import MetatraderAccountApi from './metatraderAccountApi'; import MetatraderAccountClient from '../clients/metaApi/metatraderAccount.client'; import MetatraderAccountGeneratorApi from './metatraderAccountGeneratorApi'; import MetatraderAccountGeneratorClient from '../clients/metaApi/metatraderAccountGenerator.client'; import HistoricalMarketDataClient from '../clients/metaApi/historicalMarketData.client'; import ClientApiClient from '../clients/metaApi/clientApi.client'; import ConnectionRegistry from './connectionRegistry'; import {ValidationError} from '../clients/errorHandler'; import OptionsValidator from '../clients/optionsValidator'; import LatencyMonitor from './latencyMonitor'; import ExpertAdvisorClient from '../clients/metaApi/expertAdvisor.client'; import LoggerManager from '../logger'; import DomainClient from '../clients/domain.client'; import TerminalHashManager from './terminalHashManager'; import TokenManagementClient from '../clients/metaApi/tokenManagement.client'; import TokenManagementApi from './tokenManagementApi'; import {MetaApiOpts} from './metaApi'; import _ from 'lodash'; /** * MetaApi MetaTrader API SDK */ export default class MetaApi { /** * Enables using Log4js logger with extended log levels for debugging instead of * console.* functions. Note that log4js configuration performed by the user. */ static enableLog4jsLogging() { LoggerManager.useLog4js(); } /** * Constructs MetaApi class instance * @param {String} token authorization token * @param {MetaApiOpts} opts application options */ // eslint-disable-next-line complexity constructor(token, opts) { const validator = new OptionsValidator(); opts = _.omit(opts || {}, ['connections']); const application = opts.application || 'MetaApi'; const domain = opts.domain || 'agiliumtrade.agiliumtrade.ai'; const requestTimeout = validator.validateNonZero(opts.requestTimeout, 60, 'requestTimeout'); const historicalMarketDataRequestTimeout = validator.validateNonZero( opts.historicalMarketDataRequestTimeout, 240, 'historicalMarketDataRequestTimeout'); const connectTimeout = validator.validateNonZero(opts.connectTimeout, 60, 'connectTimeout'); const packetOrderingTimeout = validator.validateNonZero(opts.packetOrderingTimeout, 60, 'packetOrderingTimeout'); const retryOpts = opts.retryOpts || {}; const packetLogger = opts.packetLogger || {}; const synchronizationThrottler = opts.synchronizationThrottler || {}; const accountGeneratorRequestTimeout = validator.validateNonZero(opts.accountGeneratorRequestTimeout, 240, 'accountGeneratorRequestTimeout'); if (!application.match(/[a-zA-Z0-9_]+/)) { throw new ValidationError('Application name must be non-empty string consisting from letters, digits and _ only'); } const useSharedClientApi = opts.useSharedClientApi || false; const refreshSubscriptionsOpts = opts.refreshSubscriptionsOpts || {}; const httpClient = new HttpClient(requestTimeout, retryOpts); const domainClient = new DomainClient(httpClient, token, domain); const historicalMarketDataHttpClient = new HttpClient(historicalMarketDataRequestTimeout, retryOpts); const accountGeneratorHttpClient = new HttpClient(accountGeneratorRequestTimeout, retryOpts); const clientApiClient = new ClientApiClient(httpClient, domainClient); const tokenManagmentClient = new TokenManagementClient(httpClient, domainClient); this._terminalHashManager = new TerminalHashManager(clientApiClient, opts.keepHashTrees); this._metaApiWebsocketClient = new MetaApiWebsocketClient(this, domainClient, token, { application, domain, requestTimeout, connectTimeout, packetLogger, packetOrderingTimeout, synchronizationThrottler, retryOpts, useSharedClientApi, region: opts.region, unsubscribeThrottlingIntervalInSeconds: opts.unsubscribeThrottlingIntervalInSeconds, useNativeSocketIoServer: opts.useNativeSocketIoServer }); this._provisioningProfileApi = new ProvisioningProfileApi(new ProvisioningProfileClient(httpClient, domainClient)); this._connectionRegistry = new ConnectionRegistry(opts, this._metaApiWebsocketClient, this._terminalHashManager, application, refreshSubscriptionsOpts); let historicalMarketDataClient = new HistoricalMarketDataClient(historicalMarketDataHttpClient, domainClient); this._metatraderAccountApi = new MetatraderAccountApi(new MetatraderAccountClient(httpClient, domainClient), this._metaApiWebsocketClient, this._connectionRegistry, new ExpertAdvisorClient(httpClient, domainClient), historicalMarketDataClient, application); this._metatraderAccountGeneratorApi = new MetatraderAccountGeneratorApi( new MetatraderAccountGeneratorClient(accountGeneratorHttpClient, domainClient)); this._tokenManagementApi = new TokenManagementApi(tokenManagmentClient); if (opts.enableLatencyTracking || opts.enableLatencyMonitor) { this._latencyMonitor = new LatencyMonitor(); this._metaApiWebsocketClient.addLatencyListener(this._latencyMonitor); } this._logger = LoggerManager.getLogger('MetaAPI'); if (process.env.IS_BROWSER) { if (!this._tokenManagementApi.areTokenResourcesNarrowedDown(token)) { this._logger.warn('USING THE ADMIN TOKEN'); this._logger.info( 'It seems like you are using a admin API token. Since the token can be retrieven from the browser or ' + 'mobile apps by end user this can lead to your application being compromised, unless you understand what ' + 'are you doing. Please use Token Management API ' + '(https://github.com/metaapi/metaapi-javascript-sdk/blob/master/docs/tokenManagementApi.md) in your ' + 'backend application to produce secure tokens which you can then use in web UI or mobile apps.' ); } } } /** * Returns provisioning profile API * @returns {ProvisioningProfileApi} provisioning profile API */ get provisioningProfileApi() { return this._provisioningProfileApi; } /** * Returns MetaTrader account API * @return {MetatraderAccountApi} MetaTrader account API */ get metatraderAccountApi() { return this._metatraderAccountApi; } /** * Returns MetaTrader account generator API * @return {MetatraderDemoAccountApi} MetaTrader account generator API */ get metatraderAccountGeneratorApi() { return this._metatraderAccountGeneratorApi; } /** * Returns MetaApi application latency monitor * @return {LatencyMonitor} latency monitor */ get latencyMonitor() { return this._latencyMonitor; } /** * Returns token management API * @returns {TokenManagementApi} token management API */ get tokenManagementApi() { return this._tokenManagementApi; } /** * Closes all clients and connections and stops all internal jobs */ close() { this._metaApiWebsocketClient.removeLatencyListener(this._latencyMonitor); this._metaApiWebsocketClient.close(); this._metaApiWebsocketClient.stop(); this._terminalHashManager._stop(); } }