Skip to content

Commit e25d100

Browse files
sktbrdclaude
andauthored
fix(treasury): honest-copy notes — thin-market Sendit, whose money is staked (#292)
* fix(treasury): honest-copy notes — thin-market Sendit, whose money is staked Three notes that keep adjacent numbers from lying by omission: - Sendit's value gets a qualitative thin-market caveat (its screen price comes from one Uniswap pool with ~$0.44 of daily volume). No number in the UI — a fixed percentage would age into misinformation; the dated measurement (2026-08-23: full 474M exit realizes 88.6% of screen, 10% tranche 96.9%, reserve ~$115k) lives in the code comment. - The sponsorship card's Total staked says it is BACKERS' money — the same word 'staked' sits centimeters from the DeFi card's 'vault shares $0', and without the line the two read as a contradiction. - treasury.ts documents the page-headline consequence of marking any token unpriced: one null price nulls the whole total (a total missing a part is an unknown total, not a smaller one) — so the next person knows BEFORE flipping that switch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(treasury): BRL-length-proof layout — KPI breakdown and rider columns pt-BR is the long-string locale ("R$ 177.908,14" vs "$34,414.31") and two spots sized for the English case broke under it, caught on the PT capture: the Total KPI's wallet/DeFi line wrapped INTO the corner noggles, and the rider table's fixed 72px value column let "R$ 12.731,86" bleed into the yield column. The KPI note becomes two deliberate lines (label + tabular value) with right padding clearing the mark in any locale; the rider columns go auto-sized. Anything that fits English exactly will overflow Portuguese — sized for the long case now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 20b4280 commit e25d100

6 files changed

Lines changed: 69 additions & 22 deletions

File tree

messages/en/treasury.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
"acrossAssets": "across {count} assets",
1212
"auctionsSettled": "{count} auctions settled",
1313
"morpheusClaims": "Morpheus · {count} claims",
14-
"walletVsDefi": "In wallet {wallet} · In DeFi {defi}",
15-
"defiUnavailable": "DeFi positions unreadable — the total shows the wallet only"
14+
"defiUnavailable": "DeFi positions unreadable — the total shows the wallet only",
15+
"inWallet": "In wallet",
16+
"inDefi": "In DeFi"
1617
},
1718
"nftSection": {
1819
"title": "NFT Holdings",
@@ -27,7 +28,8 @@
2728
"description": "ERC-20 tokens held in the treasury",
2829
"empty": "No tokens found",
2930
"emptyDescription": "The treasury currently holds no ERC-20 tokens",
30-
"errorLoading": "Error loading token holdings: {error}"
31+
"errorLoading": "Error loading token holdings: {error}",
32+
"thinMarketNote": "market-price estimate from one low-volume pool — a full exit would realize less than shown"
3133
},
3234
"zoraCoin": {
3335
"title": "Zora Coins",
@@ -117,7 +119,8 @@
117119
"govCta": "Start redeem proposal",
118120
"accrualNote": "Fees materialize when someone interacts with a vault, not continuously — the figures can sit still for weeks, then jump all at once. An older small vault can carry more accrued fee than a big recent one.",
119121
"fromVaults": "Vault fee",
120-
"fromMor": "MOR rewards"
122+
"fromMor": "MOR rewards",
123+
"stakedNote": "Backers' money staked behind the riders — not the treasury's own position (that lives under In DeFi)."
121124
},
122125
"defi": {
123126
"title": "In DeFi",

messages/pt-br/treasury.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
"acrossAssets": "em {count} ativos",
1212
"auctionsSettled": "{count} leilões concluídos",
1313
"morpheusClaims": "Morpheus · {count} resgates",
14-
"walletVsDefi": "Em carteira {wallet} · Em DeFi {defi}",
15-
"defiUnavailable": "Posições DeFi ilegíveis — o total mostra só a carteira"
14+
"defiUnavailable": "Posições DeFi ilegíveis — o total mostra só a carteira",
15+
"inWallet": "Em carteira",
16+
"inDefi": "Em DeFi"
1617
},
1718
"nftSection": {
1819
"title": "Holdings de NFT",
@@ -27,7 +28,8 @@
2728
"description": "Tokens ERC-20 mantidos no tesouro",
2829
"empty": "Nenhum token encontrado",
2930
"emptyDescription": "O tesouro não tem tokens ERC-20 no momento",
30-
"errorLoading": "Erro ao carregar holdings de tokens: {error}"
31+
"errorLoading": "Erro ao carregar holdings de tokens: {error}",
32+
"thinMarketNote": "estimativa a preço de mercado de um pool de baixo volume — a saída integral realizaria menos que o valor de tela"
3133
},
3234
"zoraCoin": {
3335
"title": "Zora Coins",
@@ -117,7 +119,8 @@
117119
"govCta": "Abrir proposta de resgate",
118120
"accrualNote": "O rendimento materializa quando alguém interage com o vault, não de forma contínua — os números podem ficar parados por semanas e pular de uma vez. Um vault pequeno e antigo pode acumular mais que um grande e recente.",
119121
"fromVaults": "Taxa dos vaults",
120-
"fromMor": "Recompensas MOR"
122+
"fromMor": "Recompensas MOR",
123+
"stakedNote": "Dinheiro de apoiadores atrás dos riders — não é posição do tesouro (essa fica em Em DeFi)."
121124
},
122125
"defi": {
123126
"title": "Em DeFi",

src/components/treasury/SponsorshipYield.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ export function SponsorshipYield({ brlRate = null }: { brlRate?: number | null }
161161
</div>
162162

163163
<div>
164-
<div className="grid grid-cols-[minmax(0,1fr)_72px_66px] gap-2.5 border-b border-border pb-2 text-[11px] font-medium text-muted-foreground">
164+
<div className="grid grid-cols-[minmax(0,1fr)_auto_auto] gap-2.5 border-b border-border pb-2 text-[11px] font-medium text-muted-foreground">
165165
<span>{t("colRider")}</span>
166166
<span className="text-right">{t("colTvl")}</span>
167167
<span className="text-right">{t("colYield")}</span>
@@ -171,7 +171,7 @@ export function SponsorshipYield({ brlRate = null }: { brlRate?: number | null }
171171
{rows.map((r) => (
172172
<li
173173
key={r.id}
174-
className="grid grid-cols-[minmax(0,1fr)_72px_66px] items-center gap-2.5 py-1.5"
174+
className="grid grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-2.5 py-1.5"
175175
>
176176
<span className="flex min-w-0 items-center gap-2">
177177
{/* Cropped to the face the same way the orbit nodes are, so a
@@ -211,11 +211,20 @@ export function SponsorshipYield({ brlRate = null }: { brlRate?: number | null }
211211
</ul>
212212
</div>
213213

214-
<div className="flex items-baseline justify-between gap-2.5 border-t border-border pt-3">
215-
<span className="text-xs text-muted-foreground">{t("totalTvl")}</span>
216-
<span className="font-mono text-sm font-semibold tabular-nums">
217-
{graph ? usd(totalTvl) : "—"}
218-
</span>
214+
<div className="border-t border-border pt-3">
215+
<div className="flex items-baseline justify-between gap-2.5">
216+
<span className="text-xs text-muted-foreground">{t("totalTvl")}</span>
217+
<span className="font-mono text-sm font-semibold tabular-nums">
218+
{graph ? usd(totalTvl) : "—"}
219+
</span>
220+
</div>
221+
{/* Same word ("staked"), different subject: this figure is the
222+
SUPPORTERS' money behind the riders. The treasury's own position
223+
sits centimeters below in the In DeFi card — without this line,
224+
"$79k staked" next to "vault shares $0" reads as a contradiction. */}
225+
<p className="mt-1 text-[11px] leading-snug text-muted-foreground/70">
226+
{t("stakedNote")}
227+
</p>
219228
</div>
220229

221230
{claimable.length > 0 ? (

src/components/treasury/TokenHoldingsClient.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useLocale, useTranslations } from "next-intl";
44
import Image from "next/image";
55
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
6+
import { TREASURY_TOKEN_ALLOWLIST } from "@/lib/config";
67
import { formatFiatUsd } from "@/lib/i18n/fiat";
78
import { toIntlLocale } from "@/lib/i18n/format";
89
import { FiatFallbackNote } from "./FiatFallbackNote";
@@ -106,6 +107,19 @@ export function TokenHoldingsClient({ tokens, error, brlRate = null }: TokenHold
106107
<div className="text-sm text-muted-foreground tabular-nums">
107108
{formatBalance(token.balance, token.decimals)} {token.symbol}
108109
</div>
110+
{/* Sendit trades in exactly one thin-volume Uniswap pool, so
111+
its screen price is a market estimate, not an exit value.
112+
Measured 2026-08-23 (UTC), QuoterV2 against the Sendit/WETH
113+
0.3% pool (reserve ~$115k, 24h vol $0.44): selling the full
114+
474M position in one swap realized 88.6% of screen price;
115+
a 10% tranche realized 96.9%. The note is deliberately
116+
qualitative — a number would age into misinformation. */}
117+
{token.contractAddress.toLowerCase() ===
118+
TREASURY_TOKEN_ALLOWLIST.SENDIT.toLowerCase() && (
119+
<div className="mt-0.5 max-w-[13rem] text-[11px] leading-snug text-muted-foreground/80">
120+
{t("tokens.thinMarketNote")}
121+
</div>
122+
)}
109123
</div>
110124
</li>
111125
))}

src/components/treasury/TreasuryKpiRow.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export async function TreasuryKpiRow() {
7878
label: string;
7979
accent: string;
8080
value: ReactNode;
81-
note: string | null;
81+
note: ReactNode;
8282
extra?: ReactNode;
8383
mark: ReactNode;
8484
}> = [
@@ -87,13 +87,23 @@ export async function TreasuryKpiRow() {
8787
label: t("totalValue"),
8888
accent: "--chart-5",
8989
value: <KpiValue value={totalUsd} decimals={2} fiat brlRate={brlRate} />,
90+
// Two deliberate lines, not one that wraps: BRL strings run ~30% longer
91+
// than USD ("R$ 177.908,14" vs "$34,414.31") and the single-line form
92+
// broke across the corner noggles on pt-BR. The right padding keeps the
93+
// text clear of the mark in every locale.
9094
note:
91-
walletUsd != null
92-
? t("walletVsDefi", {
93-
wallet: formatFiatUsd(walletUsd, locale, brlRate),
94-
defi: formatFiatUsd(defiKnown, locale, brlRate),
95-
})
96-
: null,
95+
walletUsd != null ? (
96+
<span className="block space-y-0 pr-[88px]">
97+
<span className="flex items-baseline gap-1.5 whitespace-nowrap">
98+
<span>{t("inWallet")}</span>
99+
<span className="tabular-nums">{formatFiatUsd(walletUsd, locale, brlRate)}</span>
100+
</span>
101+
<span className="flex items-baseline gap-1.5 whitespace-nowrap">
102+
<span>{t("inDefi")}</span>
103+
<span className="tabular-nums">{formatFiatUsd(defiKnown, locale, brlRate)}</span>
104+
</span>
105+
</span>
106+
) : null,
97107
extra: (
98108
<>
99109
{!defiHealthy && (

src/services/treasury.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ export const loadTreasurySnapshot = cache(
129129
const nativeEthUsd = ethBalance * (ethUsd ?? 0);
130130
// `null` = "we could not price this", which every consumer must render as
131131
// unavailable. It is never the same thing as a treasury worth $0.
132+
//
133+
// KNOW THIS BEFORE MARKING ANY TOKEN AS UNPRICED: a total missing one part
134+
// is not a smaller total — it is an UNKNOWN total. One `null` price here
135+
// nulls `usdTotal`, and the page's headline number becomes a dash. That is
136+
// deliberate (a confident wrong figure is worse), but it means "mark token
137+
// X as unpriceable" is a page-headline decision, not a row decision. If a
138+
// partial figure is ever wanted instead, use the DeFi card's pattern: a
139+
// labeled floor ("known so far"), never a silent subtraction.
132140
const usdTotal: number | null = priced ? tokensUsd + nativeEthUsd : null;
133141
const totalAuctionSales = Number(formatEther(auctionSalesWei));
134142

0 commit comments

Comments
 (0)