CW-942-New-Swap-UI-Flow ()

* feat: Implement New Swap UI including fee items and coin control and extract common fee logic to a feeViewModel, use that in SendViewModel and ExchangeViewModel

* feat: Implement New Swap UI with fee items and coin control and extract common fee logic to a feeViewModel for use in SendViewModel and ExchangeViewModel

* Update colors

* Show warning if user choose a below default transaction priority

* fix: Add warning when user select less than default transaction priority and add condition to show extraId

* Complete Swap UI flow

* Handle edgecases for XRP

* Switch swap page button texts

* Handle edgecases for XLM

* Switch prompt text and handle edgecases

---------

Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
David Adegoke 2025-03-14 17:31:31 +01:00 committed by GitHub
parent 0f301a71a2
commit 9f3078740e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 1048 additions and 327 deletions

View file

@ -84,7 +84,7 @@ void main() {
exchangeTradePageRobot.hasInformationDialog();
await exchangeTradePageRobot.onGotItButtonPressed();
await exchangeTradePageRobot.onConfirmSendingButtonPressed();
await exchangeTradePageRobot.onSendFromCakeButtonPressed();
await exchangeTradePageRobot.handleConfirmSendResult();

View file

@ -27,11 +27,11 @@ class ExchangeTradePageRobot {
await commonTestCases.defaultSleepTime();
}
Future<void> onConfirmSendingButtonPressed() async {
tester.printToConsole('Now confirming sending');
Future<void> onSendFromCakeButtonPressed() async {
tester.printToConsole('Now sending from cake');
await commonTestCases.tapItemByKey(
'exchange_trade_page_confirm_sending_button_key',
'exchange_trade_page_send_from_cake_button_key',
shouldPumpAndSettle: false,
);
@ -134,7 +134,7 @@ class ExchangeTradePageRobot {
await commonTestCases.defaultSleepTime();
await onConfirmSendingButtonPressed();
await onSendFromCakeButtonPressed();
tester.printToConsole('Confirm sending button tapped');
hasError = await hasErrorWhileSending();

View file

@ -51,7 +51,7 @@ class SendPageRobot {
commonTestCases.hasValueKey('send_page_fiat_amount_textfield_key');
}
if (sendViewModel.hasFees) {
if (sendViewModel.feesViewModel.hasFees) {
commonTestCases.hasValueKey('send_page_select_fee_priority_button_key');
}
@ -104,12 +104,12 @@ class SendPageRobot {
SendPage sendPage = tester.widget(find.byType(SendPage));
final sendViewModel = sendPage.sendViewModel;
if (!sendViewModel.hasFees || priority == null) return;
if (!sendViewModel.feesViewModel.hasFees || priority == null) return;
final transactionPriorityPickerKey = 'send_page_select_fee_priority_button_key';
await commonTestCases.tapItemByKey(transactionPriorityPickerKey);
if (priority == sendViewModel.transactionPriority) {
if (priority == sendViewModel.feesViewModel.transactionPriority) {
await commonTestCases
.tapItemByKey('picker_items_index_${priority.title}_selected_item_button_key');
return;
@ -188,8 +188,8 @@ class SendPageRobot {
await authPageRobot.enterPinCode(CommonTestConstants.pin);
}
final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
if (onAuthPageDesktop) {
final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
if (onAuthPageDesktop) {
await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
}
}

View file

@ -42,6 +42,7 @@ import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
import 'package:cake_wallet/entities/wallet_manager.dart';
import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart';
import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_external_send_page.dart';
import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_page.dart';
import 'package:cake_wallet/src/screens/send/transaction_success_info_page.dart';
@ -53,6 +54,7 @@ import 'package:cake_wallet/view_model/link_view_model.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
import 'package:cake_wallet/view_model/dashboard/sign_view_model.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
import 'package:cw_core/receive_page_option.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/qr_view_data.dart';
@ -755,6 +757,7 @@ Future<void> setup({
getIt.get<AppStore>().wallet!.isHardwareWallet ? getIt.get<LedgerViewModel>() : null,
coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.nonMweb,
getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom),
getIt.get<FeesViewModel>(),
),
);
@ -1034,20 +1037,35 @@ Future<void> setup({
getIt.registerFactoryParam<WebViewPage, String, Uri>((title, uri) => WebViewPage(title, uri));
getIt.registerFactory(() => ExchangeViewModel(
getIt.registerFactory(
() => ExchangeViewModel(
getIt.get<AppStore>(),
_tradesSource,
getIt.get<ExchangeTemplateStore>(),
getIt.get<TradesStore>(),
getIt.get<AppStore>().settingsStore,
getIt.get<SharedPreferences>(),
getIt.get<ContactListViewModel>()));
getIt.get<ContactListViewModel>(),
getIt.get<FeesViewModel>(),
),
);
getIt.registerFactory(() => ExchangeTradeViewModel(
getIt.registerFactory<FeesViewModel>(
() => FeesViewModel(
getIt.get<AppStore>(),
getIt.get<BalanceViewModel>(),
),
);
getIt.registerFactory(
() => ExchangeTradeViewModel(
wallet: getIt.get<AppStore>().wallet!,
trades: _tradesSource,
tradesStore: getIt.get<TradesStore>(),
sendViewModel: getIt.get<SendViewModel>()));
sendViewModel: getIt.get<SendViewModel>(),
feesViewModel: getIt.get<FeesViewModel>(),
),
);
getIt.registerFactoryParam<ExchangePage, PaymentRequest?, void>(
(PaymentRequest? paymentRequest, __) {
@ -1059,6 +1077,9 @@ Future<void> setup({
getIt.registerFactory(
() => ExchangeTradePage(exchangeTradeViewModel: getIt.get<ExchangeTradeViewModel>()));
getIt.registerFactory(
() => ExchangeTradeExternalSendPage(exchangeTradeViewModel: getIt.get<ExchangeTradeViewModel>()));
getIt.registerFactory(() => ExchangeTemplatePage(getIt.get<ExchangeViewModel>()));
getIt.registerFactoryParam<WalletService, WalletType, void>((WalletType param1, __) {

View file

@ -40,6 +40,7 @@ import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_external_send_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
import 'package:cake_wallet/src/screens/faq/faq_page.dart';
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart';
@ -813,6 +814,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
builder: (_) => getIt.get<SeedVerificationPage>(),
);
case Routes.exchangeTradeExternalSendPage:
return MaterialPageRoute<void>(builder: (_) => getIt.get<ExchangeTradeExternalSendPage>(),);
default:
return MaterialPageRoute<void>(
builder: (_) => Scaffold(

View file

@ -118,4 +118,5 @@ class Routes {
static const walletGroupDescription = '/wallet_group_description';
static const walletGroupExistingSeedDescriptionPage = '/wallet_group_existing_seed_description_page';
static const walletSeedVerificationPage = '/wallet_seed_verification_page';
static const exchangeTradeExternalSendPage = '/exchange_trade_external_send_page';
}

View file

@ -248,7 +248,7 @@ class ExchangePage extends BasePage {
Observer(
builder: (_) => LoadingPrimaryButton(
key: ValueKey('exchange_page_exchange_button_key'),
text: exchangeViewModel.isAvailableInSelected ? S.of(context).exchange : S.of(context).change_selected_exchanges,
text: exchangeViewModel.isAvailableInSelected ? S.of(context).swap : S.of(context).change_selected_exchanges,
onPressed: exchangeViewModel.isAvailableInSelected ? () {
FocusScope.of(context).unfocus();
@ -377,7 +377,7 @@ class ExchangePage extends BasePage {
return;
}
if (exchangeViewModel.isLowFee) {
if (exchangeViewModel.feesViewModel.isLowFee) {
_showFeeAlert(context);
}
@ -640,7 +640,7 @@ class ExchangePage extends BasePage {
}) ??
false;
if (confirmed) {
exchangeViewModel.setDefaultTransactionPriority();
exchangeViewModel.feesViewModel .setDefaultTransactionPriority();
}
}

View file

@ -35,10 +35,11 @@ class PresentProviderPicker extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(S.of(context).exchange,
Text(S.of(context).swap,
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Colors.white)),
Observer(
builder: (_) => Text(

View file

@ -21,7 +21,7 @@ class ExchangeConfirmPage extends BasePage {
final Trade trade;
@override
String get title => S.current.copy_id;
String get title => S.current.swap;
@override
Widget body(BuildContext context) {
@ -40,7 +40,7 @@ class ExchangeConfirmPage extends BasePage {
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
),
)),
Container(

View file

@ -0,0 +1,143 @@
import 'package:cake_wallet/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart';
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
import 'package:cake_wallet/view_model/send/send_view_model_state.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';
class ExchangeTradeExternalSendPage extends BasePage {
ExchangeTradeExternalSendPage({required this.exchangeTradeViewModel});
final ExchangeTradeViewModel exchangeTradeViewModel;
@override
String get title => S.current.swap;
@override
bool get gradientBackground => true;
@override
bool get gradientAll => true;
@override
bool get resizeToAvoidBottomInset => false;
@override
bool get extendBodyBehindAppBar => true;
@override
AppBarStyle get appBarStyle => AppBarStyle.transparent;
final fetchingLabel = S.current.fetching;
@override
Widget body(BuildContext context) {
final copyImage = Image.asset(
'assets/images/copy_content.png',
height: 16,
width: 16,
color: Theme.of(context).extension<SendPageTheme>()!.estimatedFeeColor,
);
return Container(
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(top: 36, bottom: 24),
content: Observer(
builder: (_) {
return Column(
children: <Widget>[
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,
),
),
padding: EdgeInsets.fromLTRB(24, 110, 24, 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Spacer(flex: 3),
Flexible(
flex: 6,
child: Center(
child: AspectRatio(
aspectRatio: 1.0,
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Theme.of(context)
.extension<ExchangePageTheme>()!
.qrCodeColor,
),
),
child: QrImage(
data:
exchangeTradeViewModel.trade.inputAddress ?? fetchingLabel,
),
),
),
),
),
Spacer(flex: 3)
],
),
SizedBox(height: 24),
...exchangeTradeViewModel.items
.where((item) => item.isExternalSendDetail)
.map(
(item) => TradeItemRowWidget(
currentTheme: currentTheme,
title: item.title,
value: item.data,
isCopied: true,
copyImage: copyImage,
),
)
.toList(),
],
),
),
],
);
},
),
bottomSection: Observer(
builder: (_) {
final trade = exchangeTradeViewModel.trade;
final sendingState = exchangeTradeViewModel.sendViewModel.state;
return exchangeTradeViewModel.isSendable && !(sendingState is TransactionCommitted)
? LoadingPrimaryButton(
key: ValueKey('exchange_trade_external_send_page_continue_button_key'),
isDisabled: trade.inputAddress == null || trade.inputAddress!.isEmpty,
isLoading: sendingState is IsExecutingState,
onPressed: () {
Navigator.of(context).popUntil((route) => route.isFirst);
},
text: S.current.continue_text,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
)
: Offstage();
},
),
),
);
}
}

View file

@ -1,13 +1,15 @@
import 'package:flutter/cupertino.dart';
class ExchangeTradeItem {
ExchangeTradeItem({
required this.title,
required this.data,
required this.isCopied,
required this.isReceiveDetail,
required this.isExternalSendDetail,
});
String title;
String data;
bool isCopied;
bool isReceiveDetail;
bool isExternalSendDetail;
}

View file

@ -1,22 +1,22 @@
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
import 'package:cake_wallet/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'dart:ui';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/utils/request_review_handler.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:mobx/mobx.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart';
import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
import 'package:cake_wallet/src/widgets/list_row.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/widgets/timer_widget.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
@ -30,8 +30,7 @@ void showInformation(
final walletName = exchangeTradeViewModel.wallet.name;
final information = exchangeTradeViewModel.isSendable
? S.current.exchange_result_confirm(
trade.amount, trade.from.toString(), walletName) +
? S.current.exchange_trade_result_confirm(trade.amount, trade.from.toString(), walletName) +
exchangeTradeViewModel.extraInfo
: S.current.exchange_result_description(
trade.amount, trade.from.toString()) +
@ -50,7 +49,22 @@ class ExchangeTradePage extends BasePage {
final ExchangeTradeViewModel exchangeTradeViewModel;
@override
String get title => S.current.exchange;
String get title => S.current.swap;
@override
bool get gradientBackground => true;
@override
bool get gradientAll => true;
@override
bool get resizeToAvoidBottomInset => false;
@override
bool get extendBodyBehindAppBar => true;
@override
AppBarStyle get appBarStyle => AppBarStyle.transparent;
@override
Widget trailing(BuildContext context) {
@ -74,14 +88,20 @@ class ExchangeTradePage extends BasePage {
}
@override
Widget body(BuildContext context) =>
ExchangeTradeForm(exchangeTradeViewModel);
Widget body(BuildContext context) => ExchangeTradeForm(
exchangeTradeViewModel,
currentTheme,
);
}
class ExchangeTradeForm extends StatefulWidget {
ExchangeTradeForm(this.exchangeTradeViewModel);
ExchangeTradeForm(
this.exchangeTradeViewModel,
this.currentTheme,
);
final ExchangeTradeViewModel exchangeTradeViewModel;
final ThemeBase currentTheme;
@override
ExchangeTradeState createState() => ExchangeTradeState();
@ -115,119 +135,77 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
@override
Widget build(BuildContext context) {
final copyImage = Image.asset('assets/images/copy_content.png',
height: 16,
width: 16,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor);
_setEffects();
return Container(
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(top: 10, bottom: 16),
content: Observer(builder: (_) {
final trade = widget.exchangeTradeViewModel.trade;
contentPadding: EdgeInsets.only(top: 10, bottom: 16),
content: Observer(builder: (_) {
final trade = widget.exchangeTradeViewModel.trade;
return Column(
children: <Widget>[
trade.expiredAt != null
? Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
S.of(context).offer_expires_in,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
),
if (trade.expiredAt != null)
TimerWidget(trade.expiredAt!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)
])
: Offstage(),
Padding(
padding: EdgeInsets.only(top: 32),
child: Row(children: <Widget>[
Spacer(flex: 3),
Flexible(
flex: 4,
child: Center(
child: AspectRatio(
aspectRatio: 1.0,
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Theme.of(context).extension<ExchangePageTheme>()!.qrCodeColor
)
),
child: QrImage(data: trade.inputAddress ?? fetchingLabel),
)))),
Spacer(flex: 3)
]),
),
Padding(
padding: EdgeInsets.only(top: 16),
child: ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: widget.exchangeTradeViewModel.items.length,
separatorBuilder: (context, index) => Container(
height: 1,
color: Theme.of(context).extension<ExchangePageTheme>()!.dividerCodeColor,
),
itemBuilder: (context, index) {
final item = widget.exchangeTradeViewModel.items[index];
final value = item.data;
return Column(
children: <Widget>[
trade.expiredAt != null
? Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
S.of(context).offer_expires_in,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.extension<TransactionTradeTheme>()!
.detailsTitlesColor),
),
if (trade.expiredAt != null)
TimerWidget(trade.expiredAt!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)
])
: Offstage(),
_ExchangeTradeItemsCardSection(
viewModel: widget.exchangeTradeViewModel,
currentTheme: widget.currentTheme,
),
],
);
}),
bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
bottomSection: Column(
children: [
PrimaryButton(
key: ValueKey('exchange_trade_page_send_from_external_button_key'),
text: S.current.send_from_external_wallet,
onPressed: () async {
Navigator.of(context).pushNamed(Routes.exchangeTradeExternalSendPage);
},
color: Theme.of(context).cardColor,
textColor: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
),
SizedBox(height: 16),
Observer(
builder: (_) {
final trade = widget.exchangeTradeViewModel.trade;
final sendingState = widget.exchangeTradeViewModel.sendViewModel.state;
final content = ListRow(
title: item.title,
value: value,
valueFontSize: 14,
image: item.isCopied ? copyImage : null,
);
return item.isCopied
? Builder(
builder: (context) => GestureDetector(
onTap: () {
Clipboard.setData(
ClipboardData(text: value));
showBar<void>(context,
S.of(context).copied_to_clipboard);
},
child: content,
))
: content;
},
),
),
],
);
}),
bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
bottomSection: Observer(builder: (_) {
final trade = widget.exchangeTradeViewModel.trade;
final sendingState =
widget.exchangeTradeViewModel.sendViewModel.state;
return widget.exchangeTradeViewModel.isSendable &&
!(sendingState is TransactionCommitted)
? LoadingPrimaryButton(
key: ValueKey('exchange_trade_page_confirm_sending_button_key'),
isDisabled: trade.inputAddress == null ||
trade.inputAddress!.isEmpty,
isLoading: sendingState is IsExecutingState,
onPressed: () =>
widget.exchangeTradeViewModel.confirmSending(),
text: S.of(context).confirm,
color: Theme.of(context).primaryColor,
textColor: Colors.white)
: Offstage();
})),
return widget.exchangeTradeViewModel.isSendable &&
!(sendingState is TransactionCommitted)
? LoadingPrimaryButton(
key: ValueKey('exchange_trade_page_send_from_cake_button_key'),
isDisabled: trade.inputAddress == null || trade.inputAddress!.isEmpty,
isLoading: sendingState is IsExecutingState,
onPressed: () => widget.exchangeTradeViewModel.confirmSending(),
text:S.current.send_from_cake_wallet,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
)
: Offstage();
},
),
],
),
),
);
}
@ -412,3 +390,40 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
}
}
}
class _ExchangeTradeItemsCardSection extends StatelessWidget {
const _ExchangeTradeItemsCardSection({
required this.viewModel,
required this.currentTheme,
});
final ExchangeTradeViewModel viewModel;
final ThemeBase currentTheme;
@override
Widget build(BuildContext context) {
final firstExchangeCard = ExchangeTradeCardItemWidget(
currentTheme: currentTheme,
isReceiveDetailsCard: true,
exchangeTradeViewModel: viewModel,
);
final secondExchangeCard = ExchangeTradeCardItemWidget(
currentTheme: currentTheme,
isReceiveDetailsCard: false,
exchangeTradeViewModel: viewModel,
);
if (responsiveLayoutUtil.shouldRenderMobileUI) {
return MobileExchangeCardsSection(
firstExchangeCard: firstExchangeCard,
secondExchangeCard: secondExchangeCard,
);
}
return DesktopExchangeCardsSection(
firstExchangeCard: firstExchangeCard,
secondExchangeCard: secondExchangeCard,
);
}
}

