From 19ffffa6ccd9462cc2722b841a8c236971801448 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Tue, 13 Apr 2021 21:40:44 +0300 Subject: [PATCH] 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 --- lib/buy/buy_provider.dart | 1 + lib/buy/get_buy_provider_icon.dart | 23 +++ lib/buy/moonpay/moonpay_buy_provider.dart | 5 + lib/buy/wyre/wyre_buy_provider.dart | 9 +- lib/di.dart | 35 ++-- lib/entities/wyre_exception.dart | 8 - lib/entities/wyre_service.dart | 151 ------------------ lib/router.dart | 6 +- lib/routes.dart | 2 +- lib/src/screens/buy/buy_webview_page.dart | 108 +++++++++++++ lib/src/screens/buy/pre_order_page.dart | 32 ++-- .../screens/buy/widgets/buy_list_item.dart | 21 +-- .../screens/dashboard/widgets/order_row.dart | 10 +- .../dashboard/widgets/transactions_page.dart | 1 + lib/src/screens/wyre/wyre_page.dart | 97 ----------- lib/view_model/buy/buy_view_model.dart | 14 +- .../dashboard/dashboard_view_model.dart | 6 +- lib/view_model/order_details_view_model.dart | 85 ++++++---- lib/view_model/wyre_view_model.dart | 34 ---- res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 5 +- res/values/strings_es.arb | 5 +- res/values/strings_hi.arb | 5 +- res/values/strings_ja.arb | 5 +- res/values/strings_ko.arb | 5 +- res/values/strings_nl.arb | 5 +- res/values/strings_pl.arb | 5 +- res/values/strings_pt.arb | 5 +- res/values/strings_ru.arb | 5 +- res/values/strings_uk.arb | 5 +- res/values/strings_zh.arb | 5 +- 31 files changed, 310 insertions(+), 398 deletions(-) create mode 100644 lib/buy/get_buy_provider_icon.dart delete mode 100644 lib/entities/wyre_exception.dart delete mode 100644 lib/entities/wyre_service.dart create mode 100644 lib/src/screens/buy/buy_webview_page.dart delete mode 100644 lib/src/screens/wyre/wyre_page.dart delete mode 100644 lib/view_model/wyre_view_model.dart diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index 78ad54451..b908d7bc5 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -12,6 +12,7 @@ abstract class BuyProvider { String get title; BuyProviderDescription get description; + String get trackUrl; WalletType get walletType => wallet.type; String get walletAddress => wallet.address; diff --git a/lib/buy/get_buy_provider_icon.dart b/lib/buy/get_buy_provider_icon.dart new file mode 100644 index 000000000..d58fe19d4 --- /dev/null +++ b/lib/buy/get_buy_provider_icon.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/buy/buy_provider_description.dart'; + +Image getBuyProviderIcon(BuyProviderDescription providerDescription) { + final _wyreIcon = + Image.asset('assets/images/wyre-icon.png', width: 36, height: 36); + final _moonPayIcon = + Image.asset('assets/images/wyre-icon.png', width: 36, height: 36); + + if (providerDescription != null) { + switch (providerDescription) { + case BuyProviderDescription.wyre: + return _wyreIcon; + case BuyProviderDescription.moonPay: + //return _moonPayIcon; + return null; + default: + return null; + } + } else { + return null; + } +} \ No newline at end of file diff --git a/lib/buy/moonpay/moonpay_buy_provider.dart b/lib/buy/moonpay/moonpay_buy_provider.dart index 972b2d2a4..2fde667e4 100644 --- a/lib/buy/moonpay/moonpay_buy_provider.dart +++ b/lib/buy/moonpay/moonpay_buy_provider.dart @@ -34,6 +34,11 @@ class MoonPayBuyProvider extends BuyProvider { String get currencyCode => walletTypeToCryptoCurrency(walletType).title.toLowerCase(); + @override + String get trackUrl => isTestEnvironment + ? '' + : ''; // FIXME + String baseApiUrl; @override diff --git a/lib/buy/wyre/wyre_buy_provider.dart b/lib/buy/wyre/wyre_buy_provider.dart index 0b94816b2..3a09be0f6 100644 --- a/lib/buy/wyre/wyre_buy_provider.dart +++ b/lib/buy/wyre/wyre_buy_provider.dart @@ -16,9 +16,6 @@ class WyreBuyProvider extends BuyProvider { baseApiUrl = isTestEnvironment ? _baseTestApiUrl : _baseProductApiUrl; - trackUrl = isTestEnvironment - ? _trackTestUrl - : _trackProductUrl; } static const _baseTestApiUrl = 'https://api.testwyre.com'; @@ -40,8 +37,12 @@ class WyreBuyProvider extends BuyProvider { @override BuyProviderDescription get description => BuyProviderDescription.wyre; + @override + String get trackUrl => isTestEnvironment + ? _trackTestUrl + : _trackProductUrl; + String baseApiUrl; - String trackUrl; @override Future requestUrl(String amount, String sourceCurrency) async { diff --git a/lib/di.dart b/lib/di.dart index 8663b31de..0b107fde4 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -7,7 +7,6 @@ import 'package:cake_wallet/entities/load_current_wallet.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/entities/transaction_info.dart'; -import 'package:cake_wallet/entities/wyre_service.dart'; import 'package:cake_wallet/monero/monero_wallet_service.dart'; import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/node.dart'; @@ -15,6 +14,7 @@ import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/reactions/on_authentication_state_change.dart'; import 'package:cake_wallet/src/screens/backup/backup_page.dart'; import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; +import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; import 'package:cake_wallet/src/screens/contact/contact_page.dart'; @@ -42,7 +42,6 @@ import 'package:cake_wallet/src/screens/transaction_details/transaction_details_ import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; -import 'package:cake_wallet/src/screens/wyre/wyre_page.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; import 'package:cake_wallet/store/node_list_store.dart'; 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'; import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; -import 'package:cake_wallet/view_model/wyre_view_model.dart'; import 'package:flutter/widgets.dart'; import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; @@ -241,8 +239,7 @@ Future setup( transactionFilterStore: getIt.get(), settingsStore: settingsStore, ordersSource: _ordersSource, - ordersStore: getIt.get(), - wyreViewModel: getIt.get())); + ordersStore: getIt.get())); getIt.registerFactory(() => AuthService( secureStorage: getIt.get(), @@ -534,20 +531,6 @@ Future setup( getIt.registerFactoryParam((Trade trade, _) => TradeDetailsPage(getIt.get(param1: trade))); - getIt.registerFactory(() { - final wallet = getIt.get().wallet; - return WyreService(wallet: wallet); - }); - - getIt.registerFactory(() { - return WyreViewModel(ordersSource, getIt.get(), - wyreService: getIt.get()); - }); - - getIt.registerFactoryParam((String url, _) => - WyrePage(getIt.get(), - ordersStore: getIt.get(), url: url)); - getIt.registerFactory(() => BuyAmountViewModel()); getIt.registerFactory(() { @@ -561,10 +544,18 @@ Future setup( return PreOrderPage(buyViewModel: getIt.get()); }); + getIt.registerFactoryParam((String url, _) => + BuyWebViewPage(getIt.get(), + ordersStore: getIt.get(), url: url)); + getIt.registerFactoryParam( - (order, _) => OrderDetailsViewModel( - wyreViewModel: getIt.get(), - orderForDetails: order)); + (order, _) { + final wallet = getIt.get().wallet; + + return OrderDetailsViewModel( + wallet: wallet, + orderForDetails: order); + }); getIt.registerFactoryParam((Order order, _) => OrderDetailsPage(getIt.get(param1: order))); diff --git a/lib/entities/wyre_exception.dart b/lib/entities/wyre_exception.dart deleted file mode 100644 index 85d9f5b60..000000000 --- a/lib/entities/wyre_exception.dart +++ /dev/null @@ -1,8 +0,0 @@ -class WyreException implements Exception { - WyreException(this.description); - - String description; - - @override - String toString() => description; -} \ No newline at end of file diff --git a/lib/entities/wyre_service.dart b/lib/entities/wyre_service.dart deleted file mode 100644 index f45f33d44..000000000 --- a/lib/entities/wyre_service.dart +++ /dev/null @@ -1,151 +0,0 @@ -import 'dart:convert'; -import 'package:cake_wallet/core/wallet_base.dart'; -import 'package:cake_wallet/entities/wyre_exception.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:flutter/foundation.dart'; -import 'package:http/http.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cake_wallet/buy/order.dart'; -import 'package:cake_wallet/entities/wallet_type.dart'; - -class WyreService { - WyreService({ - @required this.wallet, - this.isTestEnvironment = false}) { - baseApiUrl = isTestEnvironment - ? _baseTestApiUrl - : _baseProductApiUrl; - trackUrl = isTestEnvironment - ? _trackTestUrl - : _trackProductUrl; - } - - static const _baseTestApiUrl = 'https://api.testwyre.com'; - static const _baseProductApiUrl = 'https://api.sendwyre.com'; - static const _trackTestUrl = 'https://dash.testwyre.com/track/'; - static const _trackProductUrl = 'https://dash.sendwyre.com/track/'; - static const _ordersSuffix = '/v3/orders'; - static const _reserveSuffix = '/reserve'; - static const _quoteSuffix = '/quote/partner'; - static const _timeStampSuffix = '?timestamp='; - static const _transferSuffix = '/v2/transfer/'; - static const _trackSuffix = '/track'; - - final bool isTestEnvironment; - final WalletBase wallet; - - WalletType get walletType => wallet.type; - String get walletAddress => wallet.address; - String get walletId => wallet.id; - - String baseApiUrl; - String trackUrl; - - Future getWyreUrl() async { - final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); - final url = baseApiUrl + _ordersSuffix + _reserveSuffix + - _timeStampSuffix + timestamp; - final secretKey = secrets.wyreSecretKey; - final accountId = secrets.wyreAccountId; - final body = { - 'amount': '1', - 'sourceCurrency': 'USD', - 'destCurrency': walletTypeToCryptoCurrency(walletType).title, - 'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress, - 'referrerAccountId': accountId, - 'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest'] - }; - - final response = await post(url, - headers: { - 'Authorization': 'Bearer $secretKey', - 'Content-Type': 'application/json', - 'cache-control': 'no-cache' - }, - body: json.encode(body)); - - if (response.statusCode != 200) { - throw WyreException('Url $url is not found!'); - } - - final responseJSON = json.decode(response.body) as Map; - final urlFromResponse = responseJSON['url'] as String; - return urlFromResponse; - } - - Future findOrderById(String id) async { - final orderUrl = baseApiUrl + _ordersSuffix + '/$id'; - final orderResponse = await get(orderUrl); - - if (orderResponse.statusCode != 200) { - throw WyreException('Order $id is not found!'); - } - - final orderResponseJSON = - json.decode(orderResponse.body) as Map; - final transferId = orderResponseJSON['transferId'] as String; - final from = orderResponseJSON['sourceCurrency'] as String; - final to = orderResponseJSON['destCurrency'] as String; - final status = orderResponseJSON['status'] as String; - final state = TradeState.deserialize(raw: status.toLowerCase()); - final createdAtRaw = orderResponseJSON['createdAt'] as int; - final createdAt = - DateTime.fromMillisecondsSinceEpoch(createdAtRaw).toLocal(); - - final transferUrl = - baseApiUrl + _transferSuffix + transferId + _trackSuffix; - final transferResponse = await get(transferUrl); - - if (transferResponse.statusCode != 200) { - throw WyreException('Transfer $transferId is not found!'); - } - - final transferResponseJSON = - json.decode(transferResponse.body) as Map; - final amount = transferResponseJSON['destAmount'] as double; - - return Order( - id: id, - transferId: transferId, - from: from, - to: to, - state: state, - createdAt: createdAt, - amount: amount.toString(), - receiveAddress: walletAddress, - walletId: walletId - ); - } - - Future getAmount() async { - final quoteUrl = baseApiUrl + _ordersSuffix + _quoteSuffix; - - final secretKey = secrets.wyreSecretKey; - final accountId = secrets.wyreAccountId; - final body = { - 'amount': '1', - 'sourceCurrency': 'USD', - 'destCurrency': walletTypeToCryptoCurrency(walletType).title, - 'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress, - 'accountId': accountId, - 'country': 'US' - }; - - final response = await post(quoteUrl, - headers: { - 'Authorization': 'Bearer $secretKey', - 'Content-Type': 'application/json', - 'cache-control': 'no-cache' - }, - body: json.encode(body)); - - if (response.statusCode != 200) { - throw WyreException('Quote is not found! '); - } - - final responseJSON = json.decode(response.body) as Map; - final amount = responseJSON['destAmount'] as double; - - return amount; - } -} \ No newline at end of file diff --git a/lib/router.dart b/lib/router.dart index f8a3d454e..a3421fa69 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/src/screens/backup/backup_page.dart'; import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; +import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; 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'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/support/support_page.dart'; -import 'package:cake_wallet/src/screens/wyre/wyre_page.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:flutter/cupertino.dart'; @@ -303,10 +303,10 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get()); - case Routes.wyre: + case Routes.buyWebView: return MaterialPageRoute( builder: (_) => - getIt.get(param1: settings.arguments as String)); + getIt.get(param1: settings.arguments as String)); case Routes.restoreWalletFromSeedDetails: final args = settings.arguments as List; diff --git a/lib/routes.dart b/lib/routes.dart index 88b9b8440..6ac75bceb 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -53,6 +53,6 @@ class Routes { static const restoreFromBackup = '/restore_from_backup'; static const support = '/support'; static const orderDetails = '/order_details'; - static const wyre = '/wyre'; static const preOrder = '/pre_order'; + static const buyWebView = '/buy_web_view'; } \ No newline at end of file diff --git a/lib/src/screens/buy/buy_webview_page.dart b/lib/src/screens/buy/buy_webview_page.dart new file mode 100644 index 000000000..91e93f902 --- /dev/null +++ b/lib/src/screens/buy/buy_webview_page.dart @@ -0,0 +1,108 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; +import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/store/dashboard/orders_store.dart'; +import 'package:cake_wallet/view_model/buy/buy_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +class BuyWebViewPage extends BasePage { + BuyWebViewPage(this.buyViewModel, + {@required this.ordersStore, @required this.url}); + + final OrdersStore ordersStore; + final String url; + final BuyViewModel buyViewModel; + + @override + String get title => S.current.buy; + + @override + Color get backgroundDarkColor => Colors.white; + + @override + Color get titleColor => Palette.darkBlueCraiola; + + @override + Widget body(BuildContext context) => + BuyWebViewPageBody(buyViewModel, ordersStore: ordersStore, url: url); +} + +class BuyWebViewPageBody extends StatefulWidget { + BuyWebViewPageBody(this.buyViewModel, {this.ordersStore, this.url}); + + final OrdersStore ordersStore; + final String url; + final BuyViewModel buyViewModel; + + @override + BuyWebViewPageBodyState createState() => BuyWebViewPageBodyState(); +} + +class BuyWebViewPageBodyState extends State { + String orderId; + WebViewController _webViewController; + GlobalKey _webViewkey; + Timer _timer; + bool _isSaving; + BuyProvider _provider; + + @override + void initState() { + super.initState(); + _webViewkey = GlobalKey(); + _isSaving = false; + widget.ordersStore.orderId = ''; + _provider = widget.buyViewModel.selectedProvider; + + if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); + + if (_provider is WyreBuyProvider) { + _timer?.cancel(); + _timer = Timer.periodic(Duration(seconds: 1), (timer) async { + + try { + if (_webViewController == null || _isSaving) { + return; + } + + final url = await _webViewController.currentUrl(); + + if (url.contains('completed')) { + final urlParts = url.split('/'); + orderId = urlParts.last; + widget.ordersStore.orderId = orderId; + + if (orderId.isNotEmpty) { + _isSaving = true; + await widget.buyViewModel.saveOrder(orderId); + timer.cancel(); + } + } + } catch (e) { + _isSaving = false; + print(e); + } + }); + } + + if (_provider is MoonPayBuyProvider) { + // FIXME: fetch orderId + } + } + + @override + Widget build(BuildContext context) { + return WebView( + key: _webViewkey, + initialUrl: widget.url, + javascriptMode: JavascriptMode.unrestricted, + onWebViewCreated: (WebViewController controller) => + setState(() => _webViewController = controller)); + } +} diff --git a/lib/src/screens/buy/pre_order_page.dart b/lib/src/screens/buy/pre_order_page.dart index e42b64790..0cf6a1f88 100644 --- a/lib/src/screens/buy/pre_order_page.dart +++ b/lib/src/screens/buy/pre_order_page.dart @@ -14,6 +14,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:mobx/mobx.dart'; class PreOrderPage extends BasePage { PreOrderPage({@required this.buyViewModel}) @@ -31,14 +32,22 @@ class PreOrderPage extends BasePage { buyViewModel.selectedProvider = null; } }); + + reaction((_) => buyViewModel.buyAmountViewModel.amount, (String amount) { + if (_amountController.text != amount) { + _amountController.text = amount; + } + }); } + static const _amountPattern = '^([0-9]+([.\,][0-9]{0,2})?|[.\,][0-9]{1,2})\$'; + final BuyViewModel buyViewModel; final FocusNode _amountFocus; final TextEditingController _amountController; @override - String get title => 'Buy Bitcoin'; + String get title => S.current.buy_bitcoin; @override Color get titleColor => Colors.white; @@ -96,7 +105,7 @@ class PreOrderPage extends BasePage { signed: false, decimal: true), inputFormatters: [ FilteringTextInputFormatter - .allow(RegExp('^([0-9]+([.\,][0-9]{0,2})?|[.\,][0-9]{1,2})\$')) + .allow(RegExp(_amountPattern)) ], prefixIcon: Padding( padding: EdgeInsets.only(top: 2), @@ -130,7 +139,7 @@ class PreOrderPage extends BasePage { Padding( padding: EdgeInsets.only(top: 38, bottom: 18), child: Text( - 'Buy with:', + S.of(context).buy_with + ':', textAlign: TextAlign.center, style: TextStyle( color: Theme.of(context).primaryTextTheme.title.color, @@ -185,16 +194,21 @@ class PreOrderPage extends BasePage { return LoadingPrimaryButton( onPressed: buyViewModel.isRunning ? null - : () { + : () async { buyViewModel.isRunning = true; - - // FIXME: Start WebView - + final url = + await buyViewModel.fetchUrl(); + if (url.isNotEmpty) { + await Navigator.of(context) + .pushNamed(Routes.buyWebView, arguments: url); + buyViewModel.reset(); + } buyViewModel.isRunning = false; }, text: buyViewModel.selectedProvider == null - ? 'Buy' - : 'Buy with ${buyViewModel.selectedProvider + ? S.of(context).buy + : S.of(context).buy_with + + ' ${buyViewModel.selectedProvider .description.title}', color: Theme.of(context).accentTextTheme.body2.color, textColor: Colors.white, diff --git a/lib/src/screens/buy/widgets/buy_list_item.dart b/lib/src/screens/buy/widgets/buy_list_item.dart index fe198a350..8ee3950aa 100644 --- a/lib/src/screens/buy/widgets/buy_list_item.dart +++ b/lib/src/screens/buy/widgets/buy_list_item.dart @@ -1,5 +1,5 @@ -import 'package:cake_wallet/buy/buy_provider_description.dart'; import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/buy/get_buy_provider_icon.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/palette.dart'; @@ -16,11 +16,6 @@ class BuyListItem extends StatelessWidget { @required this.onTap }); - final _wyreIcon = - Image.asset('assets/images/wyre-icon.png', width: 36, height: 36); - final _mooonPayIcon = - Image.asset('assets/images/wyre-icon.png', width: 36, height: 36); - final BuyProvider selectedProvider; final BuyProvider provider; final double sourceAmount; @@ -31,7 +26,7 @@ class BuyListItem extends StatelessWidget { @override Widget build(BuildContext context) { - final providerIcon = _getProviderIcon(provider.description); + final providerIcon = getBuyProviderIcon(provider.description); final backgroundColor = selectedProvider != null ? selectedProvider.description == provider.description @@ -116,16 +111,4 @@ class BuyListItem extends StatelessWidget { ) ); } - - Image _getProviderIcon(BuyProviderDescription providerDescription) { - switch (providerDescription) { - case BuyProviderDescription.wyre: - return _wyreIcon; - case BuyProviderDescription.moonPay: - //return _mooonPayIcon; - return null; - default: - return null; - } - } } \ No newline at end of file diff --git a/lib/src/screens/dashboard/widgets/order_row.dart b/lib/src/screens/dashboard/widgets/order_row.dart index cfb2c88eb..49afa7a25 100644 --- a/lib/src/screens/dashboard/widgets/order_row.dart +++ b/lib/src/screens/dashboard/widgets/order_row.dart @@ -1,22 +1,26 @@ +import 'package:cake_wallet/buy/buy_provider_description.dart'; +import 'package:cake_wallet/buy/get_buy_provider_icon.dart'; import 'package:flutter/material.dart'; class OrderRow extends StatelessWidget { OrderRow({ @required this.onTap, + @required this.provider, this.from, this.to, this.createdAtFormattedDate, this.formattedAmount}); final VoidCallback onTap; + final BuyProviderDescription provider; final String from; final String to; final String createdAtFormattedDate; final String formattedAmount; - final wyreImage = - Image.asset('assets/images/wyre-icon.png', width: 36, height: 36); @override Widget build(BuildContext context) { + final providerIcon = getBuyProviderIcon(provider); + return InkWell( onTap: onTap, child: Container( @@ -26,7 +30,7 @@ class OrderRow extends StatelessWidget { mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [ - wyreImage, + providerIcon ?? Offstage(), SizedBox(width: 12), Expanded( child: Column( diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart index 482d23a75..942177b40 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -84,6 +84,7 @@ class TransactionsPage extends StatelessWidget { onTap: () => Navigator.of(context).pushNamed( Routes.orderDetails, arguments: order), + provider: order.provider, from: order.from, to: order.to, createdAtFormattedDate: diff --git a/lib/src/screens/wyre/wyre_page.dart b/lib/src/screens/wyre/wyre_page.dart deleted file mode 100644 index 1ba49da64..000000000 --- a/lib/src/screens/wyre/wyre_page.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/store/dashboard/orders_store.dart'; -import 'package:cake_wallet/view_model/wyre_view_model.dart'; -import 'package:flutter/material.dart'; -import 'package:webview_flutter/webview_flutter.dart'; - -class WyrePage extends BasePage { - WyrePage(this.wyreViewModel, - {@required this.ordersStore, @required this.url}); - - final OrdersStore ordersStore; - final String url; - final WyreViewModel wyreViewModel; - - @override - String get title => S.current.buy; - - @override - Color get backgroundDarkColor => Colors.white; - - @override - Color get titleColor => Palette.darkBlueCraiola; - - @override - Widget body(BuildContext context) => - WyrePageBody(wyreViewModel, ordersStore: ordersStore, url: url); -} - -class WyrePageBody extends StatefulWidget { - WyrePageBody(this.wyreViewModel, {this.ordersStore, this.url}); - - final OrdersStore ordersStore; - final String url; - final WyreViewModel wyreViewModel; - - @override - WyrePageBodyState createState() => WyrePageBodyState(); -} - -class WyrePageBodyState extends State { - String orderId; - WebViewController _webViewController; - GlobalKey _webViewkey; - Timer _timer; - bool _isSaving; - - @override - void initState() { - super.initState(); - _webViewkey = GlobalKey(); - _isSaving = false; - widget.ordersStore.orderId = ''; - - if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); - - _timer?.cancel(); - _timer = Timer.periodic(Duration(seconds: 1), (timer) async { - - try { - if (_webViewController == null || _isSaving) { - return; - } - - final url = await _webViewController.currentUrl(); - - if (url.contains('completed')) { - final urlParts = url.split('/'); - orderId = urlParts.last; - widget.ordersStore.orderId = orderId; - - if (orderId.isNotEmpty) { - _isSaving = true; - await widget.wyreViewModel.saveOrder(orderId); - timer.cancel(); - } - } - } catch (e) { - _isSaving = false; - print(e); - } - }); - } - - @override - Widget build(BuildContext context) { - return WebView( - key: _webViewkey, - initialUrl: widget.url, - javascriptMode: JavascriptMode.unrestricted, - onWebViewCreated: (WebViewController controller) => - setState(() => _webViewController = controller)); - } -} diff --git a/lib/view_model/buy/buy_view_model.dart b/lib/view_model/buy/buy_view_model.dart index 6b24cadfa..10dd9a35a 100644 --- a/lib/view_model/buy/buy_view_model.dart +++ b/lib/view_model/buy/buy_view_model.dart @@ -59,14 +59,17 @@ abstract class BuyViewModelBase with Store { CryptoCurrency get cryptoCurrency => walletTypeToCryptoCurrency(type); - Future createOrder() async { + Future fetchUrl() async { + String _url = ''; + try { - final url = await selectedProvider + _url = await selectedProvider ?.requestUrl(doubleAmount?.toString(), fiatCurrency.title); - // FIXME: Start WebView } catch (e) { print(e.toString()); } + + return _url; } Future saveOrder(String orderId) async { @@ -78,4 +81,9 @@ abstract class BuyViewModelBase with Store { print(e.toString()); } } + + void reset() { + buyAmountViewModel.amount = ''; + selectedProvider = null; + } } \ No newline at end of file diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index d471c866a..10e6a5afd 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -28,7 +28,6 @@ import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/action_list_display_mode.dart'; -import 'package:cake_wallet/view_model/wyre_view_model.dart'; import 'package:crypto/crypto.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; @@ -59,8 +58,7 @@ abstract class DashboardViewModelBase with Store { this.transactionFilterStore, this.settingsStore, this.ordersSource, - this.ordersStore, - this.wyreViewModel}) { + this.ordersStore}) { filterItems = { S.current.transactions: [ FilterItem( @@ -230,8 +228,6 @@ abstract class DashboardViewModelBase with Store { TransactionFilterStore transactionFilterStore; - WyreViewModel wyreViewModel; - Map> filterItems; bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled; diff --git a/lib/view_model/order_details_view_model.dart b/lib/view_model/order_details_view_model.dart index 275247670..8e8ed3c18 100644 --- a/lib/view_model/order_details_view_model.dart +++ b/lib/view_model/order_details_view_model.dart @@ -1,12 +1,16 @@ import 'dart:async'; +import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/buy/buy_provider_description.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/utils/date_formatter.dart'; -import 'package:cake_wallet/view_model/wyre_view_model.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; +import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart'; part 'order_details_view_model.g.dart'; @@ -14,16 +18,27 @@ class OrderDetailsViewModel = OrderDetailsViewModelBase with _$OrderDetailsViewModel; abstract class OrderDetailsViewModelBase with Store { - OrderDetailsViewModelBase({this.wyreViewModel, Order orderForDetails}) { + OrderDetailsViewModelBase({WalletBase wallet, Order orderForDetails}) { order = orderForDetails; + if (order.provider != null) { + switch (order.provider) { + case BuyProviderDescription.wyre: + _provider = WyreBuyProvider(wallet: wallet); + break; + case BuyProviderDescription.moonPay: + _provider = MoonPayBuyProvider(wallet: wallet); + break; + } + } + items = ObservableList(); _updateItems(); _updateOrder(); - _timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateOrder()); + timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateOrder()); } @observable @@ -32,21 +47,20 @@ abstract class OrderDetailsViewModelBase with Store { @observable ObservableList items; - WyreViewModel wyreViewModel; + BuyProvider _provider; - Timer _timer; + Timer timer; @action Future _updateOrder() async { try { - final updatedOrder = - await wyreViewModel.wyreService.findOrderById(order.id); - - updatedOrder.receiveAddress = order.receiveAddress; - updatedOrder.walletId = order.walletId; - order = updatedOrder; - - _updateItems(); + if (_provider != null) { + final updatedOrder = await _provider.findOrderById(order.id); + updatedOrder.receiveAddress = order.receiveAddress; + updatedOrder.walletId = order.walletId; + order = updatedOrder; + _updateItems(); + } } catch (e) { print(e.toString()); } @@ -54,8 +68,6 @@ abstract class OrderDetailsViewModelBase with Store { void _updateItems() { final dateFormat = DateFormatter.withCurrentLocal(); - final buildURL = - wyreViewModel.trackUrl + '${order.transferId}'; items?.clear(); @@ -68,18 +80,37 @@ abstract class OrderDetailsViewModelBase with Store { value: order.state != null ? order.state.toString() : S.current.trade_details_fetching), - TrackTradeListItem( - title: 'Track', - value: buildURL, - onTap: () { - launch(buildURL); - }), - StandartListItem( - title: S.current.trade_details_created_at, - value: dateFormat.format(order.createdAt).toString()), - StandartListItem( - title: S.current.trade_details_pair, - value: '${order.from} → ${order.to}') ]); + + if (order.provider != null) { + items.add( + StandartListItem( + title: 'Buy provider', + value: order.provider.title) + ); + } + + if (_provider.trackUrl.isNotEmpty) { + final buildURL = _provider.trackUrl + '${order.transferId}'; + items.add( + TrackTradeListItem( + title: 'Track', + value: buildURL, + onTap: () => launch(buildURL) + ) + ); + } + + items.add( + StandartListItem( + title: S.current.trade_details_created_at, + value: dateFormat.format(order.createdAt).toString()) + ); + + items.add( + StandartListItem( + title: S.current.trade_details_pair, + value: '${order.from} → ${order.to}') + ); } } \ No newline at end of file diff --git a/lib/view_model/wyre_view_model.dart b/lib/view_model/wyre_view_model.dart deleted file mode 100644 index 2d5ab3315..000000000 --- a/lib/view_model/wyre_view_model.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:cake_wallet/entities/wyre_service.dart'; -import 'package:flutter/foundation.dart'; -import 'package:hive/hive.dart'; -import 'package:cake_wallet/buy/order.dart'; -import 'package:cake_wallet/store/dashboard/orders_store.dart'; -import 'package:mobx/mobx.dart'; - -part 'wyre_view_model.g.dart'; - -class WyreViewModel = WyreViewModelBase with _$WyreViewModel; - -abstract class WyreViewModelBase with Store { - WyreViewModelBase(this.ordersSource, this.ordersStore, - {@required this.wyreService}); - - Future get wyreUrl => wyreService.getWyreUrl(); - - String get trackUrl => wyreService.trackUrl; - - final Box ordersSource; - final OrdersStore ordersStore; - - final WyreService wyreService; - - Future saveOrder(String orderId) async { - try { - final order = await wyreService.findOrderById(orderId); - await ordersSource.add(order); - ordersStore.setOrder(order); - } catch (e) { - print(e.toString()); - } - } -} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 6d1d66b84..14c692c0d 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Unbestätigt", "displayable" : "Anzeigebar", - "submit_request" : "Einen Antrag stellen" + "submit_request" : "Einen Antrag stellen", + + "buy_bitcoin" : "Bitcoin kaufen", + "buy_with" : "Kaufen mit" } \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index b0d98b7c9..b2cebcca3 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Unconfirmed", "displayable" : "Displayable", - "submit_request" : "submit a request" + "submit_request" : "submit a request", + + "buy_bitcoin" : "Buy Bitcoin", + "buy_with" : "Buy with" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 190ad4304..20c6e1586 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Inconfirmado", "displayable" : "Visualizable", - "submit_request" : "presentar una solicitud" + "submit_request" : "presentar una solicitud", + + "buy_bitcoin" : "Comprar Bitcoin", + "buy_with" : "Compra con" } \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 6eac14e99..e93615549 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -469,5 +469,8 @@ "unconfirmed" : "अपुष्ट", "displayable" : "प्रदर्शन योग्य", - "submit_request" : "एक अनुरोध सबमिट करें" + "submit_request" : "एक अनुरोध सबमिट करें", + + "buy_bitcoin" : "बिटकॉइन खरीदें", + "buy_with" : "के साथ खरीदें" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 291d5afd3..113e60f46 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -469,5 +469,8 @@ "unconfirmed" : "未確認", "displayable" : "表示可能", - "submit_request" : "リクエストを送信する" + "submit_request" : "リクエストを送信する", + + "buy_bitcoin" : "ビットコインを購入する", + "buy_with" : "で購入" } \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 781df8d8a..e225f4746 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -469,5 +469,8 @@ "unconfirmed" : "미확인", "displayable" : "표시 가능", - "submit_request" : "요청을 제출" + "submit_request" : "요청을 제출", + + "buy_bitcoin" : "비트 코인 구매", + "buy_with" : "구매" } \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 9a6183efb..04c239ff4 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Niet bevestigd", "displayable" : "Weer te geven", - "submit_request" : "een verzoek indienen" + "submit_request" : "een verzoek indienen", + + "buy_bitcoin" : "Koop Bitcoin", + "buy_with" : "Koop met" } \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 6db66958e..542223c18 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Niepotwierdzony", "displayable" : "Wyświetlane", - "submit_request" : "złożyć wniosek" + "submit_request" : "złożyć wniosek", + + "buy_bitcoin" : "Kup Bitcoin", + "buy_with" : "Kup za pomocą" } \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 631be8f42..ea56dfca9 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Não confirmado", "displayable" : "Exibível", - "submit_request" : "enviar um pedido" + "submit_request" : "enviar um pedido", + + "buy_bitcoin" : "Compre Bitcoin", + "buy_with" : "Compre com" } \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 333a823d8..319a1753f 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Неподтвержденный", "displayable" : "Отображаемый", - "submit_request" : "отправить запрос" + "submit_request" : "отправить запрос", + + "buy_bitcoin" : "Купить Bitcoin", + "buy_with" : "Купить с помощью" } \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index cc10a2d89..06082f250 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -469,5 +469,8 @@ "unconfirmed" : "Непідтверджений", "displayable" : "Відображуваний", - "submit_request" : "надіслати запит" + "submit_request" : "надіслати запит", + + "buy_bitcoin" : "Купити Bitcoin", + "buy_with" : "Купити за допомогою" } \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 639babcbc..39f93ecb1 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -469,5 +469,8 @@ "unconfirmed" : "未经证实", "displayable" : "可显示", - "submit_request" : "提交請求" + "submit_request" : "提交請求", + + "buy_bitcoin" : "購買比特幣", + "buy_with" : "與一起購買" } \ No newline at end of file