CAKE-306 | applied buy_webview_page.dart to the app; fixed order_details_view_model.dart and order_row.dart; applied localization to the pre_order_page.dart; deleted unused files

OleksandrSobol committed Apr 13, 2021 at 21:40 UTC 19ffffa6ccd9462cc2722b841a8c236971801448
31 files changed +310 -398
lib/buy/buy_provider.dart
+1
@@ -12,6 +12,7 @@ abstract class BuyProvider {
12
13 String get title;
14 BuyProviderDescription get description;
15 + String get trackUrl;
16
17 WalletType get walletType => wallet.type;
18 String get walletAddress => wallet.address;
lib/buy/get_buy_provider_icon.dart new
+23
@@ -0,0 +1,23 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/buy/buy_provider_description.dart';
3 +
4 +Image getBuyProviderIcon(BuyProviderDescription providerDescription) {
5 + final _wyreIcon =
6 + Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
7 + final _moonPayIcon =
8 + Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
9 +
10 + if (providerDescription != null) {
11 + switch (providerDescription) {
12 + case BuyProviderDescription.wyre:
13 + return _wyreIcon;
14 + case BuyProviderDescription.moonPay:
15 + //return _moonPayIcon;
16 + return null;
17 + default:
18 + return null;
19 + }
20 + } else {
21 + return null;
22 + }
23 +}
\ No newline at end of file
lib/buy/moonpay/moonpay_buy_provider.dart
+5
@@ -34,6 +34,11 @@ class MoonPayBuyProvider extends BuyProvider {
34 String get currencyCode =>
35 walletTypeToCryptoCurrency(walletType).title.toLowerCase();
36
37 + @override
38 + String get trackUrl => isTestEnvironment
39 + ? ''
40 + : ''; // FIXME
41 +
42 String baseApiUrl;
43
44 @override
lib/buy/wyre/wyre_buy_provider.dart
+5 -4
@@ -16,9 +16,6 @@ class WyreBuyProvider extends BuyProvider {
16 baseApiUrl = isTestEnvironment
17 ? _baseTestApiUrl
18 : _baseProductApiUrl;
19 - trackUrl = isTestEnvironment
20 - ? _trackTestUrl
21 - : _trackProductUrl;
19 }
20
21 static const _baseTestApiUrl = 'https://api.testwyre.com';
@@ -40,8 +37,12 @@ class WyreBuyProvider extends BuyProvider {
37 @override
38 BuyProviderDescription get description => BuyProviderDescription.wyre;
39
40 + @override
41 + String get trackUrl => isTestEnvironment
42 + ? _trackTestUrl
43 + : _trackProductUrl;
44 +
45 String baseApiUrl;
44 - String trackUrl;
46
47 @override
48 Future<String> requestUrl(String amount, String sourceCurrency) async {
lib/di.dart
+13 -22
@@ -7,7 +7,6 @@ import 'package:cake_wallet/entities/load_current_wallet.dart';
7 import 'package:cake_wallet/buy/order.dart';
8 import 'package:cake_wallet/entities/transaction_description.dart';
9 import 'package:cake_wallet/entities/transaction_info.dart';
10 -import 'package:cake_wallet/entities/wyre_service.dart';
10 import 'package:cake_wallet/monero/monero_wallet_service.dart';
11 import 'package:cake_wallet/entities/contact.dart';
12 import 'package:cake_wallet/entities/node.dart';
@@ -15,6 +14,7 @@ import 'package:cake_wallet/exchange/trade.dart';
14 import 'package:cake_wallet/reactions/on_authentication_state_change.dart';
15 import 'package:cake_wallet/src/screens/backup/backup_page.dart';
16 import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
17 +import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
18 import 'package:cake_wallet/src/screens/buy/pre_order_page.dart';
19 import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
20 import 'package:cake_wallet/src/screens/contact/contact_page.dart';
@@ -42,7 +42,6 @@ import 'package:cake_wallet/src/screens/transaction_details/transaction_details_
42 import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
43 import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
44 import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart';
45 -import 'package:cake_wallet/src/screens/wyre/wyre_page.dart';
45 import 'package:cake_wallet/store/dashboard/orders_store.dart';
46 import 'package:cake_wallet/store/node_list_store.dart';
47 import 'package:cake_wallet/store/secret_store.dart';
@@ -91,7 +90,6 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
90 import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
91 import 'package:cake_wallet/view_model/wallet_seed_view_model.dart';
92 import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
94 -import 'package:cake_wallet/view_model/wyre_view_model.dart';
93 import 'package:flutter/widgets.dart';
94 import 'package:get_it/get_it.dart';
95 import 'package:hive/hive.dart';
@@ -241,8 +239,7 @@ Future setup(
239 transactionFilterStore: getIt.get<TransactionFilterStore>(),
240 settingsStore: settingsStore,
241 ordersSource: _ordersSource,
244 - ordersStore: getIt.get<OrdersStore>(),
245 - wyreViewModel: getIt.get<WyreViewModel>()));
242 + ordersStore: getIt.get<OrdersStore>()));
243
244 getIt.registerFactory<AuthService>(() => AuthService(
245 secureStorage: getIt.get<FlutterSecureStorage>(),
@@ -534,20 +531,6 @@ Future setup(
531 getIt.registerFactoryParam<TradeDetailsPage, Trade, void>((Trade trade, _) =>
532 TradeDetailsPage(getIt.get<TradeDetailsViewModel>(param1: trade)));
533
537 - getIt.registerFactory(() {
538 - final wallet = getIt.get<AppStore>().wallet;
539 - return WyreService(wallet: wallet);
540 - });
541 -
542 - getIt.registerFactory(() {
543 - return WyreViewModel(ordersSource, getIt.get<OrdersStore>(),
544 - wyreService: getIt.get<WyreService>());
545 - });
546 -
547 - getIt.registerFactoryParam<WyrePage, String, void>((String url, _) =>
548 - WyrePage(getIt.get<WyreViewModel>(),
549 - ordersStore: getIt.get<OrdersStore>(), url: url));
550 -
534 getIt.registerFactory(() => BuyAmountViewModel());
535
536 getIt.registerFactory(() {
@@ -561,10 +544,18 @@ Future setup(
544 return PreOrderPage(buyViewModel: getIt.get<BuyViewModel>());
545 });
546
547 + getIt.registerFactoryParam<BuyWebViewPage, String, void>((String url, _) =>
548 + BuyWebViewPage(getIt.get<BuyViewModel>(),
549 + ordersStore: getIt.get<OrdersStore>(), url: url));
550 +
551 getIt.registerFactoryParam<OrderDetailsViewModel, Order, void>(
565 - (order, _) => OrderDetailsViewModel(
566 - wyreViewModel: getIt.get<WyreViewModel>(),
567 - orderForDetails: order));
552 + (order, _) {
553 + final wallet = getIt.get<AppStore>().wallet;
554 +
555 + return OrderDetailsViewModel(
556 + wallet: wallet,
557 + orderForDetails: order);
558 + });
559
560 getIt.registerFactoryParam<OrderDetailsPage, Order, void>((Order order, _) =>
561 OrderDetailsPage(getIt.get<OrderDetailsViewModel>(param1: order)));
lib/entities/wyre_exception.dart deleted
-8
@@ -1,8 +0,0 @@
1 -class WyreException implements Exception {
2 - WyreException(this.description);
3 -
4 - String description;
5 -
6 - @override
7 - String toString() => description;
8 -}
\ No newline at end of file
lib/entities/wyre_service.dart deleted
-151
@@ -1,151 +0,0 @@
1 -import 'dart:convert';
2 -import 'package:cake_wallet/core/wallet_base.dart';
3 -import 'package:cake_wallet/entities/wyre_exception.dart';
4 -import 'package:cake_wallet/exchange/trade_state.dart';
5 -import 'package:flutter/foundation.dart';
6 -import 'package:http/http.dart';
7 -import 'package:cake_wallet/.secrets.g.dart' as secrets;
8 -import 'package:cake_wallet/buy/order.dart';
9 -import 'package:cake_wallet/entities/wallet_type.dart';
10 -
11 -class WyreService {
12 - WyreService({
13 - @required this.wallet,
14 - this.isTestEnvironment = false}) {
15 - baseApiUrl = isTestEnvironment
16 - ? _baseTestApiUrl
17 - : _baseProductApiUrl;
18 - trackUrl = isTestEnvironment
19 - ? _trackTestUrl
20 - : _trackProductUrl;
21 - }
22 -
23 - static const _baseTestApiUrl = 'https://api.testwyre.com';
24 - static const _baseProductApiUrl = 'https://api.sendwyre.com';
25 - static const _trackTestUrl = 'https://dash.testwyre.com/track/';
26 - static const _trackProductUrl = 'https://dash.sendwyre.com/track/';
27 - static const _ordersSuffix = '/v3/orders';
28 - static const _reserveSuffix = '/reserve';
29 - static const _quoteSuffix = '/quote/partner';
30 - static const _timeStampSuffix = '?timestamp=';
31 - static const _transferSuffix = '/v2/transfer/';
32 - static const _trackSuffix = '/track';
33 -
34 - final bool isTestEnvironment;
35 - final WalletBase wallet;
36 -
37 - WalletType get walletType => wallet.type;
38 - String get walletAddress => wallet.address;
39 - String get walletId => wallet.id;
40 -
41 - String baseApiUrl;
42 - String trackUrl;
43 -
44 - Future<String> getWyreUrl() async {
45 - final timestamp = DateTime.now().millisecondsSinceEpoch.toString();
46 - final url = baseApiUrl + _ordersSuffix + _reserveSuffix +
47 - _timeStampSuffix + timestamp;
48 - final secretKey = secrets.wyreSecretKey;
49 - final accountId = secrets.wyreAccountId;
50 - final body = {
51 - 'amount': '1',
52 - 'sourceCurrency': 'USD',
53 - 'destCurrency': walletTypeToCryptoCurrency(walletType).title,
54 - 'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
55 - 'referrerAccountId': accountId,
56 - 'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest']
57 - };
58 -
59 - final response = await post(url,
60 - headers: {
61 - 'Authorization': 'Bearer $secretKey',
62 - 'Content-Type': 'application/json',
63 - 'cache-control': 'no-cache'
64 - },
65 - body: json.encode(body));
66 -
67 - if (response.statusCode != 200) {
68 - throw WyreException('Url $url is not found!');
69 - }
70 -
71 - final responseJSON = json.decode(response.body) as Map<String, dynamic>;
72 - final urlFromResponse = responseJSON['url'] as String;
73 - return urlFromResponse;
74 - }
75 -
76 - Future<Order> findOrderById(String id) async {
77 - final orderUrl = baseApiUrl + _ordersSuffix + '/$id';
78 - final orderResponse = await get(orderUrl);
79 -
80 - if (orderResponse.statusCode != 200) {
81 - throw WyreException('Order $id is not found!');
82 - }
83 -
84 - final orderResponseJSON =
85 - json.decode(orderResponse.body) as Map<String, dynamic>;
86 - final transferId = orderResponseJSON['transferId'] as String;
87 - final from = orderResponseJSON['sourceCurrency'] as String;
88 - final to = orderResponseJSON['destCurrency'] as String;
89 - final status = orderResponseJSON['status'] as String;
90 - final state = TradeState.deserialize(raw: status.toLowerCase());
91 - final createdAtRaw = orderResponseJSON['createdAt'] as int;
92 - final createdAt =
93 - DateTime.fromMillisecondsSinceEpoch(createdAtRaw).toLocal();
94 -
95 - final transferUrl =
96 - baseApiUrl + _transferSuffix + transferId + _trackSuffix;
97 - final transferResponse = await get(transferUrl);
98 -
99 - if (transferResponse.statusCode != 200) {
100 - throw WyreException('Transfer $transferId is not found!');
101 - }
102 -
103 - final transferResponseJSON =
104 - json.decode(transferResponse.body) as Map<String, dynamic>;
105 - final amount = transferResponseJSON['destAmount'] as double;
106 -
107 - return Order(
108 - id: id,
109 - transferId: transferId,
110 - from: from,
111 - to: to,
112 - state: state,
113 - createdAt: createdAt,
114 - amount: amount.toString(),
115 - receiveAddress: walletAddress,
116 - walletId: walletId
117 - );
118 - }
119 -
120 - Future<double> getAmount() async {
121 - final quoteUrl = baseApiUrl + _ordersSuffix + _quoteSuffix;
122 -
123 - final secretKey = secrets.wyreSecretKey;
124 - final accountId = secrets.wyreAccountId;
125 - final body = {
126 - 'amount': '1',
127 - 'sourceCurrency': 'USD',
128 - 'destCurrency': walletTypeToCryptoCurrency(walletType).title,
129 - 'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress,
130 - 'accountId': accountId,
131 - 'country': 'US'
132 - };
133 -
134 - final response = await post(quoteUrl,
135 - headers: {
136 - 'Authorization': 'Bearer $secretKey',
137 - 'Content-Type': 'application/json',
138 - 'cache-control': 'no-cache'
139 - },
140 - body: json.encode(body));
141 -
142 - if (response.statusCode != 200) {
143 - throw WyreException('Quote is not found! ');
144 - }
145 -
146 - final responseJSON = json.decode(response.body) as Map<String, dynamic>;
147 - final amount = responseJSON['destAmount'] as double;
148 -
149 - return amount;
150 - }
151 -}
\ No newline at end of file
lib/router.dart
+3 -3
@@ -3,6 +3,7 @@ import 'package:cake_wallet/buy/order.dart';
3 import 'package:cake_wallet/entities/transaction_description.dart';
4 import 'package:cake_wallet/src/screens/backup/backup_page.dart';
5 import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
6 +import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
7 import 'package:cake_wallet/src/screens/buy/pre_order_page.dart';
8 import 'package:cake_wallet/src/screens/order_details/order_details_page.dart';
9 import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
@@ -10,7 +11,6 @@ import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart';
11 import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
12 import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
13 import 'package:cake_wallet/src/screens/support/support_page.dart';
13 -import 'package:cake_wallet/src/screens/wyre/wyre_page.dart';
14 import 'package:cake_wallet/store/settings_store.dart';
15 import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
16 import 'package:flutter/cupertino.dart';
@@ -303,10 +303,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
303 builder: (_) =>
304 getIt.get<PreOrderPage>());
305
306 - case Routes.wyre:
306 + case Routes.buyWebView:
307 return MaterialPageRoute<void>(
308 builder: (_) =>
309 - getIt.get<WyrePage>(param1: settings.arguments as String));
309 + getIt.get<BuyWebViewPage>(param1: settings.arguments as String));
310
311 case Routes.restoreWalletFromSeedDetails:
312 final args = settings.arguments as List;
lib/routes.dart
+1 -1
@@ -53,6 +53,6 @@ class Routes {
53 static const restoreFromBackup = '/restore_from_backup';
54 static const support = '/support';
55 static const orderDetails = '/order_details';
56 - static const wyre = '/wyre';
56 static const preOrder = '/pre_order';
57 + static const buyWebView = '/buy_web_view';
58 }
\ No newline at end of file
lib/src/screens/buy/buy_webview_page.dart new
+108
@@ -0,0 +1,108 @@
1 +import 'dart:async';
2 +import 'dart:io';
3 +import 'package:cake_wallet/buy/buy_provider.dart';
4 +import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
5 +import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +import 'package:cake_wallet/palette.dart';
8 +import 'package:cake_wallet/src/screens/base_page.dart';
9 +import 'package:cake_wallet/store/dashboard/orders_store.dart';
10 +import 'package:cake_wallet/view_model/buy/buy_view_model.dart';
11 +import 'package:flutter/material.dart';
12 +import 'package:webview_flutter/webview_flutter.dart';
13 +
14 +class BuyWebViewPage extends BasePage {
15 + BuyWebViewPage(this.buyViewModel,
16 + {@required this.ordersStore, @required this.url});
17 +
18 + final OrdersStore ordersStore;
19 + final String url;
20 + final BuyViewModel buyViewModel;
21 +
22 + @override
23 + String get title => S.current.buy;
24 +
25 + @override
26 + Color get backgroundDarkColor => Colors.white;
27 +
28 + @override
29 + Color get titleColor => Palette.darkBlueCraiola;
30 +
31 + @override
32 + Widget body(BuildContext context) =>
33 + BuyWebViewPageBody(buyViewModel, ordersStore: ordersStore, url: url);
34 +}
35 +
36 +class BuyWebViewPageBody extends StatefulWidget {
37 + BuyWebViewPageBody(this.buyViewModel, {this.ordersStore, this.url});
38 +
39 + final OrdersStore ordersStore;
40 + final String url;
41 + final BuyViewModel buyViewModel;
42 +
43 + @override
44 + BuyWebViewPageBodyState createState() => BuyWebViewPageBodyState();
45 +}
46 +
47 +class BuyWebViewPageBodyState extends State<BuyWebViewPageBody> {
48 + String orderId;
49 + WebViewController _webViewController;
50 + GlobalKey _webViewkey;
51 + Timer _timer;
52 + bool _isSaving;
53 + BuyProvider _provider;
54 +
55 + @override
56 + void initState() {
57 + super.initState();
58 + _webViewkey = GlobalKey();
59 + _isSaving = false;
60 + widget.ordersStore.orderId = '';
61 + _provider = widget.buyViewModel.selectedProvider;
62 +
63 + if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
64 +
65 + if (_provider is WyreBuyProvider) {
66 + _timer?.cancel();
67 + _timer = Timer.periodic(Duration(seconds: 1), (timer) async {
68 +
69 + try {
70 + if (_webViewController == null || _isSaving) {
71 + return;
72 + }
73 +
74 + final url = await _webViewController.currentUrl();
75 +
76 + if (url.contains('completed')) {
77 + final urlParts = url.split('/');
78 + orderId = urlParts.last;
79 + widget.ordersStore.orderId = orderId;
80 +
81 + if (orderId.isNotEmpty) {
82 + _isSaving = true;
83 + await widget.buyViewModel.saveOrder(orderId);
84 + timer.cancel();
85 + }
86 + }
87 + } catch (e) {
88 + _isSaving = false;
89 + print(e);
90 + }
91 + });
92 + }
93 +
94 + if (_provider is MoonPayBuyProvider) {
95 + // FIXME: fetch orderId
96 + }
97 + }
98 +
99 + @override
100 + Widget build(BuildContext context) {
101 + return WebView(
102 + key: _webViewkey,
103 + initialUrl: widget.url,
104 + javascriptMode: JavascriptMode.unrestricted,
105 + onWebViewCreated: (WebViewController controller) =>
106 + setState(() => _webViewController = controller));
107 + }
108 +}
lib/src/screens/buy/pre_order_page.dart
+23 -9
@@ -14,6 +14,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
14 import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
15 import 'package:cake_wallet/generated/i18n.dart';
16 import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
17 +import 'package:mobx/mobx.dart';
18
19 class PreOrderPage extends BasePage {
20 PreOrderPage({@required this.buyViewModel})
@@ -31,14 +32,22 @@ class PreOrderPage extends BasePage {
32 buyViewModel.selectedProvider = null;
33 }
34 });
35 +
36 + reaction((_) => buyViewModel.buyAmountViewModel.amount, (String amount) {
37 + if (_amountController.text != amount) {
38 + _amountController.text = amount;
39 + }
40 + });
41 }
42
43 + static const _amountPattern = '^([0-9]+([.\,][0-9]{0,2})?|[.\,][0-9]{1,2})\$';
44 +
45 final BuyViewModel buyViewModel;
46 final FocusNode _amountFocus;
47 final TextEditingController _amountController;
48
49 @override
41 - String get title => 'Buy Bitcoin';
50 + String get title => S.current.buy_bitcoin;
51
52 @override
53 Color get titleColor => Colors.white;
@@ -96,7 +105,7 @@ class PreOrderPage extends BasePage {
105 signed: false, decimal: true),
106 inputFormatters: [
107 FilteringTextInputFormatter
99 - .allow(RegExp('^([0-9]+([.\,][0-9]{0,2})?|[.\,][0-9]{1,2})\$'))
108 + .allow(RegExp(_amountPattern))
109 ],
110 prefixIcon: Padding(
111 padding: EdgeInsets.only(top: 2),
@@ -130,7 +139,7 @@ class PreOrderPage extends BasePage {
139 Padding(
140 padding: EdgeInsets.only(top: 38, bottom: 18),
141 child: Text(
133 - 'Buy with:',
142 + S.of(context).buy_with + ':',
143 textAlign: TextAlign.center,
144 style: TextStyle(
145 color: Theme.of(context).primaryTextTheme.title.color,
@@ -185,16 +194,21 @@ class PreOrderPage extends BasePage {
194 return LoadingPrimaryButton(
195 onPressed: buyViewModel.isRunning
196 ? null
188 - : () {
197 + : () async {
198 buyViewModel.isRunning = true;
190 -
191 - // FIXME: Start WebView
192 -
199 + final url =
200 + await buyViewModel.fetchUrl();
201 + if (url.isNotEmpty) {
202 + await Navigator.of(context)
203 + .pushNamed(Routes.buyWebView, arguments: url);
204 + buyViewModel.reset();
205 + }
206 buyViewModel.isRunning = false;
207 },
208 text: buyViewModel.selectedProvider == null
196 - ? 'Buy'
197 - : 'Buy with ${buyViewModel.selectedProvider
209 + ? S.of(context).buy
210 + : S.of(context).buy_with +
211 + ' ${buyViewModel.selectedProvider
212 .description.title}',
213 color: Theme.of(context).accentTextTheme.body2.color,
214 textColor: Colors.white,
lib/src/screens/buy/widgets/buy_list_item.dart
+2 -19
@@ -1,5 +1,5 @@
1 -import 'package:cake_wallet/buy/buy_provider_description.dart';
1 import 'package:cake_wallet/buy/buy_provider.dart';
2 +import 'package:cake_wallet/buy/get_buy_provider_icon.dart';
3 import 'package:cake_wallet/entities/crypto_currency.dart';
4 import 'package:cake_wallet/entities/fiat_currency.dart';
5 import 'package:cake_wallet/palette.dart';
@@ -16,11 +16,6 @@ class BuyListItem extends StatelessWidget {
16 @required this.onTap
17 });
18
19 - final _wyreIcon =
20 - Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
21 - final _mooonPayIcon =
22 - Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
23 -
19 final BuyProvider selectedProvider;
20 final BuyProvider provider;
21 final double sourceAmount;
@@ -31,7 +26,7 @@ class BuyListItem extends StatelessWidget {
26
27 @override
28 Widget build(BuildContext context) {
34 - final providerIcon = _getProviderIcon(provider.description);
29 + final providerIcon = getBuyProviderIcon(provider.description);
30
31 final backgroundColor = selectedProvider != null
32 ? selectedProvider.description == provider.description
@@ -116,16 +111,4 @@ class BuyListItem extends StatelessWidget {
111 )
112 );
113 }
119 -
120 - Image _getProviderIcon(BuyProviderDescription providerDescription) {
121 - switch (providerDescription) {
122 - case BuyProviderDescription.wyre:
123 - return _wyreIcon;
124 - case BuyProviderDescription.moonPay:
125 - //return _mooonPayIcon;
126 - return null;
127 - default:
128 - return null;
129 - }
130 - }
114 }
\ No newline at end of file
lib/src/screens/dashboard/widgets/order_row.dart
+7 -3
@@ -1,22 +1,26 @@
1 +import 'package:cake_wallet/buy/buy_provider_description.dart';
2 +import 'package:cake_wallet/buy/get_buy_provider_icon.dart';
3 import 'package:flutter/material.dart';
4
5 class OrderRow extends StatelessWidget {
6 OrderRow({
7 @required this.onTap,
8 + @required this.provider,
9 this.from,
10 this.to,
11 this.createdAtFormattedDate,
12 this.formattedAmount});
13 final VoidCallback onTap;
14 + final BuyProviderDescription provider;
15 final String from;
16 final String to;
17 final String createdAtFormattedDate;
18 final String formattedAmount;
15 - final wyreImage =
16 - Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
19
20 @override
21 Widget build(BuildContext context) {
22 + final providerIcon = getBuyProviderIcon(provider);
23 +
24 return InkWell(
25 onTap: onTap,
26 child: Container(
@@ -26,7 +30,7 @@ class OrderRow extends StatelessWidget {
30 mainAxisSize: MainAxisSize.max,
31 crossAxisAlignment: CrossAxisAlignment.center,
32 children: [
29 - wyreImage,
33 + providerIcon ?? Offstage(),
34 SizedBox(width: 12),
35 Expanded(
36 child: Column(
lib/src/screens/dashboard/widgets/transactions_page.dart
+1
@@ -84,6 +84,7 @@ class TransactionsPage extends StatelessWidget {
84 onTap: () => Navigator.of(context).pushNamed(
85 Routes.orderDetails,
86 arguments: order),
87 + provider: order.provider,
88 from: order.from,
89 to: order.to,
90 createdAtFormattedDate:
lib/src/screens/wyre/wyre_page.dart deleted
-97
@@ -1,97 +0,0 @@
1 -import 'dart:async';
2 -import 'dart:io';
3 -import 'package:cake_wallet/generated/i18n.dart';
4 -import 'package:cake_wallet/palette.dart';
5 -import 'package:cake_wallet/src/screens/base_page.dart';
6 -import 'package:cake_wallet/store/dashboard/orders_store.dart';
7 -import 'package:cake_wallet/view_model/wyre_view_model.dart';
8 -import 'package:flutter/material.dart';
9 -import 'package:webview_flutter/webview_flutter.dart';
10 -
11 -class WyrePage extends BasePage {
12 - WyrePage(this.wyreViewModel,
13 - {@required this.ordersStore, @required this.url});
14 -
15 - final OrdersStore ordersStore;
16 - final String url;
17 - final WyreViewModel wyreViewModel;
18 -
19 - @override
20 - String get title => S.current.buy;
21 -
22 - @override
23 - Color get backgroundDarkColor => Colors.white;
24 -
25 - @override
26 - Color get titleColor => Palette.darkBlueCraiola;
27 -
28 - @override
29 - Widget body(BuildContext context) =>
30 - WyrePageBody(wyreViewModel, ordersStore: ordersStore, url: url);
31 -}
32 -
33 -class WyrePageBody extends StatefulWidget {
34 - WyrePageBody(this.wyreViewModel, {this.ordersStore, this.url});
35 -
36 - final OrdersStore ordersStore;
37 - final String url;
38 - final WyreViewModel wyreViewModel;
39 -
40 - @override
41 - WyrePageBodyState createState() => WyrePageBodyState();
42 -}
43 -
44 -class WyrePageBodyState extends State<WyrePageBody> {
45 - String orderId;
46 - WebViewController _webViewController;
47 - GlobalKey _webViewkey;
48 - Timer _timer;
49 - bool _isSaving;
50 -
51 - @override
52 - void initState() {
53 - super.initState();
54 - _webViewkey = GlobalKey();
55 - _isSaving = false;
56 - widget.ordersStore.orderId = '';
57 -
58 - if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
59 -
60 - _timer?.cancel();
61 - _timer = Timer.periodic(Duration(seconds: 1), (timer) async {
62 -
63 - try {
64 - if (_webViewController == null || _isSaving) {
65 - return;
66 - }
67 -
68 - final url = await _webViewController.currentUrl();
69 -
70 - if (url.contains('completed')) {
71 - final urlParts = url.split('/');
72 - orderId = urlParts.last;
73 - widget.ordersStore.orderId = orderId;
74 -
75 - if (orderId.isNotEmpty) {
76 - _isSaving = true;
77 - await widget.wyreViewModel.saveOrder(orderId);
78 - timer.cancel();
79 - }
80 - }
81 - } catch (e) {
82 - _isSaving = false;
83 - print(e);
84 - }
85 - });
86 - }
87 -
88 - @override
89 - Widget build(BuildContext context) {
90 - return WebView(
91 - key: _webViewkey,
92 - initialUrl: widget.url,
93 - javascriptMode: JavascriptMode.unrestricted,
94 - onWebViewCreated: (WebViewController controller) =>
95 - setState(() => _webViewController = controller));
96 - }
97 -}
lib/view_model/buy/buy_view_model.dart
+11 -3
@@ -59,14 +59,17 @@ abstract class BuyViewModelBase with Store {
59
60 CryptoCurrency get cryptoCurrency => walletTypeToCryptoCurrency(type);
61
62 - Future createOrder() async {
62 + Future <String> fetchUrl() async {
63 + String _url = '';
64 +
65 try {
64 - final url = await selectedProvider
66 + _url = await selectedProvider
67 ?.requestUrl(doubleAmount?.toString(), fiatCurrency.title);
66 - // FIXME: Start WebView
68 } catch (e) {
69 print(e.toString());
70 }
71 +
72 + return _url;
73 }
74
75 Future<void> saveOrder(String orderId) async {
@@ -78,4 +81,9 @@ abstract class BuyViewModelBase with Store {
81 print(e.toString());
82 }
83 }
84 +
85 + void reset() {
86 + buyAmountViewModel.amount = '';
87 + selectedProvider = null;
88 + }
89 }
\ No newline at end of file
lib/view_model/dashboard/dashboard_view_model.dart
+1 -5
@@ -28,7 +28,6 @@ import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
28 import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
29 import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
30 import 'package:cake_wallet/view_model/dashboard/action_list_display_mode.dart';
31 -import 'package:cake_wallet/view_model/wyre_view_model.dart';
31 import 'package:crypto/crypto.dart';
32 import 'package:flutter/services.dart';
33 import 'package:hive/hive.dart';
@@ -59,8 +58,7 @@ abstract class DashboardViewModelBase with Store {
58 this.transactionFilterStore,
59 this.settingsStore,
60 this.ordersSource,
62 - this.ordersStore,
63 - this.wyreViewModel}) {
61 + this.ordersStore}) {
62 filterItems = {
63 S.current.transactions: [
64 FilterItem(
@@ -230,8 +228,6 @@ abstract class DashboardViewModelBase with Store {
228
229 TransactionFilterStore transactionFilterStore;
230
233 - WyreViewModel wyreViewModel;
234 -
231 Map<String, List<FilterItem>> filterItems;
232
233 bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
lib/view_model/order_details_view_model.dart
+58 -27
@@ -1,12 +1,16 @@
1 import 'dart:async';
2 +import 'package:cake_wallet/buy/buy_provider.dart';
3 +import 'package:cake_wallet/buy/buy_provider_description.dart';
4 import 'package:cake_wallet/buy/order.dart';
5 import 'package:cake_wallet/utils/date_formatter.dart';
4 -import 'package:cake_wallet/view_model/wyre_view_model.dart';
6 import 'package:mobx/mobx.dart';
7 import 'package:cake_wallet/generated/i18n.dart';
8 import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
9 import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart';
10 import 'package:url_launcher/url_launcher.dart';
11 +import 'package:cake_wallet/core/wallet_base.dart';
12 +import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
13 +import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart';
14
15 part 'order_details_view_model.g.dart';
16
@@ -14,16 +18,27 @@ class OrderDetailsViewModel = OrderDetailsViewModelBase
18 with _$OrderDetailsViewModel;
19
20 abstract class OrderDetailsViewModelBase with Store {
17 - OrderDetailsViewModelBase({this.wyreViewModel, Order orderForDetails}) {
21 + OrderDetailsViewModelBase({WalletBase wallet, Order orderForDetails}) {
22 order = orderForDetails;
23
24 + if (order.provider != null) {
25 + switch (order.provider) {
26 + case BuyProviderDescription.wyre:
27 + _provider = WyreBuyProvider(wallet: wallet);
28 + break;
29 + case BuyProviderDescription.moonPay:
30 + _provider = MoonPayBuyProvider(wallet: wallet);
31 + break;
32 + }
33 + }
34 +
35 items = ObservableList<StandartListItem>();
36
37 _updateItems();
38
39 _updateOrder();
40
26 - _timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateOrder());
41 + timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateOrder());
42 }
43
44 @observable
@@ -32,21 +47,20 @@ abstract class OrderDetailsViewModelBase with Store {
47 @observable
48 ObservableList<StandartListItem> items;
49
35 - WyreViewModel wyreViewModel;
50 + BuyProvider _provider;
51
37 - Timer _timer;
52 + Timer timer;
53
54 @action
55 Future<void> _updateOrder() async {
56 try {
42 - final updatedOrder =
43 - await wyreViewModel.wyreService.findOrderById(order.id);
44 -
45 - updatedOrder.receiveAddress = order.receiveAddress;
46 - updatedOrder.walletId = order.walletId;
47 - order = updatedOrder;
48 -
49 - _updateItems();
57 + if (_provider != null) {
58 + final updatedOrder = await _provider.findOrderById(order.id);
59 + updatedOrder.receiveAddress = order.receiveAddress;
60 + updatedOrder.walletId = order.walletId;
61 + order = updatedOrder;
62 + _updateItems();
63 + }
64 } catch (e) {
65 print(e.toString());
66 }
@@ -54,8 +68,6 @@ abstract class OrderDetailsViewModelBase with Store {
68
69 void _updateItems() {
70 final dateFormat = DateFormatter.withCurrentLocal();
57 - final buildURL =
58 - wyreViewModel.trackUrl + '${order.transferId}';
71
72 items?.clear();
73
@@ -68,18 +80,37 @@ abstract class OrderDetailsViewModelBase with Store {
80 value: order.state != null
81 ? order.state.toString()
82 : S.current.trade_details_fetching),
71 - TrackTradeListItem(
72 - title: 'Track',
73 - value: buildURL,
74 - onTap: () {
75 - launch(buildURL);
76 - }),
77 - StandartListItem(
78 - title: S.current.trade_details_created_at,
79 - value: dateFormat.format(order.createdAt).toString()),
80 - StandartListItem(
81 - title: S.current.trade_details_pair,
82 - value: '${order.from} → ${order.to}')
83 ]);
84 +
85 + if (order.provider != null) {
86 + items.add(
87 + StandartListItem(
88 + title: 'Buy provider',
89 + value: order.provider.title)
90 + );
91 + }
92 +
93 + if (_provider.trackUrl.isNotEmpty) {
94 + final buildURL = _provider.trackUrl + '${order.transferId}';
95 + items.add(
96 + TrackTradeListItem(
97 + title: 'Track',
98 + value: buildURL,
99 + onTap: () => launch(buildURL)
100 + )
101 + );
102 + }
103 +
104 + items.add(
105 + StandartListItem(
106 + title: S.current.trade_details_created_at,
107 + value: dateFormat.format(order.createdAt).toString())
108 + );
109 +
110 + items.add(
111 + StandartListItem(
112 + title: S.current.trade_details_pair,
113 + value: '${order.from} → ${order.to}')
114 + );
115 }
116 }
\ No newline at end of file
lib/view_model/wyre_view_model.dart deleted
-34
@@ -1,34 +0,0 @@
1 -import 'package:cake_wallet/entities/wyre_service.dart';
2 -import 'package:flutter/foundation.dart';
3 -import 'package:hive/hive.dart';
4 -import 'package:cake_wallet/buy/order.dart';
5 -import 'package:cake_wallet/store/dashboard/orders_store.dart';
6 -import 'package:mobx/mobx.dart';
7 -
8 -part 'wyre_view_model.g.dart';
9 -
10 -class WyreViewModel = WyreViewModelBase with _$WyreViewModel;
11 -
12 -abstract class WyreViewModelBase with Store {
13 - WyreViewModelBase(this.ordersSource, this.ordersStore,
14 - {@required this.wyreService});
15 -
16 - Future<String> get wyreUrl => wyreService.getWyreUrl();
17 -
18 - String get trackUrl => wyreService.trackUrl;
19 -
20 - final Box<Order> ordersSource;
21 - final OrdersStore ordersStore;
22 -
23 - final WyreService wyreService;
24 -
25 - Future<void> saveOrder(String orderId) async {
26 - try {
27 - final order = await wyreService.findOrderById(orderId);
28 - await ordersSource.add(order);
29 - ordersStore.setOrder(order);
30 - } catch (e) {
31 - print(e.toString());
32 - }
33 - }
34 -}
\ No newline at end of file
res/values/strings_de.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Unbestätigt",
470 "displayable" : "Anzeigebar",
471
472 - "submit_request" : "Einen Antrag stellen"
472 + "submit_request" : "Einen Antrag stellen",
473 +
474 + "buy_bitcoin" : "Bitcoin kaufen",
475 + "buy_with" : "Kaufen mit"
476 }
\ No newline at end of file
res/values/strings_en.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Unconfirmed",
470 "displayable" : "Displayable",
471
472 - "submit_request" : "submit a request"
472 + "submit_request" : "submit a request",
473 +
474 + "buy_bitcoin" : "Buy Bitcoin",
475 + "buy_with" : "Buy with"
476 }
\ No newline at end of file
res/values/strings_es.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Inconfirmado",
470 "displayable" : "Visualizable",
471
472 - "submit_request" : "presentar una solicitud"
472 + "submit_request" : "presentar una solicitud",
473 +
474 + "buy_bitcoin" : "Comprar Bitcoin",
475 + "buy_with" : "Compra con"
476 }
\ No newline at end of file
res/values/strings_hi.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "अपुष्ट",
470 "displayable" : "प्रदर्शन योग्य",
471
472 - "submit_request" : "एक अनुरोध सबमिट करें"
472 + "submit_request" : "एक अनुरोध सबमिट करें",
473 +
474 + "buy_bitcoin" : "बिटकॉइन खरीदें",
475 + "buy_with" : "के साथ खरीदें"
476 }
\ No newline at end of file
res/values/strings_ja.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "未確認",
470 "displayable" : "表示可能",
471
472 - "submit_request" : "リクエストを送信する"
472 + "submit_request" : "リクエストを送信する",
473 +
474 + "buy_bitcoin" : "ビットコインを購入する",
475 + "buy_with" : "で購入"
476 }
\ No newline at end of file
res/values/strings_ko.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "미확인",
470 "displayable" : "표시 가능",
471
472 - "submit_request" : "요청을 제출"
472 + "submit_request" : "요청을 제출",
473 +
474 + "buy_bitcoin" : "비트 코인 구매",
475 + "buy_with" : "구매"
476 }
\ No newline at end of file
res/values/strings_nl.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Niet bevestigd",
470 "displayable" : "Weer te geven",
471
472 - "submit_request" : "een verzoek indienen"
472 + "submit_request" : "een verzoek indienen",
473 +
474 + "buy_bitcoin" : "Koop Bitcoin",
475 + "buy_with" : "Koop met"
476 }
\ No newline at end of file
res/values/strings_pl.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Niepotwierdzony",
470 "displayable" : "Wyświetlane",
471
472 - "submit_request" : "złożyć wniosek"
472 + "submit_request" : "złożyć wniosek",
473 +
474 + "buy_bitcoin" : "Kup Bitcoin",
475 + "buy_with" : "Kup za pomocą"
476 }
\ No newline at end of file
res/values/strings_pt.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Não confirmado",
470 "displayable" : "Exibível",
471
472 - "submit_request" : "enviar um pedido"
472 + "submit_request" : "enviar um pedido",
473 +
474 + "buy_bitcoin" : "Compre Bitcoin",
475 + "buy_with" : "Compre com"
476 }
\ No newline at end of file
res/values/strings_ru.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Неподтвержденный",
470 "displayable" : "Отображаемый",
471
472 - "submit_request" : "отправить запрос"
472 + "submit_request" : "отправить запрос",
473 +
474 + "buy_bitcoin" : "Купить Bitcoin",
475 + "buy_with" : "Купить с помощью"
476 }
\ No newline at end of file
res/values/strings_uk.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "Непідтверджений",
470 "displayable" : "Відображуваний",
471
472 - "submit_request" : "надіслати запит"
472 + "submit_request" : "надіслати запит",
473 +
474 + "buy_bitcoin" : "Купити Bitcoin",
475 + "buy_with" : "Купити за допомогою"
476 }
\ No newline at end of file
res/values/strings_zh.arb
+4 -1
@@ -469,5 +469,8 @@
469 "unconfirmed" : "未经证实",
470 "displayable" : "可显示",
471
472 - "submit_request" : "提交請求"
472 + "submit_request" : "提交請求",
473 +
474 + "buy_bitcoin" : "購買比特幣",
475 + "buy_with" : "與一起購買"
476 }
\ No newline at end of file