Skip to content

volume: serve shared-ticker token charts as empty instead of merged (43 tickers, incl. USDV and PUSD) - #896

Open
BhariGowda wants to merge 1 commit into
DefiLlama:masterfrom
BhariGowda:fix/volume-skip-ambiguous-ticker-routes
Open

volume: serve shared-ticker token charts as empty instead of merged (43 tickers, incl. USDV and PUSD)#896
BhariGowda wants to merge 1 commit into
DefiLlama:masterfrom
BhariGowda:fix/volume-skip-ambiguous-ticker-routes

Conversation

@BhariGowda

@BhariGowda BhariGowda commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Addresses #892, and the volume half of #690.

The problem

The R2 volume cache keys tokens by ticker, not by stablecoin id, and uppercases them. storeVolumes.ts writes one volume/chart-token-<TICKER> route per key, so for any ticker shared by more than one stablecoin the route is the sum of all of them.

Reading stablecoins/dailyVolumes from R2 directly confirms the keys are tickers — 355 of them, all symbols: PAXG, USDT, IDRT, TUSD, DAI, XSGD, SUSD, USDC, TRYB, MUSD, GUSD, EURS, HUSD, XCHF, BUSD, FRAX, …

49 of the 416 entries in peggedData share a ticker with at least one other, several with four others. From outside, on #892's ticker:

GET https://stablecoins.llama.fi/chart/volume/token/USDV
  928 points, first 2023-09-13, max $85,297,230

Four stablecoins share USDV:

id name gecko_id
143 Verified USD verified-usd-foundation-usdv
261 Solomon USDv solomon-usdv
398 Valtorum USD valtorum-usdv
431 Delpho USDV delpho-usdv

Delpho has only existed since ~Aug 2026, so nearly all of that series belongs to the other three, and the same merged chart is served on all four coins' pages. PUSD in #690 is the same shape across five coins, one of them Palm USD.

What this does

The per-coin figures are already summed by the time this cron reads them, so nothing here can split them apart. This serves the affected routes as [] instead, so a page shows no volume rather than another coin's.

Ambiguity is computed from peggedData at module load, uppercased to match the cache keys. The comparison is case-insensitive on purpose: 86 of the 416 symbols are not all-uppercase (USDm, crvUSD, eUSD, sUSD) while the cache keys are. It logs which tickers were emptied, so the list shows up in cron output instead of being silent.

Verification

Ran the cron against the live R2 cache. 43 tickers emptied, the 49 shared ones minus 6 that have no volume data at all:

volume: served 43 shared-ticker token charts as empty: AUSD, BOLD, BTCUSD, BUSD,
CASH, CUSD, EUSD, FUSD, GUSD, HYUSD, IUSD, MONEY, MSUSD, MUSD, PUSD, REUSD, RUSD,
SUSD, USC, USD+, USDA, USDAF, USDB, USDE, USDF, USDH, USDK, USDL, USDM, USDN,
USDP, USDQ, USDR, USDS, USDU, USDV, USDX, USH, USN, USP, USX, XUSD, YUSD

Then checked the written route files. 86 of 825 are empty, being those 43 across both the total and chain-breakdown routes, and unshared tickers are untouched:

route before after
chart-token-USDV 928 pts, max $85.3M []
chart-token-USDV-chain-breakdown populated []
chart-token-PUSD populated []
chart-token-USDT 2053 pts, max 49,538,822,127
chart-token-DAI 2053 pts, max 7,398,011,733
chart-token-FRAX 2053 pts, max 522,249,316
chart-token-PAXG 2053 pts, max 163,298,418

Typecheck unchanged: 47 pre-existing errors before and after (node_modules/starknet .d.ts, the bob adapter, missing test runner types), none in this file.

Being explicit about the tradeoff

This removes data users can currently see, which is a judgement call rather than a pure bug fix, and I would not have sent it unprompted. Serving [] says "we cannot attribute this" instead of showing a number that belongs to other coins.

The real fix is for whatever writes stablecoins/dailyVolumes to key by stablecoin id or gecko_id. After that this guard stops matching anything by itself and can be deleted. Reverting in the meantime is a one-line change.

Deliberately out of scope

The aggregate token-breakdown routes (chart-total-token-breakdown and the per-chain ones) are left alone. They describe a distribution across tickers rather than attributing a series to one coin, so a merged bucket there is mislabelled but not misattributed, and emptying it would silently drop volume out of the totals.

