From 8f7418757c0d6d5c81fc27b854da7ee69709b92a Mon Sep 17 00:00:00 2001 From: gh14 Date: Sun, 31 Aug 2025 23:08:58 +0000 Subject: [PATCH] unimportant fixes to markets, im just bored waiting for sal testnet to achieve right height to check if previous changes work ;) --- lib/market.js | 435 +++++++++++++++++------------------ website_example/config.js | 2 +- website_example/js/common.js | 11 +- 3 files changed, 219 insertions(+), 229 deletions(-) diff --git a/lib/market.js b/lib/market.js index 9ac06d9..bf7c126 100644 --- a/lib/market.js +++ b/lib/market.js @@ -111,160 +111,229 @@ function getExchangeMarkets (exchange, callback) { let price = 0.0; let data = {}; - // Altex - if (exchange == "altex") { - apiInterfaces.jsonHttpRequest('api.altex.exchange', 443, '', function (error, response) { + // CoinEx + if (exchange === "coinex") { + const cfgSymRaw = (config && config.symbol); + if (!cfgSymRaw) { + log('error', logSystem, 'CoinEx: config.symbol not set; skipping'); + return callback(null, data); + } + const poolSymbol = String(cfgSymRaw).toUpperCase(); + + // exchange base: only map SAL1->SAL when Salvium is enabled + let exchangeBase = poolSymbol; + try { + if (typeof utils?.isSalviumEnabled === 'function' && utils.isSalviumEnabled() && poolSymbol === 'SAL1') { + exchangeBase = 'SAL'; + } + } catch (_) {} + + const exCfg = (config && config.exchanges && config.exchanges.coinex) || {}; + const quotesRaw = exCfg.quotes ?? exCfg.quote ?? 'USDT'; + const quotes = Array.isArray(quotesRaw) ? quotesRaw : [quotesRaw]; + if (quotes.length === 0) quotes.push('USDT'); + + let pending = quotes.length; + const finish = () => { + marketRequestsCache[cacheKey] = { ts: currentTimestamp, data }; + callback(null, data); + }; + + quotes.forEach((q) => { + const quote = String(q).toUpperCase(); + const pair = `${exchangeBase}${quote}`; + const path = `/v2/spot/ticker?market=${pair}`; + + apiInterfaces.jsonHttpRequest('api.coinex.com', 443, '', function (error, response) { + if (error || !response) { + log('error', logSystem, 'CoinEx %s failed: %s', [pair, error || 'no response']); + } else { + try { + // { code, data: [ { market: "BASEQUOTE", last: "..." , ... } ] } + const items = (response && response.data) || []; + const item = Array.isArray(items) ? items[0] : null; + const price = parseFloat(item?.last ?? item?.ticker?.last); + if (price > 0) { + const rspBase = exchangeBase; // request is single-market + const rspQuote = quote; + + if (!data[rspBase]) data[rspBase] = {}; + data[rspBase][rspQuote] = price; + + // mirror under pool symbol if exchange base differs (e.g., SAL vs SAL1) + if (rspBase !== poolSymbol) { + if (!data[poolSymbol]) data[poolSymbol] = {}; + data[poolSymbol][rspQuote] = price; + } + } else { + log('warn', logSystem, 'CoinEx %s non-positive or missing price: %j', [pair, response]); + } + } catch (e) { + log('error', logSystem, 'CoinEx parse error for %s: %s', [pair, e && e.stack || e]); + } + } + if (--pending === 0) finish(); + }, path); + }); + } + + // MEXC (single-market request; unified pattern) + else if (exchange === "mexc") { + const cfgSymRaw = (config && config.symbol); + if (!cfgSymRaw) { + log('error', logSystem, 'MEXC: config.symbol not set; skipping'); + return callback(null, data); + } + const poolSymbol = String(cfgSymRaw).toUpperCase(); + + // exchange base: only map SAL1->SAL when Salvium is enabled + let exchangeBase = poolSymbol; + try { + if (typeof utils?.isSalviumEnabled === 'function' && utils.isSalviumEnabled() && poolSymbol === 'SAL1') { + exchangeBase = 'SAL'; + } + } catch (_) {} + + const exCfg = (config && config.exchanges && config.exchanges.mexc) || {}; + const quotesRaw = exCfg.quotes ?? exCfg.quote ?? 'USDT'; + const quotes = Array.isArray(quotesRaw) ? quotesRaw : [quotesRaw]; + if (quotes.length === 0) quotes.push('USDT'); + + let pending = quotes.length; + const finish = () => { + marketRequestsCache[cacheKey] = { ts: currentTimestamp, data }; + callback(null, data); + }; + + quotes.forEach((q) => { + const quote = String(q).toUpperCase(); + const pair = `${exchangeBase}${quote}`; // e.g., SALUSDT + const path = `/api/v3/ticker/price?symbol=${pair}`; // single-symbol + + apiInterfaces.jsonHttpRequest('api.mexc.com', 443, '', function (error, response) { + if (error || !response) { + log('error', logSystem, 'MEXC %s failed: %s', [pair, error || 'no response']); + } else { + try { + // single: { symbol: "BASEQUOTE", price: "..." } + const price = parseFloat(response.price ?? response.last ?? response.lastPrice); + if (price > 0) { + const rspBase = exchangeBase; + const rspQuote = quote; + + if (!data[rspBase]) data[rspBase] = {}; + data[rspBase][rspQuote] = price; + + if (rspBase !== poolSymbol) { + if (!data[poolSymbol]) data[poolSymbol] = {}; + data[poolSymbol][rspQuote] = price; + } + } else { + log('warn', logSystem, 'MEXC %s non-positive or missing price: %j', [pair, response]); + } + } catch (e) { + log('error', logSystem, 'MEXC parse error for %s: %s', [pair, e && e.stack || e]); + } + } + if (--pending === 0) finish(); + }, path); + }); + } + // NonKYC.io + else if (exchange === "nonkyc") { + // Base symbol comes strictly from config (no SAL fallback). + const cfgSymRaw = (config && config.symbol); + if (!cfgSymRaw) { + log('error', logSystem, 'NonKYC: config.symbol not set; skipping price fetch'); + return callback(null, data); + } + const poolSymbol = String(cfgSymRaw).toUpperCase(); + + // Exchange symbol: special-case only for Salvium -> map SAL1 (pool) to SAL (exchange). + let exchangeBase = poolSymbol; + try { + if (typeof utils?.isSalviumEnabled === 'function' && utils.isSalviumEnabled() && poolSymbol === 'SAL1') { + exchangeBase = 'SAL'; + } + } catch (_) {} + + // Quotes from settings; default to USDT if none provided. + const exCfg = (config && config.exchanges && config.exchanges.nonkyc) || {}; + const quotesRaw = exCfg.quotes ?? exCfg.quote ?? 'USDT'; + const quotes = Array.isArray(quotesRaw) ? quotesRaw : [quotesRaw]; + + if (quotes.length === 0) quotes.push('USDT'); + + let pending = quotes.length; + const finish = () => { + marketRequestsCache[cacheKey] = { ts: currentTimestamp, data }; + callback(null, data); + }; + + quotes.forEach((q) => { + const quote = String(q).toUpperCase(); + const pair = `${exchangeBase}_${quote}`; + const path = `/api/v2/ticker/${pair}`; + + apiInterfaces.jsonHttpRequest('api.nonkyc.io', 443, '', function (error, response) { + if (error || !response) { + log('error', logSystem, 'NonKYC API %s failed: %s', [pair, error || 'no response']); + } else { + try { + // Example: + // {"ticker_id":"SAL_USDT","base_currency":"SAL","target_currency":"USDT","last_price":"0.069706",...} + const rspBase = String(response.base_currency || exchangeBase).toUpperCase(); + const rspQuote = String(response.target_currency || quote).toUpperCase(); + const price = parseFloat(response.last_price || response.last || response.price); + + if (price > 0) { + if (!data[rspBase]) data[rspBase] = {}; + data[rspBase][rspQuote] = price; + + // Mirror under pool symbol iff exchange base differs (e.g., pool SAL1 vs exchange SAL) + if (rspBase !== poolSymbol) { + if (!data[poolSymbol]) data[poolSymbol] = {}; + data[poolSymbol][rspQuote] = price; + } + } else { + log('warn', logSystem, 'NonKYC %s returned non-positive price: %j', [pair, response]); + } + } catch (e) { + log('error', logSystem, 'NonKYC parse error for %s: %s', [pair, e && e.stack || e]); + } + } + + if (--pending === 0) finish(); + }, path); + }); + } + // Exbitron + else if (exchange == "exbitron") { + apiInterfaces.jsonHttpRequest('api.exbitron.digital', 443, '', function (error, response) { if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); - if (error) callback(error, {}); - if (!response || !response.success) callback('No market informations', {}); - let ticker = null; - for (ticker in response.data) { - tickerParts = ticker.split('_'); - target = tickerParts[0]; - symbol = tickerParts[1]; + let data = {}; + if (!error && response && response.status === "OK" && response.data) { + let market = response.data.market; + let pairParts = market.id.split('-'); + let symbol = pairParts[0]; + let target = pairParts[1]; - price = +parseFloat(response.data[ticker].last); - if (price === 0) continue; - - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; + let price = +market.marketDynamics.lastPrice; + if (price !== 0) { + if (!data[symbol]) data[symbol] = {}; + data[symbol][target] = price; + } } + if (!error) marketRequestsCache[cacheKey] = { ts: currentTimestamp, data: data }; callback(null, data); - }, '/v1/ticker'); + }, '/api/v1/trading/info/' + config.symbol + '-USDT'); } -// Exbitron -else if (exchange == "exbitron") { - apiInterfaces.jsonHttpRequest('api.exbitron.digital', 443, '', function (error, response) { - if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); - - let data = {}; - if (!error && response && response.status === "OK" && response.data) { - let market = response.data.market; - let pairParts = market.id.split('-'); - let symbol = pairParts[0]; - let target = pairParts[1]; - - let price = +market.marketDynamics.lastPrice; - if (price !== 0) { - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; - } - } - - if (!error) marketRequestsCache[cacheKey] = { - ts: currentTimestamp, - data: data - }; - callback(null, data); - }, '/api/v1/trading/info/' + config.symbol + '-USDT'); -} - - - // Crex24 - else if (exchange == "crex24") { - apiInterfaces.jsonHttpRequest('api.crex24.com', 443, '', function (error, response) { - if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); - - if (error) callback(error, {}); - if (!response || !response.Tickers) callback('No market informations', {}); - - let ticker = null; - let pairName = null; - let pairParts = null; - for (let i in response.Tickers) { - ticker = response.Tickers[i]; - - pairName = ticker.PairName; - pairParts = pairName.split('_'); - target = pairParts[0]; - symbol = pairParts[1]; - - price = +ticker.Last; - if (!price || price === 0) continue; - - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; - } - if (!error) marketRequestsCache[cacheKey] = { - ts: currentTimestamp, - data: data - }; - callback(null, data); - }, '/CryptoExchangeService/BotPublic/ReturnTicker'); - } - - // Cryptopia - else if (exchange == "cryptopia") { - apiInterfaces.jsonHttpRequest('www.cryptopia.co.nz', 443, '', function (error, response) { - if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); - - if (error) callback(error, {}); - if (!response || !response.Success) callback('No market informations', {}); - - let ticker = null; - let pairName = null; - let pairParts = null; - for (let i in response.Data) { - ticker = response.Data[i]; - - pairName = ticker.Label; - pairParts = pairName.split('/'); - target = pairParts[1]; - symbol = pairParts[0]; - - price = +ticker.LastPrice; - if (!price || price === 0) continue; - - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; - } - if (!error) marketRequestsCache[cacheKey] = { - ts: currentTimestamp, - data: data - }; - callback(null, data); - }, '/api/GetMarkets'); - } - - // Stocks.Exchange - else if (exchange == "stocks.exchange") { - apiInterfaces.jsonHttpRequest('stocks.exchange', 443, '', function (error, response) { - if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); - - if (error) callback(error, {}); - if (!response) callback('No market informations', {}); - - let ticker = null; - let pairName = null; - let pairParts = null; - for (let i in response) { - ticker = response[i]; - - pairName = ticker.market_name; - pairParts = pairName.split('_'); - target = pairParts[1]; - symbol = pairParts[0]; - - price = +ticker.last; - if (!price || price === 0) continue; - - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; - } - if (!error) marketRequestsCache[cacheKey] = { - ts: currentTimestamp, - data: data - }; - callback(null, data); - }, '/api2/ticker'); - } - - // TradeOgre + // TradeOgre - śpij słodko aniołku U_U' else if (exchange == "tradeogre") { apiInterfaces.jsonHttpRequest('tradeogre.com', 443, '', function (error, response) { if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); @@ -291,58 +360,6 @@ else if (exchange == "exbitron") { }; callback(null, data); }, '/api/v1/markets'); - } else if (exchange == "maplechange") { - apiInterfaces.jsonHttpRequest('maplechange.com', 443, '', function (error, response) { - if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); - - let data = {}; - if (!error && response) { - for (let model in response) { - let len = model.length; - if (len <= 3) continue; - target = model.substring(len - 3, len) - .toUpperCase(); - symbol = model.substring(0, len - 3) - .toUpperCase(); - - price = +response[model]['ticker']['last']; - if (price === 0) continue; - - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; - } - } - if (!error) marketRequestsCache[cacheKey] = { - ts: currentTimestamp, - data: data - }; - callback(null, data); - }, '/api/v2/tickers'); - } else if (exchange == "stex") { - apiInterfaces.jsonHttpRequest('app.stex.com', 443, '', function (error, response) { - if (error) log('error', logSystem, 'API request to %s has failed: %s', [exchange, error]); - - let pieces = null; - - if (!error && response) { - for (let model in response) { - pieces = response[model]['market_name'].split('_'); - target = pieces[1]; - symbol = pieces[0]; - - price = +response[model]['last']; - if (price === 0) continue; - - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; - } - } - if (!error) marketRequestsCache[cacheKey] = { - ts: currentTimestamp, - data: data - }; - callback(null, data); - }, '/api2/ticker'); } // Btc-Alpha else if (exchange == "btcalpha") { @@ -369,32 +386,6 @@ else if (exchange == "exbitron") { }; callback(null, data); }, '/api/v1/exchanges/' /*JUST FOR 20DEC!! '/api/v1/exchanges/?pair=BDX_BTC'*/ ); - } - // tradesatoshi - else if (exchange == "tradesatoshi") { - apiInterfaces.jsonHttpRequest('tradesatoshi.com', 443, '', function (error, response) { - if (error) console.log('error', 'API request to has failed: ' + error); - - let pieces = null; - if (!error && response.success) { - for (let model in response.result) { - pieces = response.result[model]['market'].split('_'); - target = pieces[1]; - symbol = pieces[0]; - - price = +response.result[model]['last']; - if (price === 0) continue; - - if (!data[symbol]) data[symbol] = {}; - data[symbol][target] = price; - } - } - if (!error) marketRequestsCache[cacheKey] = { - ts: currentTimestamp, - data: data - }; - callback(null, data); - }, '/api/public/getmarketsummaries'); } else if (exchange == "coinmarketcap") { apiInterfaces.jsonHttpRequest('coinmarketcap.coindeal.com', 443, '', function (error, response) { if (error) console.log('error', 'API request to has failed: ' + error); diff --git a/website_example/config.js b/website_example/config.js index 8761bb4..d282c57 100644 --- a/website_example/config.js +++ b/website_example/config.js @@ -7,7 +7,7 @@ var email = "support@poolhost.com"; var telegram = "https://t.me/YourPool"; var discord = "https://discordapp.com/invite/YourPool"; -var marketCurrencies = ["{symbol}-BTC", "{symbol}-USD", "{symbol}-EUR", "{symbol}-CAD"]; +var marketCurrencies = ["{symbol}-BTC", "{symbol}-USDT"]; var blockchainExplorer = "http://chainradar.com/{symbol}/block/{id}"; var transactionExplorer = "http://chainradar.com/{symbol}/transaction/{id}"; diff --git a/website_example/js/common.js b/website_example/js/common.js index b7cd686..4cba1f3 100644 --- a/website_example/js/common.js +++ b/website_example/js/common.js @@ -1301,6 +1301,7 @@ function market_RenderMarketPrice(base, target, price, source, stats, marketPric if (target == 'BTC') icon = 'fa-btc'; if (target == 'BCH') icon = 'fa-btc'; if (target == 'USD') icon = 'fa-dollar'; + if (target == 'USDT') icon = 'fa-dollar'; if (target == 'CAD') icon = 'fa-dollar'; if (target == 'EUR') icon = 'fa-eur'; if (target == 'GBP') icon = 'fa-gbp'; @@ -1310,18 +1311,16 @@ function market_RenderMarketPrice(base, target, price, source, stats, marketPric marketPrices[stats.config.coin][target] = price; } - if (target == 'USD' || target == 'CAD' || target == 'EUR' || target == 'GBP' || target == 'JPY') { + if (target == 'USD' || target == 'USDT' || target == 'CAD' || target == 'EUR' || target == 'GBP' || target == 'JPY') { price = price.toFixed(4); } else { price = price.toFixed(8); } let sourceURL = null; - if (source == 'cryptonator') sourceURL = 'https://www.cryptonator.com/'; - else if (source == 'altex') sourceURL = 'https://altex.exchange/'; - else if (source == 'crex24') sourceURL = 'https://crex24.com/'; - else if (source == 'cryptopia') sourceURL = 'https://www.cryptopia.co.nz/'; - else if (source == 'stocks.exchange') sourceURL = 'https://stocks.exchange/'; + if (source == 'coinex') sourceURL = 'https://www.coinex.com/'; + else if (source == 'mexc') sourceURL = 'https://www.mexc.com/'; + else if (source == 'nonkyc') sourceURL = 'https://nonkyc.io/'; else if (source == 'tradeogre') sourceURL = 'https://tradeogre.com/'; else if (source == 'exbitron') sourceURL = 'https://app.exbitron.com/';