CAKE-359 | added text field for extracted (from Yat, Unstoppable Domains, OpenAlias) address to send_card.dart; added extractedAddress and isParsedAddress parameters to output.dart; applied extractedAddress to monero_wallet.dart and electrum_wallet.dart; added TextValidator to send_view_model.dart
OleksandrSobol committed
Sep 22, 2021 at 16:47 UTC
3b649ef6829628ff6a4bb5a6b431605c99288ad8
7 files changed
+118
-71
lib/bitcoin/electrum_wallet.dart
+5
-1
@@ -280,8 +280,12 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
280
? item.formattedCryptoAmount
281
: amount;
282
283
+ final outputAddress = item.isParsedAddress
284
+ ? item.extractedAddress
285
+ : item.address;
286
+
287
txb.addOutput(
284
- addressToOutputScript(item.address, networkType),
288
+ addressToOutputScript(outputAddress, networkType),
289
outputAmount);
290
});
291
lib/monero/monero_wallet.dart
+12
-6
@@ -175,11 +175,15 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
175
throw MoneroTransactionCreationException('Wrong balance. Not enough XMR on your balance.');
176
}
177
178
- final moneroOutputs = outputs.map((output) =>
179
- MoneroOutput(
180
- address: output.address,
181
- amount: output.cryptoAmount.replaceAll(',', '.')))
182
- .toList();
178
+ final moneroOutputs = outputs.map((output) {
179
+ final outputAddress = output.isParsedAddress
180
+ ? output.extractedAddress
181
+ : output.address;
182
+
183
+ return MoneroOutput(
184
+ address: outputAddress,
185
+ amount: output.cryptoAmount.replaceAll(',', '.'));
186
+ }).toList();
187
188
pendingTransactionDescription =
189
await transaction_history.createTransactionMultDest(
@@ -188,7 +192,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
192
accountIndex: walletAddresses.account.id);
193
} else {
194
final output = outputs.first;
191
- final address = output.address;
195
+ final address = output.isParsedAddress
196
+ ? output.extractedAddress
197
+ : output.address;
198
final amount = output.sendAll
199
? null
200
: output.cryptoAmount.replaceAll(',', '.');
lib/src/screens/send/send_page.dart
-1
@@ -1,5 +1,4 @@
1
import 'dart:ui';
2
-import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_alert.dart';
2
import 'package:cake_wallet/src/screens/send/widgets/send_card.dart';
3
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
4
import 'package:cake_wallet/src/widgets/template_tile.dart';
lib/src/screens/send/widgets/confirm_sending_alert.dart
+8
-9
@@ -1,4 +1,3 @@
1
-import 'package:cake_wallet/entities/parsed_address.dart';
1
import 'package:cake_wallet/palette.dart';
2
import 'package:cake_wallet/view_model/send/output.dart';
3
import 'package:flutter/material.dart';
@@ -274,16 +273,15 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
273
itemCount: itemCount,
274
itemBuilder: (context, index) {
275
final item = outputs[index];
277
- final _address = item.address;
276
+ final _address = item.isParsedAddress
277
+ ? item.extractedAddress
278
+ : item.address;
279
final _amount =
280
item.cryptoAmount.replaceAll(',', '.');
280
- final isParsedAddress =
281
- item.parsedAddress.parseFrom !=
282
- ParseFrom.notParsed;
281
282
return Column(
283
children: [
286
- if (isParsedAddress) Padding(
284
+ if (item.isParsedAddress) Padding(
285
padding: EdgeInsets.only(top: 8),
286
child: Text(
287
item.parsedAddress.name,
@@ -334,8 +332,7 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
332
})
333
: Column(
334
children: [
337
- if (outputs.first.parsedAddress.parseFrom !=
338
- ParseFrom.notParsed) Padding(
335
+ if (outputs.first.isParsedAddress) Padding(
336
padding: EdgeInsets.only(top: 8),
337
child: Text(
338
outputs.first.parsedAddress.name,
@@ -352,7 +349,9 @@ class ConfirmSendingAlertContentState extends State<ConfirmSendingAlertContent>
349
Padding(
350
padding: EdgeInsets.only(top: 8),
351
child: Text(
355
- outputs.first.address,
352
+ outputs.first.isParsedAddress
353
+ ? outputs.first.extractedAddress
354
+ : outputs.first.address,
355
style: TextStyle(
356
fontSize: 10,
357
fontWeight: FontWeight.w600,
lib/src/screens/send/widgets/send_card.dart
+81
-53
@@ -1,7 +1,6 @@
1
import 'dart:ui';
2
import 'package:cake_wallet/entities/transaction_priority.dart';
3
import 'package:cake_wallet/routes.dart';
4
-import 'package:cake_wallet/src/screens/send/widgets/parse_address_from_domain_alert.dart';
4
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
5
import 'package:cake_wallet/src/widgets/picker.dart';
6
import 'package:cake_wallet/view_model/send/output.dart';
@@ -38,6 +37,7 @@ class SendCardState extends State<SendCard>
37
cryptoAmountController = TextEditingController(),
38
fiatAmountController = TextEditingController(),
39
noteController = TextEditingController(),
40
+ extractedAddressController = TextEditingController(),
41
cryptoAmountFocus = FocusNode(),
42
fiatAmountFocus = FocusNode(),
43
addressFocusNode = FocusNode();
@@ -52,6 +52,7 @@ class SendCardState extends State<SendCard>
52
final TextEditingController cryptoAmountController;
53
final TextEditingController fiatAmountController;
54
final TextEditingController noteController;
55
+ final TextEditingController extractedAddressController;
56
final FocusNode cryptoAmountFocus;
57
final FocusNode fiatAmountFocus;
58
final FocusNode addressFocusNode;
@@ -101,58 +102,80 @@ class SendCardState extends State<SendCard>
102
child: Padding(
103
padding: EdgeInsets.fromLTRB(24, 100, 24, 32),
104
child: SingleChildScrollView(
104
- child: Column(
105
+ child: Observer(builder: (_) => Column(
106
mainAxisSize: MainAxisSize.min,
107
children: <Widget>[
107
- AddressTextField(
108
- focusNode: addressFocusNode,
109
- controller: addressController,
110
- onURIScanned: (uri) {
111
- var address = '';
112
- var amount = '';
113
-
114
- if (uri != null) {
115
- address = uri.path;
116
- amount = uri.queryParameters['tx_amount'] ??
117
- uri.queryParameters['amount'];
118
- } else {
119
- address = uri.toString();
120
- }
121
-
122
- addressController.text = address;
123
- cryptoAmountController.text = amount;
124
- },
125
- options: [
126
- AddressTextFieldOption.paste,
127
- AddressTextFieldOption.qrCode,
128
- AddressTextFieldOption.addressBook
129
- ],
130
- buttonColor: Theme.of(context)
131
- .primaryTextTheme
132
- .display1
133
- .color,
134
- borderColor: Theme.of(context)
135
- .primaryTextTheme
136
- .headline
137
- .color,
138
- textStyle: TextStyle(
139
- fontSize: 14,
140
- fontWeight: FontWeight.w500,
141
- color: Colors.white),
142
- hintStyle: TextStyle(
143
- fontSize: 14,
144
- fontWeight: FontWeight.w500,
145
- color: Theme.of(context)
146
- .primaryTextTheme
147
- .headline
148
- .decorationColor),
149
- onPushPasteButton: (context) async {
150
- output.resetParsedAddress();
151
- await output.fetchParsedAddress(context);
152
- },
153
- onPushAddressBookButton: (context) =>
154
- output.resetParsedAddress(),
155
- validator: sendViewModel.addressValidator,
108
+ Observer(builder: (_) {
109
+ final validator = output.isParsedAddress
110
+ ? sendViewModel.textValidator
111
+ : sendViewModel.addressValidator;
112
+
113
+ return AddressTextField(
114
+ focusNode: addressFocusNode,
115
+ controller: addressController,
116
+ onURIScanned: (uri) {
117
+ var address = '';
118
+ var amount = '';
119
+
120
+ if (uri != null) {
121
+ address = uri.path;
122
+ amount = uri.queryParameters['tx_amount'] ??
123
+ uri.queryParameters['amount'];
124
+ } else {
125
+ address = uri.toString();
126
+ }
127
+
128
+ addressController.text = address;
129
+ cryptoAmountController.text = amount;
130
+ },
131
+ options: [
132
+ AddressTextFieldOption.paste,
133
+ AddressTextFieldOption.qrCode,
134
+ AddressTextFieldOption.addressBook
135
+ ],
136
+ buttonColor: Theme.of(context)
137
+ .primaryTextTheme
138
+ .display1
139
+ .color,
140
+ borderColor: Theme.of(context)
141
+ .primaryTextTheme
142
+ .headline
143
+ .color,
144
+ textStyle: TextStyle(
145
+ fontSize: 14,
146
+ fontWeight: FontWeight.w500,
147
+ color: Colors.white),
148
+ hintStyle: TextStyle(
149
+ fontSize: 14,
150
+ fontWeight: FontWeight.w500,
151
+ color: Theme.of(context)
152
+ .primaryTextTheme
153
+ .headline
154
+ .decorationColor),
155
+ onPushPasteButton: (context) async {
156
+ output.resetParsedAddress();
157
+ await output.fetchParsedAddress(context);
158
+ },
159
+ onPushAddressBookButton: (context) =>
160
+ output.resetParsedAddress(),
161
+ validator: validator,
162
+ );
163
+ }),
164
+ if (output.isParsedAddress) Padding(
165
+ padding: const EdgeInsets.only(top: 20),
166
+ child: BaseTextFormField(
167
+ controller: extractedAddressController,
168
+ readOnly: true,
169
+ borderColor: Theme.of(context)
170
+ .primaryTextTheme
171
+ .headline
172
+ .color,
173
+ textStyle: TextStyle(
174
+ fontSize: 14,
175
+ fontWeight: FontWeight.w500,
176
+ color: Colors.white),
177
+ validator: sendViewModel.addressValidator
178
+ )
179
),
180
Observer(
181
builder: (_) => Padding(
@@ -440,7 +463,7 @@ class SendCardState extends State<SendCard>
463
)
464
)
465
],
443
- )
466
+ ))
467
),
468
),
469
)
@@ -453,6 +476,7 @@ class SendCardState extends State<SendCard>
476
cryptoAmountController.text = output.cryptoAmount;
477
fiatAmountController.text = output.fiatAmount;
478
noteController.text = output.note;
479
+ extractedAddressController.text = output.extractedAddress;
480
481
if (_effectsInstalled) {
482
return;
@@ -520,6 +544,7 @@ class SendCardState extends State<SendCard>
544
final address = addressController.text;
545
546
if (output.address != address) {
547
+ output.resetParsedAddress();
548
output.address = address;
549
}
550
});
@@ -532,11 +557,14 @@ class SendCardState extends State<SendCard>
557
558
addressFocusNode.addListener(() async {
559
if (!addressFocusNode.hasFocus && addressController.text.isNotEmpty) {
535
- output.resetParsedAddress();
560
await output.fetchParsedAddress(context);
561
}
562
});
563
564
+ reaction((_) => output.extractedAddress, (String extractedAddress) {
565
+ extractedAddressController.text = extractedAddress;
566
+ });
567
+
568
_effectsInstalled = true;
569
}
570
lib/view_model/send/output.dart
+10
-1
@@ -47,8 +47,16 @@ abstract class OutputBase with Store {
47
@observable
48
bool sendAll;
49
50
+ @observable
51
ParsedAddress parsedAddress;
52
53
+ @observable
54
+ String extractedAddress;
55
+
56
+ @computed
57
+ bool get isParsedAddress => parsedAddress.parseFrom != ParseFrom.notParsed
58
+ && parsedAddress.name.isNotEmpty;
59
+
60
@computed
61
int get formattedCryptoAmount {
62
int amount = 0;
@@ -134,6 +142,7 @@ abstract class OutputBase with Store {
142
}
143
144
void resetParsedAddress() {
145
+ extractedAddress = '';
146
parsedAddress = ParsedAddress(addresses: []);
147
}
148
@@ -206,6 +215,6 @@ abstract class OutputBase with Store {
215
final domain = address;
216
final ticker = _wallet.currency.title.toLowerCase();
217
parsedAddress = await parseAddressFromDomain(domain, ticker);
209
- address = await defineAddress(context, parsedAddress);
218
+ extractedAddress = await defineAddress(context, parsedAddress);
219
}
220
}
\ No newline at end of file
lib/view_model/send/send_view_model.dart
+2
@@ -117,6 +117,8 @@ abstract class SendViewModelBase with Store {
117
118
Validator get addressValidator => AddressValidator(type: _wallet.currency);
119
120
+ Validator get textValidator => TextValidator();
121
+
122
@observable
123
PendingTransaction pendingTransaction;
124