Skip to content

Render CLI-linked wallets as their own provenance - #378

Merged
blockchain-maxis merged 2 commits into
blockchain-maxis:mainfrom
funmilayo-ui:fix/285-wallet-source-badge
Sep 3, 2026
Merged

Render CLI-linked wallets as their own provenance#378
blockchain-maxis merged 2 commits into
blockchain-maxis:mainfrom
funmilayo-ui:fix/285-wallet-source-badge

Conversation

@funmilayo-ui

Copy link
Copy Markdown
Contributor

Summary

apps/web/app/(dashboard)/app/wallets/page.tsx rendered provenance with a binary ternary — w.source === 'onchain' ? '● on-chain' : '○ curated' — so a cli wallet displayed as "curated", understating a cryptographically proven binding as a hand-entered one.

closes #285

Changes

packages/types/src/wallet.ts (new) — the shared source vocabulary, since the badge is a claim about how much a binding is worth and every surface has to agree on it:

  • WALLET_SOURCES / WalletSourceonchain, cli, curated.
  • describeWalletSource(source){ source, marker, label, description }, one distinct marker and label each: ● on-chain, ◆ CLI-linked, ○ curated.
  • An explicit unknown case (◌ unrecognised) for a source this build does not know — e.g. a row written by a newer indexer. Falling back to "curated" there would be the same bug in a different disguise, so it does not.

apps/web/lib/wallet-source.ts (new) — maps a descriptor to its Tailwind tone and badge text. Only the presentation lives in the web app; which sources exist and what they are called stays in @signet/types so surfaces cannot drift.

apps/web/app/(dashboard)/app/wallets/page.tsx — derives the badge from that shared type rather than comparing strings, and carries the descriptor's one-line explanation as the badge title. This covers both states the page renders: the populated list, and the registry-read fallback used when the database has nothing yet (which constructs an onchain wallet directly).

apps/web/lib/server/account.tsLinkedWallet.source is documented and typed against WalletSource while still accepting an unrecognised string from the database, which is what makes the unknown case reachable rather than theoretical.

Verification

  • packages/types: node --test15 pass, 0 fail (6 new): each source has a distinct label and marker; a CLI link is never described as curated; on-chain/curated keep the labels they had; unknown values (including null, undefined, numbers, objects) report as unknown; isWalletSource narrows only the three; and an exhaustiveness check that fails to compile if a source is added without a descriptor.
  • apps/web: node --test "lib/**/*.test.ts"211 pass, 0 fail (4 new, covering badge text per source, CLI ≠ curated in both text and tone, all three visually distinct, and the unknown fallback).
  • tsc --noEmit clean for apps/web; eslint clean on every touched file.
  • The page diff is kept to the badge itself — the file is not Prettier-clean on main, so it was not reformatted wholesale.

The wallets list rendered provenance with a binary ternary, so a cli
wallet displayed as 'curated' - the one thing a cryptographically proven
link is not.

- packages/types gains WalletSource, the three-value source vocabulary,
  with a descriptor per source and an explicit unknown case so a source
  a build does not recognise is never described as curated either.
- apps/web/lib/wallet-source.ts maps a descriptor to its badge tone.
- The wallets page derives the badge from that shared type instead of
  comparing strings, and carries the description as a tooltip.
@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@funmilayo-ui Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@netlify

netlify Bot commented Aug 31, 2026

Copy link
Copy Markdown

Deploy Preview for stellar-signet ready!

Name Link
🔨 Latest commit 61735d1
🔍 Latest deploy log https://app.netlify.com/projects/stellar-signet/deploys/6a99568189833a00085330c1
😎 Deploy Preview https://deploy-preview-378--stellar-signet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

@funmilayo-ui is attempting to deploy a commit to the blockchainmaxis-8449's projects Team on Vercel.

A member of the Team first needs to authorize it.

@blockchain-maxis blockchain-maxis left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The framing in your module comment is right — a cli binding displayed as "curated" is a cryptographically proven link labelled as a hand-entered one, and that's worth being strict about.

The trouble is that #285 was fixed on main while this was open, by #329 ("fix(types): define Wallet.source as a shared, generated vocabulary"), and this PR adds a second, competing vocabulary rather than building on it.

Main already has packages/types/src/wallet-source.ts:

export const WALLET_SOURCES = ['curated', 'onchain', 'cli'] as const;
export type WalletSource = (typeof WALLET_SOURCES)[number];
export function isWalletSource(value: string): value is WalletSource

getAccountWallets validates against it on read (apps/web/lib/server/account.ts:136, via toWalletSource), and the wallets page already renders a cli badge from SOURCE_BADGE (apps/web/app/(dashboard)/app/wallets/page.tsx:13-17). This PR adds packages/types/src/wallet.ts exporting another WALLET_SOURCES and WalletSource with a different member order, plus a parallel apps/web/lib/wallet-source.ts. Both would be exported from packages/types/src/index.ts, which is the conflict git is reporting:

CONFLICT (content): Merge conflict in apps/web/app/(dashboard)/app/wallets/page.tsx
CONFLICT (content): Merge conflict in apps/web/lib/server/account.ts
CONFLICT (content): Merge conflict in packages/types/src/index.ts

There's a further constraint you couldn't have known about: wallet-source.ts on main is the input to scripts/generate-wallet-source-go.mjs, which regenerates packages/types/generated/wallet_source.go for the Go CLI, and scripts/check-wallet-source-go.mjs fails CI if the two drift. A second vocabulary module has nothing keeping it in step with the Go side.

So I can't take this as it stands. Two things in your version are genuinely better than main's, and I'd merge either as a follow-up on top of wallet-source.ts:

  • the 'unknown' fallback. Main's toWalletSource validates on read, but the render path indexes SOURCE_BADGE[w.source] directly — a value that somehow got past validation would throw rather than degrade. Your descriptor returning 'unknown' is the safer shape.
  • description per source. Main's badge is a label and a colour with no explanation; a tooltip saying what onchain vs cli vs curated actually means is a real improvement, and your one-liners are well written.

If you want to take that on, rebase onto main and move those two ideas into packages/types/src/wallet-source.ts (remembering to re-run node scripts/generate-wallet-source-go.mjs if the source list itself changes). If you'd rather close this and start clean, that's fine too — just say so.

Main landed its own WALLET_SOURCES in packages/types/src/wallet-source.ts,
which also feeds the Go codegen for the CLI. Resolve by keeping that file as
the single source of truth for the list and layering this branch's descriptors
on top, rather than duplicating the vocabulary:

- wallet.ts imports WALLET_SOURCES/isWalletSource from wallet-source.ts and
  only adds how each source reads. The generated wallet_source.go stays in
  sync (scripts/check-wallet-source-go.mjs passes).
- isWalletSource widened from `string` to `unknown` so a raw database column
  can be narrowed at the boundary without a cast.
- account.ts keeps main's logger warning for an unrecognised source but no
  longer substitutes 'curated' for it. Coercing an unknown provenance to
  curated reintroduces the mislabelling this branch exists to remove.
- wallets/page.tsx drops main's SOURCE_BADGE table, which derived from the
  shared type but still gave 'cli' curated's glyph and tone, and keeps main's
  UnlinkWalletButton.
@blockchain-maxis
blockchain-maxis merged commit 9265fb1 into blockchain-maxis:main Sep 3, 2026
10 of 11 checks passed
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.

Wallets list cannot render a CLI-linked source

2 participants