mango-ui-v2/public/datafeeds/udf/lib/udf-compatible-datafeed-bas...

375 lines
11 KiB
JavaScript

import { getErrorMessage, logMessage } from './helpers';
import { HistoryProvider } from './history-provider';
import { DataPulseProvider } from './data-pulse-provider';
import { QuotesPulseProvider } from './quotes-pulse-provider';
import { SymbolsStorage } from './symbols-storage';
function extractField(data, field, arrayIndex) {
var value = data[field];
return Array.isArray(value) ? value[arrayIndex] : value;
}
/**
* This class implements interaction with UDF-compatible datafeed.
* See UDF protocol reference at https://github.com/tradingview/charting_library/wiki/UDF
*/
var UDFCompatibleDatafeedBase = /** @class */ (function () {
function UDFCompatibleDatafeedBase(
datafeedURL,
quotesProvider,
requester,
updateFrequency,
) {
var _this = this;
if (updateFrequency === void 0) {
updateFrequency = 10 * 1000;
}
this._configuration = defaultConfiguration();
this._symbolsStorage = null;
this._datafeedURL = datafeedURL;
this._requester = requester;
this._historyProvider = new HistoryProvider(datafeedURL, this._requester);
this._quotesProvider = quotesProvider;
this._dataPulseProvider = new DataPulseProvider(
this._historyProvider,
updateFrequency,
);
this._quotesPulseProvider = new QuotesPulseProvider(this._quotesProvider);
this._configurationReadyPromise = this._requestConfiguration().then(
function (configuration) {
if (configuration === null) {
configuration = defaultConfiguration();
}
_this._setupWithConfiguration(configuration);
},
);
}
UDFCompatibleDatafeedBase.prototype.onReady = function (callback) {
var _this = this;
this._configurationReadyPromise.then(function () {
callback(_this._configuration);
});
};
UDFCompatibleDatafeedBase.prototype.getQuotes = function (
symbols,
onDataCallback,
onErrorCallback,
) {
this._quotesProvider
.getQuotes(symbols)
.then(onDataCallback)
.catch(onErrorCallback);
};
UDFCompatibleDatafeedBase.prototype.subscribeQuotes = function (
symbols,
fastSymbols,
onRealtimeCallback,
listenerGuid,
) {
this._quotesPulseProvider.subscribeQuotes(
symbols,
fastSymbols,
onRealtimeCallback,
listenerGuid,
);
};
UDFCompatibleDatafeedBase.prototype.unsubscribeQuotes = function (
listenerGuid,
) {
this._quotesPulseProvider.unsubscribeQuotes(listenerGuid);
};
UDFCompatibleDatafeedBase.prototype.calculateHistoryDepth = function (
resolution,
resolutionBack,
intervalBack,
) {
return undefined;
};
UDFCompatibleDatafeedBase.prototype.getMarks = function (
symbolInfo,
from,
to,
onDataCallback,
resolution,
) {
if (!this._configuration.supports_marks) {
return;
}
var requestParams = {
symbol: symbolInfo.ticker || '',
from: from,
to: to,
resolution: resolution,
};
this._send('marks', requestParams)
.then(function (response) {
if (!Array.isArray(response)) {
var result = [];
for (var i = 0; i < response.id.length; ++i) {
result.push({
id: extractField(response, 'id', i),
time: extractField(response, 'time', i),
color: extractField(response, 'color', i),
text: extractField(response, 'text', i),
label: extractField(response, 'label', i),
labelFontColor: extractField(response, 'labelFontColor', i),
minSize: extractField(response, 'minSize', i),
});
}
response = result;
}
onDataCallback(response);
})
.catch(function (error) {
logMessage(
'UdfCompatibleDatafeed: Request marks failed: ' +
getErrorMessage(error),
);
onDataCallback([]);
});
};
UDFCompatibleDatafeedBase.prototype.getTimescaleMarks = function (
symbolInfo,
from,
to,
onDataCallback,
resolution,
) {
if (!this._configuration.supports_timescale_marks) {
return;
}
var requestParams = {
symbol: symbolInfo.ticker || '',
from: from,
to: to,
resolution: resolution,
};
this._send('timescale_marks', requestParams)
.then(function (response) {
if (!Array.isArray(response)) {
var result = [];
for (var i = 0; i < response.id.length; ++i) {
result.push({
id: extractField(response, 'id', i),
time: extractField(response, 'time', i),
color: extractField(response, 'color', i),
label: extractField(response, 'label', i),
tooltip: extractField(response, 'tooltip', i),
});
}
response = result;
}
onDataCallback(response);
})
.catch(function (error) {
logMessage(
'UdfCompatibleDatafeed: Request timescale marks failed: ' +
getErrorMessage(error),
);
onDataCallback([]);
});
};
UDFCompatibleDatafeedBase.prototype.getServerTime = function (callback) {
if (!this._configuration.supports_time) {
return;
}
this._send('time')
.then(function (response) {
var time = parseInt(response);
if (!isNaN(time)) {
callback(time);
}
})
.catch(function (error) {
logMessage(
'UdfCompatibleDatafeed: Fail to load server time, error=' +
getErrorMessage(error),
);
});
};
UDFCompatibleDatafeedBase.prototype.searchSymbols = function (
userInput,
exchange,
symbolType,
onResult,
) {
if (this._configuration.supports_search) {
var params = {
limit: 30 /* SearchItemsLimit */,
query: userInput.toUpperCase(),
type: symbolType,
exchange: exchange,
};
this._send('search', params)
.then(function (response) {
if (response.s !== undefined) {
logMessage(
'UdfCompatibleDatafeed: search symbols error=' + response.errmsg,
);
onResult([]);
return;
}
onResult(response);
})
.catch(function (reason) {
logMessage(
"UdfCompatibleDatafeed: Search symbols for '" +
userInput +
"' failed. Error=" +
getErrorMessage(reason),
);
onResult([]);
});
} else {
if (this._symbolsStorage === null) {
throw new Error(
'UdfCompatibleDatafeed: inconsistent configuration (symbols storage)',
);
}
this._symbolsStorage
.searchSymbols(
userInput,
exchange,
symbolType,
30 /* SearchItemsLimit */,
)
.then(onResult)
.catch(onResult.bind(null, []));
}
};
UDFCompatibleDatafeedBase.prototype.resolveSymbol = function (
symbolName,
onResolve,
onError,
extension,
) {
logMessage('Resolve requested');
var currencyCode = extension && extension.currencyCode;
var resolveRequestStartTime = Date.now();
function onResultReady(symbolInfo) {
logMessage(
'Symbol resolved: ' + (Date.now() - resolveRequestStartTime) + 'ms',
);
onResolve(symbolInfo);
}
if (!this._configuration.supports_group_request) {
var params = {
symbol: symbolName,
};
if (currencyCode !== undefined) {
params.currencyCode = currencyCode;
}
this._send('symbols', params)
.then(function (response) {
if (response.s !== undefined) {
onError('unknown_symbol');
} else {
onResultReady(response);
}
})
.catch(function (reason) {
logMessage(
'UdfCompatibleDatafeed: Error resolving symbol: ' +
getErrorMessage(reason),
);
onError('unknown_symbol');
});
} else {
if (this._symbolsStorage === null) {
throw new Error(
'UdfCompatibleDatafeed: inconsistent configuration (symbols storage)',
);
}
this._symbolsStorage
.resolveSymbol(symbolName, currencyCode)
.then(onResultReady)
.catch(onError);
}
};
UDFCompatibleDatafeedBase.prototype.getBars = function (
symbolInfo,
resolution,
rangeStartDate,
rangeEndDate,
onResult,
onError,
) {
this._historyProvider
.getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate)
.then(function (result) {
onResult(result.bars, result.meta);
})
.catch(onError);
};
UDFCompatibleDatafeedBase.prototype.subscribeBars = function (
symbolInfo,
resolution,
onTick,
listenerGuid,
onResetCacheNeededCallback,
) {
this._dataPulseProvider.subscribeBars(
symbolInfo,
resolution,
onTick,
listenerGuid,
);
};
UDFCompatibleDatafeedBase.prototype.unsubscribeBars = function (
listenerGuid,
) {
this._dataPulseProvider.unsubscribeBars(listenerGuid);
};
UDFCompatibleDatafeedBase.prototype._requestConfiguration = function () {
return this._send('config').catch(function (reason) {
logMessage(
'UdfCompatibleDatafeed: Cannot get datafeed configuration - use default, error=' +
getErrorMessage(reason),
);
return null;
});
};
UDFCompatibleDatafeedBase.prototype._send = function (urlPath, params) {
return this._requester.sendRequest(this._datafeedURL, urlPath, params);
};
UDFCompatibleDatafeedBase.prototype._setupWithConfiguration = function (
configurationData,
) {
this._configuration = configurationData;
if (configurationData.exchanges === undefined) {
configurationData.exchanges = [];
}
if (
!configurationData.supports_search &&
!configurationData.supports_group_request
) {
throw new Error(
'Unsupported datafeed configuration. Must either support search, or support group request',
);
}
if (
configurationData.supports_group_request ||
!configurationData.supports_search
) {
this._symbolsStorage = new SymbolsStorage(
this._datafeedURL,
configurationData.supported_resolutions || [],
this._requester,
);
}
logMessage(
'UdfCompatibleDatafeed: Initialized with ' +
JSON.stringify(configurationData),
);
};
return UDFCompatibleDatafeedBase;
})();
export { UDFCompatibleDatafeedBase };
function defaultConfiguration() {
return {
supports_search: false,
supports_group_request: true,
supported_resolutions: ['1', '5', '15', '30', '60', '1D', '1W', '1M'],
supports_marks: false,
supports_timescale_marks: false,
};
}