Skip to content

feat: real designs for Keystone hardware wallet signup and signing - #591

Merged
n13 merged 4 commits into
mainfrom
feat/keystone_design
Aug 3, 2026
Merged

feat: real designs for Keystone hardware wallet signup and signing#591
n13 merged 4 commits into
mainfrom
feat/keystone_design

Conversation

@n13

@n13 n13 commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Replaces the dev-design Keystone screens with the real designs from the Quantus Redesign Figma.

Screenshots: See below (simulator)

Designs:

Add Keystone flow (2 screens)

  • AddHardwareAccountScreen rewritten as the intro screen: hero product image, headline, "Connect Hardware Wallet" button, and a "Don't have one? Get a Keystone ↗" link. Constructor unchanged, so existing callers (add-account menu, create-account) are untouched.
  • New ConnectKeystoneScreen: firmware reminder + on-device steps with the Figma icons, then "Ready to Scan" opens the QR scanner. The name/address form is gone — the account is created directly after scanning (name defaults to "Keystone Wallet"). Debug test-address path kept in kDebugMode.

Send signing flow — now a 3-step journey

Most of the send flow is unchanged; the branch where the user signs with Keystone is redesigned:

  • Step 1/3 KeystoneSignScreen: step indicator, "Scan with your Keystone", bordered QR card, "YOU ARE SIGNING" details (amount/recipient + checksum), "Continue to Sign" / "Cancel Transaction".
  • Step 2/3 new KeystoneVerifyScreen: "Check your Keystone Screen" — dark summary card with amount and recipient, red mismatch warning, "Continue to Sign" / "It doesn't match".
  • Step 3/3 AnimatedQrScanner restyled: app bar, step header, rounded camera view with corner brackets, "RECEIVING SIGNATURE" progress bar.
  • New KeystoneRejectScreen ("It doesn't match"): reject-on-device instructions, "I rejected it on Keystone", "Contact Support" mailto.

Multisig hardware signing gets the same new flow automatically since it shares these screens.

Supporting changes

  • New textSubtle color in AppColorsV2, shared KeystoneStepLabel / KeystoneWarningCard widgets, UnderlinedTextLink component
  • Figma assets (hero image, logo, step icons) added to assets/v2/
  • New/updated l10n strings; stale Indonesian overrides for changed/removed strings dropped (fall back to English)
  • Removed unused KeystoneSigningSession.title (app bar is "Sign with Keystone" per design)

Deliberate deviations from Figma

  • Step 2 "≈ $10" fiat row omitted — no fiat data in the signing session
  • Scanner torch button dropped to match the design

Testing

  • melos run format clean; dart analyze --fatal-infos clean on lib/ and test/ (melos' own analyze run kept crashing its analysis server on mobile-app — env flake, not a code issue)
  • Not yet tested on device — set AppConstants.debugHardwareWallet to force the Keystone path for testing without hardware

@n13

n13 commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author
Simulator Screenshot - iPhone 17 - 2026-08-02 at 15 22 47 Simulator Screenshot - iPhone 17 - 2026-08-02 at 15 22 52 Simulator Screenshot - iPhone 17 - 2026-08-02 at 15 22 59

label: widget.debugActionLabel,
onTap: _simulateScan,
variant: ButtonVariant.danger,
width: null,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why do we have width null?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

hmmm ????

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hm... why do we have to create new component for this, we can extend the button variant.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

we already have an underlined text button?

gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF1A1A1A), Color(0xFF141210)],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this a new color or we already have this in the theme?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

will fix colors

accountType: AccountType.keystone,
);
await _accountsService.addAccount(account);
ref.invalidate(accountsProvider);

@dewabisma dewabisma Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we always invalidate accounts and activeAccount providers?

If so, we could have a refactor of this maybe, to not repeat ourselves many times and one place to handle logic of the account invalidation.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

if we add an account we need to

final session = KeystoneSigningSession(
account: signer,
buildCall: () => widget.buildCall(signer, _callBytes),
title: widget.labels.title(l10n),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this intentional removing title? Just confirming it's not unintentionally deleted

Widget _details(AppColorsV2 colors, AppTextTheme text, KeystoneSigningSession session) {
Widget _details(AppColorsV2 colors, AppTextTheme text, AppLocalizations l10n, KeystoneSigningSession session) {
final labelStyle = text.transactionDetailRowLabel?.copyWith(color: colors.textTertiary);
final valueStyle = text.transactionDetailRowValue?.copyWith(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we will need to revisit how we manage text style, right now it's already drifting from the original purpose of supporting adaptive font because we supported iPad before. Now it only bring noise since the way we use it now just arbitrary customizing.

We might don't need it anymore except the basic font family and size scaling.

gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [colors.textError.withValues(alpha: 0.1), const Color(0xFF5A1B14).withValues(alpha: 0.1)],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Need to check this color if reused or not.

height: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFFFF5B5B).withValues(alpha: 0.1)),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hm.... two ways of controlling alpha ??? kind of smelly to me

Comment thread AGENTS.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So, we are okay to have repo rule now?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yeah so AI knows how to check it in without errors

@dewabisma dewabisma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Need clarifications

- New theme colors errorLight, errorDeep, surfaceHero replace hardcoded
  hex values in the keystone hero and warning cards; alpha derivation
  unified on useOpacity (no withValues in widgets)
- UnderlinedTextLink folded into QuantusButton as ButtonVariant.underline
- invalidateAccountProviders() replaces the repeated accountsProvider +
  activeAccountProvider invalidation pairs
- Scanner overlay/brackets use theme colors; drop redundant width: null
- AGENTS.md: UI conventions (theme colors, useOpacity, theme text styles,
  extend existing components)

@dewabisma dewabisma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM!

@n13
n13 merged commit 0bc4fa9 into main Aug 3, 2026
1 check passed
@n13
n13 deleted the feat/keystone_design branch August 3, 2026 13:31
n13 added a commit that referenced this pull request Aug 4, 2026
Main landed the Keystone redesign (#591/#594) in a newer form, so the
add/add and screen conflicts resolve to main's versions (theme
conventions, invalidateAccountProviders, underline button variant,
simplified connect steps + matching l10n cleanup). Re-applied on top:

- animated_qr_scanner: DetectionSpeed.unrestricted + QR-only formats
- keystone_sign_screen: 400-byte fragments via encodeUr maxFragmentLength

Regenerated app_localizations from the merged .arb files.
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.

2 participants