// /home/def/monitor/backend/providers/klingex.js // // Minimal KlingEx provider used ONLY for ETHO and EGAZ (spot price). // We intentionally do NOT try to use KlingEx for all assets. // This provider returns a consistent shape expected by server.js: // // { price: , points: [], source: 'klingex:sdk' } // // Pair input accepted as "ETHO-USDT" or "ETHO_USDT" (case-insensitive). const { KlingEx } = require("klingex"); let client = null; async function getClient() { if (client) return client; client = new KlingEx(); // public endpoints work without auth for markets/tickers return client; } function normalizePair(pair) { const p = String(pair || "").trim().toUpperCase().replace("_", "-"); const m = p.match(/^([A-Z0-9]+)-([A-Z0-9]+)$/); if (!m) return null; return { base: m[1], quote: m[2], dash: `${m[1]}-${m[2]}`, underscore: `${m[1]}_${m[2]}` }; } async function fetchPair(pair) { const norm = normalizePair(pair); if (!norm) throw new Error(`Bad klingex_pair: ${pair}`); const kx = await getClient(); // KlingEx SDK: client.markets.tickers() -> array of tickers like: // { ticker_id: 'ETHO_USDT', last_price: '0.005', ... } (or sometimes integer-ish strings) const tickers = await kx.markets.tickers(); if (!Array.isArray(tickers)) { throw new Error(`KlingEx tickers() returned non-array`); } const t = tickers.find(x => String(x?.ticker_id || "").toUpperCase() === norm.underscore); if (!t) { throw new Error(`KlingEx: pair not found in tickers(): ${norm.underscore}`); } // Prefer last_price. Some exchanges also provide "last" etc, but your data uses last_price. const raw = t.last_price ?? t.last ?? t.price ?? null; const price = raw != null ? Number(raw) : NaN; if (!isFinite(price)) { throw new Error(`KlingEx: non-numeric last_price for ${norm.underscore}: ${String(raw)}`); } return { price, // <-- server.js expects r.price points: [], // no OHLCV implemented yet source: "klingex:sdk" }; } module.exports = { fetchPair };