Cw 45 implement yat sending (#269)

* resolve YAT emoji * remove animation in route builder change YAT api * remove yat sending page * fix crypto address resolving * check if text is emoji * use getter for string extension hasOnlyEmojis * refactor parsed domain from address * update PR based on changes from code review * import missing dependencies

Godwin Asuquo committed Mar 15, 2022 at 10:11 UTC d2cc8128847a8a9fd74f03844741b03af51970e5
15 files changed +178 -363
lib/core/yat_service.dart new
+47
@@ -0,0 +1,47 @@
1 +import 'dart:convert';
2 +
3 +import 'package:cake_wallet/entities/yat_record.dart';
4 +import 'package:http/http.dart';
5 +
6 +class YatService {
7 + static bool isDevMode = false;
8 +
9 + static String get apiUrl =>
10 + YatService.isDevMode ? YatService.apiDevUrl : YatService.apiReleaseUrl;
11 + static const apiReleaseUrl = "https://a.y.at";
12 + static const apiDevUrl = 'https://yat.fyi';
13 +
14 + static String lookupEmojiUrl(String emojiId) =>
15 + "$apiUrl/emoji_id/$emojiId/payment";
16 +
17 + static const tags = {
18 + 'XMR': '0x1001,0x1002',
19 + 'BTC': '0x1003',
20 + 'LTC': '0x3fff'
21 + };
22 +
23 + Future<List<YatRecord>> fetchYatAddress(String emojiId, String ticker) async {
24 + final formattedTicker = ticker.toUpperCase();
25 + final formattedEmojiId = emojiId.replaceAll(' ', '');
26 + final uri = Uri.parse(lookupEmojiUrl(formattedEmojiId)).replace(
27 + queryParameters: <String, dynamic>{
28 + "tags": tags[formattedTicker]
29 + });
30 +
31 + final yatRecords = <YatRecord>[];
32 +
33 + try {
34 + final response = await get(uri);
35 + final resBody = json.decode(response.body) as Map<String, dynamic>;
36 +
37 + final results = resBody["result"] as Map<dynamic, dynamic>;
38 + results.forEach((dynamic key, dynamic value) {
39 + yatRecords.add(YatRecord.fromJson(value as Map<String, dynamic>));
40 + });
41 +
42 + return yatRecords;
43 + } catch (_) {
44 + return yatRecords;
45 + }
46 + }
47 +}
lib/di.dart
+6
@@ -1,3 +1,5 @@
1 +import 'package:cake_wallet/core/yat_service.dart';
2 +import 'package:cake_wallet/entities/parse_address_from_domain.dart';
3 import 'package:cake_wallet/entities/wake_lock.dart';
4 import 'package:cake_wallet/monero/monero.dart';
5 import 'package:cake_wallet/bitcoin/bitcoin.dart';
@@ -623,5 +625,9 @@ Future setup(
625
626 getIt.registerFactory(() => WakeLock());
627
628 + getIt.registerFactory(() => YatService());
629 +
630 + getIt.registerFactory(() => AddressResolver(yatService: getIt.get<YatService>()));
631 +
632 _isSetupFinished = true;
633 }
lib/entities/emoji_string_extension.dart new
+25
@@ -0,0 +1,25 @@
1 +import 'package:flutter/material.dart';
2 +
3 +extension Emoji on String {
4 + static final REGEX_EMOJI = RegExp(
5 + r'[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}'
6 + r'\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}'
7 + r'-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}'
8 + r'\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}'
9 + r'-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}'
10 + r'\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}'
11 + r'-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}'
12 + r'\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}'
13 + r'-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}\u{200d}]+',
14 + unicode: true,
15 + );
16 +
17 + bool _hasOnlyEmojis() {
18 + final parsedText = this.replaceAll(' ', '');
19 + for (final c in Characters(parsedText))
20 + if (!REGEX_EMOJI.hasMatch(c)) return false;
21 + return true;
22 + }
23 + /// Returns true if the given text contains only emojis.
24 + bool get hasOnlyEmojis => _hasOnlyEmojis();
25 +}
lib/entities/parse_address_from_domain.dart
+32 -49
@@ -1,10 +1,17 @@
1 +import 'package:cake_wallet/core/yat_service.dart';
2 import 'package:cake_wallet/entities/openalias_record.dart';
3 import 'package:cake_wallet/entities/parsed_address.dart';
4 import 'package:cake_wallet/entities/unstoppable_domain_address.dart';
4 -import 'package:cake_wallet/store/yat/yat_store.dart';
5 -import 'package:cw_core/wallet_type.dart';
6 -
7 -const unstoppableDomains = [
5 +import 'package:cake_wallet/entities/emoji_string_extension.dart';
6 +import 'package:flutter/foundation.dart';
7 +
8 +class AddressResolver {
9 +
10 + AddressResolver({@required this.yatService});
11 +
12 + final YatService yatService;
13 +
14 + static const unstoppableDomains = [
15 'crypto',
16 'zil',
17 'x',
@@ -17,57 +24,33 @@ const unstoppableDomains = [
24 'blockchain'
25 ];
26
20 -Future<ParsedAddress> parseAddressFromDomain(
21 - String domain, String ticker) async {
22 - try {
23 - final formattedName = OpenaliasRecord.formatDomainName(domain);
24 - final domainParts = formattedName.split('.');
25 - final name = domainParts.last;
26 -
27 - if (domainParts.length <= 1 || domainParts.first.isEmpty || name.isEmpty) {
28 - try {
29 - final addresses = await fetchYatAddress(domain, ticker);
30 -
31 - if (addresses?.isEmpty ?? true) {
32 - return ParsedAddress(
33 - addresses: [domain], parseFrom: ParseFrom.yatRecord);
34 - }
35 -
36 - return ParsedAddress(
37 - addresses: addresses, name: domain, parseFrom: ParseFrom.yatRecord);
38 - } catch (e) {
39 - return ParsedAddress(addresses: [domain]);
27 + Future<ParsedAddress> resolve(String text, String ticker) async {
28 + try {
29 + if (text.hasOnlyEmojis) {
30 + final addresses = await yatService.fetchYatAddress(text, ticker);
31 + return ParsedAddress.fetchEmojiAddress(addresses: addresses, name: text);
32 }
41 - }
33 + final formattedName = OpenaliasRecord.formatDomainName(text);
34 + final domainParts = formattedName.split('.');
35 + final name = domainParts.last;
36
43 - if (unstoppableDomains.any((domain) => name.contains(domain))) {
44 - final address = await fetchUnstoppableDomainAddress(domain, ticker);
45 -
46 - if (address?.isEmpty ?? true) {
47 - return ParsedAddress(addresses: [domain]);
37 + if (domainParts.length <= 1 || domainParts.first.isEmpty || name.isEmpty) {
38 + return ParsedAddress(addresses: [text]);
39 }
40
50 - return ParsedAddress(
51 - addresses: [address],
52 - name: domain,
53 - parseFrom: ParseFrom.unstoppableDomains);
54 - }
55 -
56 - final record = await OpenaliasRecord.fetchAddressAndName(
57 - formattedName: formattedName, ticker: ticker);
41 + if (unstoppableDomains.any((domain) => name.contains(domain))) {
42 + final address = await fetchUnstoppableDomainAddress(text, ticker);
43 + return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text);
44 + }
45
59 - if (record == null || record.address.contains(formattedName)) {
60 - return ParsedAddress(addresses: [domain]);
46 + final record = await OpenaliasRecord.fetchAddressAndName(
47 + formattedName: formattedName, ticker: ticker);
48 + return ParsedAddress.fetchOpenAliasAddress(record: record, name: text);
49 +
50 + } catch (e) {
51 + print(e.toString());
52 }
53
63 - return ParsedAddress(
64 - addresses: [record.address],
65 - name: record.name,
66 - description: record.description,
67 - parseFrom: ParseFrom.openAlias);
68 - } catch (e) {
69 - print(e.toString());
54 + return ParsedAddress(addresses: [text]);
55 }
71 -
72 - return ParsedAddress(addresses: [domain]);
56 }
lib/entities/parsed_address.dart
+46
@@ -1,3 +1,7 @@
1 +import 'package:cake_wallet/entities/openalias_record.dart';
2 +import 'package:cake_wallet/entities/yat_record.dart';
3 +import 'package:flutter/material.dart';
4 +
5 enum ParseFrom { unstoppableDomains, openAlias, yatRecord, notParsed }
6
7 class ParsedAddress {
@@ -12,4 +16,46 @@ class ParsedAddress {
16 final String name;
17 final String description;
18 final ParseFrom parseFrom;
19 +
20 + factory ParsedAddress.fetchEmojiAddress({
21 + @required List<YatRecord> addresses,
22 + @required String name,
23 + }){
24 + if (addresses?.isEmpty ?? true) {
25 + return ParsedAddress(
26 + addresses: [name], parseFrom: ParseFrom.yatRecord);
27 + }
28 + return ParsedAddress(
29 + addresses: addresses.map((e) => e.address).toList(),
30 + name: name,
31 + parseFrom: ParseFrom.yatRecord,
32 + );
33 + }
34 +
35 + factory ParsedAddress.fetchUnstoppableDomainAddress({
36 + @required String address,
37 + @required String name,
38 + }){
39 + if (address?.isEmpty ?? true) {
40 + return ParsedAddress(addresses: [name]);
41 + }
42 + return ParsedAddress(
43 + addresses: [address],
44 + name: name,
45 + parseFrom: ParseFrom.unstoppableDomains,
46 + );
47 + }
48 +
49 + factory ParsedAddress.fetchOpenAliasAddress({@required OpenaliasRecord record, @required String name}){
50 + final formattedName = OpenaliasRecord.formatDomainName(name);
51 + if (record == null || record.address.contains(formattedName)) {
52 + return ParsedAddress(addresses: [name]);
53 + }
54 + return ParsedAddress(
55 + addresses: [record.address],
56 + name: record.name,
57 + description: record.description,
58 + parseFrom: ParseFrom.openAlias,
59 + );
60 + }
61 }
lib/entities/yat_record.dart new
+16
@@ -0,0 +1,16 @@
1 +class YatRecord {
2 + String category;
3 + String address;
4 +
5 + YatRecord({
6 + this.category,
7 + this.address,
8 + });
9 +
10 + YatRecord.fromJson(Map<String, dynamic> json) {
11 + address = json['address'] as String;
12 + category = json['category'] as String;
13 + }
14 +
15 +
16 +}
lib/main.dart
-2
@@ -2,9 +2,7 @@ import 'dart:async';
2 import 'package:cake_wallet/bitcoin/bitcoin.dart';
3 import 'package:cake_wallet/entities/language_service.dart';
4 import 'package:cake_wallet/buy/order.dart';
5 -import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
5 import 'package:cake_wallet/store/yat/yat_store.dart';
7 -import 'package:cake_wallet/utils/show_pop_up.dart';
6 import 'package:flutter/foundation.dart';
7 import 'package:flutter/material.dart';
8 import 'package:flutter/services.dart';
lib/src/screens/dashboard/dashboard_page.dart
-18
@@ -178,24 +178,6 @@ class DashboardPage extends BasePage {
178 pages.add(TransactionsPage(dashboardViewModel: walletViewModel));
179 _isEffectsInstalled = true;
180
181 - //if (walletViewModel.shouldShowYatPopup) {
182 - // await Future<void>.delayed(Duration(seconds: 1));
183 -
184 - // if (currentRouteSettings.name == Routes.preSeed
185 - // || currentRouteSettings.name == Routes.seed) {
186 - // return;
187 - // }
188 -
189 - // await showPopUp<void>(
190 - // context: context,
191 - // builder: (BuildContext context) {
192 - // return YatPopup(
193 - // dashboardViewModel: walletViewModel,
194 - // onClose: () => Navigator.of(context).pop());
195 - // });
196 - // walletViewModel.furtherShowYatPopup(false);
197 - //}
198 -
181 autorun((_) async {
182 if (!walletViewModel.isOutdatedElectrumWallet) {
183 return;
lib/src/screens/exchange/exchange_page.dart
+2 -2
@@ -1,5 +1,5 @@
1 import 'dart:ui';
2 -import 'package:cake_wallet/entities/parsed_address.dart';
2 +import 'package:cake_wallet/di.dart';
3 import 'package:cake_wallet/utils/debounce.dart';
4 import 'package:cw_core/sync_status.dart';
5 import 'package:cw_core/wallet_type.dart';
@@ -790,7 +790,7 @@ class ExchangePage extends BasePage {
790
791 Future<String> fetchParsedAddress(
792 BuildContext context, String domain, String ticker) async {
793 - final parsedAddress = await parseAddressFromDomain(domain, ticker);
793 + final parsedAddress = await getIt.get<AddressResolver>().resolve(domain, ticker);
794 final address = await extractAddressFromParsed(context, parsedAddress);
795 return address;
796 }
lib/src/screens/send/send_page.dart
+2 -10
@@ -1,6 +1,6 @@
1 import 'dart:ui';
2 +import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
3 import 'package:cake_wallet/src/screens/send/widgets/send_card.dart';
3 -import 'package:cake_wallet/src/screens/yat/widgets/yat_close_button.dart';
4 import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
5 import 'package:cake_wallet/src/widgets/template_tile.dart';
6 import 'package:cake_wallet/view_model/send/output.dart';
@@ -22,9 +22,6 @@ import 'package:dotted_border/dotted_border.dart';
22 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
23 import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
24 import 'package:smooth_page_indicator/smooth_page_indicator.dart';
25 -import 'package:cake_wallet/store/yat/yat_store.dart';
26 -import 'package:cake_wallet/src/screens/yat/yat_sending.dart';
27 -import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
25
26 class SendPage extends BasePage {
27 SendPage({@required this.sendViewModel}) : _formKey = GlobalKey<FormState>();
@@ -304,11 +301,6 @@ class SendPage extends BasePage {
301
302 await sendViewModel.createTransaction();
303
307 - if (!sendViewModel.isBatchSending &&
308 - sendViewModel.hasYat) {
309 - Navigator.of(context)
310 - .push<void>(YatSending.createRoute(sendViewModel));
311 - }
304 },
305 text: S.of(context).send,
306 color: Theme.of(context).accentTextTheme.body2.color,
@@ -345,7 +337,7 @@ class SendPage extends BasePage {
337 }
338
339 if (state is ExecutedSuccessfullyState &&
348 - !(!sendViewModel.isBatchSending && sendViewModel.hasYat)) {
340 + !sendViewModel.isBatchSending) {
341 WidgetsBinding.instance.addPostFrameCallback((_) {
342 showPopUp<void>(
343 context: context,
lib/src/screens/yat/circle_clipper.dart deleted
-15
@@ -1,15 +0,0 @@
1 -import 'package:flutter/material.dart';
2 -
3 -class CircleClipper extends CustomClipper<Path> {
4 - CircleClipper(this.center, this.radius);
5 -
6 - final Offset center;
7 - final double radius;
8 -
9 - @override
10 - Path getClip(Size size) =>
11 - Path()..addOval(Rect.fromCircle(radius: radius, center: center));
12 -
13 - @override
14 - bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
15 -}
\ No newline at end of file
lib/src/screens/yat/yat_alert.dart deleted
-124
@@ -1,124 +0,0 @@
1 -import 'package:cake_wallet/src/screens/yat/widgets/yat_bar.dart';
2 -import 'package:cake_wallet/src/widgets/primary_button.dart';
3 -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
4 -import 'package:cake_wallet/store/yat/yat_store.dart';
5 -import 'package:flutter/cupertino.dart';
6 -import 'package:flutter/material.dart';
7 -import 'package:cake_wallet/palette.dart';
8 -import 'package:url_launcher/url_launcher.dart';
9 -import 'package:cake_wallet/generated/i18n.dart';
10 -import 'package:lottie/lottie.dart';
11 -
12 -class YatAlert extends StatelessWidget {
13 - YatAlert(this.yatStore);
14 -
15 - final YatStore yatStore;
16 - static const aspectRatioImage = 1.133;
17 - final animation = Lottie.asset('assets/animation/anim1.json');
18 -
19 - @override
20 - Widget build(BuildContext context) {
21 - final screenHeight = MediaQuery.of(context).size.height;
22 - final screenWidth = MediaQuery.of(context).size.width;
23 -
24 - return Container(
25 - height: screenHeight,
26 - width: screenWidth,
27 - color: Colors.white,
28 - child: ScrollableWithBottomSection(
29 - contentPadding: EdgeInsets.only(top: 40, bottom: 40),
30 - content: Column(
31 - children: [
32 - Container(
33 - height: 45,
34 - padding: EdgeInsets.only(left: 24, right: 24),
35 - child: YatBar(onClose: () => Navigator.of(context).pop())
36 - ),
37 - animation,
38 - Container(
39 - padding: EdgeInsets.only(left: 30, right: 30),
40 - child: Column(
41 - children: [
42 - Text(
43 - S.of(context).yat_alert_title,
44 - textAlign: TextAlign.center,
45 - style: TextStyle(
46 - fontSize: 24,
47 - fontWeight: FontWeight.bold,
48 - fontFamily: 'Lato',
49 - color: Colors.black,
50 - decoration: TextDecoration.none,
51 - )
52 - ),
53 - Padding(
54 - padding: EdgeInsets.only(top: 20),
55 - child: Text(
56 - S.of(context).yat_alert_content,
57 - textAlign: TextAlign.center,
58 - style: TextStyle(
59 - fontSize: 16,
60 - fontWeight: FontWeight.normal,
61 - fontFamily: 'Lato',
62 - color: Colors.black,
63 - decoration: TextDecoration.none,
64 - )
65 - )
66 - )
67 - ]
68 - )
69 - )
70 - ]
71 - ),
72 - bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 40),
73 - bottomSection: Column(
74 - crossAxisAlignment: CrossAxisAlignment.center,
75 - children: [
76 - PrimaryIconButton(
77 - text: S.of(context).get_your_yat,
78 - textColor: Colors.white,
79 - color: Palette.protectiveBlue,
80 - borderColor: Palette.protectiveBlue,
81 - iconColor: Colors.white,
82 - iconBackgroundColor: Colors.transparent,
83 - iconData: CupertinoIcons
84 - .arrow_up_right_square,
85 - mainAxisAlignment: MainAxisAlignment.end,
86 - onPressed: () {
87 - var createNewYatUrl = YatLink.startFlowUrl;
88 - final createNewYatUrlParameters =
89 - yatStore.defineQueryParameters();
90 -
91 - if (createNewYatUrlParameters.isNotEmpty) {
92 - createNewYatUrl += '?sub1=' + createNewYatUrlParameters;
93 - }
94 -
95 - launch(createNewYatUrl, forceSafariVC: false);
96 - }),
97 - Padding(
98 - padding: EdgeInsets.only(top: 24),
99 - child: PrimaryIconButton(
100 - text: S.of(context).connect_an_existing_yat,
101 - textColor: Colors.black,
102 - color: Palette.blueAlice,
103 - borderColor: Palette.blueAlice,
104 - iconColor: Colors.black,
105 - iconBackgroundColor: Colors.transparent,
106 - iconData: CupertinoIcons
107 - .arrow_up_right_square,
108 - mainAxisAlignment: MainAxisAlignment.end,
109 - onPressed: () {
110 - String url = YatLink.baseUrl + YatLink.signInSuffix;
111 - final parameters =
112 - yatStore.defineQueryParameters();
113 - if (parameters.isNotEmpty) {
114 - url += YatLink.queryParameter + parameters;
115 - }
116 - launch(url, forceSafariVC: false);
117 - })
118 - )
119 - ]
120 - ),
121 - )
122 - );
123 - }
124 -}
\ No newline at end of file
lib/src/screens/yat/yat_sending.dart deleted
-141
@@ -1,141 +0,0 @@
1 -import 'package:flutter/cupertino.dart';
2 -import 'package:flutter/material.dart';
3 -import 'package:flutter_mobx/flutter_mobx.dart';
4 -import 'package:mobx/mobx.dart';
5 -import 'package:cake_wallet/src/screens/yat/widgets/yat_close_button.dart';
6 -import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
7 -import 'package:cake_wallet/src/screens/yat/circle_clipper.dart';
8 -import 'package:cake_wallet/src/screens/base_page.dart';
9 -import 'package:cake_wallet/generated/i18n.dart';
10 -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
11 -import 'package:cake_wallet/utils/show_pop_up.dart';
12 -import 'package:cake_wallet/src/widgets/primary_button.dart';
13 -import 'package:cake_wallet/store/yat/yat_store.dart';
14 -import 'package:cake_wallet/core/execution_state.dart';
15 -import 'package:cake_wallet/view_model/send/send_view_model.dart';
16 -
17 -class YatSending extends BasePage {
18 - YatSending(this.sendViewModel);
19 -
20 - static Route createRoute(SendViewModel sendViewModel) {
21 - return PageRouteBuilder<void>(
22 - transitionDuration: Duration(seconds: 1),
23 - reverseTransitionDuration: Duration(seconds: 1),
24 - opaque: false,
25 - barrierDismissible: false,
26 - pageBuilder: (context, animation, secondaryAnimation) => YatSending(sendViewModel),
27 - transitionsBuilder: (context, animation, secondaryAnimation, child) {
28 - final screenSize = MediaQuery.of(context).size;
29 - final center = Offset(screenSize.width / 2, screenSize.height / 2);
30 - final endRadius = screenSize.height * 1.2;
31 - final tween = Tween(begin: 0.0, end: endRadius);
32 -
33 - return ClipPath(
34 - clipper: CircleClipper(center, animation.drive(tween).value),
35 - child: child,
36 - );
37 - },
38 - );
39 - }
40 -
41 - final SendViewModel sendViewModel;
42 -
43 - @override
44 - Color get titleColor => Colors.white;
45 -
46 - @override
47 - bool get resizeToAvoidBottomInset => false;
48 -
49 - @override
50 - bool get extendBodyBehindAppBar => true;
51 -
52 - @override
53 - AppBarStyle get appBarStyle => AppBarStyle.transparent;
54 -
55 - @override
56 - Widget trailing(context) =>
57 - YatCloseButton(onClose: () => Navigator.of(context).pop());
58 -
59 - @override
60 - Widget leading(BuildContext context) => Container();
61 -
62 - @override
63 - Widget body(BuildContext context) {
64 - final screenWidth = MediaQuery.of(context).size.width;
65 - return Container(
66 - color: Colors.black,
67 - child: Stack(
68 - children: [
69 - //Center(
70 - // child:FutureBuilder<String>(
71 - // future: visualisationForEmojiId(sendViewModel.outputs.first.address),
72 - // builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
73 - // switch (snapshot.connectionState) {
74 - // case ConnectionState.done:
75 - // if (snapshot.hasError || snapshot.data.isEmpty) {
76 - // return Image.asset('assets/images/yat_logo.png', width: screenWidth, color: Colors.white);
77 - // }
78 -
79 - // return Image.network(
80 - // snapshot.data,
81 - // scale: 0.7,
82 - // loadingBuilder: (Object z, Widget child, ImageChunkEvent loading)
83 - // => loading != null
84 - // ? CupertinoActivityIndicator(animating: true)
85 - // : child);
86 - // default:
87 - // return Image.asset('assets/images/yat_logo.png', width: screenWidth, color: Colors.white);
88 - // }
89 - // }),
90 - // ),
91 - Positioned(
92 - bottom: 20,
93 - child: Container(
94 - width: screenWidth,
95 - padding: EdgeInsets.fromLTRB(20, 0, 20, 10),
96 - child: Column(children: [
97 - Text(
98 - 'You are sending ${sendViewModel.outputs.first.cryptoAmount} ${sendViewModel.currency.title} to ${sendViewModel.outputs.first.address}'.toUpperCase(),
99 - style: TextStyle(
100 - fontSize: 28,
101 - decoration: TextDecoration.none,
102 - color: Theme.of(context).accentTextTheme.display3.backgroundColor),
103 - textAlign: TextAlign.center),
104 - Container(height: 30),
105 - LoadingPrimaryButton(
106 - onPressed: () {
107 - sendViewModel.commitTransaction();
108 - showPopUp<void>(
109 - context: context,
110 - builder: (BuildContext popContext) {
111 - return Observer(builder: (_) {
112 - final state = sendViewModel.state;
113 -
114 - if (state is FailureState) {
115 - Navigator.of(context).pop();
116 - }
117 -
118 - if (state is TransactionCommitted) {
119 - return AlertWithOneAction(
120 - alertTitle: '',
121 - alertContent: S.of(popContext).send_success(
122 - sendViewModel.currency
123 - .toString()),
124 - buttonText: S.of(popContext).ok,
125 - buttonAction: () {
126 - Navigator.of(popContext).pop();
127 - Navigator.of(context).pop();
128 - });
129 - }
130 -
131 - return Offstage();
132 - });
133 - });
134 - },
135 - text: S.of(context).confirm_sending,
136 - color: Theme.of(context).accentTextTheme.body2.color,
137 - textColor: Colors.white,
138 - isLoading: sendViewModel.state is IsExecutingState ||
139 - sendViewModel.state is TransactionCommitting)])))]));
140 - }
141 -}
\ No newline at end of file
lib/view_model/send/output.dart
+2 -1
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/di.dart';
2 import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
3 import 'package:cake_wallet/entities/parse_address_from_domain.dart';
4 import 'package:cake_wallet/entities/parsed_address.dart';
@@ -216,7 +217,7 @@ abstract class OutputBase with Store {
217 Future<void> fetchParsedAddress(BuildContext context) async {
218 final domain = address;
219 final ticker = _wallet.currency.title.toLowerCase();
219 - parsedAddress = await parseAddressFromDomain(domain, ticker);
220 + parsedAddress = await getIt.get<AddressResolver>().resolve(domain, ticker);
221 extractedAddress = await extractAddressFromParsed(context, parsedAddress);
222 note = parsedAddress.description;
223 }
lib/view_model/settings/settings_view_model.dart
-1
@@ -1,4 +1,3 @@
1 -import 'package:cake_wallet/src/screens/yat/yat_alert.dart';
1 import 'package:cake_wallet/store/yat/yat_store.dart';
2 import 'package:cake_wallet/utils/show_pop_up.dart';
3 import 'package:cake_wallet/view_model/settings/link_list_item.dart';