wiki/examples/js/exchange-capabilities.md
// @NO_AUTO_TRANSPILE
import ccxt from '../../js/ccxt.js';
import ololog from 'ololog';
import ansicolor from 'ansicolor';
import asTable from 'as-table';
const { noLocate } = ololog;
const log = noLocate;
ansicolor.nice;
const csv = process.argv.includes('--csv'), delimiter = csv ? ',' : '|', asTableConfig = { delimiter: ' ' + delimiter + ' ', /* print: require ('string.ify').noPretty */ };
asTable.configure(asTableConfig);
const sortCertified = process.argv.includes('--sort-certified') || process.argv.includes('--certified');
const exchangesArgument = process.argv.find(arg => arg.startsWith('--exchanges='));
const exchangesArgumentParts = exchangesArgument ? exchangesArgument.split('=') : [];
const selectedExchanges = (exchangesArgumentParts.length > 1) ? exchangesArgumentParts[1].split(',') : [];
console.log(ccxt.iso8601(ccxt.milliseconds()));
console.log('CCXT v' + ccxt.version);
async function main() {
let total = 0;
let notImplemented = 0;
let inexistentApi = 0;
let implemented = 0;
let emulated = 0;
const exchangeNames = ccxt.exchanges;
let exchanges = exchangeNames.map(id => new ccxt[id]());
exchanges = exchanges.map(exchange => exchange.pro ? new ccxt.pro[exchange.id]() : exchange);
if (sortCertified) {
exchanges.sort((a, b) => {
if (a.certified && !b.certified) {
return -1;
}
else if (!a.certified && b.certified) {
return 1;
}
else {
return 0;
}
});
}
const metainfo = ccxt.flatten(exchanges.map(exchange => Object.keys(exchange.has)));
const reduced = metainfo.reduce((previous, current) => {
previous[current] = (previous[current] || 0) + 1;
return previous;
}, {});
const unified = Object.entries(reduced).filter(([_, count]) => count > 1);
const methods = unified.map(([method, _]) => method).sort();
if (selectedExchanges.length > 0) {
exchanges = exchanges.filter((exchange) => selectedExchanges.includes(exchange.id));
}
const table = asTable(exchanges.map(exchange => {
let result = {};
const basics = [
'CORS',
'spot',
'margin',
'swap',
'future',
'option',
];
ccxt.unique(basics.concat(methods)).forEach(key => {
total += 1;
let coloredString = '';
const feature = exchange.has[key];
const isFunction = (typeof exchange[key] === 'function');
const isBasic = basics.includes(key);
if (feature === false) {
// if explicitly set to 'false' in exchange.has (to exclude mistake, we check if it's undefined too)
coloredString = exchange.id.red.dim;
inexistentApi += 1;
}
else if (feature === 'emulated') {
// if explicitly set to 'emulated' in exchange.has
coloredString = exchange.id.yellow;
emulated += 1;
}
else if (feature) {
if (isBasic) {
// if neither 'false' nor 'emulated', and if method exists
coloredString = exchange.id.green;
implemented += 1;
}
else {
if (isFunction) {
coloredString = exchange.id.green;
implemented += 1;
}
else {
// the feature is available in exchange.has and not implemented
// this is an error
coloredString = exchange.id.lightMagenta;
}
}
}
else {
coloredString = exchange.id.lightRed;
notImplemented += 1;
}
result[key] = coloredString;
});
return result;
}));
if (csv) {
let lines = table.split("\n");
lines = lines.slice(0, 1).concat(lines.slice(2));
log(lines.join("\n"));
}
else {
log(table);
}
log('Summary: ', ccxt.exchanges.length.toString(), 'exchanges; ', 'Methods [' + total.toString() + ' total]: ', implemented.toString().green, 'implemented,', emulated.toString().yellow, 'emulated,', inexistentApi.toString().red.dim, 'inexistentApi,', notImplemented.toString().lightRed, 'notImplemented');
log(("\nMessy? Try piping to less (e.g. node script.js | less -S -R --header=3 )\n").red);
}
main();