feat(frontend): track treasury vFDUSD and USD price via session-once RPC #10
Labels
No labels
bug
docs
documentation
duplicate
enhancement
frontend
good first issue
help wanted
invalid
missing-implementation
priority
medium
product
QA
question
testing
UX
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/ustr-cmm#10
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Show vFDUSD as a live treasury asset on the Treasury page, with a USD valuation from on-chain RPC/LCD — rate-limited and fetched at most once per browser session. Do not put vFDUSD through the existing Binance/DEX 60s poll loop.
Companion context: treasury already custodies bridged vFDUSD for
ust1-windowredeem (#6, #7). Mainnet token:terra1mnl9azefrqpmu888ar2u6zrcwr80hxlt3avf4300r576cw5ar7esvxsvj3(6 decimals). On-chain Venus-normalized rate lives onust1-oracleterra1fmht0t6svq3n24zx03nkfja0m40zhfyyxkdcvlrkl6u7gfe6aagq4gch8n(R / 1e18= FDUSD per 1 vFDUSD). Related CR work: follow-up issue for UST1 circulating + key ratios.Current codebase
frontend/public/assets/tokenlist.jsonfrontend/src/hooks/useTreasury.tstokenlist.json; skips USTR; native via bank, CW20 viagetTokenBalance(token, treasury). vFDUSD never queried.frontend/src/components/treasury/TreasuryAssetsCard.tsxusePrices(); hides sub-$1 dust when a price exists; USTC excluded from rank badges.frontend/src/services/price.ts+usePrices.tssimulateon LCD, keyed off base-price updates.frontend/src/services/contract.ts,LCD_CONFIGfrontend/src/utils/constants.ts→PRICE_CACHEbasePrices: 60s,dexRates: 120s,staleTime: 30s. No session-once primitive.CONTRACTSinconstants.tsustrToken,treasury,ustcSwap,referralonly. Novfdusd/ust1Oracle.TokenIcon→/assets/tokens/{SYMBOL}.pngLUNC.pngis present; unknown symbols fall back to first letter.docs/DEPLOYMENT.mdWhy DEX pricing cannot be reused: vFDUSD is inventory for the window, not a Terra AMM pair. Adding it to the CW20 DEX loop would burn LCD quota and return
null.Why this is needed
Transferit in). The public Treasury page omits the largest USD-stable collateral sleeve.$1is wrong: Venus vFDUSD accrues (~1.22 FDUSD per vFDUSD at the 2026-08-08 seed).eth_callfrom every tab) will get the site rate-limited and can look like abuse.Without this, the asset grid and any later CR math understate collateral.
Constraints / guardrails
exchangeRateStoredfrom the browser (CORS, keyless public RPC, easy to hammer).simulatepoll loops.useTreasury’s 30s interval, window focus, orusePrices60s tick.sessionStorage(or an equivalent session-scoped module cache). Reload / new tab may fetch again.LCD_CONFIGrate limiting + endpoint fallbacks for the oracle query. Deduplicate in-flight requests.vFDUSD_USD = (R / 1e18) * 1. Do not add a second CEX poll “just for FDUSD” unless product later asks; if added it must also be session-once.<= 0, or absurdR(e.g.R/1e18outside a documented sanity band such as0.5 … 10). On reject: show balance without a USD line; do not silently assume$1per vFDUSD.paused=trueor missingR: same as price unavailable — no fake USD.Relevant files
frontend/public/assets/tokenlist.jsonpool)frontend/src/utils/constants.tsCONTRACTS.mainnet.vfdusd,ust1Oracle; session-cache / price knobsfrontend/src/hooks/useTreasury.tsfrontend/src/hooks/usePrices.tsfrontend/src/services/price.tsstate(or dedicated small service)frontend/src/components/treasury/TreasuryAssetsCard.tsxfrontend/src/types/price.tssource: 'oracle'frontend/public/assets/tokens/VFDUSD.pngTokenIconuppercases symbol)docs/DEPLOYMENT.md/README.mdMainnet pins (do not invent new addresses):
terra1mnl9azefrqpmu888ar2u6zrcwr80hxlt3avf4300r576cw5ar7esvxsvj3terra1fmht0t6svq3n24zx03nkfja0m40zhfyyxkdcvlrkl6u7gfe6aagq4gch8nterra16j5u6ey7a84g40sr3gd94nzg5w5fm45046k9s2347qhfpwm5fr6sem3lr2Recommended direction
tokenlist.json(type: cw20,decimals: 6, nopool). AddCONTRACTS.*.vfdusd+ust1Oracle.usePrices/priceService: ifsessionStoragehas a validatedvFDUSDUSD, return it. Else one LCD{"state":{}}(or equivalent documented query) onust1Oracle, computeusd = R / 1e18, persist to session, never schedule a refetch.symbol === 'vFDUSD'from the tokenlist DEXforloop so a missing pool cannot trigger Garuda/Terraswap fallbacks.getUsdValue('vFDUSD')path; addVFDUSD.png.Acceptance criteria
> 0(and>= $1when a valid USD price exists).oracle R / 1e18(FDUSD-per-vFDUSD × $1), not$1per token and not a DEX quote.pausedoracle or invalidR: balance shown, USD hidden.Test plan (all paths)
Display / data
> 0→ row + formatted amount (6 decimals).0→ hidden.>= 1→ USD line; sorts with other priced assets; eligible for rank badge.< 1→ hidden (existing dust rule).> 0→ row without USD (existingpx <= 0rule).Session-once + rate limit
sessionStoragewritten.useTreasury30s refetch: balance may update; no new oracle query.LCD_CONFIG.minRequestIntervalrespected if any other LCD traffic is in flight.Oracle / LCD failure
R/R=0/Rhuge → treat as unavailable.paused=true→ no USD.Regression
Test plan (attack, hack, abuse)
refetchOnWindowFocus, no DEX fallbacks for vFDUSD; 10× refresh of SPA client routes without full reload does not multiply oracle callsbsc-dataseed/ leaked operator URLsvFDUSD=100000→ huge USD / CRRafter oracle pause or incidentpausedis observed on a later balance path, do not keep showing USD from cache as “live”; acceptable: hide USD or label session-cached. Do not pretend 60s freshnessRinflates reservesR; never use query string / user input as oracle addressterra1address$1fallback on failurepoolon vFDUSD triggers simulate spam / wrong quotepoolVerification criteria
cw20 balanceof treasury on finder forterra1mnl9…svj3.treasury_vfdusd * (oracle R / 1e18)(FDUSD ≈ $1), within rounding.$1/vFDUSD.tokenlist+CONTRACTSaddresses matchdocs/DEPLOYMENT.md/ ust1-window registry.mentioned in issue #11
Related liability/CR work: #11 (UST1 mint/burn/circ, cLUNC/cUSTC supply, collateralization from UST1 circulating). CR numerator should include vFDUSD USD from this issue once it ships.
mentioned in commit
737f560578mentioned in merge request !32
Implemented on !32 (
feat/treasury-ust1-legal-10-11-12).Shipped: tokenlist +
CONTRACTSpins, session-once ust1-oracle USD (rate/ 1e18, also acceptsR), DEX skip by symbol and address, in-flight dedupe, sessionStorage schema/sanity-band, no$1/vFDUSDfallback, LCD min-interval + fallbacks. Unit tests infrontend/src/utils/vfdusdOracle.test.ts. Playbook:skills/frontend-vfdusd-oracle/SKILL.md.mentioned in commit
09a54333aamentioned in issue #14
mentioned in issue #16
mentioned in issue #19
marked as related to #19