CW-398-MoonPay-offramp-(Sell)-improvements (#964)

* Implement MoonPay offramp widget

* Add Litecoin to strings

* improve webview page

* Rename route string

---------

Co-authored-by: Justin Ehrenhofer <justin.ehrenhofer@gmail.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
Serhii
2023-06-14 02:15:10 +03:00
committed by GitHub
co-authored by Justin Ehrenhofer Omar Hatem
parent affc35f335
commit a7ba4a84e8
32 changed files with 92 additions and 52 deletions
+28 -3
View File
@@ -1,4 +1,7 @@
import 'dart:convert';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:crypto/crypto.dart';
import 'package:cake_wallet/buy/buy_exception.dart';
import 'package:http/http.dart';
@@ -16,20 +19,42 @@ class MoonPaySellProvider {
MoonPaySellProvider({this.isTest = false})
: baseUrl = isTest ? _baseTestUrl : _baseProductUrl;
static const _baseTestUrl = 'sell-staging.moonpay.com';
static const _baseTestUrl = 'sell-sandbox.moonpay.com';
static const _baseProductUrl = 'sell.moonpay.com';
static String themeToMoonPayTheme(ThemeBase theme) {
switch (theme.type) {
case ThemeType.bright:
return 'light';
case ThemeType.light:
return 'light';
case ThemeType.dark:
return 'dark';
}
}
static String get _apiKey => secrets.moonPayApiKey;
static String get _secretKey => secrets.moonPaySecretKey;
final bool isTest;
final String baseUrl;
Future<Uri> requestUrl({required CryptoCurrency currency, required String refundWalletAddress}) async {
Future<Uri> requestUrl(
{required CryptoCurrency currency,
required String refundWalletAddress,
required SettingsStore settingsStore}) async {
final customParams = {
'theme': themeToMoonPayTheme(settingsStore.currentTheme),
'language': settingsStore.languageCode,
'colorCode': settingsStore.currentTheme.type == ThemeType.dark
? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}'
: '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}',
};
final originalUri = Uri.https(
baseUrl, '', <String, dynamic>{
'apiKey': _apiKey,
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
'refundWalletAddress': refundWalletAddress
});
}..addAll(customParams));
final messageBytes = utf8.encode('?${originalUri.query}');
final key = utf8.encode(_secretKey);
final hmac = Hmac(sha256, key);
+3 -2
View File
@@ -1,6 +1,7 @@
import 'package:cake_wallet/anonpay/anonpay_api.dart';
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
import 'package:cake_wallet/core/yat_service.dart';
@@ -12,7 +13,7 @@ import 'package:cake_wallet/ionia/ionia_gift_card.dart';
import 'package:cake_wallet/ionia/ionia_tip.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart';
import 'package:cake_wallet/src/screens/buy/onramper_page.dart';
import 'package:cake_wallet/src/screens/buy/webview_page.dart';
import 'package:cake_wallet/src/screens/buy/payfura_page.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_dashboard_page.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
@@ -677,7 +678,7 @@ Future setup({
wallet: getIt.get<AppStore>().wallet!,
));
getIt.registerFactory(() => OnRamperPage(getIt.get<OnRamperBuyProvider>()));
getIt.registerFactoryParam<WebViewPage, String, Uri>((title, uri) => WebViewPage(title, uri));
getIt.registerFactory<PayfuraBuyProvider>(() => PayfuraBuyProvider(
settingsStore: getIt.get<AppStore>().settingsStore,
+12 -3
View File
@@ -49,10 +49,11 @@ class MainActions {
case WalletType.bitcoin:
case WalletType.litecoin:
if (viewModel.isEnabledBuyAction) {
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
if (DeviceInfo.instance.isMobile) {
Navigator.of(context).pushNamed(Routes.onramperPage);
Navigator.of(context)
.pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);
} else {
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
await launchUrl(uri);
}
}
@@ -119,14 +120,22 @@ class MainActions {
switch (walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
if (viewModel.isEnabledSellAction) {
final moonPaySellProvider = MoonPaySellProvider();
final uri = await moonPaySellProvider.requestUrl(
currency: viewModel.wallet.currency,
refundWalletAddress: viewModel.wallet.walletAddresses.address,
settingsStore: viewModel.settingsStore,
);
await launchUrl(uri);
if (DeviceInfo.instance.isMobile) {
Navigator.of(context).pushNamed(Routes.webViewPage,
arguments: [S.of(context).sell, uri]);
} else {
await launchUrl(uri);
}
}
break;
default:
await showPopUp<void>(
+10 -3
View File
@@ -8,7 +8,7 @@ import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dar
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/onramper_page.dart';
import 'package:cake_wallet/src/screens/buy/webview_page.dart';
import 'package:cake_wallet/src/screens/buy/payfura_page.dart';
import 'package:cake_wallet/src/screens/buy/pre_order_page.dart';
import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart';
@@ -97,6 +97,8 @@ import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/node.dart';
import 'buy/moonpay/moonpay_buy_provider.dart';
late RouteSettings currentRouteSettings;
Route<dynamic> createRoute(RouteSettings settings) {
@@ -518,8 +520,13 @@ Route<dynamic> createRoute(RouteSettings settings) {
param1: paymentInfo,
param2: commitedInfo));
case Routes.onramperPage:
return CupertinoPageRoute<void>(builder: (_) => getIt.get<OnRamperPage>());
case Routes.webViewPage:
final args = settings.arguments as List;
final title = args.first as String;
final url = args[1] as Uri;
return CupertinoPageRoute<void>(builder: (_) => getIt.get<WebViewPage>(
param1: title,
param2: url));
case Routes.payfuraPage:
return CupertinoPageRoute<void>(builder: (_) => getIt.get<PayFuraPage>());
+1 -1
View File
@@ -70,7 +70,7 @@ class Routes {
static const ioniaPaymentStatusPage = '/ionia_payment_status_page';
static const ioniaMoreOptionsPage = '/ionia_more_options_page';
static const ioniaCustomRedeemPage = '/ionia_custom_redeem_page';
static const onramperPage = '/onramper';
static const webViewPage = '/web_view_page';
static const connectionSync = '/connection_sync_page';
static const securityBackupPage = '/security_and_backup_page';
static const privacyPage = '/privacy_page';
@@ -5,33 +5,32 @@ import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
class OnRamperPage extends BasePage {
OnRamperPage(this._onRamperBuyProvider);
class WebViewPage extends BasePage {
WebViewPage(this._title, this._url);
final OnRamperBuyProvider _onRamperBuyProvider;
final String _title;
final Uri _url;
@override
String get title => S.current.buy;
String get title => _title;
@override
Widget body(BuildContext context) {
return OnRamperPageBody(_onRamperBuyProvider);
return WebViewPageBody(_url);
}
}
class OnRamperPageBody extends StatefulWidget {
OnRamperPageBody(this.onRamperBuyProvider);
class WebViewPageBody extends StatefulWidget {
WebViewPageBody(this.uri);
final OnRamperBuyProvider onRamperBuyProvider;
Uri get uri => onRamperBuyProvider.requestUrl();
final Uri uri;
@override
OnRamperPageBodyState createState() => OnRamperPageBodyState();
WebViewPageBodyState createState() => WebViewPageBodyState();
}
class OnRamperPageBodyState extends State<OnRamperPageBody> {
OnRamperPageBodyState();
class WebViewPageBodyState extends State<WebViewPageBody> {
WebViewPageBodyState();
@override
Widget build(BuildContext context) {
@@ -296,8 +296,7 @@ abstract class DashboardViewModelBase with Store {
bool get isEnabledSellAction =>
!settingsStore.disableSell &&
wallet.type != WalletType.haven &&
wallet.type != WalletType.monero &&
wallet.type != WalletType.litecoin;
wallet.type != WalletType.monero;
@observable
bool hasSellAction;