// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 #include "exchange_info.h" #include #include #include namespace dragonx { namespace data { const std::vector& getExchangeRegistry() { // Offline seed / fallback. The live list from CoinGecko (parseCoinGeckoTickers) // supersedes this when available; keep the known venues here so the tab is never // empty without network. static const std::vector registry = { { "Nonkyc.io", "https://nonkyc.io", { {"DRGX", "USDT", "DRGX/USDT", "https://nonkyc.io/market/DRGX_USDT"}, } }, { "OurBit", "https://www.ourbit.com", { {"DRGX", "USDT", "DRGX/USDT", "https://www.ourbit.com/exchange/DRGX_USDT"}, } }, }; return registry; } namespace { // Extract the scheme://host origin from a URL (for ExchangeInfo.baseUrl). std::string originOf(const std::string& url) { const auto scheme = url.find("://"); if (scheme == std::string::npos) return url; const auto host = url.find('/', scheme + 3); return (host == std::string::npos) ? url : url.substr(0, host); } } // namespace std::vector parseCoinGeckoTickers(const std::string& body) { std::vector exchanges; try { const nlohmann::json j = nlohmann::json::parse(body); if (!j.contains("tickers") || !j["tickers"].is_array()) return {}; std::unordered_map byName; // exchange name -> index for (const auto& t : j["tickers"]) { if (!t.is_object()) continue; const std::string base = t.value("base", std::string{}); const std::string target = t.value("target", std::string{}); std::string market; if (t.contains("market") && t["market"].is_object()) market = t["market"].value("name", std::string{}); const std::string tradeUrl = t.value("trade_url", std::string{}); if (base.empty() || target.empty() || market.empty()) continue; auto it = byName.find(market); if (it == byName.end()) { byName[market] = exchanges.size(); exchanges.push_back(ExchangeInfo{market, originOf(tradeUrl), {}}); it = byName.find(market); } ExchangePair pair{base, target, base + "/" + target, tradeUrl}; // Skip duplicate pairs on the same exchange. bool dup = false; for (const auto& p : exchanges[it->second].pairs) if (p.displayName == pair.displayName) { dup = true; break; } if (!dup) exchanges[it->second].pairs.push_back(std::move(pair)); } } catch (...) { return {}; } // Drop exchanges that ended up with no pairs (defensive). exchanges.erase(std::remove_if(exchanges.begin(), exchanges.end(), [](const ExchangeInfo& e) { return e.pairs.empty(); }), exchanges.end()); return exchanges; } } // namespace data } // namespace dragonx