Summary by CodeRabbit

  • Bug Fixes
    • Prevented charts for ticker symbols shared by multiple stablecoins from displaying potentially misleading aggregated data.
    • Ambiguous ticker symbols now show empty chart results instead of incorrect breakdowns.
    • Added logging for skipped ambiguous tickers.

The R2 volume cache keys tokens by ticker rather than by stablecoin id, and
uppercases them, so storeVolumes writes one volume/chart-token-<TICKER> route
per ticker. 49 of the 416 entries in peggedData share a ticker with at least one
other, several with four others, and for those the route is the sum of every
coin using that ticker.

Reading the R2 cache directly confirms the keys are tickers: 355 of them, all
symbols, PAXG / USDT / IDRT / TUSD / DAI / XSGD / SUSD / USDC and so on.

What that looks like from outside, on the ticker from DefiLlama#892:

  GET https://stablecoins.llama.fi/chart/volume/token/USDV
    928 points, first 2023-09-13, max $85,297,230

Four stablecoins share USDV: Verified USD (143), Solomon USDv (261), Valtorum
USD (398) and Delpho USDV (431). Delpho has only existed since around August
2026, so nearly all of that series belongs to the other three, and the same
merged chart is served on all four coins' pages. PUSD in DefiLlama#690 is the same shape
with five coins, one of them Palm USD.

The per-coin figures are already added together by the time this cron reads
them, so nothing here can split them back apart. This serves the affected
routes as empty instead, so a page shows no volume rather than another coin's.

Ambiguity is computed from peggedData at module load, uppercased to match the
cache's keys, and the comparison is case-insensitive because 86 of the 416
symbols are not all-uppercase (USDm, crvUSD, eUSD, sUSD) while the cache keys
are. It logs which tickers were emptied so the list is visible in cron output
rather than silent.

Ran the cron against the live cache. 43 tickers were emptied, being the 49
shared ones minus 6 that have no volume data at all:

  AUSD BOLD BTCUSD BUSD CASH CUSD EUSD FUSD GUSD HYUSD IUSD MONEY MSUSD MUSD
  PUSD REUSD RUSD SUSD USC USD+ USDA USDAF USDB USDE USDF USDH USDK USDL USDM
  USDN USDP USDQ USDR USDS USDU USDV USDX USH USN USP USX XUSD YUSD

Verified against the written route files. 86 of 825 are now empty, being those
43 across both the total and chain-breakdown routes, and unshared tickers are
untouched:

  chart-token-USDV                  EMPTY []
  chart-token-USDV-chain-breakdown  EMPTY []
  chart-token-PUSD                  EMPTY []
  chart-token-USDT                  2053 points, max 49,538,822,127
  chart-token-DAI                   2053 points, max  7,398,011,733
  chart-token-FRAX                  2053 points, max    522,249,316
  chart-token-PAXG                  2053 points, max    163,298,418

Typecheck is unchanged: 47 pre-existing errors before and after, none of them
in this file.

Worth being explicit that this removes data users can currently see, which is a
judgement call rather than a pure bug fix. The real fix is for whatever writes
stablecoins/dailyVolumes to key by stablecoin id or gecko_id, after which this
guard stops matching anything on its own and can be deleted. Reverting is a
one-line change if you would rather keep serving the merged series in the
meantime.

The aggregate token-breakdown routes (chart-total-token-breakdown and the
per-chain ones) are deliberately left alone. They describe a distribution across
tickers rather than attributing a series to one coin, so a merged bucket there is
mislabelled but not misattributed, and dropping it would silently lose volume
from the totals.
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 829b9d92-f65c-4cf4-811f-496f76a37b75

📥 Commits

Reviewing files that changed from the base of the PR and between 728302a and e2c99b7.

📒 Files selected for processing (1)
  • api2/cron-task/storeVolumes.ts

Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The volume cron task now identifies stablecoin tickers shared by multiple pegged assets. It stores empty token and chain-breakdown charts for ambiguous tickers and logs the sorted list of skipped keys.

Changes

Stablecoin volume disambiguation

Layer / File(s) Summary
Detect and suppress ambiguous tickers
api2/cron-task/storeVolumes.ts
The cron task imports pegged-asset metadata, counts normalized stablecoin symbols, suppresses aggregated charts for shared ticker keys, and logs skipped keys.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to e2c99

The change serves empty volume charts for tokens whose ticker is shared across multiple stablecoins, avoiding misleading merged data. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states that shared-ticker token charts will be served as empty instead of merged and identifies the affected scope.
Description check ✅ Passed The description is detailed, relevant, and covers the problem, implementation, verification, tradeoffs, and out-of-scope changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant