feat(market): per-exchange 24h volume in the hero
The hero's "24H Vol" showed CoinGecko's cross-exchange aggregate even after the chart/price went per-venue. Capture the per-exchange converted_volume.usd from the tickers (previously discarded, alongside converted_last) and show the SELECTED exchange's own 24h volume; fall back to the aggregate when unknown. Market cap stays aggregate (it's coin-wide, not per-venue). This is a big real difference — e.g. Ourbit ~$14.3K vs NonKYC ~$253 for DRGX/USDT — so the header now reflects the venue you're actually looking at. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -66,9 +66,12 @@ std::vector<ExchangeInfo> parseCoinGeckoTickers(const std::string& body)
|
||||
}
|
||||
const std::string tradeUrl = t.value("trade_url", std::string{});
|
||||
if (base.empty() || target.empty() || market.empty()) continue;
|
||||
double lastUsd = 0.0; // this venue's current USD price — differs per exchange
|
||||
double lastUsd = 0.0; // this venue's current USD price + 24h volume — differ per exchange
|
||||
if (t.contains("converted_last") && t["converted_last"].is_object())
|
||||
lastUsd = t["converted_last"].value("usd", 0.0);
|
||||
double volumeUsd = 0.0;
|
||||
if (t.contains("converted_volume") && t["converted_volume"].is_object())
|
||||
volumeUsd = t["converted_volume"].value("usd", 0.0);
|
||||
|
||||
auto it = byName.find(market);
|
||||
if (it == byName.end()) {
|
||||
@@ -76,7 +79,7 @@ std::vector<ExchangeInfo> parseCoinGeckoTickers(const std::string& body)
|
||||
exchanges.push_back(ExchangeInfo{market, originOf(tradeUrl), {}});
|
||||
it = byName.find(market);
|
||||
}
|
||||
ExchangePair pair{base, target, base + "/" + target, tradeUrl, identifier, lastUsd};
|
||||
ExchangePair pair{base, target, base + "/" + target, tradeUrl, identifier, lastUsd, volumeUsd};
|
||||
// Skip duplicate pairs on the same exchange.
|
||||
bool dup = false;
|
||||
for (const auto& p : exchanges[it->second].pairs)
|
||||
|
||||
@@ -20,6 +20,7 @@ struct ExchangePair {
|
||||
std::string tradeUrl; ///< Link to the exchange pair page
|
||||
std::string identifier; ///< CoinGecko exchange id (e.g. "ourbit", "nonkyc_io") — keys the candle adapter
|
||||
double lastUsd = 0.0; ///< This venue's current price in USD (CoinGecko converted_last.usd); 0 if unknown
|
||||
double volumeUsd = 0.0; ///< This venue's 24h volume in USD (CoinGecko converted_volume.usd); 0 if unknown
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1440,8 +1440,15 @@ static void mktDrawPriceChart(const MktCtx& cx)
|
||||
sxr -= Layout::spacingMd();
|
||||
};
|
||||
if (market.price_usd > 0) {
|
||||
// Market cap is coin-wide (stays aggregate); 24h volume is per-venue — show the SELECTED
|
||||
// exchange's own volume when we have it, else the CoinGecko aggregate.
|
||||
drawStat(TR("market_cap_short"), FormatCompactUSD(market.market_cap));
|
||||
drawStat(TR("market_vol_short"), FormatCompactUSD(market.volume_24h));
|
||||
double vol = market.volume_24h;
|
||||
const auto& exch = *cx.currentExchange;
|
||||
if (!exch.pairs.empty() && s_mkt.pairIdx < (int)exch.pairs.size()
|
||||
&& exch.pairs[s_mkt.pairIdx].volumeUsd > 0.0)
|
||||
vol = exch.pairs[s_mkt.pairIdx].volumeUsd;
|
||||
drawStat(TR("market_vol_short"), FormatCompactUSD(vol));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user