Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CW-774: Enforce Seed Verification #1874

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1ad39b6
feat: Switch UI for seeds display
Blazebrain Dec 11, 2024
b9625bd
feat: Add localization for disclaimer text
Blazebrain Dec 11, 2024
dd657d8
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into …
Blazebrain Dec 11, 2024
2d53d82
fix: Modify color for warning on seeds screen
Blazebrain Dec 11, 2024
ff6e657
Fix: Adjust UI styling for seed page
Blazebrain Dec 11, 2024
1bf3d2b
chore: Revert podfile.lock
Blazebrain Dec 11, 2024
061e532
Fix column colors
tuxpizza Dec 11, 2024
688add3
Fix more colors
tuxpizza Dec 11, 2024
a883a3a
Fix more colors and update strings
tuxpizza Dec 11, 2024
5c58f36
feat: Enforce Seed Verification Implementation
Blazebrain Dec 12, 2024
784035d
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into …
Blazebrain Dec 12, 2024
484faf6
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into …
Blazebrain Dec 12, 2024
bce7612
Merge branch 'CW-703-Better-Seed-UI-UX' of https://github.com/cake-te…
Blazebrain Dec 12, 2024
97e91fe
fix: Error extracting seed words in Japanese because of spacing type …
Blazebrain Dec 12, 2024
b5c8776
Merge branch 'CW-703-Better-Seed-UI-UX' of https://github.com/cake-te…
Blazebrain Dec 12, 2024
89968c4
fix: Modify styling for copy image button
Blazebrain Dec 12, 2024
f62bd80
fix: Add back button to the seed page and adjust styling to seed veri…
Blazebrain Dec 12, 2024
5f57aec
Update seed verification image [skip ci]
tuxpizza Dec 12, 2024
a14000c
Update description text weight [skip ci]
tuxpizza Dec 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/images/seed_verified.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions lib/di.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import 'package:cake_wallet/entities/wallet_manager.dart';
import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart';
import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart';
import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_page.dart';
import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart';
import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart';
import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart';
Expand Down Expand Up @@ -1413,5 +1414,7 @@ Future<void> setup({

getIt.registerFactory(() => SignViewModel(getIt.get<AppStore>().wallet!));

getIt.registerFactory(() => SeedVerificationPage(getIt.get<WalletSeedViewModel>()));

_isSetupFinished = true;
}
7 changes: 7 additions & 0 deletions lib/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_choose_derivation.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_page.dart';
import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart';
import 'package:cake_wallet/src/screens/send/send_page.dart';
import 'package:cake_wallet/src/screens/send/send_template_page.dart';
Expand Down Expand Up @@ -794,6 +795,12 @@ Route<dynamic> createRoute(RouteSettings settings) {
),
);

case Routes.walletSeedVerificationPage:
return MaterialPageRoute<void>(
fullscreenDialog: true,
builder: (_) => getIt.get<SeedVerificationPage>(),
);

default:
return MaterialPageRoute<void>(
builder: (_) => Scaffold(
Expand Down
1 change: 1 addition & 0 deletions lib/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,5 @@ class Routes {
static const urqrAnimatedPage = '/urqr/animated_page';
static const walletGroupsDisplayPage = '/wallet_groups_display_page';
static const walletGroupDescription = '/wallet_group_description';
static const walletSeedVerificationPage = '/wallet_seed_verification_page';
}
2 changes: 1 addition & 1 deletion lib/src/screens/seed/pre_seed_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ class PreSeedPage extends InfoPage {

@override
void Function(BuildContext) get onPressed =>
(BuildContext context) => Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true);
(BuildContext context) => Navigator.of(context).pushNamed(Routes.seed, arguments: true);
}
35 changes: 35 additions & 0 deletions lib/src/screens/seed/seed_verification/seed_verification_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_step_view.dart';
import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_success_view.dart';
import 'package:cake_wallet/view_model/wallet_seed_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';

class SeedVerificationPage extends BasePage {
final WalletSeedViewModel walletSeedViewModel;

SeedVerificationPage(this.walletSeedViewModel);

@override
String? get title => S.current.verify_seed;

@override
Widget body(BuildContext context) {
return Observer(
builder: (context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: walletSeedViewModel.isVerificationComplete
? SeedVerificationSuccessView(
imageColor: titleColor(context),
)
: SeedVerificationStepView(
walletSeedViewModel: walletSeedViewModel,
questionTextColor: titleColor(context),
),
);
},
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/view_model/wallet_seed_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';

class SeedVerificationStepView extends StatelessWidget {
const SeedVerificationStepView({
required this.walletSeedViewModel,
required this.questionTextColor,
super.key,
});

final WalletSeedViewModel walletSeedViewModel;
final Color questionTextColor;

@override
Widget build(BuildContext context) {
return Observer(
builder: (context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 48),
Align(
alignment: Alignment.center,
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${S.current.seed_position_question_one} ',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: questionTextColor,
),
),
TextSpan(
text: '${getOrdinal(walletSeedViewModel.currentWordIndex + 1)} ',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w800,
color: questionTextColor,
),
),
TextSpan(
text: S.current.seed_position_question_two,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: questionTextColor,
),
),
],
),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 24),
Align(
alignment: Alignment.center,
child: Wrap(
spacing: 8,
runSpacing: 8,
alignment: WrapAlignment.center,
children: walletSeedViewModel.currentOptions.map(
(option) {
return GestureDetector(
onTap: () async {
final isCorrectWord = walletSeedViewModel.isChosenWordCorrect(option);
final isSecondWrongEntry = walletSeedViewModel.wrongEntries == 2;
if (!isCorrectWord) {
await showBar<void>(
context,
isSecondWrongEntry
? S.current.incorrect_seed_option_back
: S.current.incorrect_seed_option,
);

if (isSecondWrongEntry) {
Navigator.pop(context);
}
}
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Theme.of(context).cardColor,
),
child: Text(
option,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w800,
color: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
),
),
),
);
},
).toList(),
),
),
],
),
);
},
);
}

String getOrdinal(int number) {
// Handle special cases for 11th, 12th, 13th
final lastTwoDigits = number % 100;
if (lastTwoDigits >= 11 && lastTwoDigits <= 13) {
return '${number}th';
}

// Check the last digit for st, nd, rd, or default th
final lastDigit = number % 10;
switch (lastDigit) {
case 1:
return '${number}st';
case 2:
return '${number}nd';
case 3:
return '${number}rd';
default:
return '${number}th';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:flutter/material.dart';

class SeedVerificationSuccessView extends StatelessWidget {
const SeedVerificationSuccessView({required this.imageColor, super.key});

final Color imageColor;

@override
Widget build(BuildContext context) {
final image = Image.asset('assets/images/seed_verified.png', color: imageColor);

return Center(
child: Column(
children: [
ConstrainedBox(
constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3),
child: AspectRatio(
aspectRatio: 1.8,
child: image,
),
),
SizedBox(height: 16),
Text(
S.current.seed_verified,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
),
SizedBox(height: 48),
RichText(
text: TextSpan(
children: [
TextSpan(
text: '${S.current.seed_verified_subtext} ',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
),
),
TextSpan(
text: S.current.seed_display_path,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w800,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
),
),
],
),
textAlign: TextAlign.center,
),
Spacer(),
PrimaryButton(
key: ValueKey('wallet_seed_page_open_wallet_button_key'),
onPressed: () {
Navigator.of(context).popUntil((route) => route.isFirst);
},
text: S.current.open_wallet,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
),
SizedBox(height: 16),
],
),
);
}
}
Loading