View file

@ -0,0 +1,312 @@
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/list_row.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import '../../../../themes/extensions/cake_text_theme.dart';
import '../../../../themes/extensions/transaction_trade_theme.dart';
import '../../../../themes/theme_base.dart';
class ExchangeTradeCardItemWidget extends StatelessWidget {
ExchangeTradeCardItemWidget({
required this.isReceiveDetailsCard,
required this.exchangeTradeViewModel,
required this.currentTheme,
Key? key,
}) : feesViewModel = exchangeTradeViewModel.feesViewModel,
output = exchangeTradeViewModel.output;
final Output output;
final bool isReceiveDetailsCard;
final FeesViewModel feesViewModel;
final ExchangeTradeViewModel exchangeTradeViewModel;
final ThemeBase currentTheme;
@override
Widget build(BuildContext context) {
final copyImage = Image.asset(
'assets/images/copy_content.png',
height: 16,
width: 16,
color: Theme.of(context).extension<SendPageTheme>()!.estimatedFeeColor,
);
return Container(
width: double.infinity,
color: Colors.transparent,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 10),
...exchangeTradeViewModel.items
.where((item) => item.isReceiveDetail == isReceiveDetailsCard)
.map(
(item) => TradeItemRowWidget(
currentTheme: currentTheme,
title: item.title,
value: item.data,
isCopied: item.isCopied,
copyImage: copyImage,
),
)
.toList(),
if (!isReceiveDetailsCard && exchangeTradeViewModel.isSendable) ...[
if (feesViewModel.hasFees)
FeeSelectionWidget(
feesViewModel: feesViewModel,
output: output,
onTap: () => pickTransactionPriority(context),
),
if (exchangeTradeViewModel.sendViewModel.hasCoinControl)
CoinControlWidget(
onTap: () => Navigator.of(context).pushNamed(
Routes.unspentCoinsList,
arguments: exchangeTradeViewModel.sendViewModel.coinTypeToSpendFrom,
),
),
],
],
),
);
}
Future<void> pickTransactionPriority(BuildContext context) async {
final items = priorityForWalletType(feesViewModel.walletType);
final selectedItem = items.indexOf(feesViewModel.transactionPriority);
final customItemIndex = feesViewModel.getCustomPriorityIndex(items);
final isBitcoinWallet = feesViewModel.walletType == WalletType.bitcoin;
final maxCustomFeeRate = feesViewModel.maxCustomFeeRate?.toDouble();
double? customFeeRate = isBitcoinWallet ? feesViewModel.customBitcoinFeeRate.toDouble() : null;
await showPopUp<void>(
context: context,
builder: (BuildContext context) {
int selectedIdx = selectedItem;
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Picker(
items: items,
displayItem: (TransactionPriority priority) =>
feesViewModel.displayFeeRate(priority, customFeeRate?.round()),
selectedAtIndex: selectedIdx,
customItemIndex: customItemIndex,
maxValue: maxCustomFeeRate,
title: S.of(context).please_select,
headerEnabled: !isBitcoinWallet,
closeOnItemSelected: !isBitcoinWallet,
mainAxisAlignment: MainAxisAlignment.center,
sliderValue: customFeeRate,
onSliderChanged: (double newValue) => setState(() => customFeeRate = newValue),
onItemSelected: (TransactionPriority priority) {
feesViewModel.setTransactionPriority(priority);
setState(() => selectedIdx = items.indexOf(priority));
if (feesViewModel.isLowFee) {
_showFeeAlert(context);
}
},
);
},
);
},
);
if (isBitcoinWallet) {
feesViewModel.customBitcoinFeeRate = customFeeRate!.round();
if (feesViewModel.showAlertForCustomFeeRate()) {
_showFeeAlert(context);
}
}
}
void _showFeeAlert(BuildContext context) async {
final confirmed = await showPopUp<bool>(
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).low_fee,
alertContent: S.of(context).low_fee_alert,
leftButtonText: S.of(context).ignor,
rightButtonText: S.of(context).use_suggested,
actionLeftButton: () => Navigator.of(dialogContext).pop(false),
actionRightButton: () => Navigator.of(dialogContext).pop(true));
}) ??
false;
if (confirmed) {
feesViewModel.setDefaultTransactionPriority();
}
}
}
class TradeItemRowWidget extends StatelessWidget {
final String title;
final String value;
final bool isCopied;
final Image copyImage;
final ThemeBase currentTheme;
const TradeItemRowWidget({
required this.title,
required this.value,
required this.isCopied,
required this.copyImage,
required this.currentTheme,
});
@override
Widget build(BuildContext context) {
final hintTextColor = currentTheme == ThemeType.bright
? Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor
: Colors.white.withAlpha(175);
final mainTextColor = currentTheme == ThemeType.bright
? Theme.of(context).extension<CakeTextTheme>()!.titleColor
: Colors.white;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: GestureDetector(
onTap: () {
if (!isCopied) return;
Clipboard.setData(ClipboardData(text: value));
showBar<void>(context, S.of(context).transaction_details_copied(title));
},
child: ListRow(
padding: EdgeInsets.zero,
title: title,
value: value,
image: isCopied ? copyImage : null,
color: Colors.transparent,
hintTextColor: hintTextColor,
mainTextColor: mainTextColor,
),
),
);
}
}
class FeeSelectionWidget extends StatelessWidget {
final FeesViewModel feesViewModel;
final Output output;
final VoidCallback onTap;
const FeeSelectionWidget({
required this.feesViewModel,
required this.output,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return Observer(
builder: (_) => GestureDetector(
key: ValueKey('exchange_trade_card_item_widget_select_fee_priority_button_key'),
onTap: feesViewModel.hasFeesPriority ? onTap : () {},
child: Container(
padding: EdgeInsets.only(top: 24),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
S.of(context).send_estimated_fee,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'${output.estimatedFee} ${feesViewModel.currency}',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
if (!feesViewModel.isFiatDisabled)
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
'${output.estimatedFeeFiatAmount} ${feesViewModel.fiat.title}',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color:
Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor,
),
),
),
],
),
Padding(
padding: EdgeInsets.only(top: 2, left: 5),
child: Icon(
Icons.arrow_forward_ios,
size: 12,
color: Colors.white,
),
),
],
),
],
),
),
),
);
}
}
class CoinControlWidget extends StatelessWidget {
final VoidCallback onTap;
const CoinControlWidget({required this.onTap});
@override
Widget build(BuildContext context) {
return GestureDetector(
key: ValueKey('exchange_trade_card_item_widget_unspent_coin_button_key'),
onTap: onTap,
child: Container(
color: Colors.transparent,
padding: EdgeInsets.only(top: 6),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
S.of(context).coin_control,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
Icon(
Icons.arrow_forward_ios,
size: 12,
color: Colors.white,
),
],
),
),
);
}
}

