Skip to content

feat(wallet): put USDY on the recorded cost-basis view - #1271

Merged
Miracle656 merged 1 commit into
Miracle656:mainfrom
Ugasutun:feat/usdy-cost-basis-yield-view
Oct 27, 2026
Merged

Miracle656 merged 1 commit into
Miracle656:mainfrom
Ugasutun:feat/usdy-cost-basis-yield-view

Conversation

@Ugasutun

Copy link
Copy Markdown
Contributor

Closes #734. Successor to #883, which I am closing as superseded.

What

USDY accrues through its price, not its balance, so a portfolio line that never moves reads as "no yield" to someone who is in fact earning. main already expresses this honestly for USTRY via a manually recorded USDC cost; this puts USDY on the same view.

Why this is smaller than #883

The earlier branch carried a full FIFO lot tracker with its own storage and a separate YieldDisplay component, alongside the simpler lib/costBasis.ts that landed. Two sources of truth for one number is the failure mode, so this takes the recorded-basis path and generalises the single hardcoded asset check instead of adding a parallel system. No new source files; 19 lines of component change.

Basis matches code and issuer, so a counterfeit token reusing the USDY code cannot inherit someone else's recorded basis.

One bug fixed on the way

The stored basis was read in a useEffect, so a client that already had a basis recorded painted "change in value unknown" until the effect committed and re-rendered. Moved to the state initialiser. This also blocked the new tests' static render, which is how it was found.

Verification

Mirrors the wallet CI job locally:

  • npx tsc --noEmit — clean
  • npm run build — succeeded
  • npx jest --coverage — 95 suites, 1,472 tests passed
  • 7 new cases in components/__tests__/PortfolioSummaryCostBasis.test.ts: no-basis prompt, recorded change, refusal after the holding changes, USDC excluded, counterfeit issuer excluded, no wallet address, hideAmounts

Scope

One area: the wallet portfolio line. No swap, privacy or SEP-8 changes, and no markdown. The process documentation from the old stack is not here.

USDY accrues through its price, not its balance, so a portfolio line that
never moves reads as "no yield" to people who are in fact earning. The
recorded-basis view already expresses this honestly for USTRY; extend it to
USDY so the same holding shows its change in value.

The earlier attempt shipped a full FIFO lot tracker with its own storage and
a YieldDisplay component alongside a simpler recorded-basis module doing the
same job. Two sources of truth for one number is the failure mode, so this
takes the recorded-basis path and generalises the hardcoded single-asset
check instead. Basis is matched by code AND issuer, so a counterfeit token
reusing the code cannot inherit someone else's basis.

Also reads the stored basis in the state initialiser rather than an effect.
Under the previous effect, a client that already had a basis recorded painted
"change in value unknown" until the effect committed and re-rendered.
@Ugasutun
Ugasutun requested a review from Miracle656 as a code owner October 26, 2026 18:45
@vercel

vercel Bot commented Oct 26, 2026

Copy link
Copy Markdown

@Ugasutun is attempting to deploy a commit to the miracle656's projects Team on Vercel.

A member of the Team first needs to authorize it.

@Miracle656
Miracle656 merged commit 1554d4e into Miracle656:main Oct 27, 2026
13 of 17 checks passed
@Miracle656

Copy link
Copy Markdown
Owner

Merged — thanks, the issuer-pinned matching and the init-time read are both right, and moving off the effect fixes a real first-paint flash.

I adjusted one thing before merging. recordedBasisIssuer returned the code, and the storage key is built from that return value, so the key moved from

veil:recorded-cost-basis:v1:<wallet>:GCRYUGD5NVARGXT56XEZI5CIFCQETYHAPQQTHO2O3IQZTHDH4LATMYWC

to …:USTRY. Anyone who had already recorded a USTRY cost would have seen it read back as "unknown" — the value still on disk, just unreachable, with no migration to move it.

It now returns the issuer, which is the key already written. Your pairing check is what keeps a counterfeit out, so the issuer alone is still safe as a key. I added a regression test for a USTRY basis stored under the pre-USDY key; switching the return back to the code fails it.

Everything else is yours as written.

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.

Show yield as it actually works: price accrual, not payouts

2 participants