From 62007975e1693b061fa87b00fac6cf1879f0f501 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 14 Jul 2023 01:48:47 +0300 Subject: [PATCH] Old state (#999) * Fix Bitcoin transactions not showing (#978) * handle multiple responses coming in a single event * Add timeout for getting transaction info, to allow other transactions to be returned in case of any failure or network issue * Handle other cases of receiving multiple messages in the same response * Fix shib and storj (#997) * Merge main branch * Add missing files --------- Co-authored-by: Justin Ehrenhofer --- assets/images/shib_icon.png | Bin 0 -> 7996 bytes cw_bitcoin/lib/bitcoin_wallet_service.dart | 41 ++-- cw_bitcoin/lib/electrum.dart | 88 +++++---- .../lib/electrum_transaction_history.dart | 1 - cw_bitcoin/lib/litecoin_wallet_service.dart | 35 ++-- cw_core/lib/crypto_currency.dart | 2 +- cw_monero/lib/monero_wallet_service.dart | 3 +- lib/buy/moonpay/moonpay_buy_provider.dart | 114 +++++++---- lib/core/wallet_loading_service.dart | 26 ++- lib/di.dart | 18 +- lib/entities/main_actions.dart | 15 +- lib/main.dart | 1 + lib/router.dart | 16 +- lib/routes.dart | 2 +- .../{onramper_page.dart => webview_page.dart} | 25 ++- .../dashboard/widgets/address_page.dart | 2 +- .../dashboard/widgets/market_place_page.dart | 3 +- .../dashboard/widgets/transactions_page.dart | 179 +++++++++--------- lib/src/screens/exchange/exchange_page.dart | 4 +- .../screens/receive/anonpay_invoice_page.dart | 69 ++++--- lib/src/screens/send/send_page.dart | 4 +- lib/src/screens/send/widgets/send_card.dart | 6 +- lib/src/widgets/add_template_button.dart | 2 +- lib/utils/distribution_info.dart | 2 +- .../dashboard/market_place_view_model.dart | 17 ++ .../wallet_list/wallet_list_view_model.dart | 4 - macos/Flutter/GeneratedPluginRegistrant.swift | 2 - macos/Podfile.lock | 34 ++-- res/values/strings_ar.arb | 6 + res/values/strings_bg.arb | 6 + res/values/strings_ha.arb | 7 +- res/values/strings_yo.arb | 4 +- 32 files changed, 399 insertions(+), 339 deletions(-) create mode 100644 assets/images/shib_icon.png rename lib/src/screens/buy/{onramper_page.dart => webview_page.dart} (68%) create mode 100644 lib/view_model/dashboard/market_place_view_model.dart diff --git a/assets/images/shib_icon.png b/assets/images/shib_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..97bc94468f435e27783486e243e1f1822bed6ece GIT binary patch literal 7996 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 { +class BitcoinWalletService extends WalletService { BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); final Box walletInfoSource; @@ -45,10 +43,12 @@ class BitcoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = await BitcoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, + password: password, + name: name, + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.init(); @@ -57,22 +57,23 @@ class BitcoinWalletService extends WalletService< @override Future remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await BitcoinWalletBase.open( - password: password, - name: currentName, - walletInfo: currentWalletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: currentName, + walletInfo: currentWalletInfo, + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect), + ); await currentWallet.renameWalletFiles(newName); @@ -84,13 +85,11 @@ class BitcoinWalletService extends WalletService< } @override - Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async => throw UnimplementedError(); @override - Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 70b072f7b..a05c251fe 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -66,54 +66,68 @@ class ElectrumClient { socket!.listen((Uint8List event) { try { final msg = utf8.decode(event.toList()); - final response = - json.decode(msg) as Map; - _handleResponse(response); - } on FormatException catch (e) { - final msg = e.message.toLowerCase(); - - if (e.source is String) { - unterminatedString += e.source as String; - } - - if (msg.contains("not a subtype of type")) { - unterminatedString += e.source as String; - return; - } - - if (isJSONStringCorrect(unterminatedString)) { - final response = - json.decode(unterminatedString) as Map; - _handleResponse(response); - unterminatedString = ''; - } - } on TypeError catch (e) { - if (!e.toString().contains('Map') && !e.toString().contains('Map')) { - return; - } - - final source = utf8.decode(event.toList()); - unterminatedString += source; - - if (isJSONStringCorrect(unterminatedString)) { - final response = - json.decode(unterminatedString) as Map; - _handleResponse(response); - // unterminatedString = null; - unterminatedString = ''; + final messagesList = msg.split("\n"); + for (var message in messagesList) { + if (message.isEmpty) { + continue; + } + _parseResponse(message); } } catch (e) { print(e.toString()); } }, onError: (Object error) { print(error.toString()); + unterminatedString = ''; _setIsConnected(false); }, onDone: () { + unterminatedString = ''; _setIsConnected(false); }); keepAlive(); } + void _parseResponse(String message) { + try { + final response = json.decode(message) as Map; + _handleResponse(response); + } on FormatException catch (e) { + final msg = e.message.toLowerCase(); + + if (e.source is String) { + unterminatedString += e.source as String; + } + + if (msg.contains("not a subtype of type")) { + unterminatedString += e.source as String; + return; + } + + if (isJSONStringCorrect(unterminatedString)) { + final response = + json.decode(unterminatedString) as Map; + _handleResponse(response); + unterminatedString = ''; + } + } on TypeError catch (e) { + if (!e.toString().contains('Map') && !e.toString().contains('Map')) { + return; + } + + unterminatedString += message; + + if (isJSONStringCorrect(unterminatedString)) { + final response = + json.decode(unterminatedString) as Map; + _handleResponse(response); + // unterminatedString = null; + unterminatedString = ''; + } + } catch (e) { + print(e.toString()); + } + } + void keepAlive() { _aliveTimer?.cancel(); _aliveTimer = Timer.periodic(aliveTimerDuration, (_) async => ping()); @@ -217,7 +231,7 @@ class ElectrumClient { Future> getTransactionRaw( {required String hash}) async => - call(method: 'blockchain.transaction.get', params: [hash, true]) + callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000) .then((dynamic result) { if (result is Map) { return result; @@ -228,7 +242,7 @@ class ElectrumClient { Future getTransactionHex( {required String hash}) async => - call(method: 'blockchain.transaction.get', params: [hash, false]) + callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000) .then((dynamic result) { if (result is String) { return result; diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index a591bc173..664a8841b 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -86,5 +86,4 @@ abstract class ElectrumTransactionHistoryBase void _update(ElectrumTransactionInfo transaction) => transactions[transaction.id] = transaction; - } diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 0ab7918d5..1df08d8e0 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -13,10 +13,8 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:collection/collection.dart'; -class LitecoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { +class LitecoinWalletService extends WalletService { LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); final Box walletInfoSource; @@ -46,10 +44,12 @@ class LitecoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; final wallet = await LitecoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, + password: password, + name: name, + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, encryptionFileUtils: encryptionFileUtilsFor(isDirect)); await wallet.init(); @@ -58,22 +58,23 @@ class LitecoinWalletService extends WalletService< @override Future remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await LitecoinWalletBase.open( - password: password, - name: currentName, - walletInfo: currentWalletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: currentName, + walletInfo: currentWalletInfo, + unspentCoinsInfo: unspentCoinsInfoSource, + encryptionFileUtils: encryptionFileUtilsFor(isDirect), + ); await currentWallet.renameWalletFiles(newName); diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 9d586c85b..86ea3f214 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -191,7 +191,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const nexo = CryptoCurrency(title: 'NEXO', tag: 'ETH', fullName: 'Nexo', raw: 76, name: 'nexo', iconPath: 'assets/images/nexo_icon.png'); static const cake = CryptoCurrency(title: 'CAKE', tag: 'BSC', fullName: 'PancakeSwap', raw: 77, name: 'cake', iconPath: 'assets/images/cake_icon.png'); static const pepe = CryptoCurrency(title: 'PEPE', tag: 'ETH', fullName: 'Pepe', raw: 78, name: 'pepe', iconPath: 'assets/images/pepe_icon.png'); - static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/stroj_icon.png'); + static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/storj_icon.png'); static const tusd = CryptoCurrency(title: 'TUSD', tag: 'ETH', fullName: 'TrueUSD', raw: 80, name: 'tusd', iconPath: 'assets/images/tusd_icon.png'); static const wbtc = CryptoCurrency(title: 'WBTC', tag: 'ETH', fullName: 'Wrapped Bitcoin', raw: 81, name: 'wbtc', iconPath: 'assets/images/wbtc_icon.png'); static const weth = CryptoCurrency(title: 'WETH', tag: 'ETH', fullName: 'Wrapped Ethereum', raw: 82, name: 'weth', iconPath: 'assets/images/weth_icon.png'); diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 107af54b0..6f5645f66 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -3,7 +3,6 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:hive/hive.dart'; import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; -import 'package:cw_monero/api/wallet.dart' as monero_wallet; import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; import 'package:cw_monero/monero_wallet.dart'; import 'package:cw_core/wallet_credentials.dart'; @@ -161,7 +160,7 @@ class MoneroWalletService extends WalletService< String currentName, String password, String newName) async { final currentWalletInfo = walletInfoSource.values.firstWhere( (info) => info.id == WalletBase.idFor(currentName, getType())); - final currentWallet = MoneroWallet(walletInfo: currentWalletInfo); + final currentWallet = MoneroWallet(walletInfo: currentWalletInfo, password: password); await currentWallet.renameWalletFiles(newName); diff --git a/lib/buy/moonpay/moonpay_buy_provider.dart b/lib/buy/moonpay/moonpay_buy_provider.dart index 372b6d6cc..ab62fcf68 100644 --- a/lib/buy/moonpay/moonpay_buy_provider.dart +++ b/lib/buy/moonpay/moonpay_buy_provider.dart @@ -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'; @@ -13,23 +16,48 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cw_core/crypto_currency.dart'; class MoonPaySellProvider { - MoonPaySellProvider({this.isTest = false}) - : baseUrl = isTest ? _baseTestUrl : _baseProductUrl; + 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 get _apiKey => secrets.moonPayApiKey; - static String get _secretKey => secrets.moonPaySecretKey; + + 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 requestUrl({required CryptoCurrency currency, required String refundWalletAddress}) async { + Future 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, '', { - 'apiKey': _apiKey, - 'defaultBaseCurrencyCode': currency.toString().toLowerCase(), - 'refundWalletAddress': refundWalletAddress - }); + baseUrl, + '', + { + '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); @@ -68,8 +96,7 @@ class MoonPayBuyProvider extends BuyProvider { @override BuyProviderDescription get description => BuyProviderDescription.moonPay; - String get currencyCode => - walletTypeToCryptoCurrency(walletType).title.toLowerCase(); + String get currencyCode => walletTypeToCryptoCurrency(walletType).title.toLowerCase(); @override String get trackUrl => baseUrl + '/transaction_receipt?transactionId='; @@ -78,16 +105,24 @@ class MoonPayBuyProvider extends BuyProvider { @override Future requestUrl(String amount, String sourceCurrency) async { - final enabledPaymentMethods = - 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' + final enabledPaymentMethods = 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' '%2Csepa_bank_transfer%2Cgbp_bank_transfer%2Cgbp_open_banking_payment'; - final suffix = '?apiKey=' + _apiKey + '¤cyCode=' + - currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods + - '&walletAddress=' + walletAddress + - '&baseCurrencyCode=' + sourceCurrency.toLowerCase() + - '&baseCurrencyAmount=' + amount + '&lockAmount=true' + - '&showAllCurrencies=false' + '&showWalletAddressForm=false'; + final suffix = '?apiKey=' + + _apiKey + + '¤cyCode=' + + currencyCode + + '&enabledPaymentMethods=' + + enabledPaymentMethods + + '&walletAddress=' + + walletAddress + + '&baseCurrencyCode=' + + sourceCurrency.toLowerCase() + + '&baseCurrencyAmount=' + + amount + + '&lockAmount=true' + + '&showAllCurrencies=false' + + '&showWalletAddressForm=false'; final originalUrl = baseUrl + suffix; @@ -96,25 +131,28 @@ class MoonPayBuyProvider extends BuyProvider { final hmac = Hmac(sha256, key); final digest = hmac.convert(messageBytes); final signature = base64.encode(digest.bytes); - final urlWithSignature = originalUrl + - '&signature=${Uri.encodeComponent(signature)}'; + final urlWithSignature = originalUrl + '&signature=${Uri.encodeComponent(signature)}'; return isTestEnvironment ? originalUrl : urlWithSignature; } @override Future calculateAmount(String amount, String sourceCurrency) async { - final url = _apiUrl + _currenciesSuffix + '/$currencyCode' + - _quoteSuffix + '/?apiKey=' + _apiKey + - '&baseCurrencyAmount=' + amount + - '&baseCurrencyCode=' + sourceCurrency.toLowerCase(); + final url = _apiUrl + + _currenciesSuffix + + '/$currencyCode' + + _quoteSuffix + + '/?apiKey=' + + _apiKey + + '&baseCurrencyAmount=' + + amount + + '&baseCurrencyCode=' + + sourceCurrency.toLowerCase(); final uri = Uri.parse(url); final response = await get(uri); if (response.statusCode != 200) { - throw BuyException( - description: description, - text: 'Quote is not found!'); + throw BuyException(description: description, text: 'Quote is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -123,22 +161,17 @@ class MoonPayBuyProvider extends BuyProvider { final minSourceAmount = responseJSON['baseCurrency']['minAmount'] as int; return BuyAmount( - sourceAmount: sourceAmount, - destAmount: destAmount, - minAmount: minSourceAmount); + sourceAmount: sourceAmount, destAmount: destAmount, minAmount: minSourceAmount); } @override Future findOrderById(String id) async { - final url = _apiUrl + _transactionsSuffix + '/$id' + - '?apiKey=' + _apiKey; + final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey; final uri = Uri.parse(url); final response = await get(uri); if (response.statusCode != 200) { - throw BuyException( - description: description, - text: 'Transaction $id is not found!'); + throw BuyException(description: description, text: 'Transaction $id is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -156,8 +189,7 @@ class MoonPayBuyProvider extends BuyProvider { createdAt: createdAt, amount: amount.toString(), receiveAddress: walletAddress, - walletId: walletId - ); + walletId: walletId); } static Future onEnabled() async { @@ -176,4 +208,4 @@ class MoonPayBuyProvider extends BuyProvider { return isBuyEnable; } -} \ No newline at end of file +} diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart index 6d65a7604..4ce9fa4dd 100644 --- a/lib/core/wallet_loading_service.dart +++ b/lib/core/wallet_loading_service.dart @@ -7,21 +7,19 @@ import 'package:cw_core/wallet_type.dart'; import 'package:shared_preferences/shared_preferences.dart'; class WalletLoadingService { - WalletLoadingService( - this.sharedPreferences, this.keyService, this.walletServiceFactory); + WalletLoadingService(this.sharedPreferences, this.keyService, this.walletServiceFactory); final SharedPreferences sharedPreferences; final KeyService keyService; final WalletService Function(WalletType type) walletServiceFactory; - Future renameWallet( - WalletType type, String name, String newName, {String? password}) async { + Future renameWallet(WalletType type, String name, String newName, + {String? password}) async { final walletService = walletServiceFactory.call(type); final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name)); // Save the current wallet's password to the new wallet name's key - await keyService.saveWalletPassword( - walletName: newName, password: walletPassword); + await keyService.saveWalletPassword(walletName: newName, password: walletPassword); // Delete previous wallet name from keyService to keep only new wallet's name // otherwise keeps duplicate (old and new names) await keyService.deleteWalletPassword(walletName: name); @@ -29,10 +27,10 @@ class WalletLoadingService { await walletService.rename(name, walletPassword, newName); } - Future load(WalletType type, String name, {String? password}) async { - final walletService = walletServiceFactory.call(type); - final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name)); - final wallet = await walletService.openWallet(name, walletPassword); + Future load(WalletType type, String name, {String? password}) async { + final walletService = walletServiceFactory.call(type); + final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name)); + final wallet = await walletService.openWallet(name, walletPassword); if (type == WalletType.monero) { await updateMoneroWalletPassword(wallet); @@ -53,12 +51,10 @@ class WalletLoadingService { // Save new generated password with backup key for case where // wallet will change password, but it will fail to update in secure storage final bakWalletName = '#__${wallet.name}_bak__#'; - await keyService.saveWalletPassword( - walletName: bakWalletName, password: password); + await keyService.saveWalletPassword(walletName: bakWalletName, password: password); await wallet.changePassword(password); - await keyService.saveWalletPassword( - walletName: wallet.name, password: password); + await keyService.saveWalletPassword(walletName: wallet.name, password: password); isPasswordUpdated = true; await sharedPreferences.setBool(key, isPasswordUpdated); } -} \ No newline at end of file +} diff --git a/lib/di.dart b/lib/di.dart index 91a8f0628..a31b00d1f 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1,4 +1,3 @@ -import 'dart:io'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/core/yat_service.dart'; @@ -7,25 +6,19 @@ import 'package:cake_wallet/entities/preferences_key.dart'; 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/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart'; -import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; -import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/entities/receive_page_option.dart'; import 'package:cake_wallet/ionia/ionia_anypay.dart'; 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/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_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'; -import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart'; import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; @@ -45,11 +38,8 @@ import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; -import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; -import 'package:cake_wallet/utils/payment_request.dart'; -import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/anonpay_details_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; @@ -83,7 +73,6 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/view_model/wallet_unlock_loadable_view_model.dart'; import 'package:cake_wallet/view_model/wallet_unlock_verifiable_view_model.dart'; -import 'package:cake_wallet/view_model/wallet_unlock_view_model.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/core/backup_service.dart'; import 'package:cw_core/wallet_service.dart'; @@ -176,7 +165,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:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; @@ -709,15 +697,13 @@ Future setup({ wallet: getIt.get().wallet!, )); - getIt.registerFactory(() => OnRamperPage(getIt.get())); + getIt.registerFactoryParam((title, uri) => WebViewPage(title, uri)); getIt.registerFactory(() => PayfuraBuyProvider( settingsStore: getIt.get().settingsStore, wallet: getIt.get().wallet!, )); - getIt.registerFactory(() => PayFuraPage(getIt.get())); - getIt.registerFactory(() => ExchangeViewModel( getIt.get().wallet!, _tradesSource, diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index f7a322096..3c3cfa32f 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -48,10 +48,11 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: if (viewModel.isEnabledBuyAction) { + final uri = getIt.get().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().requestUrl(); await launchUrl(uri); } } @@ -118,14 +119,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( diff --git a/lib/main.dart b/lib/main.dart index efb058ee5..0223f84f7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/root_dir.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; diff --git a/lib/router.dart b/lib/router.dart index 2f10e7143..148d94ecb 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -8,8 +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/payfura_page.dart'; +import 'package:cake_wallet/src/screens/buy/webview_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart'; @@ -48,7 +47,6 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; -import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -564,11 +562,13 @@ Route createRoute(RouteSettings settings) { param1: paymentInfo, param2: commitedInfo)); - case Routes.onramperPage: - return CupertinoPageRoute(builder: (_) => getIt.get()); - - case Routes.payfuraPage: - return CupertinoPageRoute(builder: (_) => getIt.get()); + case Routes.webViewPage: + final args = settings.arguments as List; + final title = args.first as String; + final url = args[1] as Uri; + return CupertinoPageRoute(builder: (_) => getIt.get( + param1: title, + param2: url)); case Routes.advancedPrivacySettings: final type = settings.arguments as WalletType; diff --git a/lib/routes.dart b/lib/routes.dart index e3f8c01ea..e86093b91 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -71,7 +71,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'; diff --git a/lib/src/screens/buy/onramper_page.dart b/lib/src/screens/buy/webview_page.dart similarity index 68% rename from lib/src/screens/buy/onramper_page.dart rename to lib/src/screens/buy/webview_page.dart index cbdf9e1b1..205b87c47 100644 --- a/lib/src/screens/buy/onramper_page.dart +++ b/lib/src/screens/buy/webview_page.dart @@ -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 { - OnRamperPageBodyState(); +class WebViewPageBodyState extends State { + WebViewPageBodyState(); @override Widget build(BuildContext context) { diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index e137a8da2..c9c7efde2 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -73,7 +73,7 @@ class AddressPage extends BasePage { ? closeButtonImageDarkTheme : closeButtonImage; - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context); + bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; return MergeSemantics( child: SizedBox( diff --git a/lib/src/screens/dashboard/widgets/market_place_page.dart b/lib/src/screens/dashboard/widgets/market_place_page.dart index dbce5dbb3..9f781081d 100644 --- a/lib/src/screens/dashboard/widgets/market_place_page.dart +++ b/lib/src/screens/dashboard/widgets/market_place_page.dart @@ -1,6 +1,5 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; @@ -85,7 +84,7 @@ class MarketPlacePage extends StatelessWidget { switch (walletType) { case WalletType.haven: - showPopUp( + showPopUp( context: context, builder: (BuildContext context) { return AlertWithOneAction( diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart index 5a01efe1d..39d446059 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -45,9 +45,11 @@ class TransactionsPage extends StatelessWidget { return Padding( padding: const EdgeInsets.fromLTRB(24, 0, 24, 8), child: DashBoardRoundedCardWidget( - onTap: () => Navigator.of(context).pushNamed( - Routes.webViewPage, - arguments: ['', Uri.parse('https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')]), + onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [ + '', + Uri.parse( + 'https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/') + ]), title: S.of(context).syncing_wallet_alert_title, subTitle: S.of(context).syncing_wallet_alert_content, ), @@ -60,96 +62,97 @@ class TransactionsPage extends StatelessWidget { Expanded(child: Observer(builder: (_) { final items = dashboardViewModel.items; - return items.isNotEmpty - ? ListView.builder( - itemCount: items.length, - itemBuilder: (context, index) { - final item = items[index]; + return items.isNotEmpty + ? ListView.builder( + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; - if (item is DateSectionItem) { - return DateSectionRaw(date: item.date); - } + if (item is DateSectionItem) { + return DateSectionRaw(date: item.date); + } - if (item is TransactionListItem) { - final transaction = item.transaction; + if (item is TransactionListItem) { + final transaction = item.transaction; - return Observer( - builder: (_) => TransactionRow( - onTap: () => Navigator.of(context) - .pushNamed(Routes.transactionDetails, arguments: transaction), - direction: transaction.direction, - formattedDate: DateFormat('HH:mm').format(transaction.date), - formattedAmount: item.formattedCryptoAmount, - formattedFiatAmount: - dashboardViewModel.balanceViewModel.isFiatDisabled - ? '' - : item.formattedFiatAmount, - isPending: transaction.isPending, - title: item.formattedTitle + item.formattedStatus)); - } - - if (item is AnonpayTransactionListItem) { - final transactionInfo = item.transaction; - - return AnonpayTransactionRow( - onTap: () => Navigator.of(context) - .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo), - currency: transactionInfo.fiatAmount != null - ? transactionInfo.fiatEquiv ?? '' - : CryptoCurrency.fromFullName(transactionInfo.coinTo) - .name - .toUpperCase(), - provider: transactionInfo.provider, - amount: transactionInfo.fiatAmount?.toString() ?? - (transactionInfo.amountTo?.toString() ?? ''), - createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt), - ); - } - - if (item is TradeListItem) { - final trade = item.trade; - - return Observer( - builder: (_) => TradeRow( - onTap: () => Navigator.of(context) - .pushNamed(Routes.tradeDetails, arguments: trade), - provider: trade.provider, - from: trade.from, - to: trade.to, - createdAtFormattedDate: trade.createdAt != null - ? DateFormat('HH:mm').format(trade.createdAt!) - : null, - formattedAmount: item.tradeFormattedAmount)); - } - - if (item is OrderListItem) { - final order = item.order; - - return Observer( - builder: (_) => OrderRow( + return Observer( + builder: (_) => TransactionRow( onTap: () => Navigator.of(context) - .pushNamed(Routes.orderDetails, arguments: order), - provider: order.provider, - from: order.from!, - to: order.to!, - createdAtFormattedDate: - DateFormat('HH:mm').format(order.createdAt), - formattedAmount: item.orderFormattedAmount, - )); - } + .pushNamed(Routes.transactionDetails, arguments: transaction), + direction: transaction.direction, + formattedDate: DateFormat('HH:mm').format(transaction.date), + formattedAmount: item.formattedCryptoAmount, + formattedFiatAmount: + dashboardViewModel.balanceViewModel.isFiatDisabled + ? '' + : item.formattedFiatAmount, + isPending: transaction.isPending, + title: item.formattedTitle + item.formattedStatus)); + } - return Container(color: Colors.transparent, height: 1); - }) - : Center( - child: Text( - S.of(context).placeholder_transactions, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).primaryTextTheme!.labelSmall!.decorationColor!), - ), - ); - })) - ], + if (item is AnonpayTransactionListItem) { + final transactionInfo = item.transaction; + + return AnonpayTransactionRow( + onTap: () => Navigator.of(context) + .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo), + currency: transactionInfo.fiatAmount != null + ? transactionInfo.fiatEquiv ?? '' + : CryptoCurrency.fromFullName(transactionInfo.coinTo) + .name + .toUpperCase(), + provider: transactionInfo.provider, + amount: transactionInfo.fiatAmount?.toString() ?? + (transactionInfo.amountTo?.toString() ?? ''), + createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt), + ); + } + + if (item is TradeListItem) { + final trade = item.trade; + + return Observer( + builder: (_) => TradeRow( + onTap: () => Navigator.of(context) + .pushNamed(Routes.tradeDetails, arguments: trade), + provider: trade.provider, + from: trade.from, + to: trade.to, + createdAtFormattedDate: trade.createdAt != null + ? DateFormat('HH:mm').format(trade.createdAt!) + : null, + formattedAmount: item.tradeFormattedAmount)); + } + + if (item is OrderListItem) { + final order = item.order; + + return Observer( + builder: (_) => OrderRow( + onTap: () => Navigator.of(context) + .pushNamed(Routes.orderDetails, arguments: order), + provider: order.provider, + from: order.from!, + to: order.to!, + createdAtFormattedDate: + DateFormat('HH:mm').format(order.createdAt), + formattedAmount: item.orderFormattedAmount, + )); + } + + return Container(color: Colors.transparent, height: 1); + }) + : Center( + child: Text( + S.of(context).placeholder_transactions, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).primaryTextTheme.labelSmall!.decorationColor!), + ), + ); + })) + ], + ), ), ); } diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 3fb198bfa..78f98f6ca 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -117,7 +117,7 @@ class ExchangePage extends BasePage { final _closeButton = currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context); + bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; return MergeSemantics( child: SizedBox( @@ -733,7 +733,7 @@ class ExchangePage extends BasePage { }, )); - if (ResponsiveLayoutUtil.instance.isMobile(context)) { + if (ResponsiveLayoutUtil.instance.isMobile) { return MobileExchangeCardsSection( firstExchangeCard: firstExchangeCard, secondExchangeCard: secondExchangeCard, diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index 88547e483..1e3950f0d 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -40,6 +40,7 @@ class AnonPayInvoicePage extends BasePage { final _formKey = GlobalKey(); bool effectsInstalled = false; + @override Color get titleColor => Colors.white; @@ -82,34 +83,33 @@ class AnonPayInvoicePage extends BasePage { disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .backgroundColor!, - nextFocus: false, - actions: [ - KeyboardActionsItem( - focusNode: _amountFocusNode, - toolbarButtons: [(_) => KeyboardDoneButton()], - ), - ]), - child: Container( - color: Theme.of(context).colorScheme.background, - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24), - content: Container( - decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), - gradient: LinearGradient( - colors: [ - Theme.of(context).primaryTextTheme!.titleSmall!.color!, - Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!, - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, + keyboardBarColor: Theme.of(context).accentTextTheme!.bodyLarge!.backgroundColor!, + nextFocus: false, + actions: [ + KeyboardActionsItem( + focusNode: _amountFocusNode, + toolbarButtons: [(_) => KeyboardDoneButton()], ), - ) : null, + ]), + child: Container( + color: Theme.of(context).colorScheme.background, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24), + content: Container( + decoration: ResponsiveLayoutUtil.instance.isMobile + ? BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), + gradient: LinearGradient( + colors: [ + Theme.of(context).primaryTextTheme!.titleSmall!.color!, + Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!, + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ) + : null, child: Observer(builder: (_) { return Padding( padding: EdgeInsets.fromLTRB(24, 120, 24, 0), @@ -142,12 +142,10 @@ class AnonPayInvoicePage extends BasePage { : S.of(context).anonpay_description("a donation link", "donate"), textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context) - .primaryTextTheme! - .displayLarge! - .decorationColor!, - fontWeight: FontWeight.w500, - fontSize: 12), + color: + Theme.of(context).primaryTextTheme!.displayLarge!.decorationColor!, + fontWeight: FontWeight.w500, + fontSize: 12), ), ), ), @@ -173,10 +171,7 @@ class AnonPayInvoicePage extends BasePage { anonInvoicePageViewModel.generateDonationLink(); } }, - color: Theme.of(context) - .accentTextTheme! - .bodyLarge! - .color!, + color: Theme.of(context).accentTextTheme!.bodyLarge!.color!, textColor: Colors.white, isLoading: anonInvoicePageViewModel.state is IsExecutingState, ), diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 4d99244fa..b3cc3078e 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -62,7 +62,7 @@ class SendPage extends BasePage { final _closeButton = currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context); + bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; return MergeSemantics( child: SizedBox( @@ -94,7 +94,7 @@ class SendPage extends BasePage { double _sendCardHeight(BuildContext context) { final double initialHeight = sendViewModel.isElectrumWallet ? 490 : 465; - if (!ResponsiveLayoutUtil.instance.isMobile(context)) { + if (!ResponsiveLayoutUtil.instance.isMobile) { return initialHeight - 66; } return initialHeight; diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 96045b1bd..2b4b40fa3 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -122,7 +122,7 @@ class SendCardState extends State color: Colors.transparent, )), Container( - decoration: ResponsiveLayoutUtil.instance.isMobile(context) ? BoxDecoration( + decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration( borderRadius: BorderRadius.only( bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), @@ -137,9 +137,9 @@ class SendCardState extends State child: Padding( padding: EdgeInsets.fromLTRB( 24, - ResponsiveLayoutUtil.instance.isMobile(context) ? 100 : 55, + ResponsiveLayoutUtil.instance.isMobile ? 100 : 55, 24, - ResponsiveLayoutUtil.instance.isMobile(context) ? 32 : 0, + ResponsiveLayoutUtil.instance.isMobile ? 32 : 0, ), child: SingleChildScrollView( child: Observer(builder: (_) => Column( diff --git a/lib/src/widgets/add_template_button.dart b/lib/src/widgets/add_template_button.dart index 87951e044..c88b72e7f 100644 --- a/lib/src/widgets/add_template_button.dart +++ b/lib/src/widgets/add_template_button.dart @@ -26,7 +26,7 @@ class AddTemplateButton extends StatelessWidget { child: Container( height: 34, padding: EdgeInsets.symmetric( - horizontal: ResponsiveLayoutUtil.instance.isMobile(context) ? 10 : 30), + horizontal: ResponsiveLayoutUtil.instance.isMobile ? 10 : 30), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(20)), diff --git a/lib/utils/distribution_info.dart b/lib/utils/distribution_info.dart index 859c507a3..0d7f65db4 100644 --- a/lib/utils/distribution_info.dart +++ b/lib/utils/distribution_info.dart @@ -1,5 +1,5 @@ import 'dart:io'; -import 'package:package_info/package_info.dart'; +import 'package:package_info_plus/package_info_plus.dart'; enum DistributionType { googleplay, github, appstore, fdroid } diff --git a/lib/view_model/dashboard/market_place_view_model.dart b/lib/view_model/dashboard/market_place_view_model.dart new file mode 100644 index 000000000..470041127 --- /dev/null +++ b/lib/view_model/dashboard/market_place_view_model.dart @@ -0,0 +1,17 @@ +import 'package:cake_wallet/ionia/ionia_service.dart'; +import 'package:mobx/mobx.dart'; + +part 'market_place_view_model.g.dart'; + +class MarketPlaceViewModel = MarketPlaceViewModelBase with _$MarketPlaceViewModel; + +abstract class MarketPlaceViewModelBase with Store { + final IoniaService _ioniaService; + + MarketPlaceViewModelBase(this._ioniaService); + + + Future isIoniaUserAuthenticated() async { + return await _ioniaService.isLogined(); + } +} \ No newline at end of file diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart index 09527ee0f..b12fe0c90 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -1,10 +1,6 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/balance.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/wallet_base.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/store/app_store.dart'; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index c0a406a37..d99b4bedd 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,7 +9,6 @@ import connectivity_macos import cw_monero import device_info_plus import devicelocale -import flutter_secure_storage_macos import in_app_review import package_info_plus import path_provider_foundation @@ -25,7 +24,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) - FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 36dee3d83..2ccdc183c 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,7 +1,7 @@ PODS: - - connectivity_macos (0.0.1): + - connectivity_plus_macos (0.0.1): - FlutterMacOS - - Reachability + - ReachabilitySwift - cw_monero (0.0.1): - cw_monero/Boost (= 0.0.1) - cw_monero/Monero (= 0.0.1) @@ -28,7 +28,7 @@ PODS: - FlutterMacOS (1.0.0) - in_app_review (0.2.0): - FlutterMacOS - - package_info_plus (0.0.1): + - package_info (0.0.1): - FlutterMacOS - path_provider_foundation (0.0.1): - Flutter @@ -37,7 +37,7 @@ PODS: - FlutterMacOS - platform_device_id_macos (0.0.1): - FlutterMacOS - - Reachability (3.2) + - ReachabilitySwift (5.0.0) - share_plus_macos (0.0.1): - FlutterMacOS - shared_preferences_foundation (0.0.1): @@ -49,14 +49,14 @@ PODS: - FlutterMacOS DEPENDENCIES: - - connectivity_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_macos/macos`) + - connectivity_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos`) - cw_monero (from `Flutter/ephemeral/.symlinks/plugins/cw_monero/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) - - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) + - package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) - platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`) - platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`) @@ -67,11 +67,11 @@ DEPENDENCIES: SPEC REPOS: trunk: - - Reachability + - ReachabilitySwift EXTERNAL SOURCES: - connectivity_macos: - :path: Flutter/ephemeral/.symlinks/plugins/connectivity_macos/macos + connectivity_plus_macos: + :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos cw_monero: :path: Flutter/ephemeral/.symlinks/plugins/cw_monero/macos device_info_plus: @@ -84,8 +84,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral in_app_review: :path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos - package_info_plus: - :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos + package_info: + :path: Flutter/ephemeral/.symlinks/plugins/package_info/macos path_provider_foundation: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos platform_device_id: @@ -102,23 +102,23 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos SPEC CHECKSUMS: - connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9 + connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 - package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 + package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2 + path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763 platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94 - Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 + ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451 wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9 -PODFILE CHECKSUM: 505596d150d38022472859d890f709281982e016 +PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f -COCOAPODS: 1.11.2 +COCOAPODS: 1.12.1 diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index e3ee883f9..e42b9a8f3 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -321,6 +321,12 @@ "trade_state_timeout": "نفذ الوقت", "trade_state_created": "تم الأنشاء", "trade_state_finished": "تم", + "invalid_password": "رمز مرور خاطئ", + "unlock": "الغاء القفل", + "enter_wallet_password": "أدخل كلمة مرور المحفظة", + "repeate_wallet_password": "كرر كلمة مرور المحفظة", + "wallet_password_is_empty": "كلمة مرور المحفظة فارغة. يجب ألا تكون كلمة مرور المحفظة فارغة", + "repeated_password_is_incorrect": "كلمة المرور المتكررة غير صحيحة. يرجى إعادة كلمة مرور المحفظة مرة أخرى.", "change_language": "تغيير اللغة", "change_language_to": "هل تريد تغيير اللغة إلى ${language}؟", "paste": "لصق", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 97f0c415e..af8147f7f 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -321,6 +321,12 @@ "trade_state_timeout": "Време за изчакване", "trade_state_created": "Създадено", "trade_state_finished": "Завършено", + "invalid_password" : "Невалидна парола", + "unlock" : "Отключи", + "enter_wallet_password" : "Въведете паролата на портфейла", + "repeate_wallet_password" : "Повторете паролата на портфейла", + "wallet_password_is_empty" : "Паролата за Wallet е празна. Паролата за Wallet не трябва да е празна", + "repeated_password_is_incorrect" : "Повтарящата се парола е неправилна. Моля, повторете отново паролата за портфейла.", "change_language": "Смяна на езика", "change_language_to": "Смяна на езика на ${language}?", "paste": "Поставяне", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 9c6dabbb6..25be43579 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -321,6 +321,12 @@ "trade_state_timeout": "lokacin da ya ƙare", "trade_state_created": "an halicci", "trade_state_finished": "an kammala", + "invalid_password" : "Mot de passe incorrect", + "unlock" : "Ouvrir", + "enter_wallet_password" : "Entrez le mot de passe du portefeuille", + "repeate_wallet_password" : "Répétez le mot de passe du portefeuille", + "wallet_password_is_empty" : "Le mot de passe du portefeuille est vide. Le mot de passe du portefeuille ne doit pas être vide", + "repeated_password_is_incorrect" : "Le mot de passe répété est incorrect. Veuillez répéter le mot de passe du portefeuille.", "change_language": "canja harshen", "change_language_to": "canja harshen zuwa ${language}?", "paste": "Manna", @@ -619,4 +625,3 @@ "share": "Raba", "slidable": "Mai iya zamewa" } - diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index a875b220d..3a940e381 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -250,8 +250,8 @@ "transaction_details_recipient_address": "Àwọn àdírẹ́sì olùgbà", "wallet_list_title": "Àpamọ́wọ́ Monero", "wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun", - "wallet_list_edit_wallet" : "Ṣatunkọ apamọwọ", - "wallet_list_wallet_name" : "Orukọ apamọwọ", + "wallet_list_edit_wallet" : "Ṣatunkọ apamọwọ", + "wallet_list_wallet_name" : "Orukọ apamọwọ", "wallet_list_restore_wallet": "Restore àpamọ́wọ́", "wallet_list_load_wallet": "Load àpamọ́wọ́", "wallet_list_loading_wallet": "Ń ṣí àpamọ́wọ́ ${wallet_name}",