View file

@ -308,11 +308,11 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
),
),
if (sendViewModel.hasFees)
if (sendViewModel.feesViewModel.hasFees)
Observer(
builder: (_) => GestureDetector(
key: ValueKey('send_page_select_fee_priority_button_key'),
onTap: sendViewModel.hasFeesPriority
onTap: sendViewModel.feesViewModel.hasFeesPriority
? () => pickTransactionPriority(context)
: () {},
child: Container(
@ -570,11 +570,11 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
Future<void> pickTransactionPriority(BuildContext context) async {
final items = priorityForWalletType(sendViewModel.walletType);
final selectedItem = items.indexOf(sendViewModel.transactionPriority);
final customItemIndex = sendViewModel.getCustomPriorityIndex(items);
final selectedItem = items.indexOf(sendViewModel.feesViewModel.transactionPriority);
final customItemIndex = sendViewModel.feesViewModel.getCustomPriorityIndex(items);
final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin;
final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
double? customFeeRate = isBitcoinWallet ? sendViewModel.customBitcoinFeeRate.toDouble() : null;
final maxCustomFeeRate = sendViewModel.feesViewModel.maxCustomFeeRate?.toDouble();
double? customFeeRate = isBitcoinWallet ? sendViewModel.feesViewModel.customBitcoinFeeRate.toDouble() : null;
await showPopUp<void>(
context: context,
@ -585,7 +585,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
return Picker(
items: items,
displayItem: (TransactionPriority priority) =>
sendViewModel.displayFeeRate(priority, customFeeRate?.round()),
sendViewModel.feesViewModel.displayFeeRate(priority, customFeeRate?.round()),
selectedAtIndex: selectedIdx,
customItemIndex: customItemIndex,
maxValue: maxCustomFeeRate,
@ -596,7 +596,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
sliderValue: customFeeRate,
onSliderChanged: (double newValue) => setState(() => customFeeRate = newValue),
onItemSelected: (TransactionPriority priority) {
sendViewModel.setTransactionPriority(priority);
sendViewModel.feesViewModel.setTransactionPriority(priority);
setState(() => selectedIdx = items.indexOf(priority));
},
);
@ -604,7 +604,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
);
},
);
if (isBitcoinWallet) sendViewModel.customBitcoinFeeRate = customFeeRate!.round();
if (isBitcoinWallet) sendViewModel.feesViewModel.customBitcoinFeeRate = customFeeRate!.round();
}
void _presentPicker(BuildContext context) {

View file

@ -1,30 +1,37 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
class ListRow extends StatelessWidget {
ListRow(
{required this.title,
required this.value,
this.titleFontSize = 14,
this.valueFontSize = 16,
this.image});
ListRow({
required this.title,
required this.value,
this.titleFontSize = 14,
this.valueFontSize = 16,
this.image,
this.padding,
this.color,
this.hintTextColor,
this.mainTextColor
});
final String title;
final String value;
final double titleFontSize;
final double valueFontSize;
final Image? image;
final EdgeInsetsGeometry? padding;
final Color? color;
final Color? hintTextColor;
final Color? mainTextColor;
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: Theme.of(context).colorScheme.background,
color: color ?? Theme.of(context).colorScheme.background,
child: Padding(
padding:
const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
padding: padding ?? const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
@ -32,7 +39,7 @@ class ListRow extends StatelessWidget {
style: TextStyle(
fontSize: titleFontSize,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
color: hintTextColor ?? Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
textAlign: TextAlign.left),
Padding(
padding: const EdgeInsets.only(top: 12),
@ -46,7 +53,7 @@ class ListRow extends StatelessWidget {
style: TextStyle(
fontSize: valueFontSize,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
color: mainTextColor ?? Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
),
image != null
? Padding(

View file

@ -16,6 +16,8 @@ import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_item.dart';
import 'package:cake_wallet/store/dashboard/trades_store.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cake_wallet/view_model/send/send_view_model.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
@ -28,14 +30,16 @@ part 'exchange_trade_view_model.g.dart';
class ExchangeTradeViewModel = ExchangeTradeViewModelBase with _$ExchangeTradeViewModel;
abstract class ExchangeTradeViewModelBase with Store {
ExchangeTradeViewModelBase(
{required this.wallet,
required this.trades,
required this.tradesStore,
required this.sendViewModel})
: trade = tradesStore.trade!,
ExchangeTradeViewModelBase({
required this.wallet,
required this.trades,
required this.tradesStore,
required this.sendViewModel,
required this.feesViewModel,
}) : trade = tradesStore.trade!,
isSendable = _checkIfCanSend(tradesStore, wallet),
items = ObservableList<ExchangeTradeItem>() {
setUpOutput();
switch (trade.provider) {
case ExchangeProviderDescription.changeNow:
_provider =
@ -81,6 +85,9 @@ abstract class ExchangeTradeViewModelBase with Store {
final Box<Trade> trades;
final TradesStore tradesStore;
final SendViewModel sendViewModel;
final FeesViewModel feesViewModel;
late Output output;
@observable
Trade trade;
@ -112,16 +119,18 @@ abstract class ExchangeTradeViewModelBase with Store {
Timer? timer;
@action
Future<void> confirmSending() async {
if (!isSendable) return;
void setUpOutput() {
sendViewModel.clearOutputs();
final output = sendViewModel.outputs.first;
output = sendViewModel.outputs.first;
output.address = trade.inputAddress ?? '';
output.setCryptoAmount(trade.amount);
if (_provider is ThorChainExchangeProvider) output.memo = trade.memo;
if (trade.isSendAll == true) output.sendAll = true;
}
@action
Future<void> confirmSending() async {
if (!isSendable) return;
sendViewModel.selectedCryptoCurrency = trade.from;
final pendingTransaction = await sendViewModel.createTransaction(provider: _provider);
if (_provider is ThorChainExchangeProvider) {
@ -154,7 +163,7 @@ abstract class ExchangeTradeViewModelBase with Store {
void _updateItems() {
final tagFrom =
tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : '';
tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : '';
final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : '';
items.clear();
@ -164,6 +173,8 @@ abstract class ExchangeTradeViewModelBase with Store {
title: "${trade.provider.title} ${S.current.id}",
data: '${trade.id}',
isCopied: true,
isReceiveDetail: true,
isExternalSendDetail: false,
),
);
@ -171,28 +182,51 @@ abstract class ExchangeTradeViewModelBase with Store {
ExchangeTradeItem(
title: S.current.amount,
data: '${trade.amount} ${trade.from}',
isCopied: true,
isCopied: false,
isReceiveDetail: false,
isExternalSendDetail: true,
),
ExchangeTradeItem(
title: S.current.estimated_receive_amount + ':',
title: S.current.you_will_receive_estimated_amount + ':',
data: '${tradesStore.trade?.receiveAmount} ${trade.to}',
isCopied: true,
isReceiveDetail: true,
isExternalSendDetail: false,
),
ExchangeTradeItem(
title: S.current.send_to_this_address('${tradesStore.trade!.from}', tagFrom) + ':',
data: trade.inputAddress ?? '',
isCopied: true,
isCopied: false,
isReceiveDetail: false,
isExternalSendDetail: true,
),
]);
if (trade.extraId != null) {
final title = trade.from == CryptoCurrency.xrp
? S.current.destination_tag
: trade.from == CryptoCurrency.xlm
? S.current.memo
: S.current.extra_id;
final shouldAddExtraId = trade.from == CryptoCurrency.xrp || trade.from == CryptoCurrency.xlm;
items.add(ExchangeTradeItem(title: title, data: '${trade.extraId}', isCopied: true));
if (shouldAddExtraId) {
final title = trade.from == CryptoCurrency.xrp
? S.current.destination_tag
: trade.from == CryptoCurrency.xlm
? S.current.memo
: S.current.extra_id;
items.add(
ExchangeTradeItem(
title: title,
data: '${trade.extraId}',
isCopied: true,
isReceiveDetail: (trade.from == CryptoCurrency.xrp || trade.from == CryptoCurrency.xlm)
? false
: true,
isExternalSendDetail:
(trade.from == CryptoCurrency.xrp || trade.from == CryptoCurrency.xlm)
? true
: false,
),
);
}
}
items.add(
@ -200,6 +234,8 @@ abstract class ExchangeTradeViewModelBase with Store {
title: S.current.arrive_in_this_address('${tradesStore.trade!.to}', tagTo) + ':',
data: trade.payoutAddress ?? '',
isCopied: true,
isReceiveDetail: true,
isExternalSendDetail: false,
),
);
}

View file

@ -7,6 +7,7 @@ import 'package:cake_wallet/core/create_trade_result.dart';
import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/letsexchange_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/sync_status.dart';
@ -22,12 +23,10 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/wallet_contact.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
import 'package:cake_wallet/exchange/exchange_template.dart';
import 'package:cake_wallet/exchange/exchange_trade_state.dart';
@ -44,8 +43,6 @@ import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/store/dashboard/trades_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
@ -72,6 +69,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
this._settingsStore,
this.sharedPreferences,
this.contactListViewModel,
this.feesViewModel,
) : _cryptoNumberFormat = NumberFormat(),
isSendAllEnabled = false,
isFixedRateMode = false,
@ -169,8 +167,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
wallet.type == WalletType.bitcoinCash;
bool get hideAddressAfterExchange =>
wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero;
wallet.type == WalletType.monero || wallet.type == WalletType.wownero;
bool _useTorOnly;
final Box<Trade> trades;
@ -319,27 +316,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
bool get isMoneroWallet => wallet.type == WalletType.monero;
bool get isLowFee {
switch (wallet.type) {
case WalletType.monero:
case WalletType.wownero:
case WalletType.haven:
case WalletType.zano:
return transactionPriority == monero!.getMoneroTransactionPrioritySlow();
case WalletType.bitcoin:
return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow();
case WalletType.litecoin:
return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow();
case WalletType.ethereum:
return transactionPriority == ethereum!.getEthereumTransactionPrioritySlow();
case WalletType.bitcoinCash:
return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow();
case WalletType.polygon:
return transactionPriority == polygon!.getPolygonTransactionPrioritySlow();
default:
return false;
}
}
List<CryptoCurrency> receiveCurrencies;
@ -351,6 +328,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
final ContactListViewModel contactListViewModel;
final FeesViewModel feesViewModel;
@observable
double bestRate = 0.0;
@ -434,6 +413,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
return true;
}
Future<void> calculateBestRate() async {
if (depositCurrency == receiveCurrency) {
bestRate = 0.0;
@ -876,35 +856,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
selectedProviders.where((provider) => providersForCurrentPair().contains(provider)));
}
@action
void setDefaultTransactionPriority() {
switch (wallet.type) {
case WalletType.monero:
case WalletType.haven:
case WalletType.wownero:
case WalletType.zano:
_settingsStore.priority[wallet.type] = monero!.getMoneroTransactionPriorityAutomatic();
break;
case WalletType.bitcoin:
_settingsStore.priority[wallet.type] = bitcoin!.getBitcoinTransactionPriorityMedium();
break;
case WalletType.litecoin:
_settingsStore.priority[wallet.type] = bitcoin!.getLitecoinTransactionPriorityMedium();
break;
case WalletType.ethereum:
_settingsStore.priority[wallet.type] = ethereum!.getDefaultTransactionPriority();
break;
case WalletType.bitcoinCash:
_settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority();
break;
case WalletType.polygon:
_settingsStore.priority[wallet.type] = polygon!.getDefaultTransactionPriority();
break;
default:
break;
}
}
void _setProviders() {
if (_settingsStore.exchangeStatus == ExchangeApiMode.torOnly)
providerList = _allProviders.where((provider) => provider.supportsOnionAddress).toList();

View file

@ -0,0 +1,191 @@
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:collection/collection.dart';
part 'fees_view_model.g.dart';
class FeesViewModel = FeesViewModelBase with _$FeesViewModel;
abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Store {
FeesViewModelBase(
AppStore appStore,
this.balanceViewModel,
) : _settingsStore = appStore.settingsStore,
super(appStore: appStore) {
if (wallet.type == WalletType.bitcoin &&
_settingsStore.priority[wallet.type] == bitcoinTransactionPriorityCustom) {
setTransactionPriority(bitcoinTransactionPriorityMedium);
}
final priority = _settingsStore.priority[wallet.type];
final priorities = priorityForWalletType(wallet.type);
if (!priorityForWalletType(wallet.type).contains(priority) && priorities.isNotEmpty) {
_settingsStore.priority[wallet.type] = priorities.first;
}
}
@computed
WalletType get walletType => wallet.type;
CryptoCurrency get currency => wallet.currency;
FiatCurrency get fiat => _settingsStore.fiatCurrency;
bool get isFiatDisabled => balanceViewModel.isFiatDisabled;
final BalanceViewModel balanceViewModel;
TransactionPriority get transactionPriority {
final priority = _settingsStore.priority[wallet.type];
if (priority == null) {
throw Exception('Unexpected type ${wallet.type}');
}
return priority;
}
int? getCustomPriorityIndex(List<TransactionPriority> priorities) {
if (wallet.type == WalletType.bitcoin) {
final customItem = priorities
.firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom());
return customItem != null ? priorities.indexOf(customItem) : null;
}
return null;
}
int? get maxCustomFeeRate {
if (wallet.type == WalletType.bitcoin) {
return bitcoin!.getMaxCustomFeeRate(wallet);
}
return null;
}
bool get isLowFee {
switch (wallet.type) {
case WalletType.monero:
case WalletType.wownero:
case WalletType.haven:
case WalletType.zano:
return transactionPriority == monero!.getMoneroTransactionPrioritySlow();
case WalletType.bitcoin:
return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow();
case WalletType.litecoin:
return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow();
case WalletType.ethereum:
return transactionPriority == ethereum!.getEthereumTransactionPrioritySlow();
case WalletType.bitcoinCash:
return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow();
case WalletType.polygon:
return transactionPriority == polygon!.getPolygonTransactionPrioritySlow();
default:
return false;
}
}
@computed
int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate;
void set customBitcoinFeeRate(int value) => _settingsStore.customBitcoinFeeRate = value;
@computed
bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano;
@computed
bool get hasFeesPriority =>
wallet.type != WalletType.nano &&
wallet.type != WalletType.banano &&
wallet.type != WalletType.solana &&
wallet.type != WalletType.tron;
@computed
bool get isElectrumWallet =>
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash;
String? get walletCurrencyName => wallet.currency.fullName?.toLowerCase() ?? wallet.currency.name;
@computed
FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
final SettingsStore _settingsStore;
@action
void setTransactionPriority(TransactionPriority priority) =>
_settingsStore.priority[wallet.type] = priority;
bool showAlertForCustomFeeRate() {
if (wallet.type != WalletType.bitcoin || isLowFee) {
return false;
}
if (transactionPriority != bitcoinTransactionPriorityCustom) {
return false;
}
final mediumRate = bitcoin!.getFeeRate(wallet, bitcoinTransactionPriorityMedium);
return customBitcoinFeeRate < mediumRate;
}
String displayFeeRate(dynamic priority, int? customValue) {
final _priority = priority as TransactionPriority;
if (wallet.type == WalletType.bitcoin) {
final rate = bitcoin!.getFeeRate(wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue);
}
if (isElectrumWallet) {
final rate = bitcoin!.getFeeRate(wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate);
}
return priority.toString();
}
TransactionPriority get bitcoinTransactionPriorityCustom =>
bitcoin!.getBitcoinTransactionPriorityCustom();
TransactionPriority get bitcoinTransactionPriorityMedium =>
bitcoin!.getBitcoinTransactionPriorityMedium();
@action
void setDefaultTransactionPriority() {
switch (wallet.type) {
case WalletType.monero:
case WalletType.haven:
case WalletType.wownero:
case WalletType.zano:
_settingsStore.priority[wallet.type] = monero!.getMoneroTransactionPriorityAutomatic();
break;
case WalletType.bitcoin:
_settingsStore.priority[wallet.type] = bitcoin!.getBitcoinTransactionPriorityMedium();
break;
case WalletType.litecoin:
_settingsStore.priority[wallet.type] = bitcoin!.getLitecoinTransactionPriorityMedium();
break;
case WalletType.ethereum:
_settingsStore.priority[wallet.type] = ethereum!.getDefaultTransactionPriority();
break;
case WalletType.bitcoinCash:
_settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority();
break;
case WalletType.polygon:
_settingsStore.priority[wallet.type] = polygon!.getDefaultTransactionPriority();
break;
default:
break;
}
}
}

View file

@ -18,6 +18,7 @@ import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
@ -76,7 +77,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
this.contactListViewModel,
this.transactionDescriptionBox,
this.ledgerViewModel,
this.unspentCoinsListViewModel, {
this.unspentCoinsListViewModel,
this.feesViewModel, {
this.coinTypeToSpendFrom = UnspentCoinType.nonMweb,
}) : state = InitialExecutionState(),
currencies = appStore.wallet!.balance.keys.toList(),
@ -89,16 +91,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
_settingsStore = appStore.settingsStore,
fiatFromSettings = appStore.settingsStore.fiatCurrency,
super(appStore: appStore) {
if (wallet.type == WalletType.bitcoin &&
_settingsStore.priority[wallet.type] == bitcoinTransactionPriorityCustom) {
setTransactionPriority(bitcoinTransactionPriorityMedium);
}
final priority = _settingsStore.priority[wallet.type];
final priorities = priorityForWalletType(wallet.type);
if (!priorityForWalletType(wallet.type).contains(priority) && priorities.isNotEmpty) {
_settingsStore.priority[wallet.type] = priorities.first;
}
outputs
.add(Output(wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency));
@ -205,38 +197,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
FiatCurrency get fiat => _settingsStore.fiatCurrency;
TransactionPriority get transactionPriority {
final priority = _settingsStore.priority[wallet.type];
if (priority == null) {
throw Exception('Unexpected type ${wallet.type}');
}
return priority;
}
int? getCustomPriorityIndex(List<TransactionPriority> priorities) {
if (wallet.type == WalletType.bitcoin) {
final customItem = priorities
.firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom());
return customItem != null ? priorities.indexOf(customItem) : null;
}
return null;
}
int? get maxCustomFeeRate {
if (wallet.type == WalletType.bitcoin) {
return bitcoin!.getMaxCustomFeeRate(wallet);
}
return null;
}
@computed
int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate;
void set customBitcoinFeeRate(int value) => _settingsStore.customBitcoinFeeRate = value;
CryptoCurrency get currency => wallet.currency;
Validator<String> get amountValidator =>
@ -299,16 +259,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash;
@computed
bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano;
@computed
bool get hasFeesPriority =>
wallet.type != WalletType.nano &&
wallet.type != WalletType.banano &&
wallet.type != WalletType.solana &&
wallet.type != WalletType.tron;
@observable
CryptoCurrency selectedCryptoCurrency;
@ -331,6 +281,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
final BalanceViewModel balanceViewModel;
final ContactListViewModel contactListViewModel;
final LedgerViewModel? ledgerViewModel;
final FeesViewModel feesViewModel;
final FiatConversionStore _fiatConversationStore;
final Box<TransactionDescription> transactionDescriptionBox;
@ -531,10 +482,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
}
@action
void setTransactionPriority(TransactionPriority priority) =>
_settingsStore.priority[wallet.type] = priority;
Object _credentials([ExchangeProvider? provider]) {
final priority = _settingsStore.priority[wallet.type];
@ -552,14 +499,14 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
return bitcoin!.createBitcoinTransactionCredentials(
outputs,
priority: priority!,
feeRate: customBitcoinFeeRate,
feeRate:feesViewModel. customBitcoinFeeRate,
coinTypeToSpendFrom: coinTypeToSpendFrom,
);
case WalletType.litecoin:
return bitcoin!.createBitcoinTransactionCredentials(
outputs,
priority: priority!,
feeRate: customBitcoinFeeRate,
feeRate:feesViewModel. customBitcoinFeeRate,
// if it's an exchange flow then disable sending from mweb coins
coinTypeToSpendFrom: provider != null ? UnspentCoinType.nonMweb : coinTypeToSpendFrom,
);
@ -597,32 +544,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
}
String displayFeeRate(dynamic priority, int? customValue) {
final _priority = priority as TransactionPriority;
if (walletType == WalletType.bitcoin) {
final rate = bitcoin!.getFeeRate(wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue);
}
if (isElectrumWallet) {
final rate = bitcoin!.getFeeRate(wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate);
}
return priority.toString();
}
bool _isEqualCurrency(String currency) =>
wallet.balance.keys.any((e) => currency.toLowerCase() == e.title.toLowerCase());
TransactionPriority get bitcoinTransactionPriorityCustom =>
bitcoin!.getBitcoinTransactionPriorityCustom();
TransactionPriority get bitcoinTransactionPriorityMedium =>
bitcoin!.getBitcoinTransactionPriorityMedium();
@action
void onClose() => _settingsStore.fiatCurrency = fiatFromSettings;
@action

View file

@ -576,11 +576,11 @@ abstract class TransactionDetailsViewModelBase with Store {
}
final priorities = priorityForWalletType(wallet.type);
final selectedItem = priorities.indexOf(sendViewModel.transactionPriority);
final customItem = priorities
.firstWhereOrNull((element) => element == sendViewModel.bitcoinTransactionPriorityCustom);
final selectedItem = priorities.indexOf(sendViewModel.feesViewModel.transactionPriority);
final customItem = priorities.firstWhereOrNull(
(element) => element == sendViewModel.feesViewModel.bitcoinTransactionPriorityCustom);
final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null;
final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
final maxCustomFeeRate = sendViewModel.feesViewModel.maxCustomFeeRate?.toDouble();
RBFListItems.add(
StandardPickerListItem(
@ -594,7 +594,7 @@ abstract class TransactionDetailsViewModelBase with Store {
selectedIdx: selectedItem,
customItemIndex: customItemIndex ?? 0,
displayItem: (dynamic priority, double sliderValue) =>
sendViewModel.displayFeeRate(priority, sliderValue.round()),
sendViewModel.feesViewModel.displayFeeRate(priority, sliderValue.round()),
onSliderChanged: (double newValue) =>
setNewFee(value: newValue, priority: transactionPriority!),
onItemSelected: (dynamic item, double sliderValue) {
@ -788,7 +788,8 @@ abstract class TransactionDetailsViewModelBase with Store {
final comment = tx.additionalInfo['comment'] as String?;
items.addAll([
StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
StandartListItem(title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
StandartListItem(
title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
StandartListItem(
title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
@ -798,5 +799,5 @@ abstract class TransactionDetailsViewModelBase with Store {
if (comment != null && comment.isNotEmpty)
StandartListItem(title: S.current.transaction_details_title, value: comment),
]);
}
}
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "* يرجى نسخ أو كتابة معرف هويتك الأعلى لحفظة.",
"exchange_result_write_down_trade_id": "يرجى نسخ أو كتابة معرّف العملية للمتابعة.",
"exchange_sync_alert_content": "يرجى الانتظار حتى تتم مزامنة محفظتك",
"exchange_trade_result_confirm": "بالضغط على إرسال من Cake Wallet ، ستقوم بإرسال ${fetchingLabel} ${from} من محفظتك التي تسمى ${walletName} إلى العنوان الموضح أدناه. أو يمكنك إرسالها من محفظتك الخارجية إلى العنوان / QR رمز الإرسال من صفحة تفاصيل المحفظة الخارجية. \n\n يرجى الضغط على أي من الأزرار للمتابعة أو العودة لتغيير المبالغ.",
"expired": "منتهي الصلاحية",
"expires": "تنتهي",
"expiresOn": "ﻲﻓ ﻪﺘﻴﺣﻼﺻ ﻲﻬﺘﻨﺗ",
@ -694,6 +695,8 @@
"send_error_minimum_value": "الحد الأدنى لقيمة المبلغ هو 0.01",
"send_estimated_fee": "الرسوم المقدرة:",
"send_fee": "الرسوم:",
"send_from_cake_wallet": "أرسل من محفظة الكيك",
"send_from_external_wallet": "أرسل من محفظة خارجية",
"send_name": "الأسم",
"send_new": "جديد",
"send_payment_id": "معرف عملية الدفع (اختياري)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "لديك الآن بطاقة ائتمان",
"you_pay": "انت تدفع",
"you_will_get": "حول الى",
"you_will_receive_estimated_amount": "سوف تتلقى(ooded )",
"you_will_send": "تحويل من",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Please copy or write down your ID shown above.",
"exchange_result_write_down_trade_id": "Моля, запишете trade ID-то, за да продължите.",
"exchange_sync_alert_content": "Моля, изчакайте синхронизирането на Вашия портфейл",
"exchange_trade_result_confirm": "Натискайки изпращане от портфейла за торта, ще изпращате ${fetchingLabel} ${from} от вашия портфейл, наречен ${walletName} на адреса, показан по -долу. Или можете да изпратите от външния си портфейл до адреса / QR код на страницата за изпращане от външния портфейл.",
"expired": "Изтекло",
"expires": "Изтича",
"expiresOn": "Изтича на",
@ -694,6 +695,8 @@
"send_error_minimum_value": "Минималната сума е 0.01",
"send_estimated_fee": "Изчислена такса:",
"send_fee": "Такса:",
"send_from_cake_wallet": "Изпратете от портфейла за торта",
"send_from_external_wallet": "Изпратете от външен портфейл",
"send_name": "Име",
"send_new": "Ново",
"send_payment_id": "Payment ID (не е задължително)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "Вече имате дебитна карта",
"you_pay": "Вие плащате",
"you_will_get": "Обръщане в",
"you_will_receive_estimated_amount": "Ще получите(прогнозно )",
"you_will_send": "Обръщане от",
"yy": "гг"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Prosím zkopírujte si, nebo zapište si výše uvedené ID.",
"exchange_result_write_down_trade_id": "Prosím zkopírujte si, nebo zapište si ID transakce (trade ID) pro pokračování.",
"exchange_sync_alert_content": "Prosím počkejte, dokud nebude vaše peněženka synchronizována",
"exchange_trade_result_confirm": "Stisknutím odeslání z peněženky Cake Wallet posíláte ${fetchingLabel} ${from} z peněženky nazvané ${walletName} na níže uvedenou adresu. Nebo můžete odeslat z externí peněženky na adresu / qr kód na stránce Odeslat ze stránky externích detailů peněženky. \n\n Stisknutím některého z tlačítek pokračujte nebo se vrátíte a změňte částky.",
"expired": "Vypršelo",
"expires": "Vyprší",
"expiresOn": "Vyprší dne",
@ -694,6 +695,8 @@
"send_error_minimum_value": "Minimální částka je 0,01",
"send_estimated_fee": "Odhadovaný poplatek:",
"send_fee": "Poplatek:",
"send_from_cake_wallet": "Odeslat z peněženky",
"send_from_external_wallet": "Odeslat z externí peněženky",
"send_name": "Název",
"send_new": "Nová",
"send_payment_id": "ID platby (nepovinné)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "Nyní máte debetní kartu",
"you_pay": "Zaplatíte",
"you_will_get": "Směnit na",
"you_will_receive_estimated_amount": "Obdržíte(odhadovaný )",
"you_will_send": "Směnit z",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Bitte kopieren oder notieren Sie sich die oben gezeigte ID.",
"exchange_result_write_down_trade_id": "Bitte kopieren oder notieren Sie die Handels-ID, um fortzufahren.",
"exchange_sync_alert_content": "Bitte warten Sie, bis Ihre Wallet synchronisiert ist",
"exchange_trade_result_confirm": "Durch Drücken von Send von Cake Wallet senden Sie ${fetchingLabel} ${from} von Ihrer Brieftasche mit dem Namen ${walletName} an die unten gezeigte Adresse. Oder Sie können von Ihrem externen Brieftaschen an den Adresse \n\nqR auf der Seite \"Senden von externen Brieftaschen\" senden.",
"expired": "Abgelaufen",
"expires": "Läuft ab",
"expiresOn": "Läuft aus am",
@ -695,6 +696,8 @@
"send_error_minimum_value": "Der Mindestbetrag ist 0,01",
"send_estimated_fee": "Geschätzte Gebühr:",
"send_fee": "Gebühr:",
"send_from_cake_wallet": "Senden Sie aus Kuchenbrieftasche",
"send_from_external_wallet": "Senden Sie aus der Außenschreibe",
"send_name": "Name",
"send_new": "Neu",
"send_payment_id": "Zahlungs-ID (optional)",
@ -1011,6 +1014,7 @@
"you_now_have_debit_card": "Sie haben jetzt eine Debitkarte",
"you_pay": "Sie bezahlen",
"you_will_get": "Konvertieren zu",
"you_will_receive_estimated_amount": "Sie erhalten(geschätzt )",
"you_will_send": "Konvertieren von",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Please copy or write down your ID shown above.",
"exchange_result_write_down_trade_id": "Please copy or write down the trade ID to continue.",
"exchange_sync_alert_content": "Please wait until your wallet is synchronized",
"exchange_trade_result_confirm": "By pressing send from cake wallet, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown below. Or you can send from your external wallet to the address/QR code on the send from external wallet details page.\n\nPlease press either of the buttons to continue or go back to change the amounts.",
"expired": "Expired",
"expires": "Expires",
"expiresOn": "Expires on",
@ -695,6 +696,8 @@
"send_error_minimum_value": "Minimum value of amount is 0.01",
"send_estimated_fee": "Estimated fee:",
"send_fee": "Fee:",
"send_from_cake_wallet": "Send from Cake Wallet",
"send_from_external_wallet": "Send from External Wallet",
"send_name": "Name",
"send_new": "New",
"send_payment_id": "Payment ID (optional)",
@ -1009,6 +1012,7 @@
"you_now_have_debit_card": "You now have a debit card",
"you_pay": "You Pay",
"you_will_get": "Convert to",
"you_will_receive_estimated_amount": "You will receive (estimated)",
"you_will_send": "Convert from",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Copie o escriba su identificación que se muestra arriba.",
"exchange_result_write_down_trade_id": "Por favor, copia o escribe el ID.",
"exchange_sync_alert_content": "Espere hasta que su billetera esté sincronizada",
"exchange_trade_result_confirm": "Al presionar el envío de la billetera de la torta, enviará ${fetchingLabel} ${from} desde su billetera llamada ${walletName} a la dirección que se muestra a continuación. O puede enviar desde su billetera externa a la dirección / Código QR en la página Enviar desde la página Detalles de la billetera externa. \n\n Por favor presione cualquiera de los botones para continuar o regrese para cambiar las cantidades.",
"expired": "Muerto",
"expires": "Caduca",
"expiresOn": "Expira el",
@ -695,6 +696,8 @@
"send_error_minimum_value": "El valor mínimo de la cantidad es 0.01",
"send_estimated_fee": "Tarifa estimada:",
"send_fee": "Cuota:",
"send_from_cake_wallet": "Enviar desde la billetera de pastel",
"send_from_external_wallet": "Enviar desde la billetera externa",
"send_name": "Nombre",
"send_new": "Nuevo",
"send_payment_id": "ID de pago (opcional)",
@ -1009,6 +1012,7 @@
"you_now_have_debit_card": "Ahora tienes una tarjeta de débito",
"you_pay": "Tú pagas",
"you_will_get": "Convertir a",
"you_will_receive_estimated_amount": "Recibirá(estimado )",
"you_will_send": "Convertir de",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Merci de copier ou écrire votre ID présenté ci-dessus.",
"exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.",
"exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé",
"exchange_trade_result_confirm": "En appuyant sur Send de Cake Wallet, vous enverrez ${fetchingLabel} ${from} de votre portefeuille appelé ${walletName} à l'adresse ci-dessous. Ou vous pouvez envoyer à partir de votre portefeuille externe à l'adresse / QR Code sur la page Send from External Wallet Détails. \n\n Veuillez appuyer sur l'un des boutons pour continuer ou revenir pour modifier les montants.",
"expired": "Expirée",
"expires": "Expire",
"expiresOn": "Expire le",
@ -694,6 +695,8 @@
"send_error_minimum_value": "La valeur minimale du montant est 0.01",
"send_estimated_fee": "Estimation des frais :",
"send_fee": "Frais:",
"send_from_cake_wallet": "Envoyer du portefeuille à gâteau",
"send_from_external_wallet": "Envoyer du portefeuille externe",
"send_name": "Nom",
"send_new": "Nouveau",
"send_payment_id": "ID de paiement (optionnel)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "Vous avez maintenant une carte de débit",
"you_pay": "Vous payez",
"you_will_get": "Convertir vers",
"you_will_receive_estimated_amount": "Vous recevrez ( estimé )",
"you_will_send": "Convertir depuis",
"yy": "AA"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Don Allah kwafi ko rubuta ID dake nuna sama.",
"exchange_result_write_down_trade_id": "Da fatan za a kwafa ko rubuta ID ɗin ciniki don ci gaba.",
"exchange_sync_alert_content": "Da fatan za a jira har sai an daidaita walat ɗin ku",
"exchange_trade_result_confirm": "Ta latsa Aika daga Wallet Caza, zaku aika ${fetchingLabel} ${from} daga walat ɗinku da ake kira ${walletName} zuwa adireshin da aka nuna a ƙasa. Ko zaka iya aika daga walat na waje zuwa adireshin / QR Code a kan Shafin Wallake Daga Shafin Tallar waje. \n\n Latsa don Allah a danna Duk da haka.",
"expired": "Karewa",
"expires": "Ya ƙare",
"expiresOn": "Yana ƙarewa",
@ -696,6 +697,8 @@
"send_error_minimum_value": "Mafi ƙarancin ƙimar adadin shine 0.01",
"send_estimated_fee": "Ƙimar kuɗi:",
"send_fee": "Kudin:",
"send_from_cake_wallet": "Aika daga Wallet Caza",
"send_from_external_wallet": "Aika daga walat na waje",
"send_name": "Sunan",
"send_new": "Sabon",
"send_payment_id": "ID na biyan kuɗi (optional)",
@ -1010,6 +1013,7 @@
"you_now_have_debit_card": "Yanzu kana da katin zare kudi",
"you_pay": "Ka Bayar",
"you_will_get": "Maida zuwa",
"you_will_receive_estimated_amount": "Za ku (karɓi )",
"you_will_send": "Maida daga",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*कृपया ऊपर दिखाए गए अपने ID को कॉपी या लिख लें.",
"exchange_result_write_down_trade_id": "जारी रखने के लिए कृपया ट्रेड ID की प्रतिलिपि बनाएँ या लिखें.",
"exchange_sync_alert_content": "कृपया प्रतीक्षा करें जब तक आपका बटुआ सिंक्रनाइज़ नहीं किया जाता है",
"exchange_trade_result_confirm": "केक वॉलेट से भेजने से, आप नीचे दिखाए गए पते पर ${walletName} नामक अपने वॉलेट से ${fetchingLabel} ${from} भेजेंगे। या आप अपने बाहरी वॉलेट से एक्सटर्नल वॉलेट विवरण पृष्ठ से भेजने पर पते / QR कोड पर भेज सकते हैं। \n\n कृपया जारी रखने के लिए या वापस जाने के लिए वापस बटन में से किसी एक को दबाएं।",
"expired": "समय सीमा समाप्त",
"expires": "समाप्त हो जाता है",
"expiresOn": "पर समय सीमा समाप्त",
@ -696,6 +697,8 @@
"send_error_minimum_value": "राशि का न्यूनतम मूल्य 0.01 है",
"send_estimated_fee": "अनुमानित शुल्क:",
"send_fee": "शुल्क:",
"send_from_cake_wallet": "केक वॉलेट से भेजें",
"send_from_external_wallet": "बाहरी बटुए से भेजें",
"send_name": "नाम",
"send_new": "नया",
"send_payment_id": "भुगतान ID (ऐच्छिक)",
@ -1010,6 +1013,7 @@
"you_now_have_debit_card": "अब आपके पास डेबिट कार्ड है",
"you_pay": "आप भुगतान करते हैं",
"you_will_get": "में बदलें",
"you_will_receive_estimated_amount": "आपको#अनुमानित ( प्राप्त होगा)",
"you_will_send": "से रूपांतरित करें",
"yy": "वाईवाई"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Molimo kopirajte ili zapišite svoj ID prikazan ispod.",
"exchange_result_write_down_trade_id": "Molimo kopirajte ili zapišite transakcijski ID za nastavak.",
"exchange_sync_alert_content": "Molimo pričekajte dok se Vaš novčanik ne sinkronizira.",
"exchange_trade_result_confirm": "Pritiskom na WALLET WALLET, šaljet ćete ${fetchingLabel} ${from} iz vašeg novčanika nazvanu ${walletName} na adresu prikazanu u nastavku. Ili možete poslati iz svog vanjskog novčanika na adresu / QR kôd na stranici Slanje s Detalji vanjskih novčanika. \n\n Pritisnite bilo koji od gumba da biste nastavili ili se vratili da biste promijenili količine.",
"expired": "Isteklo",
"expires": "Ističe",
"expiresOn": "Istječe",
@ -694,6 +695,8 @@
"send_error_minimum_value": "Minimalna vrijednost iznosa je 0.01",
"send_estimated_fee": "Procijenjena naknada:",
"send_fee": "Naknada:",
"send_from_cake_wallet": "Pošaljite iz novčanika",
"send_from_external_wallet": "Pošaljite iz vanjskog novčanika",
"send_name": "Ime",
"send_new": "Novi",
"send_payment_id": "ID plaćanja (nije obvezno)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "Sada imate debitnu karticu",
"you_pay": "Vi plaćate",
"you_will_get": "Razmijeni u",
"you_will_receive_estimated_amount": "Primit ćete(procijenjeno )",
"you_will_send": "Razmijeni iz",
"yy": "GG"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Խնդրում ենք պատճենել կամ գրել ձեր ID-ն վերևում",
"exchange_result_write_down_trade_id": "Խնդրում ենք պատճենել կամ գրել առևտրի ID-ն շարունակելու համար",
"exchange_sync_alert_content": "Խնդրում ենք սպասել մինչև ձեր հաշվեհամարը համաժամացվի",
"exchange_trade_result_confirm": "Տորթի դրամապանակից ուղարկելու միջոցով ձեր դրամապանակից ${fetchingLabel} կուղարկեք ${from} անունով ${walletName}, ստորեւ նշված հասցեով: Կամ դուք կարող եք ձեր արտաքին դրամապանակից ուղարկել / QR կոդ, արտաքին դրամապանակի մանրամասների էջից ուղարկելու համար: \n\n Խնդրում ենք սեղմել կոճակներից կամ վերադառնալ, գումարները շարունակելու կամ վերադառնալու համար:",
"expired": "Վավերականությունը լրացել է",
"expires": "Վավերականությունը լրանում է",
"expiresOn": "Վավերականությունը լրանում է",
@ -692,6 +693,8 @@
"send_error_minimum_value": "Քանակի նվազագույն արժեքը 0.01 է",
"send_estimated_fee": "Գնահատված վարձը՝",
"send_fee": "Վարձը՝",
"send_from_cake_wallet": "Ուղարկել տորթի դրամապանակից",
"send_from_external_wallet": "Ուղարկել արտաքին դրամապանակից",
"send_name": "Անվանում",
"send_new": "Նոր",
"send_payment_id": "Վճարման ID (կամավոր)",
@ -1006,6 +1009,7 @@
"you_now_have_debit_card": "Դուք այժմ ունեք դեբետային քարտ",
"you_pay": "Դուք վճարում եք",
"you_will_get": "Ստացեք",
"you_will_receive_estimated_amount": "Դուք կստանաք ( գնահատված )",
"you_will_send": "Փոխանակեք",
"yy": "ՏՏ"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Silakan salin atau tulis ID Anda yang ditampilkan di atas.",
"exchange_result_write_down_trade_id": "Silakan salin atau tulis ID perdagangan untuk melanjutkan.",
"exchange_sync_alert_content": "Silakan tunggu sampai dompet Anda tersinkronisasi",
"exchange_trade_result_confirm": "Dengan menekan kirim dari dompet kue, Anda akan mengirim ${fetchingLabel} ${from} dari dompet Anda yang disebut ${walletName} ke alamat yang ditunjukkan di bawah ini. Atau Anda dapat mengirim dari dompet eksternal Anda ke alamat / Kode QR pada halaman Dompet Dompet Kirim dari Eksternal. \n\n Tekan salah satu tombol untuk melanjutkan atau kembali untuk mengubah jumlah.",
"expired": "Kedaluwarsa",
"expires": "Kadaluarsa",
"expiresOn": "Kadaluarsa pada",
@ -697,6 +698,8 @@
"send_error_minimum_value": "Nilai minimum jumlah adalah 0.01",
"send_estimated_fee": "Biaya yang diperkirakan:",
"send_fee": "Biaya:",
"send_from_cake_wallet": "Kirim dari Dompet Kue",
"send_from_external_wallet": "Kirim dari dompet eksternal",
"send_name": "Nama",
"send_new": "Baru",
"send_payment_id": "ID Pembayaran (opsional)",
@ -1011,6 +1014,7 @@
"you_now_have_debit_card": "Anda sekarang memiliki kartu debit",
"you_pay": "Anda Membayar",
"you_will_get": "Konversi ke",
"you_will_receive_estimated_amount": "Anda akan menerima(estimasi )",
"you_will_send": "Konversi dari",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Copia o trascrivi il tuo ID mostrato in alto.",
"exchange_result_write_down_trade_id": "Copia o trascrivi l'ID dello scambio per continuare.",
"exchange_sync_alert_content": "Gentilmente aspetta che il tuo portafoglio venga sincronizzato",
"exchange_trade_result_confirm": "Premendo Invia dal portafoglio Cake, invierai ${fetchingLabel} ${from} dal tuo portafoglio chiamato ${walletName} all'indirizzo mostrato di seguito. Oppure puoi inviare dal tuo portafoglio esterno all'indirizzo / QR Codice sulla pagina Invio da Dettagli del portafoglio esterno. \n\n Premere uno dei pulsanti per continuare o tornare a modificare gli importi.",
"expired": "Scaduto",
"expires": "Scade",
"expiresOn": "Scade il",
@ -695,6 +696,8 @@
"send_error_minimum_value": "L'importo minimo è 0.01",
"send_estimated_fee": "Commissione stimata:",
"send_fee": "Commissione:",
"send_from_cake_wallet": "Invia dal portafoglio Cake",
"send_from_external_wallet": "Invia dal portafoglio esterno",
"send_name": "Nome",
"send_new": "Nuovo",
"send_payment_id": "ID Pagamento (opzionale)",
@ -1010,6 +1013,7 @@
"you_now_have_debit_card": "Ora hai una carta di debito",
"you_pay": "Tu paghi",
"you_will_get": "Converti a",
"you_will_receive_estimated_amount": "Riceverai(stimato )",
"you_will_send": "Conveti da",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*上記のIDをコピーまたは書き留めてください.",
"exchange_result_write_down_trade_id": "続行するには、取引IDをコピーまたは書き留めてください.",
"exchange_sync_alert_content": "ウォレットが同期されるまでお待ちください",
"exchange_trade_result_confirm": "Cake Walletから送信を押すことにより、${walletName}というウォレットから ${fetchingLabel} ${from}を以下に示すアドレスに送信します。または、外部ウォレットから外部ウォレットの詳細ページから送信のアドレス/ QRコードに送信することもできます。",
"expired": "期限切れ",
"expires": "Expires",
"expiresOn": "有効期限は次のとおりです",
@ -695,6 +696,8 @@
"send_error_minimum_value": "金額の最小値は0.01です",
"send_estimated_fee": "見積手数料:",
"send_fee": "費用:",
"send_from_cake_wallet": "ケーキウォレットから送信します",
"send_from_external_wallet": "外部ウォレットから送信します",
"send_name": "名前",
"send_new": "新着",
"send_payment_id": "支払いID (オプショナル)",
@ -1009,6 +1012,7 @@
"you_now_have_debit_card": "デビットカードができました",
"you_pay": "あなたが支払う",
"you_will_get": "に変換",
"you_will_receive_estimated_amount": "あなたは(推定)を受け取ります",
"you_will_send": "から変換",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*위에 표시된 ID를 복사하거나 적어 두십시오.",
"exchange_result_write_down_trade_id": "계속하려면 거래 ID를 복사하거나 적어 두십시오..",
"exchange_sync_alert_content": "지갑이 동기화 될 때까지 기다리십시오",
"exchange_trade_result_confirm": "Cake 지갑에서 보내기를 누르면 ${walletName}이라는 지갑에서 아래에 표시된 주소로 ${fetchingLabel} ${from}을 보내는 것입니다. 또는 외부 지갑에서 외부 지갑 세부 정보 페이지에서 주소 / QR 코드로 보낼 수 있습니다.",
"expired": "만료",
"expires": "만료",
"expiresOn": "만료 날짜",
@ -694,6 +695,8 @@
"send_error_minimum_value": "금액의 최소값은 0.01입니다",
"send_estimated_fee": "예상 수수료:",
"send_fee": "회비:",
"send_from_cake_wallet": "케이크 지갑에서 보내십시오",
"send_from_external_wallet": "외부 지갑에서 보내십시오",
"send_name": "이름",
"send_new": "새로운",
"send_payment_id": "지불 ID (optional)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "이제 직불카드가 있습니다.",
"you_pay": "당신이 지불합니다",
"you_will_get": "로 변환하다",
"you_will_receive_estimated_amount": "(추정 )을 받게됩니다.",
"you_will_send": "다음에서 변환",
"YY": "YY",
"yy": "YY"

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "* ကျေးဇူးပြု၍ အထက်ဖော်ပြပါ သင်၏ ID ကို ကော်ပီ သို့မဟုတ် ရေးမှတ်ပါ။",
"exchange_result_write_down_trade_id": "ရှေ့ဆက်ရန် ကုန်သွယ်မှု ID ကို ကူးယူ သို့မဟုတ် ချရေးပါ။",
"exchange_sync_alert_content": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်ထားသည့်အချိန်အထိ စောင့်ပါ။",
"exchange_trade_result_confirm": "Cake Wallet မှ Send ကိုနှိပ်ခြင်းအားဖြင့်သင်သည် ${walletName} ဟုခေါ်သည့်သင်၏ပိုက်ဆံအိတ်မှ ${fetchingLabel} ကို ${from} ကိုအောက်တွင်ဖော်ပြထားသောလိပ်စာသို့ပို့လိမ့်မည်။ သို့မဟုတ်ပြင်ပပိုက်ဆံအိတ်အသေးစိတ်စာမျက်နှာမှ Send People ၏ Send People ၏ Send People မှသင်၏ပြင်ပပိုက်ဆံအိတ်မှလိပ်စာသို့သင်ပို့နိုင်သည်။ \n\n ဆက်လုပ်ရန်သို့မဟုတ်ပမာဏကိုပြောင်းလဲရန်ပြန်သွားပါ။",
"expired": "သက်တမ်းကုန်သွားပြီ",
"expires": "သက်တမ်းကုန်သည်။",
"expiresOn": "သက်တမ်းကုန်သည်။",
@ -694,6 +695,8 @@
"send_error_minimum_value": "ပမာဏ၏ အနည်းဆုံးတန်ဖိုးမှာ 0.01 ဖြစ်သည်။",
"send_estimated_fee": "ခန့်မှန်းကြေး-",
"send_fee": "အခကြေးငွေ-",
"send_from_cake_wallet": "ကိတ်မုန့်ပိုက်ဆံအိတ်မှပေးပို့ပါ",
"send_from_external_wallet": "ပြင်ပပိုက်ဆံအိတ်မှပေးပို့ပါ",
"send_name": "နာမည်",
"send_new": "အသစ်",
"send_payment_id": "ငွေပေးချေမှု ID (ချန်လှပ်ထား)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "ယခု သင့်တွင် ဒက်ဘစ်ကတ်တစ်ခုရှိသည်။",
"you_pay": "သင်ပေးချေပါ။",
"you_will_get": "သို့ပြောင်းပါ။",
"you_will_receive_estimated_amount": "သင် ( ခန့်မှန်းခြေ ) လက်ခံရရှိလိမ့်မည်",
"you_will_send": "မှပြောင်းပါ။",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Kopieer of noteer uw hierboven getoonde ID.",
"exchange_result_write_down_trade_id": "Kopieer of noteer de handels-ID om door te gaan.",
"exchange_sync_alert_content": "Wacht tot uw portemonnee is gesynchroniseerd",
"exchange_trade_result_confirm": "Door te drukken op verzenden vanaf cake -portemonnee, verzendt u ${fetchingLabel} ${from} vanuit uw portemonnee genaamd ${walletName} naar het hieronder getoonde adres. Of u kunt van uw externe portemonnee verzenden naar het adres / QR -code op de pagina Verzenden van externe portemonnee -details. \n\n Druk op een van de knoppen om door te gaan of terug te gaan om de bedragen te wijzigen.",
"expired": "Verlopen",
"expires": "Verloopt",
"expiresOn": "Verloopt op",
@ -694,6 +695,8 @@
"send_error_minimum_value": "Minimale waarde van bedrag is 0,01",
"send_estimated_fee": "Geschatte vergoeding:",
"send_fee": "Vergoeding:",
"send_from_cake_wallet": "Stuur vanaf cake -portemonnee",
"send_from_external_wallet": "Stuur vanuit een externe portemonnee",
"send_name": "Naam",
"send_new": "Nieuw",
"send_payment_id": "Betaling ID (facultatief)",
@ -1009,6 +1012,7 @@
"you_now_have_debit_card": "Je hebt nu een debetkaart",
"you_pay": "U betaalt",
"you_will_get": "Converteren naar",
"you_will_receive_estimated_amount": "U ontvangt(geschat )",
"you_will_send": "Converteren van",
"yy": "JJ"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Skopiuj lub zanotuj identyfikator transakcji pokazany powyżej.",
"exchange_result_write_down_trade_id": "Skopiuj lub zanotuj identyfikator transakcji (ID), aby kontynuować.",
"exchange_sync_alert_content": "Poczekaj, aż portfel zostanie zsynchronizowany",
"exchange_trade_result_confirm": "Naciskając wyślij z portfela ciasta, wyślesz ${fetchingLabel} ${from} z portfela o nazwie ${walletName} na adres pokazany poniżej. Lub możesz wysłać z portfela zewnętrznego na adres / qr kod na stronie Wyślij ze strony szczegółów portfela zewnętrznego. \n\n naciśnij którykolwiek z przycisków, aby kontynuować lub wróć, aby zmienić kwoty.",
"expired": "Przedawniony",
"expires": "Wygasa",
"expiresOn": "Upływa w dniu",
@ -694,6 +695,8 @@
"send_error_minimum_value": "Minimalna wartość to 0,01",
"send_estimated_fee": "Szacowana opłata:",
"send_fee": "Opłata:",
"send_from_cake_wallet": "Wyślij z portfela ciasta",
"send_from_external_wallet": "Wyślij z portfela zewnętrznego",
"send_name": "Imię",
"send_new": "Nowy",
"send_payment_id": "Identyfikator płatności (opcjonalny)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "Masz teraz kartę debetową",
"you_pay": "Płacisz",
"you_will_get": "Konwertuj na",
"you_will_receive_estimated_amount": "Otrzymasz(oszacowane )",
"you_will_send": "Konwertuj z",
"yy": "RR"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Copie ou anote seu ID mostrado acima.",
"exchange_result_write_down_trade_id": "Copie ou anote o ID da troca para continuar.",
"exchange_sync_alert_content": "Por favor, espere até que sua carteira seja sincronizada",
"exchange_trade_result_confirm": "Ao pressionar o envio da carteira de bolo, você estará enviando ${fetchingLabel} ${from} da sua carteira chamada ${walletName} para o endereço mostrado abaixo. Ou você pode enviar da sua carteira externa para o endereço / QR Código na página Enviar da carteira externa. \n\n Pressione qualquer um dos botões para continuar ou voltar para alterar os valores.",
"expired": "Expirada",
"expires": "Expira",
"expiresOn": "Expira em",
@ -696,6 +697,8 @@
"send_error_minimum_value": "O valor mínimo da quantia é 0,01",
"send_estimated_fee": "Taxa estimada:",
"send_fee": "Taxa:",
"send_from_cake_wallet": "Enviar da carteira de bolo",
"send_from_external_wallet": "Enviar da carteira externa",
"send_name": "Nome",
"send_new": "Novo",
"send_payment_id": "ID de pagamento (opcional)",
@ -1011,6 +1014,7 @@
"you_now_have_debit_card": "Agora você tem um cartão de débito",
"you_pay": "Você paga",
"you_will_get": "Converter para",
"you_will_receive_estimated_amount": "Você receberá(estimado )",
"you_will_send": "Converter de",
"yy": "aa"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Пожалуйста, скопируйте или запишите ID, указанный выше.",
"exchange_result_write_down_trade_id": "Пожалуйста, скопируйте или запишите ID сделки.",
"exchange_sync_alert_content": "Подождите, пока ваш кошелек синхронизируется",
"exchange_trade_result_confirm": "Нажав отправить из кошелька для торта, вы отправите ${fetchingLabel} ${from} из своего кошелька под названием ${walletName} на адрес, показанный ниже. Или вы можете отправить из своего внешнего кошелька на адрес / QR -код на странице «Отправить с внешнего кошелька». \n\n Нажмите любую кнопки, чтобы продолжить или вернуться, чтобы изменить суммы.",
"expired": "Истекает",
"expires": "Истекает",
"expiresOn": "Годен до",
@ -695,6 +696,8 @@
"send_error_minimum_value": "Mинимальная сумма 0.01",
"send_estimated_fee": "Предполагаемая комиссия:",
"send_fee": "Комиссия:",
"send_from_cake_wallet": "Отправить с кошелька для торта",
"send_from_external_wallet": "Отправить с внешнего кошелька",
"send_name": "Имя",
"send_new": "Новый",
"send_payment_id": "ID платежа (опционально)",
@ -1009,6 +1012,7 @@
"you_now_have_debit_card": "Теперь у вас есть дебетовая карта",
"you_pay": "Вы платите",
"you_will_get": "Конвертировать в",
"you_will_receive_estimated_amount": "Вы получите(Оценку )",
"you_will_send": "Конвертировать из",
"yy": "ГГ"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*โปรดคัดลอกหรือเขียนรหัสของคุณด้านบน",
"exchange_result_write_down_trade_id": "โปรดคัดลอกหรือบันทึก ID ของการซื้อขายเพื่อดำเนินการต่อไป",
"exchange_sync_alert_content": "โปรดรอจนกว่ากระเป๋าของคุณจะถูกซิงค์",
"exchange_trade_result_confirm": "โดยการกดส่งจาก Cake Wallet คุณจะส่ง ${fetchingLabel} ${from} จากกระเป๋าเงินของคุณที่เรียกว่า ${walletName} ไปยังที่อยู่ที่แสดงด้านล่าง หรือคุณสามารถส่งจากกระเป๋าเงินภายนอกของคุณไปยังที่อยู่ / รหัส QR ในหน้าส่งจากรายละเอียดกระเป๋าเงินภายนอก \n\n โปรดกดปุ่มใดปุ่มหนึ่งเพื่อดำเนินการต่อหรือกลับไปเปลี่ยนจำนวนเงิน",
"expired": "หมดอายุ",
"expires": "หมดอายุ",
"expiresOn": "หมดอายุวันที่",
@ -694,6 +695,8 @@
"send_error_minimum_value": "จำนวนขั้นต่ำของจำนวนเงินคือ 0.01",
"send_estimated_fee": "ค่าธรรมเนียมที่คาดการณ์:",
"send_fee": "ค่าธรรมเนียม:",
"send_from_cake_wallet": "ส่งจากกระเป๋าเงินเค้ก",
"send_from_external_wallet": "ส่งจากกระเป๋าเงินภายนอก",
"send_name": "ชื่อ",
"send_new": "ใหม่",
"send_payment_id": "ID การชำระเงิน (ไม่จำเป็น)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "ขณะนี้คุณมีบัตรเดบิต",
"you_pay": "คุณจ่าย",
"you_will_get": "แปลงเป็น",
"you_will_receive_estimated_amount": "คุณจะได้รับ(โดยประมาณ )",
"you_will_send": "แปลงจาก",
"yy": "ปี"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Mangyaring kopyahin o isulat ang inyong ID na ipinapakita sa itaas.",
"exchange_result_write_down_trade_id": "Mangyaring kopyahin o isulat ang trade ID upang magpatuloy.",
"exchange_sync_alert_content": "Mangyaring maghintay hanggang ang iyong wallet ay naka-synchronize",
"exchange_trade_result_confirm": "Sa pamamagitan ng pagpindot sa pagpapadala mula sa cake wallet, 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 address / qr code sa pagpapadala mula sa pahina ng Mga Detalye ng Panlabas na Wallet. \n\n Mangyaring pindutin ang alinman sa mga pindutan upang magpatuloy o bumalik upang baguhin ang mga halaga.",
"expired": "Nag-expire na",
"expires": "Mag-e-expire",
"expiresOn": "Mag-e-expire sa",
@ -694,6 +695,8 @@
"send_error_minimum_value": "Ang minimum na halaga ay 0.01",
"send_estimated_fee": "Tinatayang fee:",
"send_fee": "Fee:",
"send_from_cake_wallet": "Magpadala mula sa cake wallet",
"send_from_external_wallet": "Magpadala mula sa panlabas na pitaka",
"send_name": "Pangalan",
"send_new": "Bago",
"send_payment_id": "Payment ID (opsyonal)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "Mayroon ka na ngayong debit card",
"you_pay": "Magbayad ka",
"you_will_get": "I-convert sa",
"you_will_receive_estimated_amount": "Makakatanggap ka ng(tinantyang)",
"you_will_send": "I-convert mula sa",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Lütfen yukarıda gösterilen ID'ni kopyala veya bir yere yaz.",
"exchange_result_write_down_trade_id": "Devam etmek için lütfen ID'yi kopyala veya bir yere yaz.",
"exchange_sync_alert_content": "Lütfen cüzdanın senkronize olana kadar bekle",
"exchange_trade_result_confirm": "Kek cüzdanından Gönder'e basarak, ${walletName} adlı cüzdanınızdan aşağıda gösterilen adrese ${fetchingLabel} ${from} göndereceksiniz. Veya harici cüzdanınızdan harici cüzdan detaylarından gönderme gönderisindeki / qr koduna gönderebilirsiniz.",
"expired": "Süresi doldu",
"expires": "Son kullanma tarihi",
"expiresOn": "Tarihinde sona eriyor",
@ -694,6 +695,8 @@
"send_error_minimum_value": "Minimum tutar değeri 0.01'dir",
"send_estimated_fee": "Tahmini komisyon:",
"send_fee": "Komisyon:",
"send_from_cake_wallet": "Kek cüzdanından gönder",
"send_from_external_wallet": "Harici cüzdandan gönder",
"send_name": "İsim",
"send_new": "Yeni",
"send_payment_id": "Ödeme ID'si (isteğe bağlı)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "Artık bir ön ödemeli kartın var",
"you_pay": "Şu kadar ödeyeceksin: ",
"you_will_get": "Biçimine dönüştür:",
"you_will_receive_estimated_amount": "(Tahmini ) alacaksınız",
"you_will_send": "Biçiminden dönüştür:",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*Будь ласка, скопіюйте або запишіть ID, вказаний вище.",
"exchange_result_write_down_trade_id": "Будь ласка, скопіюйте або запишіть ID операції.",
"exchange_sync_alert_content": "Зачекайте, поки ваш гаманець не синхронізується",
"exchange_trade_result_confirm": "Натиснувши надсилання з гаманця тортів, ви будете відправляти ${fetchingLabel} ${from} зі свого гаманця під назвою ${walletName} на адресу, показану нижче. Або ви можете надіслати зі свого зовнішнього гаманця на адресу / QR -код на сторінці \"Надіслати з зовнішнього гаманця\".",
"expired": "Закінчується",
"expires": "Закінчується",
"expiresOn": "Термін дії закінчується",
@ -695,6 +696,8 @@
"send_error_minimum_value": "Мінімальна сума 0.01",
"send_estimated_fee": "Ймовірна комісія:",
"send_fee": "Комісія:",
"send_from_cake_wallet": "Надіслати з гаманця торта",
"send_from_external_wallet": "Надіслати із зовнішнього гаманця",
"send_name": "Ім'я",
"send_new": "Новий",
"send_payment_id": "ID платежу (опційно)",
@ -1009,6 +1012,7 @@
"you_now_have_debit_card": "Тепер у вас є дебетова картка",
"you_pay": "Ви платите",
"you_will_get": "Конвертувати в",
"you_will_receive_estimated_amount": "Ви отримаєте(оцінюється )",
"you_will_send": "Конвертувати з",
"yy": "YY"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*براہ کرم اوپر دکھائی گئی اپنی ID کاپی کریں یا لکھیں۔",
"exchange_result_write_down_trade_id": "جاری رکھنے کے لیے براہ کرم تجارتی ID کاپی کریں یا لکھیں۔",
"exchange_sync_alert_content": "براہ کرم اس وقت تک انتظار کریں جب تک آپ کا بٹوہ مطابقت پذیر نہ ہو جائے۔",
"exchange_trade_result_confirm": "کیک پرس سے بھیجیں دبانے سے ، آپ اپنے بٹوے سے ${fetchingLabel} ${from} کہتے ہیں ${walletName} نیچے دیئے گئے پتے پر بھیج رہے ہوں گے۔ یا آپ اپنے بیرونی پرس سے بیرونی والیٹ کی تفصیلات کے صفحے پر بھیجنے والے ایڈریس \n\n QR کوڈ پر بھیج سکتے ہیں۔",
"expired": "میعاد ختم",
"expires": "میعاد ختم",
"expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ",
@ -696,6 +697,8 @@
"send_error_minimum_value": "رقم کی کم از کم قیمت 0.01 ہے۔",
"send_estimated_fee": "تخمینی فیس:",
"send_fee": "فیس:",
"send_from_cake_wallet": "کیک پرس سے بھیجیں",
"send_from_external_wallet": "بیرونی پرس سے بھیجیں",
"send_name": "نام",
"send_new": "نئی",
"send_payment_id": "ادائیگی کی شناخت (اختیاری)",
@ -1010,6 +1013,7 @@
"you_now_have_debit_card": "اب آپ کے پاس ڈیبٹ کارڈ ہے۔",
"you_pay": "تم ادا کرو",
"you_will_get": "میں تبدیل کریں۔",
"you_will_receive_estimated_amount": "آپ(تخمینہ ) وصول کریں گے",
"you_will_send": "سے تبدیل کریں۔",
"yy": "YY"
}

View file

@ -307,6 +307,7 @@
"exchange_result_write_down_ID": "*Vui lòng sao chép hoặc ghi lại ID hiển thị ở trên.",
"exchange_result_write_down_trade_id": "Vui lòng sao chép hoặc ghi lại ID giao dịch để tiếp tục.",
"exchange_sync_alert_content": "Vui lòng chờ cho đến khi ví của bạn được đồng bộ hóa",
"exchange_trade_result_confirm": "Bằng cách nhấn gửi từ ví bánh, bạn sẽ gửi ${fetchingLabel} ${from} từ ví của bạn có tên là ${walletName} đến địa chỉ được hiển thị bên dưới. Hoặc bạn có thể gửi từ ví bên ngoài của mình đến địa chỉ / Mã QR trên trang gửi từ chi tiết ví bên ngoài. \n\n Vui lòng nhấn một trong hai nút để tiếp tục hoặc quay lại để thay đổi số tiền.",
"expired": "Đã hết hạn",
"expires": "Hết hạn",
"expiresOn": "Hết hạn vào",
@ -691,6 +692,8 @@
"send_error_minimum_value": "Giá trị tối thiểu của số tiền là 0.01",
"send_estimated_fee": "Phí ước lượng:",
"send_fee": "Phí:",
"send_from_cake_wallet": "Gửi từ ví bánh",
"send_from_external_wallet": "Gửi từ ví bên ngoài",
"send_name": "Tên",
"send_new": "Mới",
"send_payment_id": "ID thanh toán (tùy chọn)",
@ -1005,6 +1008,7 @@
"you_now_have_debit_card": "Bạn hiện có một thẻ ghi nợ",
"you_pay": "Bạn thanh toán",
"you_will_get": "Chuyển đổi thành",
"you_will_receive_estimated_amount": "Bạn sẽ nhận được(ước tính )",
"you_will_send": "Chuyển đổi từ",
"yy": "YY"
}

View file

@ -309,6 +309,7 @@
"exchange_result_write_down_ID": "*Ẹ jọ̀wọ́, ṣẹ̀dà àmì ìdánimọ̀ yín tó ṣàfihàn òun lókè.",
"exchange_result_write_down_trade_id": "Ẹ jọ̀wọ́, kọ àmì ìdánimọ̀ pàṣípààrọ̀ sílẹ̀ kí tẹ̀síwájú.",
"exchange_sync_alert_content": "Ẹ jọ̀wọ́ dúró kí a ti múdọ́gba àpamọ́wọ́ yín",
"exchange_trade_result_confirm": "Nipa titẹ-titẹ lati apamọwọ akara oyinbo, iwọ yoo firanṣẹ ${fetchingLabel} ${from} lati apamọwọ rẹ ti a pe ni ${walletName} si adirẹsi ti o han ni isalẹ. Tabi o le firanṣẹ lati apamọwọ ti ita rẹ si adirẹsi / Kọlẹ oju-iwe lori Firanṣẹ lati oju opo wẹẹbu ita. \n\n Jọwọ tẹ awọn bọtini lati tẹsiwaju lati yi awọn oye silẹ.",
"expired": "Kíkú",
"expires": "Ó parí",
"expiresOn": "Ipari lori",
@ -695,6 +696,8 @@
"send_error_minimum_value": "Ránṣẹ́ owó kò kéré dé 0.01",
"send_estimated_fee": "Iye àfikún l'a fojú díwọ̀n:",
"send_fee": "Owó àfikún:",
"send_from_cake_wallet": "Firanṣẹ lati apamọwọ akara oyinbo",
"send_from_external_wallet": "Firanṣẹ lati apamọwọ ita",
"send_name": "Orúkọ",
"send_new": "Títun",
"send_payment_id": "Àmì ìdánimọ̀ àránṣẹ́ (ìyàn nìyí)",
@ -1009,6 +1012,7 @@
"you_now_have_debit_card": "Ẹ ni káàdì ìrajà lọ́wọ́lọ́wọ́",
"you_pay": "Ẹ sàn",
"you_will_get": "Ṣe pàṣípààrọ̀ sí",
"you_will_receive_estimated_amount": "Iwọ yoo gba ( excimated )",
"you_will_send": "Ṣe pàṣípààrọ̀ láti",
"yy": "Ọd"
}

View file

@ -308,6 +308,7 @@
"exchange_result_write_down_ID": "*请复制或写下您上面显示的ID.",
"exchange_result_write_down_trade_id": "请复制或写下交易编号以继续.",
"exchange_sync_alert_content": "请等待,直到您的钱包同步",
"exchange_trade_result_confirm": "通过按Cake Wallet的发送发送您将从钱包中发送 ${fetchingLabel} ${from}将###发送到下面所示的地址。或者,您可以从外部钱包${walletName} QR码从外部钱包详细信息页面发送到地址/ QR码。\n\n请按任何按钮继续或返回以更改金额。",
"expired": "已过期",
"expires": "过期",
"expiresOn": "到期",
@ -694,6 +695,8 @@
"send_error_minimum_value": "最小金额为0.01",
"send_estimated_fee": "预估费用:",
"send_fee": "手续费:",
"send_from_cake_wallet": "从蛋糕钱包发送",
"send_from_external_wallet": "从外部钱包发送",
"send_name": "名称",
"send_new": "新建",
"send_payment_id": "付款编号 (可选的)",
@ -1008,6 +1011,7 @@
"you_now_have_debit_card": "你现在有一张借记卡",
"you_pay": "你付钱",
"you_will_get": "转换到",
"you_will_receive_estimated_amount": "您将收到(估计的)",
"you_will_send": "转换自",
"yy": "YY"
}