Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cold Wallet Read-Only UI
Overview
When a wallet is "cold" (no private keys —
KeyInfo.has_secrets === false), the UI reflects that no transactions can be made. The design keeps read-only logic centralized: one derived boolean in context, one banner component, one button wrapper used at each write-action site.Detection
KeyInfo.has_secrets: booleanis returned by the backend for every key.false= cold (no secret key stored),true= hot. This is the single source of truth.State & Context
isReadOnlyis a derived boolean added toWalletContext. No new context, no new store.Global Indicator —
ReadOnlyBannerA thin bar rendered once in
WalletTransitionWrapperinLayout.tsx, above{props.children}. Uses semantic theme classes (bg-muted,text-muted-foreground) so it adapts to any active theme. Includesaria-live="polite"so screen readers announce it on wallet switch.Write-Action Gating —
ReadOnlyButtonA drop-in replacement for
Buttonthat readsisReadOnlyinternally. When true, wraps a disabled button in a<span>+Tooltip(the span is required because nativedisabledelements suppress pointer events, which prevents the Radix tooltip from firing). When false, renders a normalButton.For
DropdownMenuItementries, usedisabled={isReadOnly || ...}directly — Radix already renders these greyed-out with no extra wrapper needed.For buttons that already have their own
disabledcondition (Swap, Split, Combine, etc.), prependisReadOnly ||as the first condition rather than usingReadOnlyButton, so the existing disabled logic is preserved independently.Call Sites
ReadOnlyButton(standalone write-action buttons)TokenCardTokenListNftListDidListOffersOptionListdisabled={isReadOnly \|\| ...}(buttons with existing disabled conditions)SwapOwnedCoinsCardClawbackCoinsCarddisabled={isReadOnly \|\| ...}onDropdownMenuItemNftCardDidList(Profile sub-component)Page Reachability
Write-action pages (Send, MintNft, MintOption, MakeOffer, CreateProfile, etc.) are only reachable via their triggering buttons, which are disabled for cold wallets. No route guards or redirects are needed.
Actions Remaining Fully Enabled for Cold Wallets
Non-Goals
WalletCard)key?.has_secrets && hardenedin the existing backend call — no UI change needed