Skip to content

Commit 59b0871

Browse files
committed
Spark: add address ownership proof signing and verification
1 parent 7d9cba1 commit 59b0871

16 files changed

Lines changed: 1099 additions & 168 deletions

File tree

‎lib/pages/signing/signing_view.dart‎

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
33

4+
import '../../providers/global/wallets_provider.dart';
45
import '../../themes/stack_colors.dart';
56
import '../../utilities/text_styles.dart';
67
import '../../utilities/util.dart';
8+
import '../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart';
79
import '../../widgets/background.dart';
810
import '../../widgets/conditional_parent.dart';
911
import '../../widgets/custom_buttons/app_bar_icon_button.dart';
@@ -31,35 +33,38 @@ class _SigningViewState extends ConsumerState<SigningView> {
3133
// keep auto dispose providers alive
3234
ref.listen(pSignIsValid, (_, __) {});
3335
ref.listen(pVerifyIsValid, (_, __) {});
36+
final wallet = ref.watch(pWallets).getWallet(widget.walletId);
37+
final viewOnly = wallet is ViewOnlyOptionInterface && wallet.isViewOnly;
3438

3539
return ConditionalParent(
3640
condition: !Util.isDesktop,
3741
builder: (child) => Background(
3842
child: Scaffold(
39-
backgroundColor: Theme.of(
40-
context,
41-
).extension<StackColors>()!.background,
43+
backgroundColor: Theme.of(context)
44+
.extension<StackColors>()!
45+
.background,
4246
appBar: AppBar(
4347
leading: AppBarBackButton(
4448
onPressed: () {
4549
Navigator.of(context).pop();
4650
},
4751
),
4852
title: Text(
49-
"Sign / Verify",
53+
viewOnly ? "Verify message" : "Sign / Verify",
5054
style: STextStyles.navBarTitle(context),
5155
),
5256
),
53-
body: SafeArea(child: child),
57+
body: SafeArea(child: SingleChildScrollView(child: child)),
5458
),
5559
),
5660
child: CustomTabView(
57-
titles: const ["Sign message", "Verify message"],
61+
titles: [if (!viewOnly) "Sign message", "Verify message"],
5862
children: [
59-
SignMessageForm(
60-
key: const Key("_SignMessageFormKey"),
61-
walletId: widget.walletId,
62-
),
63+
if (!viewOnly)
64+
SignMessageForm(
65+
key: const Key("_SignMessageFormKey"),
66+
walletId: widget.walletId,
67+
),
6368
VerifyMessageForm(
6469
key: const Key("_VerifyMessageFormKey"),
6570
walletId: widget.walletId,

‎lib/pages/signing/sub_widgets/sign_message_tab.dart‎

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import '../../../widgets/detail_item.dart';
1919
import '../../../widgets/dialogs/s_dialog.dart';
2020
import '../../../widgets/rounded_container.dart';
2121
import '../../../widgets/textfields/adaptive_text_field.dart';
22+
import '../../wallet_view/transaction_views/transaction_details_view.dart'
23+
show IconCopyButton;
2224
import '../signing_view.dart';
2325
import 'address_list.dart';
2426

@@ -32,7 +34,7 @@ final class _SignState {
3234
required this.signature,
3335
});
3436

35-
bool get isValid => message.isNotEmpty && address != null;
37+
bool get isValid => message.trim().isNotEmpty && address != null;
3638

3739
_SignState copyWith({String? message, String? signature}) {
3840
return _SignState(
@@ -77,9 +79,9 @@ class _SignMessageFormState extends ConsumerState<SignMessageForm> {
7779
TextStyle _getStyle(BuildContext context) {
7880
return Util.isDesktop
7981
? STextStyles.desktopTextExtraExtraSmall(context).copyWith(
80-
color: Theme.of(
81-
context,
82-
).extension<StackColors>()!.textFieldActiveSearchIconRight,
82+
color: Theme.of(context)
83+
.extension<StackColors>()!
84+
.textFieldActiveSearchIconRight,
8385
)
8486
: STextStyles.smallMed12(context);
8587
}
@@ -133,9 +135,9 @@ class _SignMessageFormState extends ConsumerState<SignMessageForm> {
133135
child: RoundedContainer(
134136
padding: EdgeInsets.zero,
135137
color: Colors.transparent,
136-
borderColor: Theme.of(
137-
context,
138-
).extension<StackColors>()!.textFieldDefaultBG,
138+
borderColor: Theme.of(context)
139+
.extension<StackColors>()!
140+
.textFieldDefaultBG,
139141
child: child,
140142
),
141143
),
@@ -181,9 +183,11 @@ class _SignMessageFormState extends ConsumerState<SignMessageForm> {
181183
onException: (e) => ex = e,
182184
);
183185

184-
if (mounted && ex != null) {
186+
if (!mounted || !identical(ref.read(_pSignState), state)) return;
187+
188+
if (ex != null) {
185189
await showSignVerifyError(ex!, context: context);
186-
} else if (signature != null && mounted) {
190+
} else if (signature != null) {
187191
ref.read(_pSignState.notifier).state = state.copyWith(
188192
signature: signature,
189193
);
@@ -214,7 +218,13 @@ class _SignMessageFormState extends ConsumerState<SignMessageForm> {
214218
AdaptiveTextField(
215219
controller: messageController,
216220
showPasteClearButton: true,
217-
maxLines: 1,
221+
trimPastedText: false,
222+
autocorrect: false,
223+
smartDashesType: SmartDashesType.disabled,
224+
smartQuotesType: SmartQuotesType.disabled,
225+
enableSuggestions: false,
226+
minLines: 1,
227+
maxLines: 5,
218228
onChangedComprehensive: (_) {
219229
if (mounted) {
220230
ref.read(_pSignState.notifier).state = ref
@@ -249,6 +259,8 @@ class _SignMessageFormState extends ConsumerState<SignMessageForm> {
249259
noPadding: Util.isDesktop,
250260
button: ref.watch(_pSignState.select((s) => s.signature)).isEmpty
251261
? null
262+
: Util.isDesktop
263+
? IconCopyButton(data: ref.read(_pSignState).signature)
252264
: SimpleCopyButton(data: ref.read(_pSignState).signature),
253265
),
254266

‎lib/pages/signing/sub_widgets/verify_message_tab.dart‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ class _VerifyMessageFormState extends ConsumerState<VerifyMessageForm> {
6767
TextStyle _getStyle(BuildContext context) {
6868
return Util.isDesktop
6969
? STextStyles.desktopTextExtraExtraSmall(context).copyWith(
70-
color: Theme.of(
71-
context,
72-
).extension<StackColors>()!.textFieldActiveSearchIconRight,
70+
color: Theme.of(context)
71+
.extension<StackColors>()!
72+
.textFieldActiveSearchIconRight,
7373
)
7474
: STextStyles.smallMed12(context);
7575
}
@@ -84,6 +84,7 @@ class _VerifyMessageFormState extends ConsumerState<VerifyMessageForm> {
8484

8585
_verify = IfNotAlreadyAsync<void>(() async {
8686
Exception? ex;
87+
final state = ref.read(_pVerifyState);
8788

8889
final verified = await showLoading(
8990
whileFuture:
@@ -100,7 +101,7 @@ class _VerifyMessageFormState extends ConsumerState<VerifyMessageForm> {
100101
onException: (e) => ex = e,
101102
);
102103

103-
if (mounted) {
104+
if (mounted && identical(ref.read(_pVerifyState), state)) {
104105
if (ex != null) {
105106
await showSignVerifyError(ex!, context: context);
106107
} else {
@@ -145,7 +146,13 @@ class _VerifyMessageFormState extends ConsumerState<VerifyMessageForm> {
145146
AdaptiveTextField(
146147
controller: messageController,
147148
showPasteClearButton: true,
148-
maxLines: 1,
149+
trimPastedText: false,
150+
autocorrect: false,
151+
smartDashesType: SmartDashesType.disabled,
152+
smartQuotesType: SmartQuotesType.disabled,
153+
enableSuggestions: false,
154+
minLines: 1,
155+
maxLines: 5,
149156
onChangedComprehensive: (_) {
150157
if (mounted) {
151158
ref.read(_pVerifyState.notifier).state = ref

0 commit comments

Comments
 (0)