feat(market): auto-populate exchange pairs from CoinGecko (adds OurBit); DRGX dashboard
- Fetch /coins/dragonx-2/tickers once per session (App::refreshExchanges, reusing the
price-fetch worker path) and build the exchange registry at runtime into
state.market.exchanges; parseCoinGeckoTickers groups tickers by venue. The Market tab
sources from this live list and falls back to the compiled-in registry (now including
OurBit + Nonkyc.io) when offline. Fixes the missing OurBit pair and auto-tracks future
listings.
- Fix stale selection defaults (TradeOgre / DRGX-BTC -> Nonkyc.io / DRGX/USDT) that never
matched the registry, and make the attribution generic ("Price data from CoinGecko").
- Reframe the single-asset portfolio card as a DRGX holdings dashboard: relabel to
"MY DRGX" and show the 24h change on the holdings value (colored by direction).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1631,6 +1631,51 @@ void App::refreshPrice()
|
||||
void App::refreshMarketData()
|
||||
{
|
||||
refreshPrice();
|
||||
refreshExchanges();
|
||||
}
|
||||
|
||||
void App::refreshExchanges()
|
||||
{
|
||||
if (!settings_ || !settings_->getFetchPrices()) return;
|
||||
if (!worker_) return;
|
||||
if (exchanges_fetch_started_) return; // once per session (venues are near-static)
|
||||
exchanges_fetch_started_ = true;
|
||||
|
||||
worker_->post([this]() -> rpc::RPCWorker::MainCb {
|
||||
std::vector<data::ExchangeInfo> exchanges;
|
||||
try {
|
||||
CURL* curl = curl_easy_init();
|
||||
if (curl) {
|
||||
std::string body;
|
||||
const char* url = "https://api.coingecko.com/api/v3/coins/dragonx-2/tickers";
|
||||
auto write_callback = [](void* contents, size_t size, size_t nmemb, std::string* userp) -> size_t {
|
||||
size_t total = size * nmemb;
|
||||
userp->append((char*)contents, total);
|
||||
return total;
|
||||
};
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +write_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 12L);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "DragonX-Wallet/1.0");
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
long http_code = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
curl_easy_cleanup(curl);
|
||||
if (res == CURLE_OK && http_code >= 200 && http_code < 300)
|
||||
exchanges = data::parseCoinGeckoTickers(body);
|
||||
}
|
||||
} catch (...) {}
|
||||
|
||||
return [this, exchanges = std::move(exchanges)]() mutable {
|
||||
if (!exchanges.empty())
|
||||
state_.market.exchanges = std::move(exchanges);
|
||||
else
|
||||
exchanges_fetch_started_ = false; // allow a retry if it failed/empty
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user