From 4c9c6a1eae2bf056e090272842abd328ddf62b23 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 14 Sep 2023 22:12:41 +0300 Subject: [PATCH 1/5] CW- 463 Fix transaction receive address not showing for Eth/Erc20 (#1076) * Fix transaction receive address not showing for Eth/Erc20 [skip ci] * Fix transaction receive address for Eth/Erc20 --- cw_core/lib/transaction_info.dart | 1 + cw_ethereum/lib/ethereum_transaction_info.dart | 4 ++++ cw_ethereum/lib/ethereum_wallet.dart | 1 + lib/exchange/sideshift/sideshift_exchange_provider.dart | 2 +- lib/view_model/transaction_details_view_model.dart | 2 ++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cw_core/lib/transaction_info.dart b/cw_core/lib/transaction_info.dart index b8e4a5e0c..38b4b799d 100644 --- a/cw_core/lib/transaction_info.dart +++ b/cw_core/lib/transaction_info.dart @@ -14,6 +14,7 @@ abstract class TransactionInfo extends Object with Keyable { String fiatAmount(); String? feeFormatted(); void changeFiatAmount(String amount); + String? to; @override dynamic get keyIndex => id; diff --git a/cw_ethereum/lib/ethereum_transaction_info.dart b/cw_ethereum/lib/ethereum_transaction_info.dart index efdc61407..a0649ba25 100644 --- a/cw_ethereum/lib/ethereum_transaction_info.dart +++ b/cw_ethereum/lib/ethereum_transaction_info.dart @@ -14,6 +14,7 @@ class EthereumTransactionInfo extends TransactionInfo { required this.isPending, required this.date, required this.confirmations, + required this.to, }) : this.amount = ethAmount.toInt(), this.fee = ethFee.toInt(); @@ -30,6 +31,7 @@ class EthereumTransactionInfo extends TransactionInfo { final int confirmations; final String tokenSymbol; String? _fiatAmount; + final String? to; @override String amountFormatted() => @@ -56,6 +58,7 @@ class EthereumTransactionInfo extends TransactionInfo { isPending: data['isPending'] as bool, confirmations: data['confirmations'] as int, tokenSymbol: data['tokenSymbol'] as String, + to: data['to'], ); } @@ -70,5 +73,6 @@ class EthereumTransactionInfo extends TransactionInfo { 'isPending': isPending, 'confirmations': confirmations, 'tokenSymbol': tokenSymbol, + 'to': to, }; } diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 8d7c477e1..b5bbdb58a 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -283,6 +283,7 @@ abstract class EthereumWalletBase ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice, exponent: transactionModel.tokenDecimal ?? 18, tokenSymbol: transactionModel.tokenSymbol ?? "ETH", + to: transactionModel.to, ); } diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index 257d339cf..84b4cd4e0 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -69,7 +69,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { final depositNetwork = _networkFor(from); final settleNetwork = _networkFor(to); - final url = "$apiBaseUrl$rangePath/$fromCurrency-$depositNetwork/$toCurrency-$settleNetwork"; + final url = "$apiBaseUrl$rangePath/$fromCurrency-$depositNetwork/$toCurrency-$settleNetwork?amount=$amount"; final uri = Uri.parse(url); final response = await get(uri); diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index bb6008754..1620870b4 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -215,6 +215,8 @@ abstract class TransactionDetailsViewModelBase with Store { StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()), if (tx.feeFormatted()?.isNotEmpty ?? false) StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!), + if (showRecipientAddress && tx.to != null) + StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!), ]; items.addAll(_items); From ce4d375abfa90f0a69527ae94fcb87ceb6914f71 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 14 Sep 2023 22:14:16 +0300 Subject: [PATCH 2/5] Generic fixes and enhancements (#1083) * Add exception handler to fiat APIs Increase send card size for coin control Fix Monero.com unspent coins hive box issue minor bug fix * Remove EIP-1559 parameters from Eth transaction Enhance error reporting * Throw error if not enough monero utx outputs are selected * Fix Search text color * Fix Ethereum sending EIP-1559 transactions * Add transaction data to ERC20 transactions * Add input check in single output transactions as well * Fix Node deletion issue Handle user input error in anonpay * Remove exception handler from fiat conversion since it's not working with isolates * Require enough utxo for amount and fees; More insightful Error messages * Add cakewallet to applinks [skip ci] * Add cakewallet app link for iOS [skip ci] * Add applink depending on app scheme variable * Add applink in iOS custom to the app getting built [skip ci] * Handle normal app links without considering them as Payment URIs * Minor fix [skip ci] * Fixate encrypt package version as the recent update they made has some issues [skip ci] --------- Co-authored-by: Konstantin Ullrich --- android/app/src/main/AndroidManifestBase.xml | 1 + cw_ethereum/lib/ethereum_client.dart | 3 ++- ...onero_transaction_no_inputs_exception.dart | 6 ++++- cw_monero/lib/monero_wallet.dart | 13 ++++++++++- ios/Podfile.lock | 23 +++++++++++++++++++ ios/Runner/InfoBase.plist | 4 ++++ lib/main.dart | 2 +- .../screens/dashboard/home_settings_page.dart | 4 +++- lib/src/screens/root/root.dart | 8 ++++--- lib/src/screens/send/send_page.dart | 2 +- .../screens/settings/manage_nodes_page.dart | 5 ++-- lib/utils/exception_handler.dart | 12 ++++++++++ .../anon_invoice_page_view_model.dart | 6 ++++- .../exchange/exchange_view_model.dart | 5 +++- pubspec_base.yaml | 2 +- scripts/android/app_env.sh | 8 ++++++- scripts/android/inject_app_details.sh | 1 + scripts/ios/app_config.sh | 5 ++++ 18 files changed, 94 insertions(+), 16 deletions(-) diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index b40aeb7c8..9b3f47314 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -46,6 +46,7 @@ + diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 7eba43aa7..e10e79f1e 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -93,6 +93,7 @@ class EthereumClient { EthereumAddress.fromHex(toAddress), BigInt.parse(amount), credentials: privateKey, + transaction: transaction, ); }; } @@ -107,7 +108,7 @@ class EthereumClient { } Future sendTransaction(Uint8List signedTransaction) async => - await _client!.sendRawTransaction(signedTransaction); + await _client!.sendRawTransaction(prependTransactionType(0x02, signedTransaction)); Future getTransactionDetails(String transactionHash) async { // Wait for the transaction receipt to become available diff --git a/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart b/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart index 5d808be8f..453482e0a 100644 --- a/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart +++ b/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart @@ -1,4 +1,8 @@ class MoneroTransactionNoInputsException implements Exception { + MoneroTransactionNoInputsException(this.inputsSize); + + int inputsSize; + @override - String toString() => 'Not enough inputs available. Please select more under Coin Control'; + String toString() => 'Not enough inputs ($inputsSize) selected. Please select more under Coin Control'; } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 69cd5458e..f9b3c1997 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -210,7 +210,7 @@ abstract class MoneroWalletBase extends WalletBase acc + (value.formattedCryptoAmount ?? 0)); + final estimatedFee = calculateEstimatedFee(_credentials.priority, totalAmount); if (unlockedBalance < totalAmount) { throw MoneroTransactionCreationException('You do not have enough XMR to send this amount.'); } + if (allInputsAmount < totalAmount + estimatedFee) { + throw MoneroTransactionNoInputsException(inputs.length); + } + final moneroOutputs = outputs.map((output) { final outputAddress = output.isParsedAddress ? output.extractedAddress @@ -262,6 +267,12 @@ abstract class MoneroWalletBase extends WalletBasecakewallet + + CFBundleTypeRole + Editor + CFBundleTypeRole Editor diff --git a/lib/main.dart b/lib/main.dart index 62d18708e..40d7468f2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -114,7 +114,7 @@ Future initializeAppConfigs() async { CakeHive.registerAdapter(OrderAdapter()); } - if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { + if (!CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { CakeHive.registerAdapter(UnspentCoinsInfoAdapter()); } diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart index 9303cb053..a08b8a8a7 100644 --- a/lib/src/screens/dashboard/home_settings_page.dart +++ b/lib/src/screens/dashboard/home_settings_page.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.da import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/themes/extensions/address_theme.dart'; import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -55,7 +56,8 @@ class HomeSettingsPage extends BasePage { padding: const EdgeInsetsDirectional.only(start: 16), child: TextFormField( controller: _searchController, - style: TextStyle(color: Theme.of(context).dialogTheme.backgroundColor), + style: TextStyle( + color: Theme.of(context).extension()!.searchHintColor), decoration: InputDecoration( hintText: S.of(context).search_add_token, prefixIcon: Image.asset("assets/images/search_icon.png"), diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 3298a50c0..af775705b 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -140,7 +140,7 @@ class RootState extends State with WidgetsBindingObserver { } _reset(); totpAuth.close( - route: launchUri != null ? Routes.send : null, + route: _isValidPaymentUri() ? Routes.send : null, arguments: PaymentRequest.fromUri(launchUri), ); launchUri = null; @@ -152,7 +152,7 @@ class RootState extends State with WidgetsBindingObserver { } else { _reset(); auth.close( - route: launchUri != null ? Routes.send : null, + route: _isValidPaymentUri() ? Routes.send : null, arguments: PaymentRequest.fromUri(launchUri), ); launchUri = null; @@ -161,7 +161,7 @@ class RootState extends State with WidgetsBindingObserver { }, ); }); - } else if (launchUri != null) { + } else if (_isValidPaymentUri()) { widget.navigatorKey.currentState?.pushNamed( Routes.send, arguments: PaymentRequest.fromUri(launchUri), @@ -183,4 +183,6 @@ class RootState extends State with WidgetsBindingObserver { _isInactive = value; _isInactiveController.add(value); } + + bool _isValidPaymentUri() => launchUri?.path.isNotEmpty ?? false; } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index b24e9b01f..961cf4ba5 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -100,7 +100,7 @@ class SendPage extends BasePage { AppBarStyle get appBarStyle => AppBarStyle.transparent; double _sendCardHeight(BuildContext context) { - final double initialHeight = sendViewModel.hasCoinControl ? 490 : 465; + final double initialHeight = sendViewModel.hasCoinControl ? 500 : 465; if (!ResponsiveLayoutUtil.instance.isMobile) { return initialHeight - 66; diff --git a/lib/src/screens/settings/manage_nodes_page.dart b/lib/src/screens/settings/manage_nodes_page.dart index 4b1034f2b..2b96a3053 100644 --- a/lib/src/screens/settings/manage_nodes_page.dart +++ b/lib/src/screens/settings/manage_nodes_page.dart @@ -34,13 +34,12 @@ class ManageNodesPage extends BasePage { SizedBox(height: 20), Observer( builder: (BuildContext context) { + int itemsCount = nodeListViewModel.nodes.length; return Flexible( child: SectionStandardList( sectionCount: 1, dividerPadding: EdgeInsets.symmetric(horizontal: 24), - itemCounter: (int sectionIndex) { - return nodeListViewModel.nodes.length; - }, + itemCounter: (int sectionIndex) => itemsCount, itemBuilder: (_, index) { return Observer( builder: (context) { diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart index e8e7702fa..5c51a8757 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -32,6 +32,14 @@ class ExceptionHandler { const String separator = '''\n\n========================================================== ==========================================================\n\n'''; + /// don't save existing errors + if (file.existsSync()) { + final String fileContent = await file.readAsString(); + if (fileContent.contains("${exception.values.first}")) { + return; + } + } + file.writeAsStringSync( "$exception $separator", mode: FileMode.append, @@ -83,6 +91,10 @@ class ExceptionHandler { library: errorDetails.library, ); + if (errorDetails.silent) { + return; + } + final sharedPrefs = await SharedPreferences.getInstance(); final lastPopupDate = diff --git a/lib/view_model/anon_invoice_page_view_model.dart b/lib/view_model/anon_invoice_page_view_model.dart index b9617e6dd..53e8473a0 100644 --- a/lib/view_model/anon_invoice_page_view_model.dart +++ b/lib/view_model/anon_invoice_page_view_model.dart @@ -93,7 +93,11 @@ abstract class AnonInvoicePageViewModelBase with Store { Future createInvoice() async { state = IsExecutingState(); if (amount.isNotEmpty) { - final amountInCrypto = double.parse(amount); + final amountInCrypto = double.tryParse(amount); + if (amountInCrypto == null) { + state = FailureState('Amount is invalid'); + return; + } if (minimum != null && amountInCrypto < minimum!) { state = FailureState('Amount is too small'); return; diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 4ff3cb390..2e90a3a33 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -225,7 +225,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @computed List get walletContactsToShow => contactListViewModel.walletContacts - .where((element) => receiveCurrency == null || element.type == receiveCurrency) + .where((element) => element.type == receiveCurrency) .toList(); @action @@ -550,6 +550,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with amount = amount.replaceAll(',', '.'); if (limitsState is LimitsLoadedSuccessfully) { + if (double.tryParse(amount) == null) { + continue; + } if (limits.max != null && double.parse(amount) < limits.min!) { continue; } else if (limits.max != null && double.parse(amount) > limits.max!) { diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 4655a70b5..da79a5076 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -49,7 +49,7 @@ dependencies: lottie: ^1.3.0 animate_do: ^2.1.0 cupertino_icons: ^1.0.5 - encrypt: ^5.0.1 + encrypt: 5.0.1 crypto: ^3.0.2 # password: ^1.0.0 basic_utils: ^5.6.1 diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 627b8d318..ed86b1933 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -5,6 +5,7 @@ APP_ANDROID_VERSION="" APP_ANDROID_BUILD_VERSION="" APP_ANDROID_ID="" APP_ANDROID_PACKAGE="" +APP_ANDROID_SCHEME="" MONERO_COM="monero.com" CAKEWALLET="cakewallet" @@ -18,12 +19,14 @@ MONERO_COM_VERSION="1.6.0" MONERO_COM_BUILD_NUMBER=56 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" +MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.9.0" CAKEWALLET_BUILD_NUMBER=169 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" +CAKEWALLET_SCHEME="cakewallet" HAVEN_NAME="Haven" HAVEN_VERSION="1.0.0" @@ -44,6 +47,7 @@ case $APP_ANDROID_TYPE in APP_ANDROID_BUILD_NUMBER=$MONERO_COM_BUILD_NUMBER APP_ANDROID_BUNDLE_ID=$MONERO_COM_BUNDLE_ID APP_ANDROID_PACKAGE=$MONERO_COM_PACKAGE + APP_ANDROID_SCHEME=$MONERO_COM_SCHEME ;; $CAKEWALLET) APP_ANDROID_NAME=$CAKEWALLET_NAME @@ -51,6 +55,7 @@ case $APP_ANDROID_TYPE in APP_ANDROID_BUILD_NUMBER=$CAKEWALLET_BUILD_NUMBER APP_ANDROID_BUNDLE_ID=$CAKEWALLET_BUNDLE_ID APP_ANDROID_PACKAGE=$CAKEWALLET_PACKAGE + APP_ANDROID_SCHEME=$CAKEWALLET_SCHEME ;; $HAVEN) APP_ANDROID_NAME=$HAVEN_NAME @@ -66,4 +71,5 @@ export APP_ANDROID_NAME export APP_ANDROID_VERSION export APP_ANDROID_BUILD_NUMBER export APP_ANDROID_BUNDLE_ID -export APP_ANDROID_PACKAGE \ No newline at end of file +export APP_ANDROID_PACKAGE +export APP_ANDROID_SCHEME \ No newline at end of file diff --git a/scripts/android/inject_app_details.sh b/scripts/android/inject_app_details.sh index 340966044..27b7efa39 100755 --- a/scripts/android/inject_app_details.sh +++ b/scripts/android/inject_app_details.sh @@ -8,6 +8,7 @@ fi cd ../.. sed -i "0,/version:/{s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/}" ./pubspec.yaml sed -i "0,/version:/{s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/}" ./android/app/src/main/AndroidManifest.xml +sed -i "0,/__APP_SCHEME__/s/__APP_SCHEME__/${APP_ANDROID_SCHEME}/" ./android/app/src/main/AndroidManifest.xml sed -i "0,/version:/{s/__versionCode__/${APP_ANDROID_BUILD_NUMBER}/}" ./android/app/src/main/AndroidManifest.xml sed -i "0,/version:/{s/__versionName__/${APP_ANDROID_VERSION}/}" ./android/app/src/main/AndroidManifest.xml cd scripts/android diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh index 470f47efc..82b333d36 100755 --- a/scripts/ios/app_config.sh +++ b/scripts/ios/app_config.sh @@ -16,6 +16,11 @@ cp -rf ./ios/Runner/InfoBase.plist ./ios/Runner/Info.plist /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier ${APP_IOS_BUNDLE_ID}" ./ios/Runner/Info.plist /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${APP_IOS_VERSION}" ./ios/Runner/Info.plist /usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${APP_IOS_BUILD_NUMBER}" ./ios/Runner/Info.plist + +/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLName string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist +/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes array" ./ios/Runner/Info.plist +/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes: string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist + CONFIG_ARGS="" case $APP_IOS_TYPE in From d972363417cc226e7d0acfef5b5388724e2546e2 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 14 Sep 2023 21:14:49 +0200 Subject: [PATCH 3/5] Add additional Buy Provider (#1071) * CW-466 Add Buy Options Page * CW-466 Add Buy Options * CW-466 Add Default Buy Provider to Other Settings * CW-466 Onramper is working from Buy Options * CW-466 Onramper is working from Buy Options * CW-466 Translation improvements * CW-466 Add Onramper & Robinhood Logos * CW-466 Implement Robinhood Flow * CW-466 Fix Robinhood Flow * CW-466 Add RH-Secrets * CW-466 Have RH Translation in English only * Add missing URI details * CW-466 Implement default Buy Provider * CW-466 Fix Padding Buy Provider Options * CW-466 Fix Bitcoin and Litecoin Signatures * CW-466 Fix Error Message * CW-466 Resolve requested changes * Add exception handler to robinhood API calls * CW-466 Fix Theming --------- Co-authored-by: Justin Ehrenhofer Co-authored-by: OmarHatem --- .github/workflows/pr_test_build.yml | 2 + assets/images/onramper_dark.png | Bin 0 -> 3697 bytes assets/images/onramper_light.png | Bin 0 -> 3269 bytes assets/images/robinhood_dark.png | Bin 0 -> 3047 bytes assets/images/robinhood_light.png | Bin 0 -> 2256 bytes cw_bitcoin/lib/electrum_wallet.dart | 10 + cw_core/lib/wallet_base.dart | 2 + cw_ethereum/lib/ethereum_wallet.dart | 5 + lib/buy/onramper/onramper_buy_provider.dart | 12 + lib/buy/robinhood/robinhood_buy_provider.dart | 92 ++++++ lib/core/backup_service.dart | 5 + lib/di.dart | 12 +- lib/entities/buy_provider_types.dart | 19 ++ lib/entities/main_actions.dart | 27 +- lib/entities/preferences_key.dart | 1 + lib/router.dart | 8 +- lib/routes.dart | 2 +- lib/src/screens/buy/buy_options_page.dart | 76 +++++ lib/src/screens/buy/pre_order_page.dart | 304 ------------------ .../screens/restore/restore_options_page.dart | 8 +- .../restore/widgets/restore_button.dart | 74 ----- .../screens/settings/other_settings_page.dart | 9 + .../widgets/settings_version_cell.dart | 2 +- lib/src/screens/support/support_page.dart | 8 +- .../option_tile.dart} | 11 +- lib/store/settings_store.dart | 14 + lib/themes/dark_theme.dart | 5 + lib/themes/extensions/option_tile_theme.dart | 30 ++ lib/themes/high_contrast_theme.dart | 5 + lib/themes/light_theme.dart | 5 + lib/themes/theme_base.dart | 4 + .../dashboard/dashboard_view_model.dart | 4 + .../settings/other_settings_view_model.dart | 14 + res/values/strings_ar.arb | 10 +- res/values/strings_bg.arb | 9 +- res/values/strings_cs.arb | 9 +- res/values/strings_de.arb | 35 +- res/values/strings_en.arb | 10 +- res/values/strings_es.arb | 9 +- res/values/strings_fr.arb | 9 +- res/values/strings_ha.arb | 9 +- res/values/strings_hi.arb | 9 +- res/values/strings_hr.arb | 9 +- res/values/strings_id.arb | 9 +- res/values/strings_it.arb | 9 +- res/values/strings_ja.arb | 9 +- res/values/strings_ko.arb | 9 +- res/values/strings_my.arb | 9 +- res/values/strings_nl.arb | 9 +- res/values/strings_pl.arb | 9 +- res/values/strings_pt.arb | 9 +- res/values/strings_ru.arb | 9 +- res/values/strings_th.arb | 9 +- res/values/strings_tr.arb | 9 +- res/values/strings_uk.arb | 9 +- res/values/strings_ur.arb | 9 +- res/values/strings_yo.arb | 9 +- res/values/strings_zh.arb | 9 +- tool/utils/secret_key.dart | 2 + 59 files changed, 548 insertions(+), 477 deletions(-) create mode 100644 assets/images/onramper_dark.png create mode 100644 assets/images/onramper_light.png create mode 100644 assets/images/robinhood_dark.png create mode 100644 assets/images/robinhood_light.png create mode 100644 lib/buy/robinhood/robinhood_buy_provider.dart create mode 100644 lib/entities/buy_provider_types.dart create mode 100644 lib/src/screens/buy/buy_options_page.dart delete mode 100644 lib/src/screens/buy/pre_order_page.dart delete mode 100644 lib/src/screens/restore/widgets/restore_button.dart rename lib/src/{screens/support/widgets/support_tiles.dart => widgets/option_tile.dart} (82%) create mode 100644 lib/themes/extensions/option_tile_theme.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 30bf3058e..92d2ad8ba 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -128,6 +128,8 @@ jobs: echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart + echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart + echo "const robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart - name: Rename app run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties diff --git a/assets/images/onramper_dark.png b/assets/images/onramper_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..62f37cd2936d03eacc8e93bcbcf7c3850de5f28b GIT binary patch literal 3697 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 literal 0 HcmV?d00001 diff --git a/assets/images/robinhood_dark.png b/assets/images/robinhood_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0d7273fc400920f97521ae096763ded867e74766 GIT binary patch literal 3047 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 literal 0 HcmV?d00001 diff --git a/assets/images/robinhood_light.png b/assets/images/robinhood_light.png new file mode 100644 index 0000000000000000000000000000000000000000..24aa345f13849ed611378c767d4e064be0630dd1 GIT binary patch literal 2256 zcmV;>2ru`EP)sTw9Js!+{POQHl)*Lt1dbaeW zHJLp=&VDDF7m$h4dOdqI#_obKN~1?8O&=k$6Da!5v@(+8LeAWnt$sT_NpLLDNS+l3xbzcX|tKf<5iwcaAKZ+_PL zN$YRy5L!5pbk>Kcoh?u#h)ER(P2e#e`)qvA5x0kOVWjoO<%zCi@C6vxNP9@4^-b&F zbx(AO-~=r*xX4bS`=(A%-d@v)i@`VO(e}?INuZR%@$oTUy?QnM_u*lAZa+UiPxbWl zguA;tj7B4L%m|K`>LwIqB_OS&4K1#(uZuj-3m@qD`UL2@{R$h911Lh))zww831o7| z?;%4=QUFEB8V-lWHW&;BUB8!B32+W{+Gr8x5?PjY{eE(Ik^<=tQjR_od)L zusb4mVJ@Mw?ylck21gXSZKybNi8M_)yhl~>56ak{mg*E}Zg67K%7*u~zH8??l zMU7pX%LvM*7b=cbgB1ef;^M-~T&h%!$K$C4LguFSFJ4xj5LEP%xtEuhOTRZJK0ZF; z%aTw@;9kLl4E=>nPWihW{qj6xa7(+0h) z{2>_b@9%MRbkx}Kw17aO2t7DBm_D}}?X=k7iY{4#5h-R-Y#aOz0b#H7P=;$(hv<<^ zt!BL^CnwkhpJ?9$3zum_5ZiI6qC~4hXJ=={?d@$bnM~HsVb9Oc=f~4=rYc3pyPzYV zTR%*y<|<|l^cF4KQBBwv+Z-~NFiU_pH#cjKr;~tbpD5elbEb`S*2BX?;frk!l^PAM z2Gdd@gBo;`7It6WGHs-j+N|l?i}mzqFZR0_%w(~DmF{eV#g4yvI#l>V)L`JSUUVs!CEHc4rlQG--r&dLOlflfBsyd~#*dT7dGnFBIYs6I1dh@2-VM;{~ zok2G~*KCuuOPc0*MkPrXj>+KH5Cj=pw}7w?J?_p8)8p>S^;=_b)A53!FDH@n8Io7jf!r(UJu6=1WV`&c!F4!APbJ8}LOLJW* z(gp7Q;;OoBv#h9_vaCbbkmn2jG-vkR()#}WdxQk*Gw}5E)GPArthr6CIDT7c%-~MJZHxaj$z|IOVc+G~W*Jd%L8D2z2!maBYxov4nvM@h50qq$!5rGt zyp9haKFn*yZEDq&SP8wGVHMMrksB~S6KR2d6?S6PW?B_sVr4YlwsXzBq3a42F|lgY zB^jJ@ZzvTjT%xZ{V#VO&7j~)X&PpYru}z7ViN3Z=i2){7wiFpGV$)sS4o5rsTsEm! z32<6e)w~Rtb8l>2beei|oEFt8hXw16?{y_dJNkU1mkKBL*4aR{u<@Ps&dR#&tG-1I z8pG*z>R8oM9`M>2HV(1jb#>}08FY7~V}@IV2bHg-P#Ru|->v5gwQlN{YNbYb-<;O#Wq z)MqrX>eiKC(Glk38R+8@K7Ra&$XZ(8Ym=daGt!K|J+4G;C3;;@!2TO;3K((mz)1=l zk^v~9SZath#IKi?i__Q3x_m)2z0iMJZxP|dA81(jwek6i_Y47kD~nKatzWQZ5(M(8 z@WS;K4hsqfmrJxEUaEQUo7P|0A?$Bf3s_g!1C&h%`|YHRwNXLCmjpfd`gcb943BYl zTO1=MUHgz%QnhVPA+yt@=>J(CcS;IbohHfL6ii4VtMj6{El44&6Qj8;pz$ImUhVZ2 z4947bB#2X}HlnG}F@%sHn(U)b=x{337OHr~vgT^hczXrmYwdKuQyiC<^%a$mS&&SE zc*!=RsQm{5FUc-kqTkURRMa++K)?r}ZdpM`Z4(ONU$%|03Oy!8ct(@4G_O^N%t;}C zBSDN<2NYzD(PSzmPk$mB>qUYxsx$C3)kNzV;!Ob?lb|%4J~Xw9X_hgRB2|>BJ{#XT zp-_IYwVG+0on2TzkF_4P?zQNfK}HaURD-LK!L$-XrXS574=p7%$2`wO _onError = onError; + + @override + String signMessage(String message, {String? address = null}) { + final index = address != null + ? walletAddresses.addresses.firstWhere((element) => element.address == address).index + : null; + return index == null + ? base64Encode(hd.sign(message)) + : base64Encode(hd.derive(index).sign(message)); + } } diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index e24fdb4b0..f8db67b24 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -83,4 +83,6 @@ abstract class WalletBase< void setExceptionHandler(void Function(FlutterErrorDetails) onError) => null; Future renameWalletFiles(String newWalletName); + + String signMessage(String message, {String? address = null}) => throw UnimplementedError(); } diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index b5bbdb58a..012b33a4b 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -31,6 +31,7 @@ import 'package:hive/hive.dart'; import 'package:hex/hex.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:web3dart/crypto.dart'; import 'package:web3dart/web3dart.dart'; import 'package:bip39/bip39.dart' as bip39; import 'package:bip32/bip32.dart' as bip32; @@ -503,4 +504,8 @@ abstract class EthereumWalletBase _transactionsUpdateTimer?.cancel(); } } + + @override + String signMessage(String message, {String? address = null}) => + bytesToHex(_ethPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); } diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index cf4cbd124..2f0e47f02 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -1,10 +1,13 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; class OnRamperBuyProvider { OnRamperBuyProvider({required SettingsStore settingsStore, required WalletBase wallet}) @@ -69,4 +72,13 @@ class OnRamperBuyProvider { 'cardColor': cardColor }); } + + Future launchProvider(BuildContext context) async { + final uri = requestUrl(context); + if (DeviceInfo.instance.isMobile) { + Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]); + } else { + await launchUrl(uri); + } + } } diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart new file mode 100644 index 000000000..0cb367298 --- /dev/null +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -0,0 +1,92 @@ +import 'dart:convert'; + +import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/exception_handler.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:url_launcher/url_launcher.dart'; + +class RobinhoodBuyProvider { + RobinhoodBuyProvider({required WalletBase wallet}) + : this._wallet = wallet; + + final WalletBase _wallet; + + static const _baseUrl = 'applink.robinhood.com'; + static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; + + String get _applicationId => secrets.robinhoodApplicationId; + String get _apiSecret => secrets.robinhoodCIdApiSecret; + + bool get isAvailable => + [WalletType.bitcoin, WalletType.litecoin, WalletType.ethereum].contains(_wallet.type); + + String getSignature(String message) { + switch (_wallet.type) { + case WalletType.ethereum: + return _wallet.signMessage(message); + case WalletType.litecoin: + case WalletType.bitcoin: + return _wallet.signMessage(message, address: _wallet.walletAddresses.address); + default: + throw Exception("WalletType is not available for Robinhood"); + } + } + + Future getConnectId() async { + final walletAddress = _wallet.walletAddresses.address; + final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10; + final message = "$_apiSecret:${valid_until}"; + + final signature = getSignature(message); + + final uri = Uri.https(_cIdBaseUrl, "/api/robinhood"); + + var response = await http.post(uri, + headers: {'Content-Type': 'application/json'}, + body: json + .encode({'valid_until': valid_until, 'wallet': walletAddress, 'signature': signature})); + + if (response.statusCode == 200) { + return (jsonDecode(response.body) as Map)['connectId'] as String; + } else { + throw Exception('Provider currently unavailable. Status: ${response.statusCode} ${response.body}'); + } + } + + Future requestUrl() async { + final connectId = await getConnectId(); + final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_"); + + return Uri.https(_baseUrl, '/u/connect', { + 'applicationId': _applicationId, + 'connectId': connectId, + 'walletAddress': _wallet.walletAddresses.address, + 'userIdentifier': _wallet.walletAddresses.address, + 'supportedNetworks': networkName + }); + } + + Future launchProvider(BuildContext context) async { + try { + final uri = await requestUrl(); + await launchUrl(uri, mode: LaunchMode.externalApplication); + } catch (e, s) { + ExceptionHandler.onError(FlutterErrorDetails(exception: e, stack: s)); + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: "Robinhood Connect", + alertContent: S.of(context).buy_provider_unavailable, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + } + } +} diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 3f430b7e9..24b5558d5 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -208,6 +208,7 @@ class BackupService { final isAppSecure = data[PreferencesKey.isAppSecureKey] as bool?; final disableBuy = data[PreferencesKey.disableBuyKey] as bool?; final disableSell = data[PreferencesKey.disableSellKey] as bool?; + final defaultBuyProvider = data[PreferencesKey.defaultBuyProvider] as int?; final currentTransactionPriorityKeyLegacy = data[PreferencesKey.currentTransactionPriorityKeyLegacy] as int?; final allowBiometricalAuthentication = @@ -276,6 +277,9 @@ class BackupService { if (disableSell != null) await _sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell); + if (defaultBuyProvider != null) + await _sharedPreferences.setInt(PreferencesKey.defaultBuyProvider, defaultBuyProvider); + if (currentTransactionPriorityKeyLegacy != null) await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); @@ -476,6 +480,7 @@ class BackupService { _sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey), PreferencesKey.disableBuyKey: _sharedPreferences.getBool(PreferencesKey.disableBuyKey), PreferencesKey.disableSellKey: _sharedPreferences.getBool(PreferencesKey.disableSellKey), + PreferencesKey.defaultBuyProvider: _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider), PreferencesKey.isDarkThemeLegacy: _sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy), PreferencesKey.currentPinLength: _sharedPreferences.getInt(PreferencesKey.currentPinLength), diff --git a/lib/di.dart b/lib/di.dart index dd3e6c495..a308b989a 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -3,6 +3,7 @@ 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/buy/robinhood/robinhood_buy_provider.dart'; import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; @@ -15,6 +16,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/buy_options_page.dart'; import 'package:cake_wallet/src/screens/buy/webview_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'; @@ -95,7 +97,6 @@ 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'; import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart'; @@ -688,6 +689,9 @@ Future setup({ editingNode: editingNode, isSelected: isSelected)); + getIt.registerFactory( + () => RobinhoodBuyProvider(wallet: getIt.get().wallet!)); + getIt.registerFactory(() => OnRamperBuyProvider( settingsStore: getIt.get().settingsStore, wallet: getIt.get().wallet!, @@ -816,6 +820,8 @@ Future setup({ getIt.registerFactory(() => BuyAmountViewModel()); + getIt.registerFactory(() => BuyOptionsPage()); + getIt.registerFactory(() { final wallet = getIt.get().wallet; @@ -824,10 +830,6 @@ Future setup({ wallet: wallet!); }); - getIt.registerFactory(() { - return PreOrderPage(buyViewModel: getIt.get()); - }); - getIt.registerFactoryParam((List args, _) { final url = args.first as String; final buyViewModel = args[1] as BuyViewModel; diff --git a/lib/entities/buy_provider_types.dart b/lib/entities/buy_provider_types.dart new file mode 100644 index 000000000..90c070e86 --- /dev/null +++ b/lib/entities/buy_provider_types.dart @@ -0,0 +1,19 @@ +import 'package:cake_wallet/generated/i18n.dart'; + +enum BuyProviderType { + AskEachTime, + Robinhood, + Onramper; + + @override + String toString() { + switch (this) { + case BuyProviderType.AskEachTime: + return S.current.ask_each_time; + case BuyProviderType.Robinhood: + return "Robinhood"; + case BuyProviderType.Onramper: + return "Onramper"; + } + } +} diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 2d91983d4..4d2abced9 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -1,6 +1,8 @@ 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/robinhood/robinhood_buy_provider.dart'; import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -41,23 +43,30 @@ class MainActions { isEnabled: (viewModel) => viewModel.isEnabledBuyAction, canShow: (viewModel) => viewModel.hasBuyAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { + final defaultBuyProvider = viewModel.defaultBuyProvider; final walletType = viewModel.type; + if (!viewModel.isEnabledBuyAction) return; + switch (walletType) { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: - case WalletType.monero: - if (viewModel.isEnabledBuyAction) { - final uri = getIt.get().requestUrl(context); - if (DeviceInfo.instance.isMobile) { - Navigator.of(context) - .pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]); - } else { - await launchUrl(uri); - } + switch (defaultBuyProvider) { + case BuyProviderType.AskEachTime: + Navigator.pushNamed(context, Routes.buy); + break; + case BuyProviderType.Onramper: + await getIt.get().launchProvider(context); + break; + case BuyProviderType.Robinhood: + await getIt.get().launchProvider(context); + break; } break; + case WalletType.monero: + await getIt.get().launchProvider(context); + break; default: await showPopUp( context: context, diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 7b4d3d0dc..f699f89f8 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -13,6 +13,7 @@ class PreferencesKey { static const isAppSecureKey = 'is_app_secure'; static const disableBuyKey = 'disable_buy'; static const disableSellKey = 'disable_sell'; + static const defaultBuyProvider = 'default_buy_provider'; static const currentFiatApiModeKey = 'current_fiat_api_mode'; static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication'; diff --git a/lib/router.dart b/lib/router.dart index 0ef91e16f..c73cf72e0 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -7,9 +7,9 @@ import 'package:cake_wallet/entities/qr_view_data.dart'; import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.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_options_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_webview_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/dashboard/edit_token_page.dart'; import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart'; import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart'; @@ -383,10 +383,8 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get(param1: settings.arguments as Order)); - case Routes.preOrder: - return MaterialPageRoute( - builder: (_) => - getIt.get()); + case Routes.buy: + return MaterialPageRoute(builder: (_) => getIt.get()); case Routes.buyWebView: final args = settings.arguments as List; diff --git a/lib/routes.dart b/lib/routes.dart index bcb4c38b5..cb479ddf6 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -50,7 +50,7 @@ class Routes { static const supportLiveChat = '/support/live_chat'; static const supportOtherLinks = '/support/other'; static const orderDetails = '/order_details'; - static const preOrder = '/pre_order'; + static const buy = '/buy'; static const buyWebView = '/buy_web_view'; static const unspentCoinsList = '/unspent_coins_list'; static const unspentCoinsDetails = '/unspent_coins_details'; diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart new file mode 100644 index 000000000..45edfc921 --- /dev/null +++ b/lib/src/screens/buy/buy_options_page.dart @@ -0,0 +1,76 @@ +import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; +import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/option_tile.dart'; +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:flutter/material.dart'; + +class BuyOptionsPage extends BasePage { + final iconDarkRobinhood = 'assets/images/robinhood_dark.png'; + final iconLightRobinhood = 'assets/images/robinhood_light.png'; + final iconDarkOnramper = 'assets/images/onramper_dark.png'; + final iconLightOnramper = 'assets/images/onramper_light.png'; + + @override + String get title => S.current.buy; + + @override + AppBarStyle get appBarStyle => AppBarStyle.regular; + + @override + Widget body(BuildContext context) { + final isLightMode = Theme.of(context).extension()?.useDarkImage ?? false; + final iconRobinhood = + Image.asset(isLightMode ? iconLightRobinhood : iconDarkRobinhood, height: 40, width: 40); + final iconOnramper = + Image.asset(isLightMode ? iconLightOnramper : iconDarkOnramper, height: 40, width: 40); + + return Container( + child: Center( + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 330), + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: iconRobinhood, + title: "Robinhood Connect", + description: S.of(context).robinhood_option_description, + onPressed: () async => + await getIt.get().launchProvider(context), + ), + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: iconOnramper, + title: "Onramper", + description: S.of(context).onramper_option_description, + onPressed: () async => + await getIt.get().launchProvider(context), + ), + ), + Spacer(), + Padding( + padding: EdgeInsets.fromLTRB(24, 24, 24, 32), + child: Text( + S.of(context).select_buy_provider_notice, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context).extension()!.detailsTitlesColor, + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/src/screens/buy/pre_order_page.dart b/lib/src/screens/buy/pre_order_page.dart deleted file mode 100644 index 67b9a18a1..000000000 --- a/lib/src/screens/buy/pre_order_page.dart +++ /dev/null @@ -1,304 +0,0 @@ -import 'package:cake_wallet/buy/buy_amount.dart'; -import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; -import 'package:cake_wallet/entities/fiat_currency.dart'; -import 'package:cake_wallet/src/widgets/picker.dart'; -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; -import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; -import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/src/screens/buy/widgets/buy_list_item.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cake_wallet/view_model/buy/buy_view_model.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:keyboard_actions/keyboard_actions.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -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:cake_wallet/src/widgets/trail_button.dart'; -import 'package:mobx/mobx.dart'; -import 'package:url_launcher/url_launcher.dart'; - -class PreOrderPage extends BasePage { - PreOrderPage({required this.buyViewModel}) - : _amountFocus = FocusNode(), - _amountController = TextEditingController() { - _amountController.addListener(() { - final amount = _amountController.text; - - if (amount != buyViewModel.buyAmountViewModel.amount) { - buyViewModel.buyAmountViewModel.amount = amount; - buyViewModel.selectedProvider = null; - } - }); - - reaction((_) => buyViewModel.buyAmountViewModel.amount, (String amount) { - if (_amountController.text != amount) { - _amountController.text = amount; - } - if (amount.isEmpty) { - buyViewModel.selectedProvider = null; - buyViewModel.isShowProviderButtons = false; - } else { - buyViewModel.isShowProviderButtons = true; - } - }); - } - - 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 => S.current.buy + ' ' + walletTypeToString(buyViewModel.wallet.type); - - @override - bool get resizeToAvoidBottomInset => false; - - @override - bool get extendBodyBehindAppBar => true; - - @override - AppBarStyle get appBarStyle => AppBarStyle.transparent; - - @override - Widget trailing(context) => TrailButton( - caption: S.of(context).clear, - onPressed: () => buyViewModel.reset()); - - @override - Widget body(BuildContext context) { - return KeyboardActions( - config: KeyboardActionsConfig( - keyboardActionsPlatform: KeyboardActionsPlatform.IOS, - keyboardBarColor: Theme.of(context).extension()!.keyboardBarColor, - nextFocus: false, - actions: [ - KeyboardActionsItem( - focusNode: _amountFocus, - toolbarButtons: [(_) => KeyboardDoneButton()], - ), - ]), - child: Container( - height: 0, - color: Theme.of(context).colorScheme.background, - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24), - content: Observer(builder: (_) => Column( - children: [ - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(24), - bottomRight: Radius.circular(24)), - gradient: LinearGradient(colors: [ - Theme.of(context).extension()!.firstGradientColor, - Theme.of(context).extension()!.secondGradientColor, - ], begin: Alignment.topLeft, end: Alignment.bottomRight), - ), - child: Padding( - padding: EdgeInsets.only(top: 100, bottom: 65), - child: Center( - child: Container( - width: 210, - child: BaseTextFormField( - focusNode: _amountFocus, - controller: _amountController, - keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true), - inputFormatters: [FilteringTextInputFormatter.allow(RegExp(_amountPattern))], - prefixIcon: GestureDetector( - onTap: () { - showPopUp( - context: context, - builder: (_) => Picker( - hintText: S.current.search_currency, - items: FiatCurrency.currenciesAvailableToBuyWith, - selectedAtIndex: - FiatCurrency.currenciesAvailableToBuyWith.indexOf(buyViewModel.fiatCurrency), - onItemSelected: (FiatCurrency selectedCurrency) { - buyViewModel.buyAmountViewModel.fiatCurrency = selectedCurrency; - }, - images: FiatCurrency.currenciesAvailableToBuyWith - .map((e) => Image.asset("assets/images/flags/${e.countryCode}.png")) - .toList(), - isGridView: true, - matchingCriteria: (FiatCurrency currency, String searchText) { - return currency.title.toLowerCase().contains(searchText) || - currency.fullName.toLowerCase().contains(searchText); - }, - ), - ); - }, - child: Padding( - padding: EdgeInsets.only(top: 2), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.keyboard_arrow_down, color: Colors.white), - Text( - buyViewModel.fiatCurrency.title + ': ', - style: TextStyle( - fontSize: 36, - fontWeight: FontWeight.w600, - color: Colors.white, - ), - ), - ], - ), - ), - ), - hintText: '0.00', - borderColor: Theme.of(context).extension()!.textFieldBorderBottomPanelColor, - borderWidth: 0.5, - textStyle: TextStyle(fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white), - placeholderTextStyle: TextStyle( - color: Theme.of(context).extension()!.textFieldHintColor, - fontWeight: FontWeight.w500, - fontSize: 36, - ), - ), - ), - ), - ), - ), - if (buyViewModel.isShowProviderButtons) Padding( - padding: EdgeInsets.only(top: 38, bottom: 18), - child: Text( - S.of(context).buy_with + ':', - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).extension()!.titleColor, - fontSize: 18, - fontWeight: FontWeight.bold - ), - ) - ), - if (buyViewModel.isShowProviderButtons) - ...buyViewModel.items.map( - (item) => Observer(builder: (_) => - FutureBuilder( - future: item.buyAmount, - builder: (context, AsyncSnapshot snapshot) { - double sourceAmount; - double destAmount; - double achAmount; - int minAmount; - - if (snapshot.hasData && snapshot.data != null) { - sourceAmount = snapshot.data!.sourceAmount; - destAmount = snapshot.data!.destAmount; - minAmount = snapshot.data!.minAmount; - achAmount = snapshot.data!.achSourceAmount ?? 0; - } else { - sourceAmount = 0.0; - destAmount = 0.0; - minAmount = 0; - achAmount = 0; - } - - return Padding( - padding: - EdgeInsets.only(left: 15, top: 20, right: 15), - child: Observer(builder: (_) { - return BuyListItem( - selectedProvider: - buyViewModel.selectedProvider, - provider: item.provider, - sourceAmount: sourceAmount, - sourceCurrency: buyViewModel.fiatCurrency, - destAmount: destAmount, - destCurrency: buyViewModel.cryptoCurrency, - achSourceAmount: achAmount, - onTap: ((buyViewModel.doubleAmount != 0.0) - && (snapshot.hasData)) ? () => - onSelectBuyProvider( - context: context, - provider: item.provider, - sourceAmount: sourceAmount, - minAmount: minAmount - ) : null - ); - }) - ); - } - )) - ) - ], - )), - bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Observer(builder: (_) { - return LoadingPrimaryButton( - onPressed: () => onPresentProvider(context: context), - text: buyViewModel.selectedProvider == null - ? S.of(context).buy - : S.of(context).buy_with + - ' ${buyViewModel.selectedProvider!.description.title}', - color: Theme.of(context).primaryColor, - textColor: Colors.white, - isLoading: buyViewModel.isRunning, - isDisabled: (buyViewModel.selectedProvider == null) || - buyViewModel.isDisabled - ); - }) - ) - ) - ); - } - - void onSelectBuyProvider({required BuildContext context, required BuyProvider provider, - required double sourceAmount, required int minAmount}) { - - if ((provider is MoonPayBuyProvider)&& - (buyViewModel.buyAmountViewModel.doubleAmount < minAmount)) { - showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: 'MoonPay', - alertContent: S.of(context).moonpay_alert_text( - minAmount.toString(), - buyViewModel.fiatCurrency.toString()), - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); - return; - } - buyViewModel.selectedProvider = provider; - sourceAmount > 0 - ? buyViewModel.isDisabled = false - : buyViewModel.isDisabled = true; - } - - Future onPresentProvider({required BuildContext context}) async { - if (buyViewModel.isRunning) { - return; - } - - buyViewModel.isRunning = true; - final url = await buyViewModel.fetchUrl(); - - if (url.isNotEmpty) { - if (buyViewModel.selectedProvider is MoonPayBuyProvider) { - if (await canLaunch(url)) await launch(url); - } else { - await Navigator.of(context) - .pushNamed(Routes.buyWebView, - arguments: [url, buyViewModel]); - } - } - - buyViewModel.reset(); - buyViewModel.isRunning = false; - } -} diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 3adad4379..191bddfec 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/option_tile.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart'; import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart'; @@ -9,7 +10,6 @@ import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:flutter/cupertino.dart'; -import 'package:cake_wallet/src/screens/restore/widgets/restore_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -35,7 +35,7 @@ class RestoreOptionsPage extends BasePage { child: SingleChildScrollView( child: Column( children: [ - RestoreButton( + OptionTile( onPressed: () => Navigator.pushNamed( context, Routes.restoreWalletFromSeedKeys, arguments: isNewInstall), @@ -45,7 +45,7 @@ class RestoreOptionsPage extends BasePage { if (isNewInstall) Padding( padding: EdgeInsets.only(top: 24), - child: RestoreButton( + child: OptionTile( onPressed: () => Navigator.pushNamed(context, Routes.restoreFromBackup), image: imageBackup, title: S.of(context).restore_title_from_backup, @@ -53,7 +53,7 @@ class RestoreOptionsPage extends BasePage { ), Padding( padding: EdgeInsets.only(top: 24), - child: RestoreButton( + child: OptionTile( onPressed: () async { bool isPinSet = false; if (isNewInstall) { diff --git a/lib/src/screens/restore/widgets/restore_button.dart b/lib/src/screens/restore/widgets/restore_button.dart deleted file mode 100644 index c196de059..000000000 --- a/lib/src/screens/restore/widgets/restore_button.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; - -class RestoreButton extends StatelessWidget { - const RestoreButton( - {required this.onPressed, - required this.image, - required this.title, - required this.description}); - - final VoidCallback onPressed; - final Image image; - final String title; - final String description; - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onPressed, - child: Container( - width: double.infinity, - height: 170, - padding: EdgeInsets.all(24), - alignment: Alignment.topLeft, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12)), - color: Theme.of(context).cardColor, - ), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - image, - Expanded( - child: Padding( - padding: EdgeInsets.only(left: 16), - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.titleColor, - ), - ), - Padding( - padding: EdgeInsets.only(top: 5), - child: Text( - description, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context) - .extension()! - .detailsTitlesColor, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index aea58eb73..0ba4618ac 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; @@ -33,6 +35,13 @@ class OtherSettingsPage extends BasePage { selectedItem: _otherSettingsViewModel.transactionPriority, onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected, ), + SettingsPickerCell( + title: S.current.default_buy_provider, + items: BuyProviderType.values, + displayItem: _otherSettingsViewModel.getBuyProviderType, + selectedItem: _otherSettingsViewModel.buyProviderType, + onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected, + ), SettingsCellWithArrow( title: S.current.settings_terms_and_conditions, handler: (BuildContext context) => diff --git a/lib/src/screens/settings/widgets/settings_version_cell.dart b/lib/src/screens/settings/widgets/settings_version_cell.dart index 8ab1a1672..1607012dc 100644 --- a/lib/src/screens/settings/widgets/settings_version_cell.dart +++ b/lib/src/screens/settings/widgets/settings_version_cell.dart @@ -25,4 +25,4 @@ class SettingsVersionCell extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/src/screens/support/support_page.dart b/lib/src/screens/support/support_page.dart index 883677832..471ff15b0 100644 --- a/lib/src/screens/support/support_page.dart +++ b/lib/src/screens/support/support_page.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/support/widgets/support_tiles.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/option_tile.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/view_model/support_view_model.dart'; import 'package:flutter/material.dart'; @@ -32,7 +32,7 @@ class SupportPage extends BasePage { children: [ Padding( padding: EdgeInsets.only(top: 24), - child: SupportTile( + child: OptionTile( image: imageLiveSupport, title: S.of(context).support_title_live_chat, description: S.of(context).support_description_live_chat, @@ -47,7 +47,7 @@ class SupportPage extends BasePage { ), Padding( padding: EdgeInsets.only(top: 24), - child: SupportTile( + child: OptionTile( image: imageWalletGuides, title: S.of(context).support_title_guides, description: S.of(context).support_description_guides, @@ -56,7 +56,7 @@ class SupportPage extends BasePage { ), Padding( padding: EdgeInsets.only(top: 24), - child: SupportTile( + child: OptionTile( image: imageMoreLinks, title: S.of(context).support_title_other_links, description: S.of(context).support_description_other_links, diff --git a/lib/src/screens/support/widgets/support_tiles.dart b/lib/src/widgets/option_tile.dart similarity index 82% rename from lib/src/screens/support/widgets/support_tiles.dart rename to lib/src/widgets/option_tile.dart index 7107efac6..6a2825003 100644 --- a/lib/src/screens/support/widgets/support_tiles.dart +++ b/lib/src/widgets/option_tile.dart @@ -1,9 +1,8 @@ -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:flutter/material.dart'; -class SupportTile extends StatelessWidget { - const SupportTile( +class OptionTile extends StatelessWidget { + const OptionTile( {required this.onPressed, required this.image, required this.title, @@ -45,7 +44,7 @@ class SupportTile extends StatelessWidget { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.titleColor, + color: Theme.of(context).extension()!.titleColor, ), ), Padding( @@ -55,7 +54,7 @@ class SupportTile extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.detailsTitlesColor, + color: Theme.of(context).extension()!.descriptionColor, ), ), ) diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index f512063a4..2690dcb64 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; +import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; @@ -47,6 +48,7 @@ abstract class SettingsStoreBase with Store { required bool initialAppSecure, required bool initialDisableBuy, required bool initialDisableSell, + required BuyProviderType initialDefaultBuyProvider, required FiatApiMode initialFiatMode, required bool initialAllowBiometricalAuthentication, required String initialTotpSecretKey, @@ -99,6 +101,7 @@ abstract class SettingsStoreBase with Store { isAppSecure = initialAppSecure, disableBuy = initialDisableBuy, disableSell = initialDisableSell, + defaultBuyProvider = initialDefaultBuyProvider, shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard, exchangeStatus = initialExchangeStatus, currentTheme = initialTheme, @@ -200,6 +203,11 @@ abstract class SettingsStoreBase with Store { (bool disableSell) => sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell)); + reaction( + (_) => defaultBuyProvider, + (BuyProviderType defaultBuyProvider) => + sharedPreferences.setInt(PreferencesKey.defaultBuyProvider, defaultBuyProvider.index)); + reaction( (_) => autoGenerateSubaddressStatus, (AutoGenerateSubaddressStatus autoGenerateSubaddressStatus) => sharedPreferences.setInt( @@ -380,6 +388,9 @@ abstract class SettingsStoreBase with Store { @observable bool disableSell; + @observable + BuyProviderType defaultBuyProvider; + @observable bool allowBiometricalAuthentication; @@ -535,6 +546,7 @@ abstract class SettingsStoreBase with Store { final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false; final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false; final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false; + final defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; final currentFiatApiMode = FiatApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw); @@ -661,6 +673,7 @@ abstract class SettingsStoreBase with Store { initialAppSecure: isAppSecure, initialDisableBuy: disableBuy, initialDisableSell: disableSell, + initialDefaultBuyProvider: defaultBuyProvider, initialFiatMode: currentFiatApiMode, initialAllowBiometricalAuthentication: allowBiometricalAuthentication, initialCake2FAPresetOptions: selectedCake2FAPreset, @@ -747,6 +760,7 @@ abstract class SettingsStoreBase with Store { isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; + defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; allowBiometricalAuthentication = sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? allowBiometricalAuthentication; diff --git a/lib/themes/dark_theme.dart b/lib/themes/dark_theme.dart index 747dc2527..4e18628fa 100644 --- a/lib/themes/dark_theme.dart +++ b/lib/themes/dark_theme.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/themes/extensions/info_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:cake_wallet/themes/extensions/order_theme.dart'; import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; @@ -215,6 +216,10 @@ class DarkTheme extends ThemeBase { qrCodeColor: PaletteDark.lightBlueGrey, qrWidgetCopyButtonColor: PaletteDark.lightBlueGrey); + @override + OptionTileTheme get optionTileTheme => OptionTileTheme( + titleColor: primaryTextColor, descriptionColor: primaryTextColor, useDarkImage: false); + @override ThemeData get themeData => super.themeData.copyWith( dividerColor: PaletteDark.dividerColor, diff --git a/lib/themes/extensions/option_tile_theme.dart b/lib/themes/extensions/option_tile_theme.dart new file mode 100644 index 000000000..6c125a4ac --- /dev/null +++ b/lib/themes/extensions/option_tile_theme.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +class OptionTileTheme extends ThemeExtension { + final Color titleColor; + final Color descriptionColor; + final bool useDarkImage; + + OptionTileTheme( + {required this.titleColor, required this.descriptionColor, this.useDarkImage = false}); + + @override + OptionTileTheme copyWith({Color? titleColor, Color? descriptionColor, bool? useDarkImage}) => + OptionTileTheme( + titleColor: titleColor ?? this.titleColor, + descriptionColor: descriptionColor ?? this.descriptionColor, + useDarkImage: useDarkImage ?? this.useDarkImage); + + @override + OptionTileTheme lerp(ThemeExtension? other, double t) { + if (other is! OptionTileTheme) { + return this; + } + + return OptionTileTheme( + titleColor: Color.lerp(titleColor, other.titleColor, t) ?? titleColor, + descriptionColor: + Color.lerp(descriptionColor, other.descriptionColor, t) ?? descriptionColor, + useDarkImage: other.useDarkImage); + } +} diff --git a/lib/themes/high_contrast_theme.dart b/lib/themes/high_contrast_theme.dart index 0483adb38..bef959a70 100644 --- a/lib/themes/high_contrast_theme.dart +++ b/lib/themes/high_contrast_theme.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/themes/extensions/filter_theme.dart'; import 'package:cake_wallet/themes/extensions/indicator_dot_theme.dart'; import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; @@ -103,6 +104,10 @@ class HighContrastTheme extends MoneroLightTheme { ReceivePageTheme get receivePageTheme => super.receivePageTheme.copyWith( tilesTextColor: Colors.white, iconsBackgroundColor: Colors.grey, iconsColor: Colors.black); + @override + OptionTileTheme get optionTileTheme => OptionTileTheme( + titleColor: Colors.white, descriptionColor: Colors.white, useDarkImage: false); + @override ThemeData get themeData => super.themeData.copyWith( disabledColor: Colors.grey, diff --git a/lib/themes/light_theme.dart b/lib/themes/light_theme.dart index f24551e66..492b2c145 100644 --- a/lib/themes/light_theme.dart +++ b/lib/themes/light_theme.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/themes/extensions/info_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:cake_wallet/themes/extensions/order_theme.dart'; import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; @@ -215,6 +216,10 @@ class LightTheme extends ThemeBase { qrCodeColor: Colors.white, qrWidgetCopyButtonColor: PaletteDark.lightBlueGrey); + @override + OptionTileTheme get optionTileTheme => OptionTileTheme( + titleColor: primaryTextColor, descriptionColor: primaryTextColor, useDarkImage: true); + @override ThemeData get themeData => super.themeData.copyWith( dividerColor: Palette.paleBlue, diff --git a/lib/themes/theme_base.dart b/lib/themes/theme_base.dart index b5f42e7de..3bba6f65f 100644 --- a/lib/themes/theme_base.dart +++ b/lib/themes/theme_base.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/themes/extensions/info_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:cake_wallet/themes/extensions/order_theme.dart'; import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cake_wallet/themes/extensions/pin_code_theme.dart'; @@ -114,6 +115,8 @@ abstract class ThemeBase { QRCodeTheme get qrCodeTheme; + OptionTileTheme get optionTileTheme; + ThemeData get themeData => generatedThemeData.copyWith( primaryColor: primaryColor, cardColor: containerColor, @@ -144,6 +147,7 @@ abstract class ThemeBase { accountListTheme, receivePageTheme, qrCodeTheme, + optionTileTheme ], scrollbarTheme: generatedThemeData.scrollbarTheme.copyWith( thumbColor: MaterialStateProperty.all(scrollbarTheme.thumbColor), diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 009fe0350..9998eb8be 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; +import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; @@ -277,6 +278,9 @@ abstract class DashboardViewModelBase with Store { Map> filterItems; + + BuyProviderType get defaultBuyProvider => settingsStore.defaultBuyProvider; + bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled; bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup; diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index c57af50d9..ef8abe8e6 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/balance.dart'; @@ -48,6 +49,9 @@ abstract class OtherSettingsViewModelBase with Store { return priority; } + @computed + BuyProviderType get buyProviderType { return _settingsStore.defaultBuyProvider; } + String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; @@ -59,6 +63,16 @@ abstract class OtherSettingsViewModelBase with Store { return priority.toString(); } + String getBuyProviderType (dynamic buyProviderType) { + final _buyProviderType = buyProviderType as BuyProviderType; + + return _buyProviderType.toString(); + } + void onDisplayPrioritySelected(TransactionPriority priority) => _settingsStore.priority[_wallet.type] = priority; + + void onBuyProviderTypeSelected(BuyProviderType buyProviderType) => + _settingsStore.defaultBuyProvider = buyProviderType; + } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index ae3f669ca..7c7b0535b 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -682,7 +682,11 @@ "support_title_other_links": "روابط دعم أخرى", "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", "select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ", + "auto_generate_subaddresses": "تلقائي توليد subddresses", "save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ", - "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", - "auto_generate_subaddresses": "تلقائي توليد subddresses" -} + "select_buy_provider_notice": "حدد مزود شراء أعلاه. يمكنك تخطي هذه الشاشة عن طريق تعيين مزود شراء الافتراضي في إعدادات التطبيق.", + "onramper_option_description": "شراء بسرعة التشفير مع العديد من طرق الدفع. متوفر في معظم البلدان. ينتشر وتختلف الرسوم.", + "default_buy_provider": "مزود شراء الافتراضي", + "ask_each_time": "اسأل في كل مرة", + "buy_provider_unavailable": "مزود حاليا غير متوفر." +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index ac2a08088..9f4c21c44 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -679,5 +679,10 @@ "support_title_other_links": "Други връзки за поддръжка", "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи", "select_destination": "Моля, изберете дестинация за архивния файл.", - "save_to_downloads": "Запазване в Изтегляния" -} + "save_to_downloads": "Запазване в Изтегляния", + "select_buy_provider_notice": "Изберете доставчик на покупка по -горе. Можете да пропуснете този екран, като зададете вашия доставчик по подразбиране по подразбиране в настройките на приложението.", + "onramper_option_description": "Бързо купувайте криптовалута с много методи за плащане. Предлага се в повечето страни. Разпространенията и таксите варират.", + "default_buy_provider": "Доставчик по подразбиране купува", + "ask_each_time": "Питайте всеки път", + "buy_provider_unavailable": "Понастоящем доставчик не е наличен." +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 38e01ca6b..82d0fd9ed 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -679,5 +679,10 @@ "support_title_other_links": "Další odkazy na podporu", "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody", "select_destination": "Vyberte cíl pro záložní soubor.", - "save_to_downloads": "Uložit do Stažených souborů" -} + "save_to_downloads": "Uložit do Stažených souborů", + "select_buy_provider_notice": "Vyberte výše uvedeného poskytovatele nákupu. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele nákupu v nastavení aplikace.", + "onramper_option_description": "Rychle si koupte krypto s mnoha metodami plateb. K dispozici ve většině zemí. Rozpětí a poplatky se liší.", + "default_buy_provider": "Výchozí poskytovatel nákupu", + "ask_each_time": "Zeptejte se pokaždé", + "buy_provider_unavailable": "Poskytovatel aktuálně nedostupný." +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index afc5fba82..e5bb7ce51 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -364,8 +364,8 @@ "enter_your_note": "Geben Sie Ihre Bemerkung ein…", "note_optional": "Bemerkung (optional)", "note_tap_to_change": "Bemerkung (zum Ändern tippen)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", + "view_in_block_explorer": "In Block Explorer anzeigen", + "view_transaction_on": "Anzeigen der Transaktion auf ", "transaction_key": "Transaktionsschlüssel", "confirmations": "Bestätigungen", "recipient_address": "Empfängeradresse", @@ -405,11 +405,11 @@ "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", "outdated_electrum_wallet_receive_warning": "Wenn diese Wallet einen 12-Wort-Seed hat und in Cake erstellt wurde, zahlen Sie KEINE Bitcoins in diese Wallet ein. Alle auf diese Wallet übertragenen BTC können verloren gehen. Erstellen Sie eine neue 24-Wort-Wallet (tippen Sie auf das Menü oben rechts, wählen Sie Wallets, wählen Sie Neue Wallet erstellen und dann Bitcoin) und verschieben Sie Ihre BTC SOFORT dorthin. Neue (24-Wort-)BTC-Wallets von Cake sind sicher", "do_not_show_me": "Zeig mir das nicht noch einmal", - "unspent_coins_title": "Nicht ausgegebene Münzen", - "unspent_coins_details_title": "Details zu nicht ausgegebenen Münzen", + "unspent_coins_title": "Nicht ausgegebene Coins", + "unspent_coins_details_title": "Details zu nicht ausgegebenen Coins", "freeze": "Einfrieren", "frozen": "Gefroren", - "coin_control": "Münzkontrolle (optional)", + "coin_control": "Coin Control (optional)", "address_detected": "Adresse erkannt", "address_from_domain": "Diese Adresse ist von ${domain} auf Unstoppable Domains", "add_receiver": "Fügen Sie einen weiteren Empfänger hinzu (optional)", @@ -551,7 +551,7 @@ "custom_redeem_amount": "Benutzerdefinierter Einlösungsbetrag", "add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen", "remaining": "Rest", - "delete_wallet": "Geldbörse löschen", + "delete_wallet": "Wallet löschen", "delete_wallet_confirm_message": "Sind Sie sicher, dass Sie das ${wallet_name} Wallet löschen möchten?", "low_fee": "Niedrige Gebühr", "low_fee_alert": "Sie verwenden derzeit eine niedrige Netzwerkgebührenpriorität. Dies kann zu langen Wartezeiten, unterschiedlichen Kursen oder stornierten Trades führen. Wir empfehlen, für ein besseres Erlebnis eine höhere Gebühr festzulegen.", @@ -560,7 +560,7 @@ "do_not_share_warning_text": "Teilen Sie diese nicht mit anderen, einschließlich Support.\n\nIhr Geld kann und wird gestohlen werden!", "help": "hilfe", "all_transactions": "Alle Transaktionen", - "all_trades": "Alle Gewerke", + "all_trades": "Alle Trades", "connection_sync": "Verbindung und Synchronisierung", "security_and_backup": "Sicherheit und Datensicherung", "create_backup": "Backup erstellen", @@ -583,7 +583,7 @@ "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein", "orbot_running_alert": "Bitte stellen Sie sicher, dass Orbot läuft, bevor Sie sich mit diesem Knoten verbinden.", "contact_list_contacts": "Kontakte", - "contact_list_wallets": "Meine Geldbörsen", + "contact_list_wallets": "Meine Wallets", "bitcoin_payments_require_1_confirmation": "Bitcoin-Zahlungen erfordern 1 Bestätigung, was 20 Minuten oder länger dauern kann. Danke für Ihre Geduld! Sie erhalten eine E-Mail, wenn die Zahlung bestätigt ist.", "send_to_this_address": "Senden Sie ${currency} ${tag}an diese Adresse", "arrive_in_this_address": "${currency} ${tag}wird an dieser Adresse ankommen", @@ -592,8 +592,8 @@ "scan_qr_code": "QR-Code scannen", "cold_or_recover_wallet": "Fügen Sie eine Cold Wallet hinzu oder stellen Sie eine Paper Wallet wieder her", "please_wait": "Warten Sie mal", - "sweeping_wallet": "Kehre Geldbörse", - "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE SWEPT-GELDER VERLOREN GEHEN", + "sweeping_wallet": "Wallet leeren", + "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE GELDER VERLOREN GEHEN", "decimal_places_error": "Zu viele Nachkommastellen", "edit_node": "Knoten bearbeiten", "frozen_balance": "Gefrorenes Guthaben", @@ -630,7 +630,7 @@ "add_secret_code": "Fügen Sie diesen Geheimcode einem anderen Gerät hinzu", "totp_secret_code": "TOTP-Geheimcode", "important_note": "Wichtiger Hinweis", - "setup_2fa_text": "Cake 2FA ist NICHT so sicher wie eine Kühllagerung. 2FA schützt vor grundlegenden Arten von Angriffen, z. B. wenn Ihr Freund Ihren Fingerabdruck bereitstellt, während Sie schlafen.\n\n Cake 2FA schützt NICHT vor einem kompromittierten Gerät durch einen raffinierten Angreifer.\n\n Wenn Sie den Zugriff auf Ihre 2FA-Codes verlieren , VERLIEREN SIE DEN ZUGANG ZU DIESEM WALLET. Sie müssen Ihre Wallet aus mnemonic Seed wiederherstellen. SIE MÜSSEN DESHALB IHRE MNEMONISCHEN SEEDS SICHERN! Außerdem kann jemand mit Zugriff auf Ihre mnemonischen Seed(s) Ihr Geld stehlen und Cake 2FA umgehen.\n\n Cake-Supportmitarbeiter können Ihnen nicht helfen, wenn Sie den Zugriff auf Ihre mnemonischen Seed(s) verlieren, da Cake Wallet eine Wallet ohne treuhänderische Verwahrung ist.", + "setup_2fa_text": "Cake 2FA ist NICHT so sicher wie eine Cold Wallet. 2FA schützt vor grundlegenden Arten von Angriffen, z.B. wenn Ihr Freund Ihren Fingerabdruck verwendet, während Sie schlafen.\n\n Cake 2FA schützt NICHT vor einem kompromittierten Gerät durch einen raffinierten Angreifer.\n\n Wenn Sie den Zugriff auf Ihre 2FA-Codes verlieren , VERLIEREN SIE DEN ZUGANG ZU DIESEM WALLET. Sie müssen Ihre Wallet aus mnemonic Seed wiederherstellen. SIE MÜSSEN DESHALB IHRE MNEMONISCHEN SEEDS SICHERN! Außerdem kann jemand mit Zugriff auf Ihre mnemonischen Seed(s) Ihr Geld stehlen und Cake 2FA umgehen.\n\n Cake-Supportmitarbeiter können Ihnen nicht helfen, wenn Sie den Zugriff auf Ihre mnemonischen Seed(s) verlieren, da Cake Wallet eine Wallet ohne treuhänderische Verwahrung ist.", "setup_totp_recommended": "TOTP einrichten (empfohlen)", "disable_buy": "Kaufaktion deaktivieren", "disable_sell": "Verkaufsaktion deaktivieren", @@ -641,7 +641,7 @@ "matrix_green_dark_theme": "Matrix Green Dark Theme", "monero_light_theme": "Monero Light-Thema", "auto_generate_subaddresses": "Unteradressen automatisch generieren", - "cake_2fa_preset" : "Cake 2FA-Voreinstellung", + "cake_2fa_preset": "Cake 2FA-Voreinstellung", "narrow": "Eng", "normal": "Normal", "aggressive": "Übereifrig", @@ -675,7 +675,7 @@ "alphabetical": "Alphabetisch", "generate_name": "Namen generieren", "balance_page": "Balance-Seite", - "share": "Aktie", + "share": "Teilen", "slidable": "Verschiebbar", "manage_nodes": "Knoten verwalten", "etherscan_history": "Etherscan-Geschichte", @@ -687,5 +687,10 @@ "support_title_other_links": "Andere Support-Links", "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden", "select_destination": "Bitte wählen Sie das Ziel für die Sicherungsdatei aus.", - "save_to_downloads": "Unter „Downloads“ speichern" -} + "save_to_downloads": "Unter „Downloads“ speichern", + "select_buy_provider_notice": "Wählen Sie oben einen Anbieter kaufen. Sie können diese Seite überspringen, indem Sie Ihren Standard-Kaufanbieter in den App-Einstellungen festlegen.", + "onramper_option_description": "Kaufen Sie schnell Krypto mit vielen Zahlungsmethoden. In den meisten Ländern erhältlich. Spreads und Gebühren variieren.", + "default_buy_provider": "Standard-Kaufanbieter", + "ask_each_time": "Jedes Mal fragen", + "buy_provider_unavailable": "Anbieter derzeit nicht verfügbar." +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4698701de..8cf6e2acb 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -687,5 +687,11 @@ "support_title_other_links": "Other support links", "support_description_other_links": "Join our communities or reach us our our partners through other methods", "select_destination": "Please select destination for the backup file.", - "save_to_downloads": "Save to Downloads" -} + "save_to_downloads": "Save to Downloads", + "select_buy_provider_notice": "Select a buy provider above. You can skip this screen by setting your default buy provider in app settings.", + "onramper_option_description": "Quickly buy crypto with many payment methods. Available in most countries. Spreads and fees vary.", + "default_buy_provider": "Default Buy Provider", + "ask_each_time": "Ask each time", + "robinhood_option_description": "Buy and transfer instantly using your debit card, bank account, or Robinhood balance. USA only.", + "buy_provider_unavailable": "Provider currently unavailable." +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 8a4519255..d84b21b94 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -687,5 +687,10 @@ "support_title_other_links": "Otros enlaces de soporte", "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos", "select_destination": "Seleccione el destino del archivo de copia de seguridad.", - "save_to_downloads": "Guardar en Descargas" -} + "save_to_downloads": "Guardar en Descargas", + "select_buy_provider_notice": "Seleccione un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.", + "onramper_option_description": "Compre rápidamente cripto con muchos métodos de pago. Disponible en la mayoría de los países. Los diferenciales y las tarifas varían.", + "default_buy_provider": "Proveedor de compra predeterminado", + "ask_each_time": "Pregunta cada vez", + "buy_provider_unavailable": "Proveedor actualmente no disponible." +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 357a73110..2daea4733 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -687,5 +687,10 @@ "support_title_other_links": "Autres liens d'assistance", "support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes", "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.", - "save_to_downloads": "Enregistrer dans les téléchargements" -} + "save_to_downloads": "Enregistrer dans les téléchargements", + "select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.", + "onramper_option_description": "Achetez rapidement la crypto avec de nombreux méthodes de paiement. Disponible dans la plupart des pays. Les écarts et les frais varient.", + "default_buy_provider": "Fournisseur d'achat par défaut", + "ask_each_time": "Demandez à chaque fois", + "buy_provider_unavailable": "Fournisseur actuellement indisponible." +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index d344bfb15..666664ec2 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -665,5 +665,10 @@ "support_title_other_links": "Sauran hanyoyin tallafi", "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi", "select_destination": "Da fatan za a zaɓi wurin da za a yi wa madadin fayil ɗin.", - "save_to_downloads": "Ajiye zuwa Zazzagewa" -} + "save_to_downloads": "Ajiye zuwa Zazzagewa", + "select_buy_provider_notice": "Zaɓi mai ba da kyauta a sama. Zaka iya tsallake wannan allon ta hanyar saita mai ba da isasshen busasshen mai ba da isasshen busasshiyar saiti.", + "onramper_option_description": "Da sauri sayi Crypto tare da hanyoyin biyan kuɗi da yawa. Akwai a yawancin ƙasashe. Yaduwa da kudade sun bambanta.", + "default_buy_provider": "Tsohuwar Siyarwa", + "ask_each_time": "Tambaya kowane lokaci", + "buy_provider_unavailable": "Mai ba da kyauta a halin yanzu babu." +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index e9ee219fe..9504baf36 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -687,5 +687,10 @@ "support_title_other_links": "अन्य समर्थन लिंक", "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें", "select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य का चयन करें।", - "save_to_downloads": "डाउनलोड में सहेजें" -} + "save_to_downloads": "डाउनलोड में सहेजें", + "select_buy_provider_notice": "ऊपर एक खरीद प्रदाता का चयन करें। आप इस स्क्रीन को ऐप सेटिंग्स में अपना डिफ़ॉल्ट बाय प्रदाता सेट करके छोड़ सकते हैं।", + "onramper_option_description": "जल्दी से कई भुगतान विधियों के साथ क्रिप्टो खरीदें। अधिकांश देशों में उपलब्ध है। फैलता है और फीस अलग -अलग होती है।", + "default_buy_provider": "डिफ़ॉल्ट खरीद प्रदाता", + "ask_each_time": "हर बार पूछें", + "buy_provider_unavailable": "वर्तमान में प्रदाता अनुपलब्ध है।" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 91176248d..08549439a 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -687,5 +687,10 @@ "support_title_other_links": "Ostale veze za podršku", "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama", "select_destination": "Odaberite odredište za datoteku sigurnosne kopije.", - "save_to_downloads": "Spremi u Preuzimanja" -} + "save_to_downloads": "Spremi u Preuzimanja", + "select_buy_provider_notice": "Odaberite gornji davatelj kupnje. Ovaj zaslon možete preskočiti postavljanjem zadanog davatelja usluga kupnje u postavkama aplikacija.", + "onramper_option_description": "Brzo kupite kriptovalute s mnogim načinima plaćanja. Dostupno u većini zemalja. Širenja i naknade variraju.", + "default_buy_provider": "Zadani davatelj kupnje", + "ask_each_time": "Pitajte svaki put", + "buy_provider_unavailable": "Davatelj trenutno nije dostupan." +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index daebfd579..031777aea 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -675,5 +675,10 @@ "support_title_other_links": "Tautan dukungan lainnya", "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain", "select_destination": "Silakan pilih tujuan untuk file cadangan.", - "save_to_downloads": "Simpan ke Unduhan" -} + "save_to_downloads": "Simpan ke Unduhan", + "select_buy_provider_notice": "Pilih penyedia beli di atas. Anda dapat melewatkan layar ini dengan mengatur penyedia pembelian default Anda di pengaturan aplikasi.", + "onramper_option_description": "Beli crypto dengan cepat dengan banyak metode pembayaran. Tersedia di sebagian besar negara. Spread dan biaya bervariasi.", + "default_buy_provider": "Penyedia beli default", + "ask_each_time": "Tanyakan setiap kali", + "buy_provider_unavailable": "Penyedia saat ini tidak tersedia." +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 691abd15c..b14531b75 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -687,5 +687,10 @@ "support_title_other_links": "Altri collegamenti di supporto", "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi", "select_destination": "Seleziona la destinazione per il file di backup.", - "save_to_downloads": "Salva in Download" -} + "save_to_downloads": "Salva in Download", + "select_buy_provider_notice": "Seleziona un fornitore di acquisto sopra. È possibile saltare questa schermata impostando il provider di acquisto predefinito nelle impostazioni dell'app.", + "onramper_option_description": "Acquista rapidamente la criptovaluta con molti metodi di pagamento. Disponibile nella maggior parte dei paesi. Gli spread e le commissioni variano.", + "default_buy_provider": "Provider di acquisto predefinito", + "ask_each_time": "Chiedi ogni volta", + "buy_provider_unavailable": "Provider attualmente non disponibile." +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 254d7bbba..baf9b8a6d 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -686,6 +686,11 @@ "support_title_other_links": "その他のサポートリンク", "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください", "select_destination": "バックアップファイルの保存先を選択してください。", + "auto_generate_subaddresses": "Autoはサブアドレスを生成します", "save_to_downloads": "ダウンロードに保存", - "auto_generate_subaddresses": "Autoはサブアドレスを生成します" -} + "select_buy_provider_notice": "上記の購入プロバイダーを選択してください。デフォルトの購入プロバイダーをアプリ設定で設定して、この画面をスキップできます。", + "onramper_option_description": "多くの支払い方法で暗号をすばやく購入してください。ほとんどの国で利用可能です。スプレッドと料金は異なります。", + "default_buy_provider": "デフォルトの購入プロバイダー", + "ask_each_time": "毎回尋ねてください", + "buy_provider_unavailable": "現在、プロバイダーは利用できません。" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 63a446fa3..3b9ed1e74 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -686,6 +686,11 @@ "support_title_other_links": "다른 지원 링크", "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.", "select_destination": "백업 파일의 대상을 선택하십시오.", + "auto_generate_subaddresses": "자동 생성 서브 아드 드레스", "save_to_downloads": "다운로드에 저장", - "auto_generate_subaddresses": "자동 생성 서브 아드 드레스" -} + "select_buy_provider_notice": "위의 구매 제공자를 선택하십시오. 앱 설정에서 기본 구매 제공자를 설정 하여이 화면을 건너 뛸 수 있습니다.", + "onramper_option_description": "많은 결제 방법으로 암호화를 신속하게 구입하십시오. 대부분의 국가에서 사용할 수 있습니다. 스프레드와 수수료는 다양합니다.", + "default_buy_provider": "기본 구매 제공자", + "ask_each_time": "매번 물어보십시오", + "buy_provider_unavailable": "제공자는 현재 사용할 수 없습니다." +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index b131e66d8..04d2f58ef 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -684,6 +684,11 @@ "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ", "select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။", + "auto_generate_subaddresses": "အော်တို Generate Subaddresses", "save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။", - "auto_generate_subaddresses": "အော်တို Generate Subaddresses" -} + "select_buy_provider_notice": "အပေါ်ကဝယ်သူတစ် ဦး ကိုရွေးချယ်ပါ။ သင်၏ default 0 ယ်သူအား app settings တွင် setting လုပ်ခြင်းဖြင့်ဤ screen ကိုကျော်သွားနိုင်သည်။", + "onramper_option_description": "ငွေပေးချေမှုနည်းလမ်းများစွာဖြင့် Crypto ကိုလျင်မြန်စွာ 0 ယ်ပါ။ နိုင်ငံအများစုတွင်ရရှိနိုင်ပါသည်။ ဖြန့်ဖြူးနှင့်အခကြေးငွေကွဲပြားခြားနားသည်။", + "default_buy_provider": "Default Provider ကိုဝယ်ပါ", + "ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ", + "buy_provider_unavailable": "လက်ရှိတွင်လက်ရှိမရနိုင်ပါ။" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index fcd683fd1..676653dcd 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -687,5 +687,10 @@ "support_title_other_links": "Andere ondersteuningslinks", "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons ​​onze partners via andere methoden", "select_destination": "Selecteer de bestemming voor het back-upbestand.", - "save_to_downloads": "Opslaan in downloads" -} + "save_to_downloads": "Opslaan in downloads", + "select_buy_provider_notice": "Selecteer hierboven een koopprovider. U kunt dit scherm overslaan door uw standaard kopenprovider in te stellen in app -instellingen.", + "onramper_option_description": "Koop snel crypto met veel betaalmethoden. Beschikbaar in de meeste landen. Spreads en vergoedingen variëren.", + "default_buy_provider": "Standaard Koopprovider", + "ask_each_time": "Vraag het elke keer", + "buy_provider_unavailable": "Provider momenteel niet beschikbaar." +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 17745ccb8..cae3d0075 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -687,5 +687,10 @@ "support_title_other_links": "Inne linki wsparcia", "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod", "select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.", - "save_to_downloads": "Zapisz w Pobranych" -} + "save_to_downloads": "Zapisz w Pobranych", + "select_buy_provider_notice": "Wybierz powyższe dostawcę zakupu. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę zakupu w ustawieniach aplikacji.", + "onramper_option_description": "Szybko kup kryptowaluty z wieloma metodami płatności. Dostępne w większości krajów. Spready i opłaty różnią się.", + "default_buy_provider": "Domyślny dostawca zakupu", + "ask_each_time": "Zapytaj za każdym razem", + "buy_provider_unavailable": "Dostawca obecnie niedostępny." +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 2148e6905..46c62c590 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -686,5 +686,10 @@ "support_title_other_links": "Outros links de suporte", "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos", "select_destination": "Selecione o destino para o arquivo de backup.", - "save_to_downloads": "Salvar em Downloads" -} + "save_to_downloads": "Salvar em Downloads", + "select_buy_provider_notice": "Selecione um provedor de compra acima. Você pode pular esta tela definindo seu provedor de compra padrão nas configurações de aplicativos.", + "onramper_option_description": "Compre rapidamente criptografia com muitos métodos de pagamento. Disponível na maioria dos países. Os spreads e taxas variam.", + "default_buy_provider": "Provedor de compra padrão", + "ask_each_time": "Pergunte cada vez", + "buy_provider_unavailable": "Provedor atualmente indisponível." +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index e229ddee9..523b4c77e 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -686,6 +686,11 @@ "support_title_other_links": "Другие ссылки на поддержку", "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов", "select_destination": "Пожалуйста, выберите место для файла резервной копии.", + "auto_generate_subaddresses": "Авто генерируйте Subaddresses", "save_to_downloads": "Сохранить в загрузках", - "auto_generate_subaddresses": "Авто генерируйте Subaddresses" -} + "select_buy_provider_notice": "Выберите поставщика покупки выше. Вы можете пропустить этот экран, установив поставщика покупки по умолчанию в настройках приложения.", + "onramper_option_description": "Быстро купите крипто со многими способами оплаты. Доступно в большинстве стран. Спреды и сборы различаются.", + "default_buy_provider": "По умолчанию поставщик покупки", + "ask_each_time": "Спросите каждый раз", + "buy_provider_unavailable": "Поставщик в настоящее время недоступен." +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 100929da2..68c13dd2d 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -684,6 +684,11 @@ "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ", "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง", + "auto_generate_subaddresses": "Auto สร้าง subaddresses", "save_to_downloads": "บันทึกลงดาวน์โหลด", - "auto_generate_subaddresses": "Auto สร้าง subaddresses" -} + "select_buy_provider_notice": "เลือกผู้ให้บริการซื้อด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการซื้อเริ่มต้นในการตั้งค่าแอป", + "onramper_option_description": "ซื้อ crypto อย่างรวดเร็วด้วยวิธีการชำระเงินจำนวนมาก มีให้บริการในประเทศส่วนใหญ่ สเปรดและค่าธรรมเนียมแตกต่างกันไป", + "default_buy_provider": "ผู้ให้บริการซื้อเริ่มต้น", + "ask_each_time": "ถามทุกครั้ง", + "buy_provider_unavailable": "ผู้ให้บริการไม่สามารถใช้งานได้ในปัจจุบัน" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index e74d1a281..2694bb1bc 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -685,5 +685,10 @@ "support_title_other_links": "Diğer destek bağlantıları", "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın", "select_destination": "Lütfen yedekleme dosyası için hedef seçin.", - "save_to_downloads": "İndirilenlere Kaydet" -} + "save_to_downloads": "İndirilenlere Kaydet", + "select_buy_provider_notice": "Yukarıda bir satın alma sağlayıcısı seçin. App ayarlarında varsayılan satın alma sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", + "onramper_option_description": "Birçok ödeme yöntemi ile hızlı bir şekilde kripto satın alın. Çoğu ülkede mevcuttur. Forma ve ücretler değişir.", + "default_buy_provider": "Varsayılan Satın Alma Sağlayıcısı", + "ask_each_time": "Her seferinde sor", + "buy_provider_unavailable": "Sağlayıcı şu anda kullanılamıyor." +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 313f6aeb0..38fe226b1 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -687,5 +687,10 @@ "support_title_other_links": "Інші посилання на підтримку", "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами", "select_destination": "Виберіть місце призначення для файлу резервної копії.", - "save_to_downloads": "Зберегти до завантажень" -} + "save_to_downloads": "Зберегти до завантажень", + "select_buy_provider_notice": "Виберіть постачальника купівлі вище. Ви можете пропустити цей екран, встановивши свого постачальника купівлі за замовчуванням у налаштуваннях додатків.", + "onramper_option_description": "Швидко купуйте криптовалюту з багатьма методами оплати. Доступний у більшості країн. Поширення та збори різняться.", + "default_buy_provider": "Постачальник покупки за замовчуванням", + "ask_each_time": "Запитайте кожен раз", + "buy_provider_unavailable": "В даний час постачальник недоступний." +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index b8e0c0a00..1ecdb5c0e 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -678,6 +678,11 @@ "support_title_other_links": "دوسرے سپورٹ لنکس", "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں", "select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ", + "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے", "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ", - "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے" -} + "select_buy_provider_notice": "اوپر خریدنے والا خریدنے والا منتخب کریں۔ آپ ایپ کی ترتیبات میں اپنے پہلے سے طے شدہ خریدنے والے کو ترتیب دے کر اس اسکرین کو چھوڑ سکتے ہیں۔", + "onramper_option_description": "ادائیگی کے بہت سے طریقوں سے جلدی سے کرپٹو خریدیں۔ زیادہ تر ممالک میں دستیاب ہے۔ پھیلاؤ اور فیس مختلف ہوتی ہے۔", + "default_buy_provider": "پہلے سے طے شدہ خریدنے والا", + "ask_each_time": "ہر بار پوچھیں", + "buy_provider_unavailable": "فراہم کنندہ فی الحال دستیاب نہیں ہے۔" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 143fd0ccd..62909f128 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -680,6 +680,11 @@ "matrix_green_dark_theme": "Matrix Green Dark Akori", "monero_light_theme": "Monero Light Akori", "select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.", + "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ", "save_to_downloads": "Fipamọ si Awọn igbasilẹ", - "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ" -} + "select_buy_provider_notice": "Yan olupese Ra loke. O le skii iboju yii nipa ṣiṣeto olupese rẹ ni awọn eto App.", + "onramper_option_description": "Ni kiakia Ra Crypto pẹlu ọpọlọpọ awọn ọna isanwo. Wa ni ọpọlọpọ awọn orilẹ-ede. Itankale ati awọn idiyele yatọ.", + "default_buy_provider": "Aiyipada Ra Olupese", + "ask_each_time": "Beere lọwọ kọọkan", + "buy_provider_unavailable": "Olupese lọwọlọwọ ko si." +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 7e3ceae31..24295e0ca 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -685,6 +685,11 @@ "matrix_green_dark_theme": "矩阵绿暗主题", "monero_light_theme": "门罗币浅色主题", "select_destination": "请选择备份文件的目的地。", + "auto_generate_subaddresses": "自动生成子辅助", "save_to_downloads": "保存到下载", - "auto_generate_subaddresses": "自动生成子辅助" -} + "select_buy_provider_notice": "在上面选择买入提供商。您可以通过在应用程序设置中设置默认的购买提供商来跳过此屏幕。", + "onramper_option_description": "快速使用许多付款方式购买加密货币。在大多数国家 /地区可用。利差和费用各不相同。", + "default_buy_provider": "默认购买提供商", + "ask_each_time": "每次问", + "buy_provider_unavailable": "提供者目前不可用。" +} \ No newline at end of file diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 7819a582c..8c86e1b7f 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -32,6 +32,8 @@ class SecretKey { SecretKey('fiatApiKey', () => ''), SecretKey('payfuraApiKey', () => ''), SecretKey('chatwootWebsiteToken', () => ''), + SecretKey('robinhoodApplicationId', () => ''), + SecretKey('robinhoodCIdApiSecret', () => ''), ]; static final ethereumSecrets = [ From 0eecf0bee560a1df420ed9d866e7257144c1f3cb Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 14 Sep 2023 23:41:54 +0200 Subject: [PATCH 4/5] Cw 483 add tagalog and filipino localizations (#1086) * CW-483 Add "Add new language Script" * CW-483 Add Filipino Language --- lib/entities/language_service.dart | 6 +- res/values/strings_tl.arb | 691 ++++++++++++++++++ tool/translation_add_lang.dart | 36 + tool/utils/translation/arb_file_utils.dart | 6 +- tool/utils/translation/translation_utils.dart | 20 +- tool/utils/utils.dart | 2 +- 6 files changed, 750 insertions(+), 11 deletions(-) create mode 100644 res/values/strings_tl.arb create mode 100644 tool/translation_add_lang.dart diff --git a/lib/entities/language_service.dart b/lib/entities/language_service.dart index 87ee99ff5..cfb850889 100644 --- a/lib/entities/language_service.dart +++ b/lib/entities/language_service.dart @@ -28,7 +28,8 @@ class LanguageService { 'ur': 'اردو (Urdu)', 'id': 'Bahasa Indonesia (Indonesian)', 'yo': 'Yorùbá (Yoruba)', - 'ha': 'Hausa Najeriya (Nigeria)' + 'ha': 'Hausa Najeriya (Nigeria)', + 'tl': 'Filipino (Tagalog)' }; static const Map localeCountryCode = { @@ -56,7 +57,8 @@ class LanguageService { 'ur': 'pak', 'id': 'idn', 'yo': 'nga', - 'ha': 'hau' + 'ha': 'hau', + 'tl': 'phl' }; static final list = {}; diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb new file mode 100644 index 000000000..d65e36609 --- /dev/null +++ b/res/values/strings_tl.arb @@ -0,0 +1,691 @@ +{ + "welcome": "Maligayang pagdating sa", + "cake_wallet": "Cake wallet", + "first_wallet_text": "Kahanga -hangang pitaka para sa Monero, Bitcoin, Ethereum, Litecoin, at Haven", + "please_make_selection": "Mangyaring gumawa ng isang pagpipilian sa ibaba upang lumikha o mabawi ang iyong pitaka.", + "create_new": "Lumikha ng bagong pitaka", + "restore_wallet": "Ibalik ang pitaka", + "monero_com": "Monero.com sa pamamagitan ng cake wallet", + "monero_com_wallet_text": "Galing ng pitaka para sa Monero", + "haven_app": "Haven sa pamamagitan ng cake wallet", + "haven_app_wallet_text": "Galing ng pitaka para sa Haven", + "accounts": "Mga Account", + "edit": "I -edit", + "account": "Account", + "add": "Idagdag", + "address_book": "Address Book", + "contact": "Makipag -ugnay", + "please_select": "Pakipili:", + "cancel": "Kanselahin", + "ok": "Ok", + "contact_name": "pangalan ng contact", + "reset": "I -reset", + "save": "I -save", + "address_remove_contact": "Alisin ang contact", + "address_remove_content": "Sigurado ka bang nais mong alisin ang napiling contact?", + "authenticated": "Napatunayan", + "authentication": "Pagpapatunay", + "failed_authentication": "Nabigong pagpapatunay. ${state_error}", + "wallet_menu": "Menu", + "Blocks_remaining": "Ang natitirang ${status} ay natitira", + "please_try_to_connect_to_another_node": "Mangyaring subukang kumonekta sa isa pang node", + "xmr_hidden": "Nakatago", + "xmr_available_balance": "Magagamit na balanse", + "xmr_full_balance": "Buong balanse", + "send": "Ipadala", + "receive": "Tumanggap", + "transactions": "Mga Transaksyon", + "incoming": "Papasok", + "outgoing": "Palabas", + "transactions_by_date": "Mga Transaksyon ayon sa Petsa", + "trades": "Trading", + "filter_by": "Filter ni", + "today": "Ngayon", + "yesterday": "Kahapon", + "received": "Natanggap", + "sent": "Ipinadala", + "pending": "(Pending)", + "rescan": "Rescan", + "reconnect": "Kumonekta muli", + "wallets": "Wallets", + "show_seed": "Magpakita ng binhi", + "show_keys": "Ipakita ang mga binhi/susi", + "address_book_menu": "Address Book", + "reconnection": "Pag -ugnay muli", + "reconnect_alert_text": "Sigurado ka bang nais mong muling kumonekta?", + "exchange": "Palitan", + "clear": "Malinaw", + "refund_address": "Refund address", + "change_exchange_provider": "Baguhin ang tagapagbigay ng palitan", + "you_will_send": "I -convert mula sa", + "you_will_get": "Mag -convert sa", + "amount_is_guaranteed": "Ang natanggap na halaga ay garantisado", + "amount_is_estimate": "Ang natanggap na halaga ay isang pagtatantya", + "powered_by": "Pinapagana ng ${title}", + "error": "Error", + "estimated": "Tinatayang", + "min_value": "Min: ${value} ${currency}", + "max_value": "Max: ${value} ${currency}", + "change_currency": "Baguhin ang pera", + "overwrite_amount": "Overwrite na halaga", + "qr_payment_amount": "Ang QR code na ito ay naglalaman ng isang halaga ng pagbabayad. Nais mo bang i -overwrite ang kasalukuyang halaga?", + "copy_id": "Kopyahin ang id", + "exchange_result_write_down_trade_id": "Mangyaring kopyahin o isulat ang trade ID upang magpatuloy.", + "trade_id": "Trade ID:", + "copied_to_clipboard": "Kinopya sa clipboard", + "saved_the_trade_id": "Nai -save ko ang trade ID", + "fetching": "Pagkuha", + "id": "ID:", + "amount": "Halaga:", + "payment_id": "Payment ID:", + "status": "Katayuan:", + "offer_expires_in": "Mag -expire ang alok sa:", + "trade_is_powered_by": "Ang kalakalan na ito ay pinalakas ng ${provider}", + "copy_address": "Kopyahin ang address", + "exchange_result_confirm": "Sa pamamagitan ng pagpindot ng kumpirmahin, magpapadala ka ng ${fetchingLabel} ${from} mula sa iyong pitaka na tinatawag na ${walletName} sa address na ipinakita sa ibaba. O maaari kang magpadala mula sa iyong panlabas na pitaka sa ibaba address/qr code.\n\nMangyaring pindutin ang kumpirmahin na magpatuloy o bumalik upang baguhin ang mga halaga.", + "exchange_result_description": "Dapat kang magpadala ng isang minimum na ${fetchingLabel} ${from} hanggang sa address na ipinakita sa susunod na pahina. Kung nagpapadala ka ng isang halaga na mas mababa kaysa sa ${fetchingLabel} ${from} maaaring hindi ito ma -convert at maaaring hindi ito ibabalik.", + "exchange_result_write_down_ID": "*Mangyaring kopyahin o isulat ang iyong ID na ipinakita sa itaas.", + "confirm": "Kumpirmahin", + "confirm_sending": "Kumpirmahin ang pagpapadala", + "commit_transaction_amount_fee": "Gumawa ng transaksyon\nHalaga: ${amount}\nBayad: ${fee}", + "sending": "Pagpapadala", + "transaction_sent": "Ipinadala ang transaksyon!", + "expired": "Nag -expire", + "time": "${minutes} m ${seconds} s", + "send_xmr": "Magpadala ng XMR", + "exchange_new_template": "Bagong template", + "faq": "FAQ", + "enter_your_pin": "Ipasok ang iyong pin", + "loading_your_wallet": "Naglo -load ng iyong pitaka", + "new_wallet": "Bagong pitaka", + "wallet_name": "Pangalan ng Wallet", + "continue_text": "Magpatuloy", + "choose_wallet_currency": "Mangyaring piliin ang Pera ng Wallet:", + "node_new": "Bagong node", + "node_address": "Node address", + "node_port": "Node port", + "login": "Mag log in", + "password": "Password", + "nodes": "Node", + "node_reset_settings_title": "I -reset ang Mga Setting", + "nodes_list_reset_to_default_message": "Sigurado ka bang nais mong i -reset ang mga setting upang default?", + "change_current_node": "Sigurado ka bang baguhin ang kasalukuyang node sa ${node}?", + "change": "Palitan", + "remove_node": "Alisin ang node", + "remove_node_message": "Sigurado ka bang nais mong alisin ang napiling node?", + "remove": "Alisin", + "delete": "Tanggalin", + "add_new_node": "Magdagdag ng bagong node", + "change_current_node_title": "Baguhin ang kasalukuyang node", + "node_test": "Pagsusulit", + "node_connection_successful": "Ang koneksyon ay matagumpay", + "node_connection_failed": "Nabigo ang koneksyon", + "new_node_testing": "Bagong pagsubok sa node", + "use": "Lumipat sa", + "digit_pin": "-digit pin", + "share_address": "Ibahagi ang address", + "receive_amount": "Halaga", + "subaddresses": "Mga Subaddresses", + "addresses": "Mga address", + "scan_qr_code_to_get_address": "I -scan ang QR code upang makuha ang address", + "qr_fullscreen": "Tapikin upang buksan ang buong screen QR code", + "rename": "Palitan ang pangalan", + "choose_account": "Pumili ng account", + "create_new_account": "Lumikha ng Bagong Account", + "accounts_subaddresses": "Mga Account at Subaddresses", + "restore_restore_wallet": "Ibalik ang pitaka", + "restore_title_from_seed_keys": "Ibalik mula sa mga binhi/susi", + "restore_description_from_seed_keys": "Ibalik ang iyong pitaka mula sa mga binhi/susi na na -save mo upang ma -secure ang lugar", + "restore_next": "Susunod", + "restore_title_from_backup": "Ibalik mula sa backup", + "restore_description_from_backup": "Maaari mong ibalik ang buong cake wallet app mula sa iyong back-up file", + "restore_seed_keys_restore": "Ibinalik ang mga binhi/susi", + "restore_title_from_seed": "Ibalik mula sa binhi", + "restore_description_from_seed": "Ibalik ang iyong pitaka mula sa alinman sa 25 salita o 13 na code ng kombinasyon ng salita", + "restore_title_from_keys": "Ibalik mula sa mga susi", + "restore_description_from_keys": "Ibalik ang iyong pitaka mula sa nabuong mga keystroke na na -save mula sa iyong mga pribadong susi", + "restore_wallet_name": "Pangalan ng Wallet", + "restore_address": "Address", + "restore_view_key_private": "Tingnan ang Key (Pribado)", + "restore_spend_key_private": "Gumastos ng susi (pribado)", + "restore_recover": "Ibalik", + "restore_wallet_restore_description": "Paglalarawan ng Wallet", + "restore_new_seed": "Bagong binhi", + "restore_active_seed": "Aktibong binhi", + "restore_bitcoin_description_from_seed": "Ibalik ang iyong pitaka mula sa 24 na code ng kombinasyon ng salita", + "restore_bitcoin_description_from_keys": "Ibalik ang iyong pitaka mula sa nabuong wif string mula sa iyong mga pribadong susi", + "restore_bitcoin_title_from_keys": "Ibalik mula sa WIF", + "restore_from_date_or_blockheight": "Mangyaring magpasok ng isang petsa ng ilang araw bago mo nilikha ang pitaka na ito. O kung alam mo ang blockheight, mangyaring ipasok ito sa halip", + "seed_reminder": "Mangyaring isulat ang mga ito kung sakaling mawala ka o punasan ang iyong telepono", + "seed_title": "Binhi", + "seed_share": "Magbahagi ng binhi", + "copy": "Kopya", + "seed_language_choose": "Mangyaring pumili ng wika ng binhi:", + "seed_choose": "Pumili ng wika ng binhi", + "seed_language_next": "Susunod", + "seed_language_english": "Ingles", + "seed_language_chinese": "Tsino", + "seed_language_dutch": "Dutch", + "seed_language_german": "Aleman", + "seed_language_japanese": "Hapon", + "seed_language_portuguese": "Portuges", + "seed_language_russian": "Russian", + "seed_language_spanish": "Espanyol", + "seed_language_french": "Pranses", + "seed_language_italian": "Italyano", + "send_title": "Ipadala", + "send_your_wallet": "Iyong pitaka", + "send_address": "${cryptoCurrency} address", + "send_payment_id": "Payment ID (Opsyonal)", + "all": "Lahat", + "send_error_minimum_value": "Ang pinakamababang halaga ng halaga ay 0.01", + "send_error_currency": "Ang pera ay maaari lamang maglaman ng mga numero", + "send_estimated_fee": "Tinatayang bayad:", + "send_priority": "Sa kasalukuyan ang bayad ay nakatakda sa ${transactionPriority} priority.\nAng priority ng transaksyon ay maaaring maiakma sa mga setting", + "send_creating_transaction": "Paglikha ng transaksyon", + "send_templates": "Mga template", + "send_new": "Bago", + "send_amount": "Halaga:", + "send_fee": "Bayad:", + "send_name": "Pangalan", + "got_it": "Nakuha ko", + "send_sending": "Pagpapadala ...", + "send_success": "Ang iyong ${crypto} ay matagumpay na naipadala", + "settings_title": "Mga setting", + "settings_nodes": "Node", + "settings_current_node": "Kasalukuyang node", + "settings_wallets": "Wallets", + "settings_display_balance": "Ipakita ang balanse", + "settings_currency": "Pera", + "settings_fee_priority": "Priority priority", + "settings_save_recipient_address": "I -save ang address ng tatanggap", + "settings_personal": "Personal", + "settings_change_pin": "Baguhin ang pin", + "settings_change_language": "Baguhin ang wika", + "settings_allow_biometrical_authentication": "Payagan ang pagpapatunay ng biometrical", + "settings_dark_mode": "Madilim na mode", + "settings_transactions": "Mga Transaksyon", + "settings_trades": "Trading", + "settings_display_on_dashboard_list": "Ipakita sa listahan ng dashboard", + "settings_all": "Lahat", + "settings_only_trades": "TRADES LAMANG", + "settings_only_transactions": "Mga transaksyon lamang", + "settings_none": "Wala", + "settings_support": "Suporta", + "settings_terms_and_conditions": "Mga Tuntunin at Kundisyon", + "pin_is_incorrect": "Mali ang pin", + "setup_pin": "Setup pin", + "enter_your_pin_again": "Ipasok muli ang iyong pin", + "setup_successful": "Matagumpay na na -set up ang iyong pin!", + "wallet_keys": "Mga buto/susi ng pitaka", + "wallet_seed": "SEED ng Wallet", + "private_key": "Pribadong susi", + "public_key": "Pampublikong susi", + "view_key_private": "Tingnan ang Key (Pribado)", + "view_key_public": "Tingnan ang Key (Publiko)", + "spend_key_private": "Gumastos ng susi (pribado)", + "spend_key_public": "Gumastos ng susi (publiko)", + "copied_key_to_clipboard": "Kinopya ang ${key} sa clipboard", + "new_subaddress_title": "Bagong tirahan", + "new_subaddress_label_name": "Pangalan ng label", + "new_subaddress_create": "Lumikha", + "address_label": "Address Label", + "subaddress_title": "Listahan ng Subaddress", + "trade_details_title": "Mga detalye sa kalakalan", + "trade_details_id": "ID", + "trade_details_state": "Katayuan", + "trade_details_fetching": "Pagkuha", + "trade_details_provider": "Tagabigay", + "trade_details_created_at": "Nilikha sa", + "trade_details_pair": "Pares", + "trade_details_copied": "${title} kinopya sa clipboard", + "trade_history_title": "Kasaysayan ng Kalakal", + "transaction_details_title": "Mga detalye ng transaksyon", + "transaction_details_transaction_id": "Transaction ID", + "transaction_details_date": "Petsa", + "transaction_details_height": "Taas", + "transaction_details_amount": "Halaga", + "transaction_details_fee": "Bayad", + "transaction_details_copied": "${title} kinopya sa clipboard", + "transaction_details_recipient_address": "Mga address ng tatanggap", + "wallet_list_title": "Monero Wallet", + "wallet_list_create_new_wallet": "Lumikha ng bagong pitaka", + "wallet_list_edit_wallet": "I -edit ang Wallet", + "wallet_list_wallet_name": "Pangalan ng Wallet", + "wallet_list_restore_wallet": "Ibalik ang pitaka", + "wallet_list_load_wallet": "Mag -load ng pitaka", + "wallet_list_loading_wallet": "Naglo -load ng ${wallet_name} Wallet", + "wallet_list_failed_to_load": "Nabigong mag -load ng ${wallet_name} pitaka. ${error}", + "wallet_list_removing_wallet": "Pag -alis ng ${wallet_name} Wallet", + "wallet_list_failed_to_remove": "Nabigong alisin ang ${wallet_name} wallet. ${error}", + "widgets_address": "Address", + "widgets_restore_from_blockheight": "Ibalik mula sa blockheight", + "widgets_restore_from_date": "Ibalik mula sa petsa", + "widgets_or": "o", + "widgets_seed": "Binhi", + "router_no_route": "Walang ruta na tinukoy para sa ${name}", + "error_text_account_name": "Ang pangalan ng account ay maaari lamang maglaman ng mga titik, numero\nat dapat sa pagitan ng 1 at 15 character ang haba", + "error_text_contact_name": "Ang pangalan ng contact ay hindi maaaring maglaman ng mga simbolo ng ',' \"\nat dapat sa pagitan ng 1 at 32 character ang haba", + "error_text_address": "Ang wallet address ay dapat na tumutugma sa uri\nng cryptocurrency", + "error_text_node_address": "Mangyaring magpasok ng isang address ng IPv4", + "error_text_node_port": "Ang Node Port ay maaari lamang maglaman ng mga numero sa pagitan ng 0 at 65535", + "error_text_node_proxy_address": "Mangyaring ipasok ang : , halimbawa 127.0.0.1:9050", + "error_text_payment_id": "Ang Payment ID ay maaari lamang maglaman mula 16 hanggang 64 chars sa hex", + "error_text_xmr": "Ang halaga ng XMR ay hindi maaaring lumampas sa magagamit na balanse.\nAng bilang ng mga numero ng fraction ay dapat na mas mababa o katumbas ng 12", + "error_text_fiat": "Ang halaga ng halaga ay hindi maaaring lumampas sa magagamit na balanse.\nAng bilang ng mga numero ng fraction ay dapat na mas mababa o katumbas ng 2", + "error_text_subaddress_name": "Ang pangalan ng subaddress ay hindi maaaring maglaman ng mga simbolo na `, '\"\nat dapat sa pagitan ng 1 at 20 character ang haba", + "error_text_amount": "Ang halaga ay maaari lamang maglaman ng mga numero", + "error_text_wallet_name": "Ang pangalan ng pitaka ay maaari lamang maglaman ng mga titik, numero, _ - mga simbolo\nat dapat sa pagitan ng 1 at 33 character ang haba", + "error_text_keys": "Ang mga susi ng wallet ay maaari lamang maglaman ng 64 chars sa hex", + "error_text_crypto_currency": "Ang bilang ng mga numero ng fraction\ndapat mas mababa o katumbas ng 12", + "error_text_minimal_limit": "Ang kalakalan para sa ${provider} ay hindi nilikha. Ang halaga ay mas mababa pagkatapos ng minimal: ${min} ${currency}", + "error_text_maximum_limit": "Ang kalakalan para sa ${provider} ay hindi nilikha. Ang halaga ay higit na maximum: ${max} ${currency}", + "error_text_limits_loading_failed": "Ang kalakalan para sa ${provider} ay hindi nilikha. Nabigo ang mga limitasyon sa paglo -load", + "error_text_template": "Ang pangalan ng template at address ay hindi maaaring maglaman ng mga simbolo ng ',' \"\nat dapat sa pagitan ng 1 at 106 na character ang haba", + "auth_store_ban_timeout": "ban_timeout", + "auth_store_banned_for": "Pinagbawalan para sa", + "auth_store_banned_minutes": "minuto", + "auth_store_incorrect_password": "Maling pin", + "wallet_store_monero_wallet": "Monero Wallet", + "wallet_restoration_store_incorrect_seed_length": "Maling haba ng binhi", + "full_balance": "Buong balanse", + "available_balance": "Magagamit na balanse", + "hidden_balance": "Nakatagong balanse", + "sync_status_syncronizing": "Pag -synchronize", + "sync_status_syncronized": "Naka -synchronize", + "sync_status_not_connected": "HINDI KONEKTADO", + "sync_status_starting_sync": "Simula sa pag -sync", + "sync_status_failed_connect": "Naka -disconnect", + "sync_status_connecting": "Pagkonekta", + "sync_status_connected": "Konektado", + "sync_status_attempting_sync": "Pagtatangka ng pag -sync", + "transaction_priority_slow": "Mabagal", + "transaction_priority_regular": "Regular", + "transaction_priority_medium": "Katamtaman", + "transaction_priority_fast": "Mabilis", + "transaction_priority_fastest": "Pinakamabilis", + "trade_for_not_created": "Ang kalakalan para sa ${title} ay hindi nilikha.", + "trade_not_created": "Hindi nilikha ang kalakalan", + "trade_id_not_found": "Trade ${tradeId} ng ${title} Hindi natagpuan.", + "trade_not_found": "Hindi natagpuan ang kalakalan.", + "trade_state_pending": "Nakabinbin", + "trade_state_confirming": "Pagkumpirma", + "trade_state_trading": "Pangangalakal", + "trade_state_traded": "Ipinagpalit", + "trade_state_complete": "Kumpleto", + "trade_state_to_be_created": "Upang malikha", + "trade_state_unpaid": "Walang bayad", + "trade_state_underpaid": "Underpaid", + "trade_state_paid_unconfirmed": "Bayad na hindi nakumpirma", + "trade_state_paid": "Bayad", + "trade_state_btc_sent": "Ipinadala ang BTC", + "trade_state_timeout": "Oras ng oras", + "trade_state_created": "Nilikha", + "trade_state_finished": "Tapos na", + "change_language": "Baguhin ang wika", + "change_language_to": "Baguhin ang wika sa ${language}?", + "paste": "I -paste", + "restore_from_seed_placeholder": "Mangyaring ipasok o i -paste ang iyong binhi dito", + "add_new_word": "Magdagdag ng bagong salita", + "incorrect_seed": "Ang teksto na ipinasok ay hindi wasto.", + "biometric_auth_reason": "I -scan ang iyong fingerprint upang mapatunayan", + "version": "Bersyon ${currentVersion}", + "extracted_address_content": "Magpapadala ka ng pondo sa\n${recipient_name}", + "card_address": "Address:", + "buy": "Bilhin", + "sell": "Ibenta", + "placeholder_transactions": "Ang iyong mga transaksyon ay ipapakita dito", + "placeholder_contacts": "Ang iyong mga contact ay ipapakita dito", + "template": "Template", + "confirm_delete_template": "Ang pagkilos na ito ay tatanggalin ang template na ito. Nais mo bang magpatuloy?", + "confirm_delete_wallet": "Ang pagkilos na ito ay tatanggalin ang pitaka na ito. Nais mo bang magpatuloy?", + "picker_description": "Upang pumili ng Changenow o MorphToken, mangyaring baguhin muna ang iyong pares ng kalakalan", + "change_wallet_alert_title": "Baguhin ang kasalukuyang pitaka", + "change_wallet_alert_content": "Nais mo bang baguhin ang kasalukuyang pitaka sa ${wallet_name}?", + "creating_new_wallet": "Lumilikha ng bagong pitaka", + "creating_new_wallet_error": "Error: ${description}", + "seed_alert_title": "Pansin", + "seed_alert_content": "Ang binhi ay ang tanging paraan upang mabawi ang iyong pitaka. Nasulat mo na ba ito?", + "seed_alert_back": "Bumalik ka", + "seed_alert_yes": "Oo meron ako", + "exchange_sync_alert_content": "Mangyaring maghintay hanggang ang iyong pitaka ay naka -synchronize", + "pre_seed_title": "Mahalaga", + "pre_seed_description": "Sa susunod na pahina makikita mo ang isang serye ng mga ${words} na mga salita. Ito ang iyong natatangi at pribadong binhi at ito ang tanging paraan upang mabawi ang iyong pitaka kung sakaling mawala o madepektong paggawa. Responsibilidad mong isulat ito at itago ito sa isang ligtas na lugar sa labas ng cake wallet app.", + "pre_seed_button_text": "Naiintindihan ko. Ipakita sa akin ang aking binhi", + "xmr_to_error": "Xmr.to error", + "xmr_to_error_description": "Di -wastong halaga. Pinakamataas na limitasyon ng 8 numero pagkatapos ng punto ng desimal", + "provider_error": "${provider} error", + "use_ssl": "Gumamit ng SSL", + "trusted": "Pinagkakatiwalaan", + "color_theme": "Tema ng kulay", + "light_theme": "Ilaw", + "bright_theme": "Maliwanag", + "dark_theme": "Madilim", + "enter_your_note": "Ipasok ang iyong tala ...", + "note_optional": "Tandaan (Opsyonal)", + "note_tap_to_change": "Tandaan (Tapikin upang baguhin)", + "view_in_block_explorer": "Tingnan sa Block Explorer", + "view_transaction_on": "Tingnan ang transaksyon sa", + "transaction_key": "Susi ng transaksyon", + "confirmations": "Mga kumpirmasyon", + "recipient_address": "Address ng tatanggap", + "extra_id": "Dagdag na ID:", + "destination_tag": "Tag ng patutunguhan:", + "memo": "Memo:", + "backup": "Backup", + "change_password": "Palitan ANG password", + "backup_password": "Backup password", + "write_down_backup_password": "Mangyaring isulat ang iyong backup password, na ginagamit para sa pag -import ng iyong mga backup file.", + "export_backup": "I -export ang backup", + "save_backup_password": "Mangyaring tiyaking nai -save mo ang iyong backup password. Hindi mo mai -import ang iyong mga backup na file nang wala ito.", + "backup_file": "Backup file", + "edit_backup_password": "I -edit ang backup password", + "save_backup_password_alert": "I -save ang backup password", + "change_backup_password_alert": "Ang iyong mga nakaraang backup file ay hindi magagamit upang mai -import gamit ang bagong backup password. Ang bagong backup na password ay gagamitin lamang para sa mga bagong backup file. Sigurado ka bang nais mong baguhin ang backup password?", + "enter_backup_password": "Ipasok ang backup password dito", + "select_backup_file": "Piliin ang backup file", + "import": "Angkat", + "please_select_backup_file": "Mangyaring piliin ang backup file at ipasok ang backup password.", + "fixed_rate": "Naayos na rate", + "fixed_rate_alert": "Magagawa mong ipasok ang makatanggap na halaga kapag naka -check ang naayos na mode ng rate. Nais mo bang lumipat sa nakapirming mode ng rate?", + "xlm_extra_info": "Mangyaring huwag kalimutan na tukuyin ang memo ID habang ipinapadala ang transaksyon ng XLM para sa palitan", + "xrp_extra_info": "Mangyaring huwag kalimutan na tukuyin ang patutunguhan na tag habang ipinapadala ang transaksyon ng XRP para sa palitan", + "exchange_incorrect_current_wallet_for_xmr": "Kung nais mong makipagpalitan ng XMR mula sa iyong balanse ng cake wallet Monero, mangyaring lumipat sa iyong Monero Wallet muna.", + "confirmed": "Nakumpirma na balanse", + "unconfirmed": "Hindi nakumpirma na balanse", + "displayable": "Maipapakita", + "submit_request": "magsumite ng isang kahilingan", + "buy_alert_content": "Sa kasalukuyan ay sinusuportahan lamang namin ang pagbili ng Bitcoin, Ethereum, Litecoin, at Monero. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum, Litecoin, o Monero Wallet.", + "sell_alert_content": "Kasalukuyan lamang naming sinusuportahan ang pagbebenta ng Bitcoin, Ethereum at Litecoin. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum o Litecoin Wallet.", + "outdated_electrum_wallet_description": "Ang mga bagong wallets ng Bitcoin na nilikha sa cake ay mayroon na ngayong 24-salitang binhi. Ipinag-uutos na lumikha ka ng isang bagong pitaka ng Bitcoin at ilipat ang lahat ng iyong mga pondo sa bagong 24-salitang pitaka, at itigil ang paggamit ng mga pitaka na may 12-salitang binhi. Mangyaring gawin ito kaagad upang ma -secure ang iyong mga pondo.", + "understand": "naiintindihan ko", + "apk_update": "APK Update", + "buy_bitcoin": "Bumili ng bitcoin", + "buy_with": "Bumili ka", + "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", + "outdated_electrum_wallet_receive_warning": "Kung ang pitaka na ito ay may 12-salitang binhi at nilikha sa cake, huwag magdeposito sa Bitcoin sa pitaka na ito. Ang anumang BTC na inilipat sa pitaka na ito ay maaaring mawala. Lumikha ng isang bagong 24-word wallet (tapikin ang menu sa kanang tuktok, piliin ang mga pitaka, piliin ang Lumikha ng Bagong Wallet, pagkatapos ay piliin ang Bitcoin) at agad na ilipat ang iyong BTC doon. Ang mga bagong (24-salita) BTC Wallets mula sa cake ay ligtas", + "do_not_show_me": "Huwag mo itong ipakita muli", + "unspent_coins_title": "Unspent barya", + "unspent_coins_details_title": "Mga Detalye ng Unspent Coins", + "freeze": "I -freeze", + "frozen": "Frozen", + "coin_control": "Control ng barya (opsyonal)", + "address_detected": "Nakita ang address", + "address_from_domain": "Ang address na ito ay mula sa ${domain} sa mga hindi mapigilan na mga domain", + "add_receiver": "Magdagdag ng isa pang tatanggap (opsyonal)", + "manage_yats": "Pamahalaan ang mga yats", + "yat_alert_title": "Magpadala at tumanggap ng crypto nang mas madali sa yat", + "yat_alert_content": "Ang mga gumagamit ng cake wallet ay maaari na ngayong magpadala at makatanggap ng lahat ng kanilang mga paboritong pera na may isang one-of-a-kind emoji-based username.", + "get_your_yat": "Kunin ang iyong yat", + "connect_an_existing_yat": "Ikonekta ang isang umiiral na yat", + "connect_yats": "Ikonekta ang mga yats", + "yat_address": "Yat address", + "yat": "Yat", + "address_from_yat": "Ang address na ito ay mula sa ${emoji} sa yat", + "yat_error": "Error sa yat", + "yat_error_content": "Walang mga address na naka -link sa yat na ito. Subukan ang isa pang yat", + "choose_address": "Mangyaring piliin ang address:", + "yat_popup_title": "Ang iyong wallet address ay maaaring ma -emojified.", + "yat_popup_content": "Maaari ka na ngayong magpadala at makatanggap ng crypto sa cake wallet kasama ang iyong yat - isang maikli, emoji na batay sa username. Pamahalaan ang mga yats anumang oras sa screen ng Mga Setting", + "second_intro_title": "Isang address ng emoji upang mamuno sa kanilang lahat", + "second_intro_content": "Ang iyong yat ay isang solong natatanging address ng emoji na pumapalit sa lahat ng iyong mahabang hexadecimal address para sa lahat ng iyong mga pera.", + "third_intro_title": "Si Yat ay mahusay na gumaganap sa iba", + "third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!", + "learn_more": "Matuto nang higit pa", + "search": "Maghanap", + "search_language": "Maghanap ng wika", + "search_currency": "Maghanap ng pera", + "new_template": "Bagong template", + "electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", + "wallet_name_exists": "Ang isang pitaka na may pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan o palitan muna ang iba pang pitaka.", + "market_place": "Marketplace", + "cake_pay_title": "Cake pay card card", + "cake_pay_subtitle": "Bumili ng mga diskwento na gift card (USA lamang)", + "cake_pay_web_cards_title": "Cake pay web card", + "cake_pay_web_cards_subtitle": "Bumili ng mga pandaigdigang prepaid card at gift card", + "about_cake_pay": "Pinapayagan ka ng cake Pay na madaling bumili ng mga kard ng regalo na may mga virtual na pag -aari, gastusin agad sa higit sa 150,000 mga mangangalakal sa Estados Unidos.", + "cake_pay_account_note": "Mag -sign up na may isang email address lamang upang makita at bumili ng mga kard. Ang ilan ay magagamit kahit sa isang diskwento!", + "already_have_account": "Mayroon nang account?", + "create_account": "Lumikha ng account", + "privacy_policy": "Patakaran sa Pagkapribado", + "welcome_to_cakepay": "Maligayang pagdating sa cake pay!", + "sign_up": "Mag -sign up", + "forgot_password": "Nakalimutan ang password", + "reset_password": "I -reset ang password", + "gift_cards": "Mga kard ng regalo", + "setup_your_debit_card": "I -set up ang iyong debit card", + "no_id_required": "Walang kinakailangang ID. I -top up at gumastos kahit saan", + "how_to_use_card": "Paano gamitin ang kard na ito", + "purchase_gift_card": "Bumili ng Gift Card", + "verification": "Pag -verify", + "fill_code": "Mangyaring punan ang verification code na ibinigay sa iyong email", + "didnt_get_code": "Hindi nakuha ang code?", + "resend_code": "Mangyaring ipagpatuloy ito", + "debit_card": "Debit card", + "cakepay_prepaid_card": "Cakepay prepaid debit card", + "no_id_needed": "Hindi kailangan ng ID!", + "frequently_asked_questions": "Madalas na nagtanong", + "debit_card_terms": "Ang pag -iimbak at paggamit ng numero ng iyong card ng pagbabayad (at mga kredensyal na naaayon sa iyong numero ng card ng pagbabayad) sa digital na pitaka na ito ay napapailalim sa mga termino at kundisyon ng naaangkop na kasunduan sa cardholder kasama ang nagbigay ng card ng pagbabayad, tulad ng sa oras -oras.", + "please_reference_document": "Mangyaring sanggunian ang mga dokumento sa ibaba para sa karagdagang impormasyon.", + "cardholder_agreement": "Kasunduan sa Cardholder", + "e_sign_consent": "E-sign na pahintulot", + "agree_and_continue": "Sumang -ayon at magpatuloy", + "email_address": "Email address", + "agree_to": "Sa pamamagitan ng paglikha ng account sumasang -ayon ka sa", + "and": "at", + "enter_code": "Ipasok ang code", + "congratulations": "Binabati kita!", + "you_now_have_debit_card": "Mayroon ka na ngayong debit card", + "min_amount": "Min: ${value}", + "max_amount": "Max: ${value}", + "enter_amount": "Ipasok ang halaga", + "billing_address_info": "Kung tatanungin ang isang address ng pagsingil, ibigay ang iyong address sa pagpapadala", + "order_physical_card": "Mag -order ng pisikal na kard", + "add_value": "Magdagdag ng halaga", + "activate": "Buhayin", + "get_a": "Kumuha ng", + "digital_and_physical_card": "Digital at Physical Prepaid Debit Card", + "get_card_note": "na maaari mong i -reload sa mga digital na pera. Walang karagdagang impormasyon na kailangan!", + "signup_for_card_accept_terms": "Mag -sign up para sa card at tanggapin ang mga termino.", + "add_fund_to_card": "Magdagdag ng prepaid na pondo sa mga kard (hanggang sa ${value})", + "use_card_info_two": "Ang mga pondo ay na -convert sa USD kapag gaganapin sila sa prepaid account, hindi sa mga digital na pera.", + "use_card_info_three": "Gamitin ang digital card online o sa mga pamamaraan ng pagbabayad na walang contact.", + "optionally_order_card": "Opsyonal na mag -order ng isang pisikal na kard.", + "hide_details": "Itago ang mga detalye", + "show_details": "Ipakita ang mga detalye", + "upto": "Hanggang sa ${value}", + "discount": "Makatipid ng ${value}%", + "gift_card_amount": "Halaga ng Gift Card", + "bill_amount": "Halaga ng Bill", + "you_pay": "Magbabayad ka", + "tip": "Tip:", + "custom": "pasadya", + "by_cake_pay": "sa pamamagitan ng cake pay", + "expires": "Mag -expire", + "mm": "Mm", + "yy": "YY", + "online": "Online", + "offline": "Offline", + "gift_card_number": "Numero ng regalo card", + "pin_number": "Numero ng pin", + "total_saving": "Kabuuang pagtitipid", + "last_30_days": "Huling 30 araw", + "avg_savings": "Avg. Matitipid", + "view_all": "Tingnan lahat", + "active_cards": "Mga aktibong kard", + "delete_account": "Tanggalin ang account", + "cards": "Mga Card", + "active": "Aktibo", + "redeemed": "Tinubos", + "gift_card_balance_note": "Ang mga kard ng regalo na may natitirang balanse ay lilitaw dito", + "gift_card_redeemed_note": "Ang mga kard ng regalo na iyong tinubos ay lilitaw dito", + "logout": "Mag -logout", + "add_tip": "Magdagdag ng tip", + "percentageOf": "ng ${amount}", + "is_percentage": "ay", + "search_category": "Kategorya ng paghahanap", + "mark_as_redeemed": "Markahan bilang tinubos", + "more_options": "Higit pang mga pagpipilian", + "awaiting_payment_confirmation": "Naghihintay ng kumpirmasyon sa pagbabayad", + "transaction_sent_notice": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang isang block explorer at ang iyong email.", + "agree": "Sumang -ayon", + "in_store": "Nakatago", + "generating_gift_card": "Bumubuo ng Gift Card", + "payment_was_received": "Natanggap ang iyong pagbabayad.", + "proceed_after_one_minute": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang iyong email.", + "order_id": "Order id", + "gift_card_is_generated": "Ang card ng regalo ay nabuo", + "open_gift_card": "Buksan ang Gift Card", + "contact_support": "Makipag -ugnay sa suporta", + "gift_cards_unavailable": "Magagamit ang mga gift card para sa pagbili lamang kasama ang Monero, Bitcoin, at Litecoin sa oras na ito", + "background_sync_mode": "Mode ng pag -sync ng background", + "sync_all_wallets": "I -sync ang lahat ng mga pitaka", + "introducing_cake_pay": "Ipinakikilala ang cake pay!", + "cake_pay_learn_more": "Agad na bumili at tubusin ang mga kard ng regalo sa app!\nMag -swipe pakaliwa sa kanan upang matuto nang higit pa.", + "automatic": "Awtomatiko", + "fixed_pair_not_supported": "Ang nakapirming pares na ito ay hindi suportado sa mga napiling palitan", + "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling palitan", + "none_of_selected_providers_can_exchange": "Wala sa mga napiling tagapagkaloob na maaaring gumawa ng palitan na ito", + "choose_one": "Pumili ng isa", + "choose_from_available_options": "Pumili mula sa magagamit na mga pagpipilian:", + "custom_redeem_amount": "Pasadyang tinubos ang halaga", + "add_custom_redemption": "Magdagdag ng pasadyang pagtubos", + "remaining": "natitira", + "delete_wallet": "Tanggalin ang pitaka", + "delete_wallet_confirm_message": "Sigurado ka bang nais mong tanggalin ang ${wallet_name} wallet?", + "low_fee": "Mababang bayad", + "low_fee_alert": "Kasalukuyan kang gumagamit ng isang mababang priyoridad sa bayad sa network. Maaari itong maging sanhi ng mahabang paghihintay, iba't ibang mga rate, o kanselahin ang mga trading. Inirerekumenda namin ang pagtatakda ng isang mas mataas na bayad para sa isang mas mahusay na karanasan.", + "ignor": "Huwag pansinin", + "use_suggested": "Gumamit ng iminungkahing", + "do_not_share_warning_text": "Huwag ibahagi ang mga ito sa sinumang iba pa, kabilang ang suporta.\n\nAng iyong mga pondo ay maaari at ninakaw!", + "help": "Tulong", + "all_transactions": "Lahat ng mga transaksyon", + "all_trades": "Lahat ng mga kalakal", + "connection_sync": "Koneksyon at pag -sync", + "security_and_backup": "Seguridad at backup", + "create_backup": "Gumawa ng backup", + "privacy_settings": "Settings para sa pagsasa-pribado", + "privacy": "Privacy", + "display_settings": "Mga setting ng pagpapakita", + "other_settings": "Iba pang mga setting", + "auto_generate_subaddresses": "Ang Auto ay bumubuo ng mga subaddresses", + "require_pin_after": "Nangangailangan ng pin pagkatapos", + "always": "Palagi", + "minutes_to_pin_code": "${minute} minuto", + "disable_exchange": "Huwag paganahin ang palitan", + "advanced_privacy_settings": "Mga setting ng advanced na privacy", + "settings_can_be_changed_later": "Ang mga setting na ito ay maaaring mabago mamaya sa mga setting ng app", + "add_custom_node": "Magdagdag ng bagong pasadyang node", + "disable_fiat": "Huwag paganahin ang Fiat", + "fiat_api": "Fiat API", + "disabled": "Hindi pinagana", + "enabled": "Pinagana", + "tor_only": "Tor lang", + "unmatched_currencies": "Ang pera ng iyong kasalukuyang pitaka ay hindi tumutugma sa na -scan na QR", + "orbot_running_alert": "Mangyaring tiyakin na ang Orbot ay tumatakbo bago kumonekta sa node na ito.", + "contact_list_contacts": "Mga contact", + "contact_list_wallets": "Ang mga wallets ko", + "bitcoin_payments_require_1_confirmation": "Ang mga pagbabayad sa Bitcoin ay nangangailangan ng 1 kumpirmasyon, na maaaring tumagal ng 20 minuto o mas mahaba. Salamat sa iyong pasensya! Mag -email ka kapag nakumpirma ang pagbabayad.", + "send_to_this_address": "Magpadala ng ${currency} ${tag} sa address na ito", + "arrive_in_this_address": "Ang ${currency} ${tag} ay darating sa address na ito", + "do_not_send": "Huwag magpadala", + "error_dialog_content": "Oops, nakakuha kami ng ilang error.\n\nMangyaring ipadala ang ulat ng pag -crash sa aming koponan ng suporta upang maging mas mahusay ang application.", + "scan_qr_code": "I -scan ang QR Code", + "cold_or_recover_wallet": "Magdagdag ng isang malamig na pitaka o mabawi ang isang wallet ng papel", + "please_wait": "Mangyaring maghintay", + "sweeping_wallet": "Pagwawalis ng pitaka", + "sweeping_wallet_alert": "Hindi ito dapat magtagal. Huwag iwanan ang screen na ito o maaaring mawala ang mga pondo ng swept.", + "invoice_details": "Mga detalye ng invoice", + "donation_link_details": "Mga Detalye ng Link ng Donasyon", + "anonpay_description": "Bumuo ng ${type}. Ang tatanggap ay maaaring ${method} na may anumang suportadong cryptocurrency, at makakatanggap ka ng mga pondo sa pitaka na ito.", + "create_invoice": "Lumikha ng invoice", + "create_donation_link": "Lumikha ng link ng donasyon", + "optional_email_hint": "Opsyonal na Payee Notification Email", + "optional_description": "Opsyonal na paglalarawan", + "optional_name": "Opsyonal na pangalan ng tatanggap", + "clearnet_link": "Link ng Clearnet", + "onion_link": "Link ng Onion", + "decimal_places_error": "Masyadong maraming mga lugar na desimal", + "edit_node": "I -edit ang node", + "frozen_balance": "Frozen na balanse", + "settings": "Mga setting", + "sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado", + "error_text_input_below_minimum_limit": "Ang halaga ay mas mababa sa minimum", + "error_text_input_above_maximum_limit": "Ang halaga ay higit pa sa maximum", + "show_market_place": "Ipakita ang Marketplace", + "prevent_screenshots": "Maiwasan ang mga screenshot at pag -record ng screen", + "profile": "Profile", + "close": "Malapit", + "modify_2fa": "Baguhin ang cake 2FA", + "disable_cake_2fa": "Huwag paganahin ang cake 2FA", + "question_to_disable_2fa": "Sigurado ka bang nais mong huwag paganahin ang cake 2fa? Ang isang 2FA code ay hindi na kinakailangan upang ma -access ang pitaka at ilang mga pag -andar.", + "disable": "Huwag paganahin", + "setup_2fa": "Setup cake 2fa", + "verify_with_2fa": "Mag -verify sa cake 2FA", + "totp_code": "TOTP code", + "please_fill_totp": "Mangyaring punan ang 8-digit na code na naroroon sa iyong iba pang aparato", + "totp_2fa_success": "Tagumpay! Pinagana ang cake 2FA para sa pitaka na ito. Tandaan na i -save ang iyong mnemonic seed kung sakaling mawalan ka ng pag -access sa pitaka.", + "totp_verification_success": "Matagumpay ang pagpapatunay!", + "totp_2fa_failure": "Maling code. Mangyaring subukan ang ibang code o makabuo ng isang bagong lihim na susi. Gumamit ng isang katugmang 2FA app na sumusuporta sa 8-digit na mga code at SHA512.", + "enter_totp_code": "Mangyaring ipasok ang TOTP code.", + "add_secret_code": "Idagdag ang lihim na code na ito sa isa pang aparato", + "totp_secret_code": "TOTP Secret Code", + "important_note": "Mahalagang paalaala", + "setup_2fa_text": "Ang cake 2FA ay hindi ligtas tulad ng malamig na imbakan. Pinoprotektahan ng 2FA laban sa mga pangunahing uri ng pag -atake, tulad ng iyong kaibigan na nagbibigay ng iyong fingerprint habang natutulog ka.\n\n Hindi pinoprotektahan ng cake 2FA laban sa isang nakompromiso na aparato ng isang sopistikadong umaatake.\n\n Kung nawalan ka ng pag -access sa iyong 2FA code, mawawalan ka ng access sa pitaka na ito. Kakailanganin mong ibalik ang iyong pitaka mula sa binhi ng mnemonic. Dapat mong i -back up ang iyong mga buto ng mnemonic! Dagdag pa, ang isang tao na may access sa iyong (mga) binhi ng mnemonic ay maaaring magnakaw ng iyong mga pondo, na lumampas sa cake 2FA.\n\n Ang mga kawani ng suporta sa cake ay hindi makakatulong sa iyo kung nawalan ka ng pag -access sa iyong mnemonic seed, dahil ang cake ay isang noncustodial wallet.", + "setup_totp_recommended": "I -set up ang TOTP (inirerekomenda)", + "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", + "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta", + "monero_dark_theme": "Monero Madilim na Tema", + "bitcoin_dark_theme": "Bitcoin Madilim na Tema", + "bitcoin_light_theme": "Tema ng ilaw ng bitcoin", + "high_contrast_theme": "Mataas na tema ng kaibahan", + "matrix_green_dark_theme": "Matrix Green Madilim na Tema", + "monero_light_theme": "Tema ng Monero Light", + "cake_2fa_preset": "Cake 2fa preset", + "narrow": "Makitid", + "normal": "Normal", + "aggressive": "Agresibo", + "require_for_assessing_wallet": "Nangangailangan para sa pag -access ng pitaka", + "require_for_sends_to_non_contacts": "Nangangailangan para sa pagpapadala sa mga hindi contact", + "require_for_sends_to_contacts": "Nangangailangan para sa pagpapadala sa mga contact", + "require_for_sends_to_internal_wallets": "Nangangailangan para sa pagpapadala sa mga panloob na mga pitaka", + "require_for_exchanges_to_internal_wallets": "Nangangailangan para sa mga palitan sa mga panloob na mga pitaka", + "require_for_adding_contacts": "Nangangailangan para sa pagdaragdag ng mga contact", + "require_for_creating_new_wallets": "Nangangailangan para sa paglikha ng mga bagong pitaka", + "require_for_all_security_and_backup_settings": "Nangangailangan para sa lahat ng mga setting ng seguridad at backup", + "available_balance_description": "Ang \"magagamit na balanse\" o \"nakumpirma na balanse\" ay mga pondo na maaaring gastusin kaagad. Kung lumilitaw ang mga pondo sa mas mababang balanse ngunit hindi ang nangungunang balanse, dapat kang maghintay ng ilang minuto para sa mga papasok na pondo upang makakuha ng mas maraming mga kumpirmasyon sa network. Matapos silang makakuha ng higit pang mga kumpirmasyon, gugugol sila.", + "syncing_wallet_alert_title": "Ang iyong pitaka ay nag -sync", + "syncing_wallet_alert_content": "Ang iyong balanse at listahan ng transaksyon ay maaaring hindi kumpleto hanggang sa sabihin nito na \"naka -synchronize\" sa tuktok. Mag -click/tap upang malaman ang higit pa.", + "home_screen_settings": "Mga setting ng home screen", + "sort_by": "Pag -uri -uriin sa pamamagitan ng", + "search_add_token": "Maghanap / Magdagdag ng Token", + "edit_token": "I -edit ang token", + "warning": "Babala", + "add_token_warning": "Huwag i -edit o magdagdag ng mga token tulad ng itinuro ng mga scammers.\nLaging kumpirmahin ang mga token address na may mga kagalang -galang na mapagkukunan!", + "add_token_disclaimer_check": "Kinumpirma ko ang address ng kontrata ng token at impormasyon gamit ang isang kagalang -galang na mapagkukunan. Ang pagdaragdag ng nakakahamak o hindi tamang impormasyon ay maaaring magresulta sa pagkawala ng mga pondo.", + "token_contract_address": "Token Address ng Kontrata", + "token_name": "Pangalan ng Token hal: Tether", + "token_symbol": "Simbolo ng token hal: USDT", + "token_decimal": "Token Decimal", + "field_required": "Kinakailangan ang patlang na ito", + "pin_at_top": "Pin ${token} sa tuktok", + "invalid_input": "Di -wastong input", + "fiat_balance": "Balanse ng fiat", + "gross_balance": "Balanse ng gross", + "alphabetical": "Alpabeto", + "generate_name": "Bumuo ng pangalan", + "balance_page": "Pahina ng Balanse", + "share": "Ibahagi", + "slidable": "Slidable", + "manage_nodes": "Pamahalaan ang mga node", + "etherscan_history": "Kasaysayan ng Etherscan", + "template_name": "Pangalan ng Template", + "support_title_live_chat": "Live na suporta", + "support_description_live_chat": "Libre at mabilis! Ang mga bihasang kinatawan ng suporta ay magagamit upang tulungan", + "support_title_guides": "Mga Gabay sa Wallet ng cake", + "support_description_guides": "Dokumentasyon at suporta para sa mga karaniwang isyu", + "support_title_other_links": "Iba pang mga link sa suporta", + "support_description_other_links": "Sumali sa aming mga komunidad o maabot sa amin ang aming mga kasosyo sa pamamagitan ng iba pang mga pamamaraan", + "select_destination": "Mangyaring piliin ang patutunguhan para sa backup file.", + "save_to_downloads": "I -save sa mga pag -download" +} \ No newline at end of file diff --git a/tool/translation_add_lang.dart b/tool/translation_add_lang.dart new file mode 100644 index 000000000..8b392df6e --- /dev/null +++ b/tool/translation_add_lang.dart @@ -0,0 +1,36 @@ +import 'dart:io'; + +import 'utils/translation/arb_file_utils.dart'; +import 'utils/translation/translation_constants.dart'; +import 'utils/translation/translation_utils.dart'; + +void main(List args) async { + if (args.length != 1) { + throw Exception( + 'Insufficient arguments!\n\nTry to run `./translation_add_lang.dart langCode`'); + } + + final targetLang = args.first; + + final fileName = getArbFileName(defaultLang); + final file = File(fileName); + final arbObj = readArbFile(file); + + final targetFileName = getArbFileName(targetLang); + final targetKeys = arbObj.keys; + + final targetFile = File(targetFileName); + targetFile.createSync(exclusive: true); + targetFile.writeAsStringSync("{}"); + + final translations = Map(); + for (var targetKey in targetKeys) { + final srcString = arbObj[targetKey] as String; + final translation = await getTranslation(srcString, targetLang); + + translations[targetKey] = translation; + } + + appendStringsToArbFile(targetFileName, translations); + print("Success! Please add your Language Code to lib/entities/language_service.dart"); +} diff --git a/tool/utils/translation/arb_file_utils.dart b/tool/utils/translation/arb_file_utils.dart index 693c5b93e..c43de091a 100644 --- a/tool/utils/translation/arb_file_utils.dart +++ b/tool/utils/translation/arb_file_utils.dart @@ -17,7 +17,8 @@ void appendStringToArbFile(String fileName, String name, String text) { .replaceAll('","', '",\n "') .replaceAll('{"', '{\n "') .replaceAll('"}', '"\n}') - .replaceAll('":"', '": "'); + .replaceAll('":"', '": "') + .replaceAll('\$ {', '\${'); file.writeAsStringSync(outputContent); } @@ -33,7 +34,8 @@ void appendStringsToArbFile(String fileName, Map strings) { .replaceAll('","', '",\n "') .replaceAll('{"', '{\n "') .replaceAll('"}', '"\n}') - .replaceAll('":"', '": "'); + .replaceAll('":"', '": "') + .replaceAll('\$ {', '\${'); file.writeAsStringSync(outputContent); } diff --git a/tool/utils/translation/translation_utils.dart b/tool/utils/translation/translation_utils.dart index a37838b91..173b66c39 100644 --- a/tool/utils/translation/translation_utils.dart +++ b/tool/utils/translation/translation_utils.dart @@ -18,20 +18,28 @@ Future appendTranslations(String lang, Map defaults) async for (var key in defaults.keys) { final value = defaults[key]!; - - if (value.contains("{")) continue; final translation = await getTranslation(value, lang); translations[key] = translation; } - print(translations); - appendStringsToArbFile(fileName, translations); } Future getTranslation(String text, String lang) async { if (lang == defaultLang) return text; - return (await translator.translate(text, from: defaultLang, to: lang)).text; -} + final regExp = RegExp(r'{(.*?)}'); + final placeholder = + regExp.allMatches(text).map((e) => text.substring(e.start, e.end)).toList().asMap(); + + var translation = (await translator.translate(text, from: defaultLang, to: lang)).text; + + placeholder.forEach((index, value) { + final translatedPlaceholder = regExp.allMatches(translation).toList()[index]; + translation = + translation.replaceRange(translatedPlaceholder.start, translatedPlaceholder.end, value); + }); + + return translation; +} diff --git a/tool/utils/utils.dart b/tool/utils/utils.dart index 2fd474de7..e43063165 100644 --- a/tool/utils/utils.dart +++ b/tool/utils/utils.dart @@ -10,4 +10,4 @@ String normalizeKeyName(String key) { } String generateConst(String name, Map config) => - 'const $name = \'${config["$name"]}\';\n'; \ No newline at end of file + 'const $name = \'${config["$name"]}\';\n'; From b6de1be6c4087d8dfafc40958f1d837c6c4bd740 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sun, 17 Sep 2023 13:23:14 +0300 Subject: [PATCH 5/5] Update app version and release notes (#1093) --- assets/text/Monerocom_Release_Notes.txt | 8 +++----- assets/text/Release_Notes.txt | 11 +++++------ lib/src/screens/restore/restore_options_page.dart | 2 +- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 4 ++-- 6 files changed, 19 insertions(+), 22 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index a8b55383d..cbe201cf8 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,5 +1,3 @@ -Ability to Auto generate new Monero subaddress when used -Coin Control for Monero -In-app Live Chat support -Additional themes -Bug Fixes and performance enhancements \ No newline at end of file +Enhance Monero coin control +Add Filipino localization +Bug Fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 263689318..263e7ccfe 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,6 +1,5 @@ -Restore Ethereum from private key and QR -Ability to Auto generate new Monero subaddress when used -Coin Control for Monero -In-app Live Chat support -Additional themes -Bug Fixes and performance enhancements \ No newline at end of file +New Buy Provider Robinhood +Fix sending Ethereum issue +Enhance Monero coin control +Add Filipino localization +Bug Fixes \ No newline at end of file diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 191bddfec..2ca210c00 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -31,7 +31,7 @@ class RestoreOptionsPage extends BasePage { child: Container( width: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint, height: double.infinity, - padding: EdgeInsets.symmetric(vertical: 24), + padding: EdgeInsets.symmetric(vertical: 24, horizontal: 24), child: SingleChildScrollView( child: Column( children: [ diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index ed86b1933..dd8c83948 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.6.0" -MONERO_COM_BUILD_NUMBER=56 +MONERO_COM_VERSION="1.6.1" +MONERO_COM_BUILD_NUMBER=57 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.9.0" -CAKEWALLET_BUILD_NUMBER=169 +CAKEWALLET_VERSION="4.9.1" +CAKEWALLET_BUILD_NUMBER=170 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 08de936e8..714441167 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.6.0" -MONERO_COM_BUILD_NUMBER=54 +MONERO_COM_VERSION="1.6.1" +MONERO_COM_BUILD_NUMBER=55 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.9.0" -CAKEWALLET_BUILD_NUMBER=178 +CAKEWALLET_VERSION="4.9.1" +CAKEWALLET_BUILD_NUMBER=183 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 28e7d5f4f..bb2aa2ebc 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.2.0" -CAKEWALLET_BUILD_NUMBER=31 +CAKEWALLET_VERSION="1.2.1" +CAKEWALLET_BUILD_NUMBER=32 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then