CakeWallet/lib/src/screens/dashboard/sign_page.dart
Matthew Fosse 83ef61e928
Cw 565 sign messages (#1378)
* version bump to 3.13.9, auth working on mac

* bump flutter version in workflow file

* workflow fix

* test fix

* downgrade flutter version

* test fix

* test fix

* update gradle version

* start working on ui for message signing

* updates

* sign working for a few wallet types

* updates & verification for electrum currencies

* nano support

* sign/verify working on eth, bitcoin broken

* update translations

* Implement Verify Message for Monero

* save [skip ci]

* pub key extraction working

* fixes for electrum signing

* verify working for solana!

* electrum still not working :( [skip ci]

* electrum messages working!

* fixes for updated dart version, localization file updates

* remove accidental inclusion

* missed some unimplemented throws

* Update res/values/strings_de.arb

Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com>

* Apply suggestions from code review

Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com>

* review suggestions and updates [skip ci]

* [skip ci] add polygon

* [skip ci] merge mac-auth/update version

* fix litecoin

* bio auth mac fix

* remove comment and change duration from 2 to 0

* cherry pick previous changes

* litecoin fixes, sign form fixes, use new walletAddressPicker

* support accounts

* verify messages working for monero

* working sign and verify messages for nano

* electrum signing working [skip ci]

* additional nano fixes

* update translations

* attempt to decode signatures with base64

* workaround for secure storage bug on mac

* bump version to 3.19.5 (because breez will need this version anyways)

* some code cleanup

* some changess didn't get saved

* just documenting the issue [skip ci]

* undo accidental removal + minor code cleanup

* merge conflicts

* merge fixes [skip ci]

* add tron support

* [wip] fixing

* remove duplicate references to electrum path for maintainability

* fixes

* minor fix

* fixes

* undo debug comment

* update migration for all electrum based wallets

* hotfixes

* copy over the rest of the fixes

* minor code cleanup [skip ci]

* updates

* electrum signing workinggit statusgit statusgit statusgit status!

* copy same fixes for litecoin

* litecoin fixes

* add v to litecoin signatures

* fix dependencies

* fix bitcoin_base version

* merge fix

* dep override

* fix conflicts with main

* trial fix for android build

* fixes

* fix

* dep fix, should build

* fix signing for bitcoin cash

* [skip ci] minor code cleanup

* [skip ci] minor code cleanup 2

* forgot wonero, various other fixes

* more fixes

* fix solana (untested)

---------

Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
2024-08-18 02:10:27 +03:00

202 lines
7.5 KiB
Dart

import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/sign_form.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/verify_form.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/sign_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:mobx/mobx.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
class SignPage extends BasePage {
SignPage(this.signViewModel)
: signFormKey = GlobalKey<SignFormState>(),
verifyFormKey = GlobalKey<VerifyFormState>(),
_pages = [],
_controller = PageController(initialPage: 0) {
_pages.add(SignForm(
key: signFormKey,
type: signViewModel.wallet.type,
includeAddress: signViewModel.signIncludesAddress,
));
_pages.add(VerifyForm(
key: verifyFormKey,
type: signViewModel.wallet.type,
));
}
@override
Widget middle(BuildContext context) => Observer(
builder: (_) => Text(
S.current.sign_verify_title,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'Lato',
color: titleColor(context),
),
));
final SignViewModel signViewModel;
final PageController _controller;
final List<Widget> _pages;
final GlobalKey<SignFormState> signFormKey;
final GlobalKey<VerifyFormState> verifyFormKey;
bool _isEffectsInstalled = false;
@override
Widget body(BuildContext context) {
_setEffects(context);
return KeyboardActions(
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
nextFocus: false,
actions: [
KeyboardActionsItem(
focusNode: FocusNode(),
toolbarButtons: [(_) => KeyboardDoneButton()],
)
],
),
child: Container(
height: 0,
color: Theme.of(context).colorScheme.background,
child: Center(
child: ConstrainedBox(
constraints:
BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: PageView.builder(
onPageChanged: (page) {
signViewModel.isSigning = page == 0;
},
controller: _controller,
itemCount: _pages.length,
itemBuilder: (_, index) => SingleChildScrollView(child: _pages[index]),
),
),
if (_pages.length > 1)
Padding(
padding: EdgeInsets.only(top: 10),
child: SmoothPageIndicator(
controller: _controller,
count: _pages.length,
effect: ColorTransitionEffect(
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context).hintColor.withOpacity(0.5),
activeDotColor: Theme.of(context).hintColor,
),
),
),
Padding(
padding: EdgeInsets.only(top: 20, bottom: 24, left: 24, right: 24),
child: Column(
children: [
Observer(
builder: (context) {
return LoadingPrimaryButton(
onPressed: () async {
await _confirmForm(context);
},
text: signViewModel.isSigning
? S.current.sign_message
: S.current.verify_message,
color: Theme.of(context)
.extension<WalletListTheme>()!
.createNewWalletButtonBackgroundColor,
textColor: Theme.of(context)
.extension<WalletListTheme>()!
.restoreWalletButtonTextColor,
isLoading: signViewModel.state is IsExecutingState,
isDisabled: signViewModel.state is IsExecutingState,
);
},
),
],
),
)
],
),
),
),
),
);
}
void _setEffects(BuildContext context) async {
if (_isEffectsInstalled) {
return;
}
_isEffectsInstalled = true;
reaction((_) => signViewModel.state, (ExecutionState state) {
if (state is FailureState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showPopUp<void>(
context: context,
builder: (_) {
return AlertWithOneAction(
alertTitle: S.current.error,
alertContent: state.error,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop(),
);
});
});
}
if (state is ExecutedSuccessfullyState) {
if (signViewModel.isSigning) {
signFormKey.currentState!.signatureController.text = state.payload as String;
} else {
WidgetsBinding.instance.addPostFrameCallback((_) {
showPopUp<void>(
context: context,
builder: (_) {
return AlertWithOneAction(
alertTitle: S.current.successful,
alertContent: S.current.message_verified,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop(),
);
});
});
}
}
});
}
Future<void> _confirmForm(BuildContext context) async {
FocusManager.instance.primaryFocus?.unfocus();
if (signViewModel.isSigning) {
String message = signFormKey.currentState!.messageController.text;
String? address;
if (signViewModel.signIncludesAddress) {
address = signFormKey.currentState!.addressController.text;
}
await signViewModel.sign(message, address: address);
} else {
String message = verifyFormKey.currentState!.messageController.text;
String signature = verifyFormKey.currentState!.signatureController.text;
String address = verifyFormKey.currentState!.addressController.text;
await signViewModel.verify(message, signature, address: address);
}
}
}