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 <justin.ehrenhofer@gmail.com>
Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
This commit is contained in:
Konstantin Ullrich 2023-09-14 21:14:49 +02:00 committed by GitHub
parent ce4d375abf
commit d972363417
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 548 additions and 477 deletions

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -740,4 +740,14 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
@override
void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _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));
}
}

View file

@ -83,4 +83,6 @@ abstract class WalletBase<
void setExceptionHandler(void Function(FlutterErrorDetails) onError) => null;
Future<void> renameWalletFiles(String newWalletName);
String signMessage(String message, {String? address = null}) => throw UnimplementedError();
}

View file

@ -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)));
}

View file

@ -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<void> 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);
}
}
}

View file

@ -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<String> 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<String, dynamic>)['connectId'] as String;
} else {
throw Exception('Provider currently unavailable. Status: ${response.statusCode} ${response.body}');
}
}
Future<Uri> requestUrl() async {
final connectId = await getConnectId();
final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_");
return Uri.https(_baseUrl, '/u/connect', <String, dynamic>{
'applicationId': _applicationId,
'connectId': connectId,
'walletAddress': _wallet.walletAddresses.address,
'userIdentifier': _wallet.walletAddresses.address,
'supportedNetworks': networkName
});
}
Future<void> 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<void>(
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());
});
}
}
}

View file

@ -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),

View file

@ -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<void> setup({
editingNode: editingNode,
isSelected: isSelected));
getIt.registerFactory<RobinhoodBuyProvider>(
() => RobinhoodBuyProvider(wallet: getIt.get<AppStore>().wallet!));
getIt.registerFactory<OnRamperBuyProvider>(() => OnRamperBuyProvider(
settingsStore: getIt.get<AppStore>().settingsStore,
wallet: getIt.get<AppStore>().wallet!,
@ -816,6 +820,8 @@ Future<void> setup({
getIt.registerFactory(() => BuyAmountViewModel());
getIt.registerFactory(() => BuyOptionsPage());
getIt.registerFactory(() {
final wallet = getIt.get<AppStore>().wallet;
@ -824,10 +830,6 @@ Future<void> setup({
wallet: wallet!);
});
getIt.registerFactory(() {
return PreOrderPage(buyViewModel: getIt.get<BuyViewModel>());
});
getIt.registerFactoryParam<BuyWebViewPage, List, void>((List args, _) {
final url = args.first as String;
final buyViewModel = args[1] as BuyViewModel;

View file

@ -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";
}
}
}

View file

@ -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<OnRamperBuyProvider>().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<OnRamperBuyProvider>().launchProvider(context);
break;
case BuyProviderType.Robinhood:
await getIt.get<RobinhoodBuyProvider>().launchProvider(context);
break;
}
break;
case WalletType.monero:
await getIt.get<OnRamperBuyProvider>().launchProvider(context);
break;
default:
await showPopUp<void>(
context: context,

View file

@ -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';

View file

@ -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<dynamic> createRoute(RouteSettings settings) {
builder: (_) =>
getIt.get<OrderDetailsPage>(param1: settings.arguments as Order));
case Routes.preOrder:
return MaterialPageRoute<void>(
builder: (_) =>
getIt.get<PreOrderPage>());
case Routes.buy:
return MaterialPageRoute<void>(builder: (_) => getIt.get<BuyOptionsPage>());
case Routes.buyWebView:
final args = settings.arguments as List;

View file

@ -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';

View file

@ -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<OptionTileTheme>()?.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<RobinhoodBuyProvider>().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<OnRamperBuyProvider>().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<TransactionTradeTheme>()!.detailsTitlesColor,
),
),
),
],
),
),
),
);
}
}

View file

@ -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<KeyboardTheme>()!.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<SendPageTheme>()!.firstGradientColor,
Theme.of(context).extension<SendPageTheme>()!.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<void>(
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<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
borderWidth: 0.5,
textStyle: TextStyle(fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white),
placeholderTextStyle: TextStyle(
color: Theme.of(context).extension<SendPageTheme>()!.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<CakeTextTheme>()!.titleColor,
fontSize: 18,
fontWeight: FontWeight.bold
),
)
),
if (buyViewModel.isShowProviderButtons)
...buyViewModel.items.map(
(item) => Observer(builder: (_) =>
FutureBuilder<BuyAmount>(
future: item.buyAmount,
builder: (context, AsyncSnapshot<BuyAmount> 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<void>(
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<void> 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;
}
}

View file

@ -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: <Widget>[
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) {

View file

@ -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: <Widget>[
image,
Expanded(
child: Padding(
padding: EdgeInsets.only(left: 16),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
description,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context)
.extension<TransactionTradeTheme>()!
.detailsTitlesColor,
),
),
)
],
),
),
)
],
),
),
);
}
}

View file

@ -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) =>

View file

@ -25,4 +25,4 @@ class SettingsVersionCell extends StatelessWidget {
),
);
}
}
}

View file

@ -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,

View file

@ -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<CakeTextTheme>()!.titleColor,
color: Theme.of(context).extension<OptionTileTheme>()!.titleColor,
),
),
Padding(
@ -55,7 +54,7 @@ class SupportTile extends StatelessWidget {
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
color: Theme.of(context).extension<OptionTileTheme>()!.descriptionColor,
),
),
)

View file

@ -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;

View file

@ -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,

View file

@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
class OptionTileTheme extends ThemeExtension<OptionTileTheme> {
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<OptionTileTheme>? 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);
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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),

View file

@ -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<String, List<FilterItem>> filterItems;
BuyProviderType get defaultBuyProvider => settingsStore.defaultBuyProvider;
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;

View file

@ -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;
}

View file

@ -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": "مزود حاليا غير متوفر."
}

View file

@ -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": "Понастоящем доставчик не е наличен."
}

View file

@ -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ý."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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": "वर्तमान में प्रदाता अनुपलब्ध है।"
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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": "現在、プロバイダーは利用できません。"
}

View file

@ -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": "제공자는 현재 사용할 수 없습니다."
}

View file

@ -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": "လက်ရှိတွင်လက်ရှိမရနိုင်ပါ။"
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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."
}

View file

@ -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": "Поставщик в настоящее время недоступен."
}

View file

@ -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": "ผู้ให้บริการไม่สามารถใช้งานได้ในปัจจุบัน"
}

View file

@ -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."
}

View file

@ -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": "В даний час постачальник недоступний."
}

View file

@ -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": "فراہم کنندہ فی الحال دستیاب نہیں ہے۔"
}

View file

@ -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."
}

View file

@ -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": "提供者目前不可用。"
}

View file

@ -32,6 +32,8 @@ class SecretKey {
SecretKey('fiatApiKey', () => ''),
SecretKey('payfuraApiKey', () => ''),
SecretKey('chatwootWebsiteToken', () => ''),
SecretKey('robinhoodApplicationId', () => ''),
SecretKey('robinhoodCIdApiSecret', () => ''),
];
static final ethereumSecrets = [