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)
167 lines (150 loc) • 5.55 kB
text/typescript
'use strict';
import MetaApiClient from '../metaApi.client';
import LoggerManager, {Logger} from '../../logger';
import {NotFoundError} from '../errorHandler';
import HttpClient from '../httpClient';
import DomainClient from '../domain.client';
/**
* metaapi.cloud client API client (see https://metaapi.cloud/docs/client/)
*/
export default class ClientApiClient extends MetaApiClient {
private _retryIntervalInSeconds: number;
private _updateInterval: number;
private _ignoredFieldListsCaches: {};
private _ignoredFieldListsFreshestCache: null;
private _logger: Logger;
/**
* Constructs client API client instance
* @param {HttpClient} httpClient HTTP client
* @param {DomainClient} domainClient domain client
*/
constructor(httpClient: HttpClient, domainClient: DomainClient) {
super(httpClient, domainClient);
this._host = 'https://mt-client-api-v1';
this._retryIntervalInSeconds = 1;
this._updateInterval = 60 * 60 * 1000;
this._ignoredFieldListsCaches = {};
this._ignoredFieldListsFreshestCache = null;
this._logger = LoggerManager.getLogger('ClientApiClient');
}
/**
* Type hashing ignored field lists
* @typedef {Object} TypeHashingIgnoredFieldLists
* @property {String[]} specification specification ignored fields
* @property {String[]} position position ignored fields
* @property {String[]} order order ignored fields
*/
/**
* Hashing ignored field lists
* @typedef {Object} HashingIgnoredFieldLists
* @property {TypeHashingIgnoredFieldLists} g1 g1 hashing ignored field lists
* @property {TypeHashingIgnoredFieldLists} g2 g2 hashing ignored field lists
*/
/**
* Refreshes hashing ignored field lists
* @param {String} region account region
* @returns {Promise} promise resolving when the hashing field lists are updated.
*/
async refreshIgnoredFieldLists(region: string): Promise<any> {
if(this._ignoredFieldListsCaches[region] && this._ignoredFieldListsCaches[region].requestPromise) {
await this._ignoredFieldListsCaches[region].requestPromise;
} else if (this._ignoredFieldListsCaches[region] &&
Date.now() - this._ignoredFieldListsCaches[region].lastUpdated < this._updateInterval) {
return;
} else {
if(!this._ignoredFieldListsCaches[region]) {
this._ignoredFieldListsCaches[region] = {
lastUpdated: 0,
data: null,
requestPromise: null,
updateJob: setInterval(() => this._refreshIgnoredFieldListsJob(region), 60000)
};
}
let resolve, reject;
this._ignoredFieldListsCaches[region].requestPromise = new Promise((res, rej) => {
resolve = res, reject = rej;
});
let isCacheUpdated = false;
while(!isCacheUpdated) {
try {
const host = await this._domainClient.getUrl(this._host, region);
const opts = {
url: `${host}/hashing-ignored-field-lists`,
method: 'GET',
json: true,
headers: {
'auth-token': this._token
}
};
const response = await this._httpClient.request(opts, 'getHashingIgnoredFieldLists');
this._ignoredFieldListsCaches[region] = { lastUpdated: Date.now(), data: response, requestPromise: null };
this._ignoredFieldListsFreshestCache = response;
resolve(response);
isCacheUpdated = true;
this._ignoredFieldListsCaches[region].retryIntervalInSeconds = this._retryIntervalInSeconds;
} catch (err) {
this._logger.error('Failed to update hashing ignored field list', err);
this._ignoredFieldListsCaches[region].retryIntervalInSeconds =
Math.min(this._ignoredFieldListsCaches[region].retryIntervalInSeconds * 2, 300);
await new Promise(res => setTimeout(res,
this._ignoredFieldListsCaches[region].retryIntervalInSeconds * 1000));
}
}
}
}
/**
* Retrieves hashing ignored field lists
* @param {String} region account region
* @returns {HashingIgnoredFieldLists} promise resolving with hashing ignored field lists
*/
getHashingIgnoredFieldLists(region: string): HashingIgnoredFieldLists {
if(region === 'combined') {
if (this._ignoredFieldListsFreshestCache) {
return this._ignoredFieldListsFreshestCache;
} else{
throw new NotFoundError('Ignored field lists not found');
}
}
if(this._ignoredFieldListsCaches[region] && this._ignoredFieldListsCaches[region].data) {
return this._ignoredFieldListsCaches[region].data;
} else {
throw new NotFoundError(`Ignored field lists for region ${region} not found`);
}
}
async _refreshIgnoredFieldListsJob(region) {
if(!this._ignoredFieldListsCaches[region].requestPromise &&
Date.now() - this._ignoredFieldListsCaches[region].lastUpdated > this._updateInterval) {
await this.refreshIgnoredFieldLists(region);
}
}
}
/**
* Type hashing ignored field lists
*/
export declare type TypeHashingIgnoredFieldLists = {
/**
* specifications ignored fields
*/
specification: string[],
/**
* position ignored fields
*/
position: string[],
/**
* order ignored fields
*/
order: string[],
}
/**
* Hashing ignored field lists
*/
export declare type HashingIgnoredFieldLists = {
/**
* g1 hashing ignored field lists
*/
g1: TypeHashingIgnoredFieldLists,
/**
* g2 hashing ignored field lists
*/
g2: TypeHashingIgnoredFieldLists,
}