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

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

David Adegoke committed Mar 14, 2025 at 17:31 UTC 9f3078740e86a0463e8f999cd919a51768fc117b
48 files changed +1051 -330
integration_test/funds_related_tests.dart
+1 -1
@@ -84,7 +84,7 @@ void main() {
84 exchangeTradePageRobot.hasInformationDialog();
85 await exchangeTradePageRobot.onGotItButtonPressed();
86
87 - await exchangeTradePageRobot.onConfirmSendingButtonPressed();
87 + await exchangeTradePageRobot.onSendFromCakeButtonPressed();
88
89 await exchangeTradePageRobot.handleConfirmSendResult();
90
integration_test/robots/exchange_trade_page_robot.dart
+4 -4
@@ -27,11 +27,11 @@ class ExchangeTradePageRobot {
27 await commonTestCases.defaultSleepTime();
28 }
29
30 - Future<void> onConfirmSendingButtonPressed() async {
31 - tester.printToConsole('Now confirming sending');
30 + Future<void> onSendFromCakeButtonPressed() async {
31 + tester.printToConsole('Now sending from cake');
32
33 await commonTestCases.tapItemByKey(
34 - 'exchange_trade_page_confirm_sending_button_key',
34 + 'exchange_trade_page_send_from_cake_button_key',
35 shouldPumpAndSettle: false,
36 );
37
@@ -134,7 +134,7 @@ class ExchangeTradePageRobot {
134
135 await commonTestCases.defaultSleepTime();
136
137 - await onConfirmSendingButtonPressed();
137 + await onSendFromCakeButtonPressed();
138 tester.printToConsole('Confirm sending button tapped');
139
140 hasError = await hasErrorWhileSending();
integration_test/robots/send_page_robot.dart
+5 -5
@@ -51,7 +51,7 @@ class SendPageRobot {
51 commonTestCases.hasValueKey('send_page_fiat_amount_textfield_key');
52 }
53
54 - if (sendViewModel.hasFees) {
54 + if (sendViewModel.feesViewModel.hasFees) {
55 commonTestCases.hasValueKey('send_page_select_fee_priority_button_key');
56 }
57
@@ -104,12 +104,12 @@ class SendPageRobot {
104 SendPage sendPage = tester.widget(find.byType(SendPage));
105 final sendViewModel = sendPage.sendViewModel;
106
107 - if (!sendViewModel.hasFees || priority == null) return;
107 + if (!sendViewModel.feesViewModel.hasFees || priority == null) return;
108
109 final transactionPriorityPickerKey = 'send_page_select_fee_priority_button_key';
110 await commonTestCases.tapItemByKey(transactionPriorityPickerKey);
111
112 - if (priority == sendViewModel.transactionPriority) {
112 + if (priority == sendViewModel.feesViewModel.transactionPriority) {
113 await commonTestCases
114 .tapItemByKey('picker_items_index_${priority.title}_selected_item_button_key');
115 return;
@@ -188,8 +188,8 @@ class SendPageRobot {
188 await authPageRobot.enterPinCode(CommonTestConstants.pin);
189 }
190
191 - final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
192 - if (onAuthPageDesktop) {
191 + final onAuthPageDesktop = authPageRobot.onAuthPageDesktop();
192 + if (onAuthPageDesktop) {
193 await authPageRobot.enterPassword(CommonTestConstants.pin.join(""));
194 }
195 }
lib/di.dart
+25 -4
@@ -42,6 +42,7 @@ import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
42 import 'package:cake_wallet/entities/wallet_manager.dart';
43 import 'package:cake_wallet/src/screens/buy/buy_sell_options_page.dart';
44 import 'package:cake_wallet/src/screens/buy/payment_method_options_page.dart';
45 +import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_external_send_page.dart';
46 import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
47 import 'package:cake_wallet/src/screens/seed/seed_verification/seed_verification_page.dart';
48 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';
54 import 'package:cake_wallet/tron/tron.dart';
55 import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
56 import 'package:cake_wallet/view_model/dashboard/sign_view_model.dart';
57 +import 'package:cake_wallet/view_model/send/fees_view_model.dart';
58 import 'package:cw_core/receive_page_option.dart';
59 import 'package:cake_wallet/entities/preferences_key.dart';
60 import 'package:cake_wallet/entities/qr_view_data.dart';
@@ -755,6 +757,7 @@ Future<void> setup({
757 getIt.get<AppStore>().wallet!.isHardwareWallet ? getIt.get<LedgerViewModel>() : null,
758 coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.nonMweb,
759 getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom),
760 + getIt.get<FeesViewModel>(),
761 ),
762 );
763
@@ -1034,20 +1037,35 @@ Future<void> setup({
1037
1038 getIt.registerFactoryParam<WebViewPage, String, Uri>((title, uri) => WebViewPage(title, uri));
1039
1037 - getIt.registerFactory(() => ExchangeViewModel(
1040 + getIt.registerFactory(
1041 + () => ExchangeViewModel(
1042 getIt.get<AppStore>(),
1043 _tradesSource,
1044 getIt.get<ExchangeTemplateStore>(),
1045 getIt.get<TradesStore>(),
1046 getIt.get<AppStore>().settingsStore,
1047 getIt.get<SharedPreferences>(),
1044 - getIt.get<ContactListViewModel>()));
1048 + getIt.get<ContactListViewModel>(),
1049 + getIt.get<FeesViewModel>(),
1050 + ),
1051 + );
1052 +
1053 + getIt.registerFactory<FeesViewModel>(
1054 + () => FeesViewModel(
1055 + getIt.get<AppStore>(),
1056 + getIt.get<BalanceViewModel>(),
1057 + ),
1058 + );
1059
1046 - getIt.registerFactory(() => ExchangeTradeViewModel(
1060 + getIt.registerFactory(
1061 + () => ExchangeTradeViewModel(
1062 wallet: getIt.get<AppStore>().wallet!,
1063 trades: _tradesSource,
1064 tradesStore: getIt.get<TradesStore>(),
1050 - sendViewModel: getIt.get<SendViewModel>()));
1065 + sendViewModel: getIt.get<SendViewModel>(),
1066 + feesViewModel: getIt.get<FeesViewModel>(),
1067 + ),
1068 + );
1069
1070 getIt.registerFactoryParam<ExchangePage, PaymentRequest?, void>(
1071 (PaymentRequest? paymentRequest, __) {
@@ -1059,6 +1077,9 @@ Future<void> setup({
1077 getIt.registerFactory(
1078 () => ExchangeTradePage(exchangeTradeViewModel: getIt.get<ExchangeTradeViewModel>()));
1079
1080 + getIt.registerFactory(
1081 + () => ExchangeTradeExternalSendPage(exchangeTradeViewModel: getIt.get<ExchangeTradeViewModel>()));
1082 +
1083 getIt.registerFactory(() => ExchangeTemplatePage(getIt.get<ExchangeViewModel>()));
1084
1085 getIt.registerFactoryParam<WalletService, WalletType, void>((WalletType param1, __) {
lib/router.dart
+4
@@ -40,6 +40,7 @@ import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
40 import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
41 import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart';
42 import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart';
43 +import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_external_send_page.dart';
44 import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart';
45 import 'package:cake_wallet/src/screens/faq/faq_page.dart';
46 import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart';
@@ -813,6 +814,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
814 builder: (_) => getIt.get<SeedVerificationPage>(),
815 );
816
817 + case Routes.exchangeTradeExternalSendPage:
818 + return MaterialPageRoute<void>(builder: (_) => getIt.get<ExchangeTradeExternalSendPage>(),);
819 +
820 default:
821 return MaterialPageRoute<void>(
822 builder: (_) => Scaffold(
lib/routes.dart
+1
@@ -118,4 +118,5 @@ class Routes {
118 static const walletGroupDescription = '/wallet_group_description';
119 static const walletGroupExistingSeedDescriptionPage = '/wallet_group_existing_seed_description_page';
120 static const walletSeedVerificationPage = '/wallet_seed_verification_page';
121 + static const exchangeTradeExternalSendPage = '/exchange_trade_external_send_page';
122 }
lib/src/screens/exchange/exchange_page.dart
+3 -3
@@ -248,7 +248,7 @@ class ExchangePage extends BasePage {
248 Observer(
249 builder: (_) => LoadingPrimaryButton(
250 key: ValueKey('exchange_page_exchange_button_key'),
251 - text: exchangeViewModel.isAvailableInSelected ? S.of(context).exchange : S.of(context).change_selected_exchanges,
251 + text: exchangeViewModel.isAvailableInSelected ? S.of(context).swap : S.of(context).change_selected_exchanges,
252 onPressed: exchangeViewModel.isAvailableInSelected ? () {
253 FocusScope.of(context).unfocus();
254
@@ -377,7 +377,7 @@ class ExchangePage extends BasePage {
377 return;
378 }
379
380 - if (exchangeViewModel.isLowFee) {
380 + if (exchangeViewModel.feesViewModel.isLowFee) {
381 _showFeeAlert(context);
382 }
383
@@ -640,7 +640,7 @@ class ExchangePage extends BasePage {
640 }) ??
641 false;
642 if (confirmed) {
643 - exchangeViewModel.setDefaultTransactionPriority();
643 + exchangeViewModel.feesViewModel .setDefaultTransactionPriority();
644 }
645 }
646
lib/src/screens/exchange/widgets/present_provider_picker.dart
+2 -1
@@ -35,10 +35,11 @@ class PresentProviderPicker extends StatelessWidget {
35 crossAxisAlignment: CrossAxisAlignment.center,
36 mainAxisSize: MainAxisSize.min,
37 children: <Widget>[
38 - Text(S.of(context).exchange,
38 + Text(S.of(context).swap,
39 style: TextStyle(
40 fontSize: 16.0,
41 fontWeight: FontWeight.w600,
42 +
43 color: Colors.white)),
44 Observer(
45 builder: (_) => Text(
lib/src/screens/exchange_trade/exchange_confirm_page.dart
+2 -2
@@ -21,7 +21,7 @@ class ExchangeConfirmPage extends BasePage {
21 final Trade trade;
22
23 @override
24 - String get title => S.current.copy_id;
24 + String get title => S.current.swap;
25
26 @override
27 Widget body(BuildContext context) {
@@ -40,7 +40,7 @@ class ExchangeConfirmPage extends BasePage {
40 style: TextStyle(
41 fontSize: 18.0,
42 fontWeight: FontWeight.w500,
43 - color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
43 + color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
44 ),
45 )),
46 Container(
lib/src/screens/exchange_trade/exchange_trade_external_send_page.dart new
+143
@@ -0,0 +1,143 @@
1 +import 'package:cake_wallet/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart';
2 +import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
3 +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
4 +import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
5 +import 'package:flutter_mobx/flutter_mobx.dart';
6 +import 'package:flutter/material.dart';
7 +import 'package:cake_wallet/generated/i18n.dart';
8 +import 'package:cake_wallet/core/execution_state.dart';
9 +import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
10 +import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
11 +import 'package:cake_wallet/src/screens/base_page.dart';
12 +import 'package:cake_wallet/src/widgets/primary_button.dart';
13 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
14 +
15 +class ExchangeTradeExternalSendPage extends BasePage {
16 + ExchangeTradeExternalSendPage({required this.exchangeTradeViewModel});
17 +
18 + final ExchangeTradeViewModel exchangeTradeViewModel;
19 + @override
20 + String get title => S.current.swap;
21 +
22 + @override
23 + bool get gradientBackground => true;
24 +
25 + @override
26 + bool get gradientAll => true;
27 +
28 + @override
29 + bool get resizeToAvoidBottomInset => false;
30 +
31 + @override
32 + bool get extendBodyBehindAppBar => true;
33 +
34 + @override
35 + AppBarStyle get appBarStyle => AppBarStyle.transparent;
36 +
37 + final fetchingLabel = S.current.fetching;
38 +
39 + @override
40 + Widget body(BuildContext context) {
41 + final copyImage = Image.asset(
42 + 'assets/images/copy_content.png',
43 + height: 16,
44 + width: 16,
45 + color: Theme.of(context).extension<SendPageTheme>()!.estimatedFeeColor,
46 + );
47 + return Container(
48 + child: ScrollableWithBottomSection(
49 + contentPadding: EdgeInsets.only(top: 36, bottom: 24),
50 + content: Observer(
51 + builder: (_) {
52 + return Column(
53 + children: <Widget>[
54 + Container(
55 + decoration: BoxDecoration(
56 + borderRadius: BorderRadius.only(
57 + bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
58 + gradient: LinearGradient(
59 + colors: [
60 + Theme.of(context).extension<SendPageTheme>()!.firstGradientColor,
61 + Theme.of(context).extension<SendPageTheme>()!.secondGradientColor,
62 + ],
63 + begin: Alignment.topLeft,
64 + end: Alignment.bottomRight,
65 + ),
66 + ),
67 + padding: EdgeInsets.fromLTRB(24, 110, 24, 32),
68 + child: Column(
69 + crossAxisAlignment: CrossAxisAlignment.start,
70 + children: <Widget>[
71 + Row(
72 + children: <Widget>[
73 + Spacer(flex: 3),
74 + Flexible(
75 + flex: 6,
76 + child: Center(
77 + child: AspectRatio(
78 + aspectRatio: 1.0,
79 + child: Container(
80 + padding: EdgeInsets.all(5),
81 + decoration: BoxDecoration(
82 + border: Border.all(
83 + width: 3,
84 + color: Theme.of(context)
85 + .extension<ExchangePageTheme>()!
86 + .qrCodeColor,
87 + ),
88 + ),
89 + child: QrImage(
90 + data:
91 + exchangeTradeViewModel.trade.inputAddress ?? fetchingLabel,
92 + ),
93 + ),
94 + ),
95 + ),
96 + ),
97 + Spacer(flex: 3)
98 + ],
99 + ),
100 + SizedBox(height: 24),
101 + ...exchangeTradeViewModel.items
102 + .where((item) => item.isExternalSendDetail)
103 + .map(
104 + (item) => TradeItemRowWidget(
105 + currentTheme: currentTheme,
106 + title: item.title,
107 + value: item.data,
108 + isCopied: true,
109 + copyImage: copyImage,
110 + ),
111 + )
112 + .toList(),
113 + ],
114 + ),
115 + ),
116 + ],
117 + );
118 + },
119 + ),
120 + bottomSection: Observer(
121 + builder: (_) {
122 + final trade = exchangeTradeViewModel.trade;
123 + final sendingState = exchangeTradeViewModel.sendViewModel.state;
124 +
125 + return exchangeTradeViewModel.isSendable && !(sendingState is TransactionCommitted)
126 + ? LoadingPrimaryButton(
127 + key: ValueKey('exchange_trade_external_send_page_continue_button_key'),
128 + isDisabled: trade.inputAddress == null || trade.inputAddress!.isEmpty,
129 + isLoading: sendingState is IsExecutingState,
130 + onPressed: () {
131 + Navigator.of(context).popUntil((route) => route.isFirst);
132 + },
133 + text: S.current.continue_text,
134 + color: Theme.of(context).primaryColor,
135 + textColor: Colors.white,
136 + )
137 + : Offstage();
138 + },
139 + ),
140 + ),
141 + );
142 + }
143 +}
lib/src/screens/exchange_trade/exchange_trade_item.dart
+4 -2
@@ -1,13 +1,15 @@
1 -import 'package:flutter/cupertino.dart';
2 -
1 class ExchangeTradeItem {
2 ExchangeTradeItem({
3 required this.title,
4 required this.data,
5 required this.isCopied,
6 + required this.isReceiveDetail,
7 + required this.isExternalSendDetail,
8 });
9
10 String title;
11 String data;
12 bool isCopied;
13 + bool isReceiveDetail;
14 + bool isExternalSendDetail;
15 }
\ No newline at end of file
lib/src/screens/exchange_trade/exchange_trade_page.dart
+135 -120
@@ -1,22 +1,22 @@
1 import 'package:cake_wallet/routes.dart';
2 +import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
3 +import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
4 +import 'package:cake_wallet/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart';
5 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
6 +import 'package:cake_wallet/themes/theme_base.dart';
7 import 'dart:ui';
4 -import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
8 import 'package:cake_wallet/utils/request_review_handler.dart';
9 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
10 import 'package:mobx/mobx.dart';
11 import 'package:flutter_mobx/flutter_mobx.dart';
12 import 'package:flutter/material.dart';
9 -import 'package:flutter/services.dart';
13 import 'package:cake_wallet/generated/i18n.dart';
14 import 'package:cake_wallet/core/execution_state.dart';
15 import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart';
16 import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
14 -import 'package:cake_wallet/src/widgets/list_row.dart';
15 -import 'package:cake_wallet/utils/show_bar.dart';
17 import 'package:cake_wallet/utils/show_pop_up.dart';
18 import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
19 import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
19 -import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
20 import 'package:cake_wallet/src/screens/base_page.dart';
21 import 'package:cake_wallet/src/screens/exchange_trade/widgets/timer_widget.dart';
22 import 'package:cake_wallet/src/widgets/primary_button.dart';
@@ -30,8 +30,7 @@ void showInformation(
30 final walletName = exchangeTradeViewModel.wallet.name;
31
32 final information = exchangeTradeViewModel.isSendable
33 - ? S.current.exchange_result_confirm(
34 - trade.amount, trade.from.toString(), walletName) +
33 + ? S.current.exchange_trade_result_confirm(trade.amount, trade.from.toString(), walletName) +
34 exchangeTradeViewModel.extraInfo
35 : S.current.exchange_result_description(
36 trade.amount, trade.from.toString()) +
@@ -50,7 +49,22 @@ class ExchangeTradePage extends BasePage {
49 final ExchangeTradeViewModel exchangeTradeViewModel;
50
51 @override
53 - String get title => S.current.exchange;
52 + String get title => S.current.swap;
53 +
54 + @override
55 + bool get gradientBackground => true;
56 +
57 + @override
58 + bool get gradientAll => true;
59 +
60 + @override
61 + bool get resizeToAvoidBottomInset => false;
62 +
63 + @override
64 + bool get extendBodyBehindAppBar => true;
65 +
66 + @override
67 + AppBarStyle get appBarStyle => AppBarStyle.transparent;
68
69 @override
70 Widget trailing(BuildContext context) {
@@ -74,14 +88,20 @@ class ExchangeTradePage extends BasePage {
88 }
89
90 @override
77 - Widget body(BuildContext context) =>
78 - ExchangeTradeForm(exchangeTradeViewModel);
91 + Widget body(BuildContext context) => ExchangeTradeForm(
92 + exchangeTradeViewModel,
93 + currentTheme,
94 + );
95 }
96
97 class ExchangeTradeForm extends StatefulWidget {
82 - ExchangeTradeForm(this.exchangeTradeViewModel);
98 + ExchangeTradeForm(
99 + this.exchangeTradeViewModel,
100 + this.currentTheme,
101 + );
102
103 final ExchangeTradeViewModel exchangeTradeViewModel;
104 + final ThemeBase currentTheme;
105
106 @override
107 ExchangeTradeState createState() => ExchangeTradeState();
@@ -115,119 +135,77 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
135
136 @override
137 Widget build(BuildContext context) {
118 - final copyImage = Image.asset('assets/images/copy_content.png',
119 - height: 16,
120 - width: 16,
121 - color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor);
122 -
138 _setEffects();
139
140 return Container(
141 child: ScrollableWithBottomSection(
127 - contentPadding: EdgeInsets.only(top: 10, bottom: 16),
128 - content: Observer(builder: (_) {
129 - final trade = widget.exchangeTradeViewModel.trade;
130 -
131 - return Column(
132 - children: <Widget>[
133 - trade.expiredAt != null
134 - ? Row(
135 - mainAxisSize: MainAxisSize.max,
136 - mainAxisAlignment: MainAxisAlignment.center,
137 - children: <Widget>[
138 - Text(
139 - S.of(context).offer_expires_in,
140 - style: TextStyle(
141 - fontSize: 14.0,
142 - fontWeight: FontWeight.w500,
143 - color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
144 - ),
145 - if (trade.expiredAt != null)
146 - TimerWidget(trade.expiredAt!,
147 - color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)
148 - ])
149 - : Offstage(),
150 - Padding(
151 - padding: EdgeInsets.only(top: 32),
152 - child: Row(children: <Widget>[
153 - Spacer(flex: 3),
154 - Flexible(
155 - flex: 4,
156 - child: Center(
157 - child: AspectRatio(
158 - aspectRatio: 1.0,
159 - child: Container(
160 - padding: EdgeInsets.all(5),
161 - decoration: BoxDecoration(
162 - border: Border.all(
163 - width: 3,
164 - color: Theme.of(context).extension<ExchangePageTheme>()!.qrCodeColor
165 - )
166 - ),
167 - child: QrImage(data: trade.inputAddress ?? fetchingLabel),
168 - )))),
169 - Spacer(flex: 3)
170 - ]),
171 - ),
172 - Padding(
173 - padding: EdgeInsets.only(top: 16),
174 - child: ListView.separated(
175 - shrinkWrap: true,
176 - physics: NeverScrollableScrollPhysics(),
177 - itemCount: widget.exchangeTradeViewModel.items.length,
178 - separatorBuilder: (context, index) => Container(
179 - height: 1,
180 - color: Theme.of(context).extension<ExchangePageTheme>()!.dividerCodeColor,
181 - ),
182 - itemBuilder: (context, index) {
183 - final item = widget.exchangeTradeViewModel.items[index];
184 - final value = item.data;
185 -
186 - final content = ListRow(
187 - title: item.title,
188 - value: value,
189 - valueFontSize: 14,
190 - image: item.isCopied ? copyImage : null,
191 - );
192 -
193 - return item.isCopied
194 - ? Builder(
195 - builder: (context) => GestureDetector(
196 - onTap: () {
197 - Clipboard.setData(
198 - ClipboardData(text: value));
199 - showBar<void>(context,
200 - S.of(context).copied_to_clipboard);
201 - },
202 - child: content,
203 - ))
204 - : content;
205 - },
206 - ),
207 - ),
208 - ],
209 - );
210 - }),
211 - bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
212 - bottomSection: Observer(builder: (_) {
213 - final trade = widget.exchangeTradeViewModel.trade;
214 - final sendingState =
215 - widget.exchangeTradeViewModel.sendViewModel.state;
216 -
217 - return widget.exchangeTradeViewModel.isSendable &&
218 - !(sendingState is TransactionCommitted)
219 - ? LoadingPrimaryButton(
220 - key: ValueKey('exchange_trade_page_confirm_sending_button_key'),
221 - isDisabled: trade.inputAddress == null ||
222 - trade.inputAddress!.isEmpty,
223 - isLoading: sendingState is IsExecutingState,
224 - onPressed: () =>
225 - widget.exchangeTradeViewModel.confirmSending(),
226 - text: S.of(context).confirm,
227 - color: Theme.of(context).primaryColor,
228 - textColor: Colors.white)
229 - : Offstage();
230 - })),
142 + contentPadding: EdgeInsets.only(top: 10, bottom: 16),
143 + content: Observer(builder: (_) {
144 + final trade = widget.exchangeTradeViewModel.trade;
145 +
146 + return Column(
147 + children: <Widget>[
148 + trade.expiredAt != null
149 + ? Row(
150 + mainAxisSize: MainAxisSize.max,
151 + mainAxisAlignment: MainAxisAlignment.center,
152 + children: <Widget>[
153 + Text(
154 + S.of(context).offer_expires_in,
155 + style: TextStyle(
156 + fontSize: 14.0,
157 + fontWeight: FontWeight.w500,
158 + color: Theme.of(context)
159 + .extension<TransactionTradeTheme>()!
160 + .detailsTitlesColor),
161 + ),
162 + if (trade.expiredAt != null)
163 + TimerWidget(trade.expiredAt!,
164 + color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)
165 + ])
166 + : Offstage(),
167 + _ExchangeTradeItemsCardSection(
168 + viewModel: widget.exchangeTradeViewModel,
169 + currentTheme: widget.currentTheme,
170 + ),
171 + ],
172 + );
173 + }),
174 + bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
175 + bottomSection: Column(
176 + children: [
177 + PrimaryButton(
178 + key: ValueKey('exchange_trade_page_send_from_external_button_key'),
179 + text: S.current.send_from_external_wallet,
180 + onPressed: () async {
181 + Navigator.of(context).pushNamed(Routes.exchangeTradeExternalSendPage);
182 + },
183 + color: Theme.of(context).cardColor,
184 + textColor: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
185 + ),
186 + SizedBox(height: 16),
187 + Observer(
188 + builder: (_) {
189 + final trade = widget.exchangeTradeViewModel.trade;
190 + final sendingState = widget.exchangeTradeViewModel.sendViewModel.state;
191 +
192 + return widget.exchangeTradeViewModel.isSendable &&
193 + !(sendingState is TransactionCommitted)
194 + ? LoadingPrimaryButton(
195 + key: ValueKey('exchange_trade_page_send_from_cake_button_key'),
196 + isDisabled: trade.inputAddress == null || trade.inputAddress!.isEmpty,
197 + isLoading: sendingState is IsExecutingState,
198 + onPressed: () => widget.exchangeTradeViewModel.confirmSending(),
199 + text:S.current.send_from_cake_wallet,
200 + color: Theme.of(context).primaryColor,
201 + textColor: Colors.white,
202 + )
203 + : Offstage();
204 + },
205 + ),
206 + ],
207 + ),
208 + ),
209 );
210 }
211
@@ -412,3 +390,40 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
390 }
391 }
392 }
393 +
394 +class _ExchangeTradeItemsCardSection extends StatelessWidget {
395 + const _ExchangeTradeItemsCardSection({
396 + required this.viewModel,
397 + required this.currentTheme,
398 + });
399 +
400 + final ExchangeTradeViewModel viewModel;
401 + final ThemeBase currentTheme;
402 +
403 + @override
404 + Widget build(BuildContext context) {
405 + final firstExchangeCard = ExchangeTradeCardItemWidget(
406 + currentTheme: currentTheme,
407 + isReceiveDetailsCard: true,
408 + exchangeTradeViewModel: viewModel,
409 + );
410 +
411 + final secondExchangeCard = ExchangeTradeCardItemWidget(
412 + currentTheme: currentTheme,
413 + isReceiveDetailsCard: false,
414 + exchangeTradeViewModel: viewModel,
415 + );
416 +
417 + if (responsiveLayoutUtil.shouldRenderMobileUI) {
418 + return MobileExchangeCardsSection(
419 + firstExchangeCard: firstExchangeCard,
420 + secondExchangeCard: secondExchangeCard,
421 + );
422 + }
423 +
424 + return DesktopExchangeCardsSection(
425 + firstExchangeCard: firstExchangeCard,
426 + secondExchangeCard: secondExchangeCard,
427 + );
428 + }
429 +}
lib/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart new
+312
@@ -0,0 +1,312 @@
1 +import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
2 +import 'package:cake_wallet/generated/i18n.dart';
3 +import 'package:cake_wallet/routes.dart';
4 +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
5 +import 'package:cake_wallet/src/widgets/list_row.dart';
6 +import 'package:cake_wallet/src/widgets/picker.dart';
7 +import 'package:cake_wallet/utils/show_bar.dart';
8 +import 'package:cake_wallet/utils/show_pop_up.dart';
9 +import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
10 +import 'package:cake_wallet/view_model/send/fees_view_model.dart';
11 +import 'package:cake_wallet/view_model/send/output.dart';
12 +import 'package:cw_core/transaction_priority.dart';
13 +import 'package:cw_core/wallet_type.dart';
14 +import 'package:flutter/material.dart';
15 +import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
16 +import 'package:flutter/services.dart';
17 +import 'package:flutter_mobx/flutter_mobx.dart';
18 +import '../../../../themes/extensions/cake_text_theme.dart';
19 +import '../../../../themes/extensions/transaction_trade_theme.dart';
20 +import '../../../../themes/theme_base.dart';
21 +
22 +class ExchangeTradeCardItemWidget extends StatelessWidget {
23 + ExchangeTradeCardItemWidget({
24 + required this.isReceiveDetailsCard,
25 + required this.exchangeTradeViewModel,
26 + required this.currentTheme,
27 + Key? key,
28 + }) : feesViewModel = exchangeTradeViewModel.feesViewModel,
29 + output = exchangeTradeViewModel.output;
30 +
31 + final Output output;
32 + final bool isReceiveDetailsCard;
33 + final FeesViewModel feesViewModel;
34 + final ExchangeTradeViewModel exchangeTradeViewModel;
35 + final ThemeBase currentTheme;
36 +
37 + @override
38 + Widget build(BuildContext context) {
39 + final copyImage = Image.asset(
40 + 'assets/images/copy_content.png',
41 + height: 16,
42 + width: 16,
43 + color: Theme.of(context).extension<SendPageTheme>()!.estimatedFeeColor,
44 + );
45 +
46 + return Container(
47 + width: double.infinity,
48 + color: Colors.transparent,
49 + child: Column(
50 + crossAxisAlignment: CrossAxisAlignment.start,
51 + children: <Widget>[
52 + SizedBox(height: 10),
53 + ...exchangeTradeViewModel.items
54 + .where((item) => item.isReceiveDetail == isReceiveDetailsCard)
55 + .map(
56 + (item) => TradeItemRowWidget(
57 + currentTheme: currentTheme,
58 + title: item.title,
59 + value: item.data,
60 + isCopied: item.isCopied,
61 + copyImage: copyImage,
62 + ),
63 + )
64 + .toList(),
65 + if (!isReceiveDetailsCard && exchangeTradeViewModel.isSendable) ...[
66 + if (feesViewModel.hasFees)
67 + FeeSelectionWidget(
68 + feesViewModel: feesViewModel,
69 + output: output,
70 + onTap: () => pickTransactionPriority(context),
71 + ),
72 + if (exchangeTradeViewModel.sendViewModel.hasCoinControl)
73 + CoinControlWidget(
74 + onTap: () => Navigator.of(context).pushNamed(
75 + Routes.unspentCoinsList,
76 + arguments: exchangeTradeViewModel.sendViewModel.coinTypeToSpendFrom,
77 + ),
78 + ),
79 + ],
80 + ],
81 + ),
82 + );
83 + }
84 +
85 + Future<void> pickTransactionPriority(BuildContext context) async {
86 + final items = priorityForWalletType(feesViewModel.walletType);
87 + final selectedItem = items.indexOf(feesViewModel.transactionPriority);
88 + final customItemIndex = feesViewModel.getCustomPriorityIndex(items);
89 + final isBitcoinWallet = feesViewModel.walletType == WalletType.bitcoin;
90 + final maxCustomFeeRate = feesViewModel.maxCustomFeeRate?.toDouble();
91 + double? customFeeRate = isBitcoinWallet ? feesViewModel.customBitcoinFeeRate.toDouble() : null;
92 +
93 + await showPopUp<void>(
94 + context: context,
95 + builder: (BuildContext context) {
96 + int selectedIdx = selectedItem;
97 + return StatefulBuilder(
98 + builder: (BuildContext context, StateSetter setState) {
99 + return Picker(
100 + items: items,
101 + displayItem: (TransactionPriority priority) =>
102 + feesViewModel.displayFeeRate(priority, customFeeRate?.round()),
103 + selectedAtIndex: selectedIdx,
104 + customItemIndex: customItemIndex,
105 + maxValue: maxCustomFeeRate,
106 + title: S.of(context).please_select,
107 + headerEnabled: !isBitcoinWallet,
108 + closeOnItemSelected: !isBitcoinWallet,
109 + mainAxisAlignment: MainAxisAlignment.center,
110 + sliderValue: customFeeRate,
111 + onSliderChanged: (double newValue) => setState(() => customFeeRate = newValue),
112 + onItemSelected: (TransactionPriority priority) {
113 + feesViewModel.setTransactionPriority(priority);
114 + setState(() => selectedIdx = items.indexOf(priority));
115 +
116 + if (feesViewModel.isLowFee) {
117 + _showFeeAlert(context);
118 + }
119 + },
120 + );
121 + },
122 + );
123 + },
124 + );
125 + if (isBitcoinWallet) {
126 + feesViewModel.customBitcoinFeeRate = customFeeRate!.round();
127 + if (feesViewModel.showAlertForCustomFeeRate()) {
128 + _showFeeAlert(context);
129 + }
130 + }
131 + }
132 +
133 + void _showFeeAlert(BuildContext context) async {
134 + final confirmed = await showPopUp<bool>(
135 + context: context,
136 + builder: (dialogContext) {
137 + return AlertWithTwoActions(
138 + alertTitle: S.of(context).low_fee,
139 + alertContent: S.of(context).low_fee_alert,
140 + leftButtonText: S.of(context).ignor,
141 + rightButtonText: S.of(context).use_suggested,
142 + actionLeftButton: () => Navigator.of(dialogContext).pop(false),
143 + actionRightButton: () => Navigator.of(dialogContext).pop(true));
144 + }) ??
145 + false;
146 + if (confirmed) {
147 + feesViewModel.setDefaultTransactionPriority();
148 + }
149 + }
150 +}
151 +
152 +class TradeItemRowWidget extends StatelessWidget {
153 + final String title;
154 + final String value;
155 + final bool isCopied;
156 + final Image copyImage;
157 + final ThemeBase currentTheme;
158 +
159 + const TradeItemRowWidget({
160 + required this.title,
161 + required this.value,
162 + required this.isCopied,
163 + required this.copyImage,
164 + required this.currentTheme,
165 + });
166 +
167 + @override
168 + Widget build(BuildContext context) {
169 +
170 + final hintTextColor = currentTheme == ThemeType.bright
171 + ? Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor
172 + : Colors.white.withAlpha(175);
173 +
174 + final mainTextColor = currentTheme == ThemeType.bright
175 + ? Theme.of(context).extension<CakeTextTheme>()!.titleColor
176 + : Colors.white;
177 +
178 + return Padding(
179 + padding: const EdgeInsets.symmetric(vertical: 8),
180 + child: GestureDetector(
181 + onTap: () {
182 + if (!isCopied) return;
183 + Clipboard.setData(ClipboardData(text: value));
184 + showBar<void>(context, S.of(context).transaction_details_copied(title));
185 + },
186 + child: ListRow(
187 + padding: EdgeInsets.zero,
188 + title: title,
189 + value: value,
190 + image: isCopied ? copyImage : null,
191 + color: Colors.transparent,
192 + hintTextColor: hintTextColor,
193 + mainTextColor: mainTextColor,
194 + ),
195 + ),
196 + );
197 + }
198 +}
199 +
200 +class FeeSelectionWidget extends StatelessWidget {
201 + final FeesViewModel feesViewModel;
202 + final Output output;
203 + final VoidCallback onTap;
204 +
205 + const FeeSelectionWidget({
206 + required this.feesViewModel,
207 + required this.output,
208 + required this.onTap,
209 + });
210 +
211 + @override
212 + Widget build(BuildContext context) {
213 + return Observer(
214 + builder: (_) => GestureDetector(
215 + key: ValueKey('exchange_trade_card_item_widget_select_fee_priority_button_key'),
216 + onTap: feesViewModel.hasFeesPriority ? onTap : () {},
217 + child: Container(
218 + padding: EdgeInsets.only(top: 24),
219 + child: Row(
220 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
221 + crossAxisAlignment: CrossAxisAlignment.start,
222 + children: <Widget>[
223 + Text(
224 + S.of(context).send_estimated_fee,
225 + style: TextStyle(
226 + fontSize: 12,
227 + fontWeight: FontWeight.w500,
228 + color: Colors.white,
229 + ),
230 + ),
231 + Row(
232 + crossAxisAlignment: CrossAxisAlignment.start,
233 + children: <Widget>[
234 + Column(
235 + crossAxisAlignment: CrossAxisAlignment.end,
236 + children: [
237 + Text(
238 + '${output.estimatedFee} ${feesViewModel.currency}',
239 + style: TextStyle(
240 + fontSize: 12,
241 + fontWeight: FontWeight.w600,
242 + color: Colors.white,
243 + ),
244 + ),
245 + if (!feesViewModel.isFiatDisabled)
246 + Padding(
247 + padding: EdgeInsets.only(top: 5),
248 + child: Text(
249 + '${output.estimatedFeeFiatAmount} ${feesViewModel.fiat.title}',
250 + style: TextStyle(
251 + fontSize: 12,
252 + fontWeight: FontWeight.w600,
253 + color:
254 + Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor,
255 + ),
256 + ),
257 + ),
258 + ],
259 + ),
260 + Padding(
261 + padding: EdgeInsets.only(top: 2, left: 5),
262 + child: Icon(
263 + Icons.arrow_forward_ios,
264 + size: 12,
265 + color: Colors.white,
266 + ),
267 + ),
268 + ],
269 + ),
270 + ],
271 + ),
272 + ),
273 + ),
274 + );
275 + }
276 +}
277 +
278 +class CoinControlWidget extends StatelessWidget {
279 + final VoidCallback onTap;
280 +
281 + const CoinControlWidget({required this.onTap});
282 +
283 + @override
284 + Widget build(BuildContext context) {
285 + return GestureDetector(
286 + key: ValueKey('exchange_trade_card_item_widget_unspent_coin_button_key'),
287 + onTap: onTap,
288 + child: Container(
289 + color: Colors.transparent,
290 + padding: EdgeInsets.only(top: 6),
291 + child: Row(
292 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
293 + children: [
294 + Text(
295 + S.of(context).coin_control,
296 + style: TextStyle(
297 + fontSize: 12,
298 + fontWeight: FontWeight.w600,
299 + color: Colors.white,
300 + ),
301 + ),
302 + Icon(
303 + Icons.arrow_forward_ios,
304 + size: 12,
305 + color: Colors.white,
306 + ),
307 + ],
308 + ),
309 + ),
310 + );
311 + }
312 +}
lib/src/screens/send/widgets/send_card.dart
+9 -9
@@ -308,11 +308,11 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
308 color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
309 ),
310 ),
311 - if (sendViewModel.hasFees)
311 + if (sendViewModel.feesViewModel.hasFees)
312 Observer(
313 builder: (_) => GestureDetector(
314 key: ValueKey('send_page_select_fee_priority_button_key'),
315 - onTap: sendViewModel.hasFeesPriority
315 + onTap: sendViewModel.feesViewModel.hasFeesPriority
316 ? () => pickTransactionPriority(context)
317 : () {},
318 child: Container(
@@ -570,11 +570,11 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
570
571 Future<void> pickTransactionPriority(BuildContext context) async {
572 final items = priorityForWalletType(sendViewModel.walletType);
573 - final selectedItem = items.indexOf(sendViewModel.transactionPriority);
574 - final customItemIndex = sendViewModel.getCustomPriorityIndex(items);
573 + final selectedItem = items.indexOf(sendViewModel.feesViewModel.transactionPriority);
574 + final customItemIndex = sendViewModel.feesViewModel.getCustomPriorityIndex(items);
575 final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin;
576 - final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
577 - double? customFeeRate = isBitcoinWallet ? sendViewModel.customBitcoinFeeRate.toDouble() : null;
576 + final maxCustomFeeRate = sendViewModel.feesViewModel.maxCustomFeeRate?.toDouble();
577 + double? customFeeRate = isBitcoinWallet ? sendViewModel.feesViewModel.customBitcoinFeeRate.toDouble() : null;
578
579 await showPopUp<void>(
580 context: context,
@@ -585,7 +585,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
585 return Picker(
586 items: items,
587 displayItem: (TransactionPriority priority) =>
588 - sendViewModel.displayFeeRate(priority, customFeeRate?.round()),
588 + sendViewModel.feesViewModel.displayFeeRate(priority, customFeeRate?.round()),
589 selectedAtIndex: selectedIdx,
590 customItemIndex: customItemIndex,
591 maxValue: maxCustomFeeRate,
@@ -596,7 +596,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
596 sliderValue: customFeeRate,
597 onSliderChanged: (double newValue) => setState(() => customFeeRate = newValue),
598 onItemSelected: (TransactionPriority priority) {
599 - sendViewModel.setTransactionPriority(priority);
599 + sendViewModel.feesViewModel.setTransactionPriority(priority);
600 setState(() => selectedIdx = items.indexOf(priority));
601 },
602 );
@@ -604,7 +604,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
604 );
605 },
606 );
607 - if (isBitcoinWallet) sendViewModel.customBitcoinFeeRate = customFeeRate!.round();
607 + if (isBitcoinWallet) sendViewModel.feesViewModel.customBitcoinFeeRate = customFeeRate!.round();
608 }
609
610 void _presentPicker(BuildContext context) {
lib/src/widgets/list_row.dart
+19 -12
@@ -1,30 +1,37 @@
1 import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
2 -import 'package:flutter/cupertino.dart';
2 import 'package:flutter/material.dart';
3 import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
4
5 class ListRow extends StatelessWidget {
7 - ListRow(
8 - {required this.title,
9 - required this.value,
10 - this.titleFontSize = 14,
11 - this.valueFontSize = 16,
12 - this.image});
6 + ListRow({
7 + required this.title,
8 + required this.value,
9 + this.titleFontSize = 14,
10 + this.valueFontSize = 16,
11 + this.image,
12 + this.padding,
13 + this.color,
14 + this.hintTextColor,
15 + this.mainTextColor
16 + });
17
18 final String title;
19 final String value;
20 final double titleFontSize;
21 final double valueFontSize;
22 final Image? image;
23 + final EdgeInsetsGeometry? padding;
24 + final Color? color;
25 + final Color? hintTextColor;
26 + final Color? mainTextColor;
27
28 @override
29 Widget build(BuildContext context) {
30 return Container(
31 width: double.infinity,
24 - color: Theme.of(context).colorScheme.background,
32 + color: color ?? Theme.of(context).colorScheme.background,
33 child: Padding(
26 - padding:
27 - const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
34 + padding: padding ?? const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
35 child: Column(
36 crossAxisAlignment: CrossAxisAlignment.start,
37 children: <Widget>[
@@ -32,7 +39,7 @@ class ListRow extends StatelessWidget {
39 style: TextStyle(
40 fontSize: titleFontSize,
41 fontWeight: FontWeight.w500,
35 - color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
42 + color: hintTextColor ?? Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
43 textAlign: TextAlign.left),
44 Padding(
45 padding: const EdgeInsets.only(top: 12),
@@ -46,7 +53,7 @@ class ListRow extends StatelessWidget {
53 style: TextStyle(
54 fontSize: valueFontSize,
55 fontWeight: FontWeight.w500,
49 - color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
56 + color: mainTextColor ?? Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
57 ),
58 image != null
59 ? Padding(
lib/view_model/exchange/exchange_trade_view_model.dart
+58 -22
@@ -16,6 +16,8 @@ import 'package:cake_wallet/exchange/trade.dart';
16 import 'package:cake_wallet/generated/i18n.dart';
17 import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_item.dart';
18 import 'package:cake_wallet/store/dashboard/trades_store.dart';
19 +import 'package:cake_wallet/view_model/send/fees_view_model.dart';
20 +import 'package:cake_wallet/view_model/send/output.dart';
21 import 'package:cake_wallet/view_model/send/send_view_model.dart';
22 import 'package:cw_core/crypto_currency.dart';
23 import 'package:cw_core/utils/print_verbose.dart';
@@ -28,14 +30,16 @@ part 'exchange_trade_view_model.g.dart';
30 class ExchangeTradeViewModel = ExchangeTradeViewModelBase with _$ExchangeTradeViewModel;
31
32 abstract class ExchangeTradeViewModelBase with Store {
31 - ExchangeTradeViewModelBase(
32 - {required this.wallet,
33 - required this.trades,
34 - required this.tradesStore,
35 - required this.sendViewModel})
36 - : trade = tradesStore.trade!,
33 + ExchangeTradeViewModelBase({
34 + required this.wallet,
35 + required this.trades,
36 + required this.tradesStore,
37 + required this.sendViewModel,
38 + required this.feesViewModel,
39 + }) : trade = tradesStore.trade!,
40 isSendable = _checkIfCanSend(tradesStore, wallet),
41 items = ObservableList<ExchangeTradeItem>() {
42 + setUpOutput();
43 switch (trade.provider) {
44 case ExchangeProviderDescription.changeNow:
45 _provider =
@@ -81,6 +85,9 @@ abstract class ExchangeTradeViewModelBase with Store {
85 final Box<Trade> trades;
86 final TradesStore tradesStore;
87 final SendViewModel sendViewModel;
88 + final FeesViewModel feesViewModel;
89 +
90 + late Output output;
91
92 @observable
93 Trade trade;
@@ -112,16 +119,18 @@ abstract class ExchangeTradeViewModelBase with Store {
119
120 Timer? timer;
121
115 - @action
116 - Future<void> confirmSending() async {
117 - if (!isSendable) return;
118 -
122 + void setUpOutput() {
123 sendViewModel.clearOutputs();
120 - final output = sendViewModel.outputs.first;
124 + output = sendViewModel.outputs.first;
125 output.address = trade.inputAddress ?? '';
126 output.setCryptoAmount(trade.amount);
127 if (_provider is ThorChainExchangeProvider) output.memo = trade.memo;
128 if (trade.isSendAll == true) output.sendAll = true;
129 + }
130 +
131 + @action
132 + Future<void> confirmSending() async {
133 + if (!isSendable) return;
134 sendViewModel.selectedCryptoCurrency = trade.from;
135 final pendingTransaction = await sendViewModel.createTransaction(provider: _provider);
136 if (_provider is ThorChainExchangeProvider) {
@@ -154,7 +163,7 @@ abstract class ExchangeTradeViewModelBase with Store {
163
164 void _updateItems() {
165 final tagFrom =
157 - tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : '';
166 + tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : '';
167 final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : '';
168 items.clear();
169
@@ -164,6 +173,8 @@ abstract class ExchangeTradeViewModelBase with Store {
173 title: "${trade.provider.title} ${S.current.id}",
174 data: '${trade.id}',
175 isCopied: true,
176 + isReceiveDetail: true,
177 + isExternalSendDetail: false,
178 ),
179 );
180
@@ -171,28 +182,51 @@ abstract class ExchangeTradeViewModelBase with Store {
182 ExchangeTradeItem(
183 title: S.current.amount,
184 data: '${trade.amount} ${trade.from}',
174 - isCopied: true,
185 + isCopied: false,
186 + isReceiveDetail: false,
187 + isExternalSendDetail: true,
188 ),
189 ExchangeTradeItem(
177 - title: S.current.estimated_receive_amount + ':',
190 + title: S.current.you_will_receive_estimated_amount + ':',
191 data: '${tradesStore.trade?.receiveAmount} ${trade.to}',
192 isCopied: true,
193 + isReceiveDetail: true,
194 + isExternalSendDetail: false,
195 ),
196 ExchangeTradeItem(
197 title: S.current.send_to_this_address('${tradesStore.trade!.from}', tagFrom) + ':',
198 data: trade.inputAddress ?? '',
184 - isCopied: true,
199 + isCopied: false,
200 + isReceiveDetail: false,
201 + isExternalSendDetail: true,
202 ),
203 ]);
204
205 if (trade.extraId != null) {
189 - final title = trade.from == CryptoCurrency.xrp
190 - ? S.current.destination_tag
191 - : trade.from == CryptoCurrency.xlm
192 - ? S.current.memo
193 - : S.current.extra_id;
194 -
195 - items.add(ExchangeTradeItem(title: title, data: '${trade.extraId}', isCopied: true));
206 + final shouldAddExtraId = trade.from == CryptoCurrency.xrp || trade.from == CryptoCurrency.xlm;
207 +
208 + if (shouldAddExtraId) {
209 + final title = trade.from == CryptoCurrency.xrp
210 + ? S.current.destination_tag
211 + : trade.from == CryptoCurrency.xlm
212 + ? S.current.memo
213 + : S.current.extra_id;
214 +
215 + items.add(
216 + ExchangeTradeItem(
217 + title: title,
218 + data: '${trade.extraId}',
219 + isCopied: true,
220 + isReceiveDetail: (trade.from == CryptoCurrency.xrp || trade.from == CryptoCurrency.xlm)
221 + ? false
222 + : true,
223 + isExternalSendDetail:
224 + (trade.from == CryptoCurrency.xrp || trade.from == CryptoCurrency.xlm)
225 + ? true
226 + : false,
227 + ),
228 + );
229 + }
230 }
231
232 items.add(
@@ -200,6 +234,8 @@ abstract class ExchangeTradeViewModelBase with Store {
234 title: S.current.arrive_in_this_address('${tradesStore.trade!.to}', tagTo) + ':',
235 data: trade.payoutAddress ?? '',
236 isCopied: true,
237 + isReceiveDetail: true,
238 + isExternalSendDetail: false,
239 ),
240 );
241 }
lib/view_model/exchange/exchange_view_model.dart
+7 -56
@@ -7,6 +7,7 @@ import 'package:cake_wallet/core/create_trade_result.dart';
7 import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart';
8 import 'package:cake_wallet/exchange/provider/letsexchange_exchange_provider.dart';
9 import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
10 +import 'package:cake_wallet/view_model/send/fees_view_model.dart';
11 import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart';
12 import 'package:cw_core/crypto_currency.dart';
13 import 'package:cw_core/sync_status.dart';
@@ -22,12 +23,10 @@ import 'package:shared_preferences/shared_preferences.dart';
23
24 import 'package:cake_wallet/.secrets.g.dart' as secrets;
25 import 'package:cake_wallet/bitcoin/bitcoin.dart';
25 -import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
26 import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
27 import 'package:cake_wallet/entities/exchange_api_mode.dart';
28 import 'package:cake_wallet/entities/preferences_key.dart';
29 import 'package:cake_wallet/entities/wallet_contact.dart';
30 -import 'package:cake_wallet/ethereum/ethereum.dart';
30 import 'package:cake_wallet/exchange/exchange_provider_description.dart';
31 import 'package:cake_wallet/exchange/exchange_template.dart';
32 import 'package:cake_wallet/exchange/exchange_trade_state.dart';
@@ -44,8 +43,6 @@ import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
43 import 'package:cake_wallet/exchange/trade.dart';
44 import 'package:cake_wallet/exchange/trade_request.dart';
45 import 'package:cake_wallet/generated/i18n.dart';
47 -import 'package:cake_wallet/monero/monero.dart';
48 -import 'package:cake_wallet/polygon/polygon.dart';
46 import 'package:cake_wallet/store/app_store.dart';
47 import 'package:cake_wallet/store/dashboard/trades_store.dart';
48 import 'package:cake_wallet/store/settings_store.dart';
@@ -72,6 +69,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
69 this._settingsStore,
70 this.sharedPreferences,
71 this.contactListViewModel,
72 + this.feesViewModel,
73 ) : _cryptoNumberFormat = NumberFormat(),
74 isSendAllEnabled = false,
75 isFixedRateMode = false,
@@ -169,8 +167,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
167 wallet.type == WalletType.bitcoinCash;
168
169 bool get hideAddressAfterExchange =>
172 - wallet.type == WalletType.monero ||
173 - wallet.type == WalletType.wownero;
170 + wallet.type == WalletType.monero || wallet.type == WalletType.wownero;
171
172 bool _useTorOnly;
173 final Box<Trade> trades;
@@ -319,27 +316,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
316
317 bool get isMoneroWallet => wallet.type == WalletType.monero;
318
322 - bool get isLowFee {
323 - switch (wallet.type) {
324 - case WalletType.monero:
325 - case WalletType.wownero:
326 - case WalletType.haven:
327 - case WalletType.zano:
328 - return transactionPriority == monero!.getMoneroTransactionPrioritySlow();
329 - case WalletType.bitcoin:
330 - return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow();
331 - case WalletType.litecoin:
332 - return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow();
333 - case WalletType.ethereum:
334 - return transactionPriority == ethereum!.getEthereumTransactionPrioritySlow();
335 - case WalletType.bitcoinCash:
336 - return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow();
337 - case WalletType.polygon:
338 - return transactionPriority == polygon!.getPolygonTransactionPrioritySlow();
339 - default:
340 - return false;
341 - }
342 - }
319 +
320
321 List<CryptoCurrency> receiveCurrencies;
322
@@ -351,6 +328,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
328
329 final ContactListViewModel contactListViewModel;
330
331 + final FeesViewModel feesViewModel;
332 +
333 @observable
334 double bestRate = 0.0;
335
@@ -434,6 +413,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
413
414 return true;
415 }
416 +
417 Future<void> calculateBestRate() async {
418 if (depositCurrency == receiveCurrency) {
419 bestRate = 0.0;
@@ -876,35 +856,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
856 selectedProviders.where((provider) => providersForCurrentPair().contains(provider)));
857 }
858
879 - @action
880 - void setDefaultTransactionPriority() {
881 - switch (wallet.type) {
882 - case WalletType.monero:
883 - case WalletType.haven:
884 - case WalletType.wownero:
885 - case WalletType.zano:
886 - _settingsStore.priority[wallet.type] = monero!.getMoneroTransactionPriorityAutomatic();
887 - break;
888 - case WalletType.bitcoin:
889 - _settingsStore.priority[wallet.type] = bitcoin!.getBitcoinTransactionPriorityMedium();
890 - break;
891 - case WalletType.litecoin:
892 - _settingsStore.priority[wallet.type] = bitcoin!.getLitecoinTransactionPriorityMedium();
893 - break;
894 - case WalletType.ethereum:
895 - _settingsStore.priority[wallet.type] = ethereum!.getDefaultTransactionPriority();
896 - break;
897 - case WalletType.bitcoinCash:
898 - _settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority();
899 - break;
900 - case WalletType.polygon:
901 - _settingsStore.priority[wallet.type] = polygon!.getDefaultTransactionPriority();
902 - break;
903 - default:
904 - break;
905 - }
906 - }
907 -
859 void _setProviders() {
860 if (_settingsStore.exchangeStatus == ExchangeApiMode.torOnly)
861 providerList = _allProviders.where((provider) => provider.supportsOnionAddress).toList();
lib/view_model/send/fees_view_model.dart new
+191
@@ -0,0 +1,191 @@
1 +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
2 +import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
3 +import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
4 +import 'package:cake_wallet/ethereum/ethereum.dart';
5 +import 'package:cake_wallet/monero/monero.dart';
6 +import 'package:cake_wallet/polygon/polygon.dart';
7 +import 'package:cake_wallet/store/app_store.dart';
8 +import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
9 +import 'package:cw_core/crypto_currency.dart';
10 +import 'package:cw_core/transaction_priority.dart';
11 +import 'package:mobx/mobx.dart';
12 +import 'package:cake_wallet/entities/fiat_currency.dart';
13 +import 'package:cw_core/wallet_type.dart';
14 +import 'package:cake_wallet/store/settings_store.dart';
15 +import 'package:cake_wallet/bitcoin/bitcoin.dart';
16 +import 'package:collection/collection.dart';
17 +
18 +part 'fees_view_model.g.dart';
19 +
20 +class FeesViewModel = FeesViewModelBase with _$FeesViewModel;
21 +
22 +abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Store {
23 + FeesViewModelBase(
24 + AppStore appStore,
25 + this.balanceViewModel,
26 + ) : _settingsStore = appStore.settingsStore,
27 + super(appStore: appStore) {
28 + if (wallet.type == WalletType.bitcoin &&
29 + _settingsStore.priority[wallet.type] == bitcoinTransactionPriorityCustom) {
30 + setTransactionPriority(bitcoinTransactionPriorityMedium);
31 + }
32 + final priority = _settingsStore.priority[wallet.type];
33 + final priorities = priorityForWalletType(wallet.type);
34 + if (!priorityForWalletType(wallet.type).contains(priority) && priorities.isNotEmpty) {
35 + _settingsStore.priority[wallet.type] = priorities.first;
36 + }
37 + }
38 +
39 + @computed
40 + WalletType get walletType => wallet.type;
41 + CryptoCurrency get currency => wallet.currency;
42 + FiatCurrency get fiat => _settingsStore.fiatCurrency;
43 + bool get isFiatDisabled => balanceViewModel.isFiatDisabled;
44 +
45 + final BalanceViewModel balanceViewModel;
46 +
47 + TransactionPriority get transactionPriority {
48 + final priority = _settingsStore.priority[wallet.type];
49 +
50 + if (priority == null) {
51 + throw Exception('Unexpected type ${wallet.type}');
52 + }
53 +
54 + return priority;
55 + }
56 +
57 + int? getCustomPriorityIndex(List<TransactionPriority> priorities) {
58 + if (wallet.type == WalletType.bitcoin) {
59 + final customItem = priorities
60 + .firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom());
61 +
62 + return customItem != null ? priorities.indexOf(customItem) : null;
63 + }
64 + return null;
65 + }
66 +
67 + int? get maxCustomFeeRate {
68 + if (wallet.type == WalletType.bitcoin) {
69 + return bitcoin!.getMaxCustomFeeRate(wallet);
70 + }
71 + return null;
72 + }
73 +
74 + bool get isLowFee {
75 + switch (wallet.type) {
76 + case WalletType.monero:
77 + case WalletType.wownero:
78 + case WalletType.haven:
79 + case WalletType.zano:
80 + return transactionPriority == monero!.getMoneroTransactionPrioritySlow();
81 + case WalletType.bitcoin:
82 + return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow();
83 + case WalletType.litecoin:
84 + return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow();
85 + case WalletType.ethereum:
86 + return transactionPriority == ethereum!.getEthereumTransactionPrioritySlow();
87 + case WalletType.bitcoinCash:
88 + return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow();
89 + case WalletType.polygon:
90 + return transactionPriority == polygon!.getPolygonTransactionPrioritySlow();
91 + default:
92 + return false;
93 + }
94 + }
95 +
96 + @computed
97 + int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate;
98 +
99 + void set customBitcoinFeeRate(int value) => _settingsStore.customBitcoinFeeRate = value;
100 +
101 + @computed
102 + bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano;
103 +
104 + @computed
105 + bool get hasFeesPriority =>
106 + wallet.type != WalletType.nano &&
107 + wallet.type != WalletType.banano &&
108 + wallet.type != WalletType.solana &&
109 + wallet.type != WalletType.tron;
110 +
111 + @computed
112 + bool get isElectrumWallet =>
113 + wallet.type == WalletType.bitcoin ||
114 + wallet.type == WalletType.litecoin ||
115 + wallet.type == WalletType.bitcoinCash;
116 +
117 + String? get walletCurrencyName => wallet.currency.fullName?.toLowerCase() ?? wallet.currency.name;
118 +
119 + @computed
120 + FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
121 +
122 + final SettingsStore _settingsStore;
123 +
124 + @action
125 + void setTransactionPriority(TransactionPriority priority) =>
126 + _settingsStore.priority[wallet.type] = priority;
127 +
128 + bool showAlertForCustomFeeRate() {
129 + if (wallet.type != WalletType.bitcoin || isLowFee) {
130 + return false;
131 + }
132 +
133 + if (transactionPriority != bitcoinTransactionPriorityCustom) {
134 + return false;
135 + }
136 +
137 + final mediumRate = bitcoin!.getFeeRate(wallet, bitcoinTransactionPriorityMedium);
138 + return customBitcoinFeeRate < mediumRate;
139 + }
140 +
141 + String displayFeeRate(dynamic priority, int? customValue) {
142 + final _priority = priority as TransactionPriority;
143 +
144 + if (wallet.type == WalletType.bitcoin) {
145 + final rate = bitcoin!.getFeeRate(wallet, _priority);
146 + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue);
147 + }
148 +
149 + if (isElectrumWallet) {
150 + final rate = bitcoin!.getFeeRate(wallet, _priority);
151 + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate);
152 + }
153 +
154 + return priority.toString();
155 + }
156 +
157 + TransactionPriority get bitcoinTransactionPriorityCustom =>
158 + bitcoin!.getBitcoinTransactionPriorityCustom();
159 +
160 + TransactionPriority get bitcoinTransactionPriorityMedium =>
161 + bitcoin!.getBitcoinTransactionPriorityMedium();
162 +
163 + @action
164 + void setDefaultTransactionPriority() {
165 + switch (wallet.type) {
166 + case WalletType.monero:
167 + case WalletType.haven:
168 + case WalletType.wownero:
169 + case WalletType.zano:
170 + _settingsStore.priority[wallet.type] = monero!.getMoneroTransactionPriorityAutomatic();
171 + break;
172 + case WalletType.bitcoin:
173 + _settingsStore.priority[wallet.type] = bitcoin!.getBitcoinTransactionPriorityMedium();
174 + break;
175 + case WalletType.litecoin:
176 + _settingsStore.priority[wallet.type] = bitcoin!.getLitecoinTransactionPriorityMedium();
177 + break;
178 + case WalletType.ethereum:
179 + _settingsStore.priority[wallet.type] = ethereum!.getDefaultTransactionPriority();
180 + break;
181 + case WalletType.bitcoinCash:
182 + _settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority();
183 + break;
184 + case WalletType.polygon:
185 + _settingsStore.priority[wallet.type] = polygon!.getDefaultTransactionPriority();
186 + break;
187 + default:
188 + break;
189 + }
190 + }
191 +}
lib/view_model/send/send_view_model.dart
+6 -82
@@ -18,6 +18,7 @@ import 'package:cake_wallet/tron/tron.dart';
18 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
19 import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
20 import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
21 +import 'package:cake_wallet/view_model/send/fees_view_model.dart';
22 import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
23 import 'package:cake_wallet/wownero/wownero.dart';
24 import 'package:cake_wallet/zano/zano.dart';
@@ -76,7 +77,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
77 this.contactListViewModel,
78 this.transactionDescriptionBox,
79 this.ledgerViewModel,
79 - this.unspentCoinsListViewModel, {
80 + this.unspentCoinsListViewModel,
81 + this.feesViewModel, {
82 this.coinTypeToSpendFrom = UnspentCoinType.nonMweb,
83 }) : state = InitialExecutionState(),
84 currencies = appStore.wallet!.balance.keys.toList(),
@@ -89,16 +91,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
91 _settingsStore = appStore.settingsStore,
92 fiatFromSettings = appStore.settingsStore.fiatCurrency,
93 super(appStore: appStore) {
92 - if (wallet.type == WalletType.bitcoin &&
93 - _settingsStore.priority[wallet.type] == bitcoinTransactionPriorityCustom) {
94 - setTransactionPriority(bitcoinTransactionPriorityMedium);
95 - }
96 - final priority = _settingsStore.priority[wallet.type];
97 - final priorities = priorityForWalletType(wallet.type);
98 - if (!priorityForWalletType(wallet.type).contains(priority) && priorities.isNotEmpty) {
99 - _settingsStore.priority[wallet.type] = priorities.first;
100 - }
101 -
94 outputs
95 .add(Output(wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency));
96
@@ -205,38 +197,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
197
198 FiatCurrency get fiat => _settingsStore.fiatCurrency;
199
208 - TransactionPriority get transactionPriority {
209 - final priority = _settingsStore.priority[wallet.type];
210 -
211 - if (priority == null) {
212 - throw Exception('Unexpected type ${wallet.type}');
213 - }
214 -
215 - return priority;
216 - }
217 -
218 - int? getCustomPriorityIndex(List<TransactionPriority> priorities) {
219 - if (wallet.type == WalletType.bitcoin) {
220 - final customItem = priorities
221 - .firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom());
222 -
223 - return customItem != null ? priorities.indexOf(customItem) : null;
224 - }
225 - return null;
226 - }
227 -
228 - int? get maxCustomFeeRate {
229 - if (wallet.type == WalletType.bitcoin) {
230 - return bitcoin!.getMaxCustomFeeRate(wallet);
231 - }
232 - return null;
233 - }
234 -
235 - @computed
236 - int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate;
237 -
238 - void set customBitcoinFeeRate(int value) => _settingsStore.customBitcoinFeeRate = value;
239 -
200 CryptoCurrency get currency => wallet.currency;
201
202 Validator<String> get amountValidator =>
@@ -299,16 +259,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
259 wallet.type == WalletType.litecoin ||
260 wallet.type == WalletType.bitcoinCash;
261
302 - @computed
303 - bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano;
304 -
305 - @computed
306 - bool get hasFeesPriority =>
307 - wallet.type != WalletType.nano &&
308 - wallet.type != WalletType.banano &&
309 - wallet.type != WalletType.solana &&
310 - wallet.type != WalletType.tron;
311 -
262 @observable
263 CryptoCurrency selectedCryptoCurrency;
264
@@ -331,6 +281,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
281 final BalanceViewModel balanceViewModel;
282 final ContactListViewModel contactListViewModel;
283 final LedgerViewModel? ledgerViewModel;
284 + final FeesViewModel feesViewModel;
285 final FiatConversionStore _fiatConversationStore;
286 final Box<TransactionDescription> transactionDescriptionBox;
287
@@ -531,10 +482,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
482 }
483 }
484
534 - @action
535 - void setTransactionPriority(TransactionPriority priority) =>
536 - _settingsStore.priority[wallet.type] = priority;
537 -
485 Object _credentials([ExchangeProvider? provider]) {
486 final priority = _settingsStore.priority[wallet.type];
487
@@ -552,14 +499,14 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
499 return bitcoin!.createBitcoinTransactionCredentials(
500 outputs,
501 priority: priority!,
555 - feeRate: customBitcoinFeeRate,
502 + feeRate:feesViewModel. customBitcoinFeeRate,
503 coinTypeToSpendFrom: coinTypeToSpendFrom,
504 );
505 case WalletType.litecoin:
506 return bitcoin!.createBitcoinTransactionCredentials(
507 outputs,
508 priority: priority!,
562 - feeRate: customBitcoinFeeRate,
509 + feeRate:feesViewModel. customBitcoinFeeRate,
510 // if it's an exchange flow then disable sending from mweb coins
511 coinTypeToSpendFrom: provider != null ? UnspentCoinType.nonMweb : coinTypeToSpendFrom,
512 );
@@ -597,32 +544,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
544 }
545 }
546
600 - String displayFeeRate(dynamic priority, int? customValue) {
601 - final _priority = priority as TransactionPriority;
602 -
603 - if (walletType == WalletType.bitcoin) {
604 - final rate = bitcoin!.getFeeRate(wallet, _priority);
605 - return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue);
606 - }
607 -
608 - if (isElectrumWallet) {
609 - final rate = bitcoin!.getFeeRate(wallet, _priority);
610 - return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate);
611 - }
612 -
613 - return priority.toString();
614 - }
615 -
547 bool _isEqualCurrency(String currency) =>
548 wallet.balance.keys.any((e) => currency.toLowerCase() == e.title.toLowerCase());
549
619 - TransactionPriority get bitcoinTransactionPriorityCustom =>
620 - bitcoin!.getBitcoinTransactionPriorityCustom();
621 -
622 - TransactionPriority get bitcoinTransactionPriorityMedium =>
623 - bitcoin!.getBitcoinTransactionPriorityMedium();
624 -
625 - @action
550 void onClose() => _settingsStore.fiatCurrency = fiatFromSettings;
551
552 @action
lib/view_model/transaction_details_view_model.dart
+8 -7
@@ -576,11 +576,11 @@ abstract class TransactionDetailsViewModelBase with Store {
576 }
577
578 final priorities = priorityForWalletType(wallet.type);
579 - final selectedItem = priorities.indexOf(sendViewModel.transactionPriority);
580 - final customItem = priorities
581 - .firstWhereOrNull((element) => element == sendViewModel.bitcoinTransactionPriorityCustom);
579 + final selectedItem = priorities.indexOf(sendViewModel.feesViewModel.transactionPriority);
580 + final customItem = priorities.firstWhereOrNull(
581 + (element) => element == sendViewModel.feesViewModel.bitcoinTransactionPriorityCustom);
582 final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null;
583 - final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
583 + final maxCustomFeeRate = sendViewModel.feesViewModel.maxCustomFeeRate?.toDouble();
584
585 RBFListItems.add(
586 StandardPickerListItem(
@@ -594,7 +594,7 @@ abstract class TransactionDetailsViewModelBase with Store {
594 selectedIdx: selectedItem,
595 customItemIndex: customItemIndex ?? 0,
596 displayItem: (dynamic priority, double sliderValue) =>
597 - sendViewModel.displayFeeRate(priority, sliderValue.round()),
597 + sendViewModel.feesViewModel.displayFeeRate(priority, sliderValue.round()),
598 onSliderChanged: (double newValue) =>
599 setNewFee(value: newValue, priority: transactionPriority!),
600 onItemSelected: (dynamic item, double sliderValue) {
@@ -788,7 +788,8 @@ abstract class TransactionDetailsViewModelBase with Store {
788 final comment = tx.additionalInfo['comment'] as String?;
789 items.addAll([
790 StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
791 - StandartListItem(title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
791 + StandartListItem(
792 + title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
793 StandartListItem(
794 title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
795 StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
@@ -798,5 +799,5 @@ abstract class TransactionDetailsViewModelBase with Store {
799 if (comment != null && comment.isNotEmpty)
800 StandartListItem(title: S.current.transaction_details_title, value: comment),
801 ]);
801 - }
802 + }
803 }
res/values/strings_ar.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "* يرجى نسخ أو كتابة معرف هويتك الأعلى لحفظة.",
309 "exchange_result_write_down_trade_id": "يرجى نسخ أو كتابة معرّف العملية للمتابعة.",
310 "exchange_sync_alert_content": "يرجى الانتظار حتى تتم مزامنة محفظتك",
311 + "exchange_trade_result_confirm": "بالضغط على إرسال من Cake Wallet ، ستقوم بإرسال ${fetchingLabel} ${from} من محفظتك التي تسمى ${walletName} إلى العنوان الموضح أدناه. أو يمكنك إرسالها من محفظتك الخارجية إلى العنوان / QR رمز الإرسال من صفحة تفاصيل المحفظة الخارجية. \n\n يرجى الضغط على أي من الأزرار للمتابعة أو العودة لتغيير المبالغ.",
312 "expired": "منتهي الصلاحية",
313 "expires": "تنتهي",
314 "expiresOn": "ﻲﻓ ﻪﺘﻴﺣﻼﺻ ﻲﻬﺘﻨﺗ",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "الحد الأدنى لقيمة المبلغ هو 0.01",
696 "send_estimated_fee": "الرسوم المقدرة:",
697 "send_fee": "الرسوم:",
698 + "send_from_cake_wallet": "أرسل من محفظة الكيك",
699 + "send_from_external_wallet": "أرسل من محفظة خارجية",
700 "send_name": "الأسم",
701 "send_new": "جديد",
702 "send_payment_id": "معرف عملية الدفع (اختياري)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "لديك الآن بطاقة ائتمان",
1012 "you_pay": "انت تدفع",
1013 "you_will_get": "حول الى",
1014 + "you_will_receive_estimated_amount": "سوف تتلقى(ooded )",
1015 "you_will_send": "تحويل من",
1016 "yy": "YY"
1017 }
\ No newline at end of file
res/values/strings_bg.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Please copy or write down your ID shown above.",
309 "exchange_result_write_down_trade_id": "Моля, запишете trade ID-то, за да продължите.",
310 "exchange_sync_alert_content": "Моля, изчакайте синхронизирането на Вашия портфейл",
311 + "exchange_trade_result_confirm": "Натискайки изпращане от портфейла за торта, ще изпращате ${fetchingLabel} ${from} от вашия портфейл, наречен ${walletName} на адреса, показан по -долу. Или можете да изпратите от външния си портфейл до адреса / QR код на страницата за изпращане от външния портфейл.",
312 "expired": "Изтекло",
313 "expires": "Изтича",
314 "expiresOn": "Изтича на",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "Минималната сума е 0.01",
696 "send_estimated_fee": "Изчислена такса:",
697 "send_fee": "Такса:",
698 + "send_from_cake_wallet": "Изпратете от портфейла за торта",
699 + "send_from_external_wallet": "Изпратете от външен портфейл",
700 "send_name": "Име",
701 "send_new": "Ново",
702 "send_payment_id": "Payment ID (не е задължително)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "Вече имате дебитна карта",
1012 "you_pay": "Вие плащате",
1013 "you_will_get": "Обръщане в",
1014 + "you_will_receive_estimated_amount": "Ще получите(прогнозно )",
1015 "you_will_send": "Обръщане от",
1016 "yy": "гг"
1017 }
\ No newline at end of file
res/values/strings_cs.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Prosím zkopírujte si, nebo zapište si výše uvedené ID.",
309 "exchange_result_write_down_trade_id": "Prosím zkopírujte si, nebo zapište si ID transakce (trade ID) pro pokračování.",
310 "exchange_sync_alert_content": "Prosím počkejte, dokud nebude vaše peněženka synchronizována",
311 + "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.",
312 "expired": "Vypršelo",
313 "expires": "Vyprší",
314 "expiresOn": "Vyprší dne",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "Minimální částka je 0,01",
696 "send_estimated_fee": "Odhadovaný poplatek:",
697 "send_fee": "Poplatek:",
698 + "send_from_cake_wallet": "Odeslat z peněženky",
699 + "send_from_external_wallet": "Odeslat z externí peněženky",
700 "send_name": "Název",
701 "send_new": "Nová",
702 "send_payment_id": "ID platby (nepovinné)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "Nyní máte debetní kartu",
1012 "you_pay": "Zaplatíte",
1013 "you_will_get": "Směnit na",
1014 + "you_will_receive_estimated_amount": "Obdržíte(odhadovaný )",
1015 "you_will_send": "Směnit z",
1016 "yy": "YY"
1017 }
\ No newline at end of file
res/values/strings_de.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Bitte kopieren oder notieren Sie sich die oben gezeigte ID.",
309 "exchange_result_write_down_trade_id": "Bitte kopieren oder notieren Sie die Handels-ID, um fortzufahren.",
310 "exchange_sync_alert_content": "Bitte warten Sie, bis Ihre Wallet synchronisiert ist",
311 + "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.",
312 "expired": "Abgelaufen",
313 "expires": "Läuft ab",
314 "expiresOn": "Läuft aus am",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "Der Mindestbetrag ist 0,01",
697 "send_estimated_fee": "Geschätzte Gebühr:",
698 "send_fee": "Gebühr:",
699 + "send_from_cake_wallet": "Senden Sie aus Kuchenbrieftasche",
700 + "send_from_external_wallet": "Senden Sie aus der Außenschreibe",
701 "send_name": "Name",
702 "send_new": "Neu",
703 "send_payment_id": "Zahlungs-ID (optional)",
@@ -1011,6 +1014,7 @@
1014 "you_now_have_debit_card": "Sie haben jetzt eine Debitkarte",
1015 "you_pay": "Sie bezahlen",
1016 "you_will_get": "Konvertieren zu",
1017 + "you_will_receive_estimated_amount": "Sie erhalten(geschätzt )",
1018 "you_will_send": "Konvertieren von",
1019 "yy": "YY"
1020 }
\ No newline at end of file
res/values/strings_en.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Please copy or write down your ID shown above.",
309 "exchange_result_write_down_trade_id": "Please copy or write down the trade ID to continue.",
310 "exchange_sync_alert_content": "Please wait until your wallet is synchronized",
311 + "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.",
312 "expired": "Expired",
313 "expires": "Expires",
314 "expiresOn": "Expires on",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "Minimum value of amount is 0.01",
697 "send_estimated_fee": "Estimated fee:",
698 "send_fee": "Fee:",
699 + "send_from_cake_wallet": "Send from Cake Wallet",
700 + "send_from_external_wallet": "Send from External Wallet",
701 "send_name": "Name",
702 "send_new": "New",
703 "send_payment_id": "Payment ID (optional)",
@@ -1009,6 +1012,7 @@
1012 "you_now_have_debit_card": "You now have a debit card",
1013 "you_pay": "You Pay",
1014 "you_will_get": "Convert to",
1015 + "you_will_receive_estimated_amount": "You will receive (estimated)",
1016 "you_will_send": "Convert from",
1017 "yy": "YY"
1018 }
\ No newline at end of file
res/values/strings_es.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Copie o escriba su identificación que se muestra arriba.",
309 "exchange_result_write_down_trade_id": "Por favor, copia o escribe el ID.",
310 "exchange_sync_alert_content": "Espere hasta que su billetera esté sincronizada",
311 + "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.",
312 "expired": "Muerto",
313 "expires": "Caduca",
314 "expiresOn": "Expira el",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "El valor mínimo de la cantidad es 0.01",
697 "send_estimated_fee": "Tarifa estimada:",
698 "send_fee": "Cuota:",
699 + "send_from_cake_wallet": "Enviar desde la billetera de pastel",
700 + "send_from_external_wallet": "Enviar desde la billetera externa",
701 "send_name": "Nombre",
702 "send_new": "Nuevo",
703 "send_payment_id": "ID de pago (opcional)",
@@ -1009,6 +1012,7 @@
1012 "you_now_have_debit_card": "Ahora tienes una tarjeta de débito",
1013 "you_pay": "Tú pagas",
1014 "you_will_get": "Convertir a",
1015 + "you_will_receive_estimated_amount": "Recibirá(estimado )",
1016 "you_will_send": "Convertir de",
1017 "yy": "YY"
1018 }
\ No newline at end of file
res/values/strings_fr.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Merci de copier ou écrire votre ID présenté ci-dessus.",
309 "exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.",
310 "exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé",
311 + "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.",
312 "expired": "Expirée",
313 "expires": "Expire",
314 "expiresOn": "Expire le",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "La valeur minimale du montant est 0.01",
696 "send_estimated_fee": "Estimation des frais :",
697 "send_fee": "Frais:",
698 + "send_from_cake_wallet": "Envoyer du portefeuille à gâteau",
699 + "send_from_external_wallet": "Envoyer du portefeuille externe",
700 "send_name": "Nom",
701 "send_new": "Nouveau",
702 "send_payment_id": "ID de paiement (optionnel)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "Vous avez maintenant une carte de débit",
1012 "you_pay": "Vous payez",
1013 "you_will_get": "Convertir vers",
1014 + "you_will_receive_estimated_amount": "Vous recevrez ( estimé )",
1015 "you_will_send": "Convertir depuis",
1016 "yy": "AA"
1017 }
\ No newline at end of file
res/values/strings_ha.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Don Allah kwafi ko rubuta ID dake nuna sama.",
309 "exchange_result_write_down_trade_id": "Da fatan za a kwafa ko rubuta ID ɗin ciniki don ci gaba.",
310 "exchange_sync_alert_content": "Da fatan za a jira har sai an daidaita walat ɗin ku",
311 + "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.",
312 "expired": "Karewa",
313 "expires": "Ya ƙare",
314 "expiresOn": "Yana ƙarewa",
@@ -696,6 +697,8 @@
697 "send_error_minimum_value": "Mafi ƙarancin ƙimar adadin shine 0.01",
698 "send_estimated_fee": "Ƙimar kuɗi:",
699 "send_fee": "Kudin:",
700 + "send_from_cake_wallet": "Aika daga Wallet Caza",
701 + "send_from_external_wallet": "Aika daga walat na waje",
702 "send_name": "Sunan",
703 "send_new": "Sabon",
704 "send_payment_id": "ID na biyan kuɗi (optional)",
@@ -1010,6 +1013,7 @@
1013 "you_now_have_debit_card": "Yanzu kana da katin zare kudi",
1014 "you_pay": "Ka Bayar",
1015 "you_will_get": "Maida zuwa",
1016 + "you_will_receive_estimated_amount": "Za ku (karɓi )",
1017 "you_will_send": "Maida daga",
1018 "yy": "YY"
1019 }
\ No newline at end of file
res/values/strings_hi.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*कृपया ऊपर दिखाए गए अपने ID को कॉपी या लिख लें.",
309 "exchange_result_write_down_trade_id": "जारी रखने के लिए कृपया ट्रेड ID की प्रतिलिपि बनाएँ या लिखें.",
310 "exchange_sync_alert_content": "कृपया प्रतीक्षा करें जब तक आपका बटुआ सिंक्रनाइज़ नहीं किया जाता है",
311 + "exchange_trade_result_confirm": "केक वॉलेट से भेजने से, आप नीचे दिखाए गए पते पर ${walletName} नामक अपने वॉलेट से ${fetchingLabel} ${from} भेजेंगे। या आप अपने बाहरी वॉलेट से एक्सटर्नल वॉलेट विवरण पृष्ठ से भेजने पर पते / QR कोड पर भेज सकते हैं। \n\n कृपया जारी रखने के लिए या वापस जाने के लिए वापस बटन में से किसी एक को दबाएं।",
312 "expired": "समय सीमा समाप्त",
313 "expires": "समाप्त हो जाता है",
314 "expiresOn": "पर समय सीमा समाप्त",
@@ -696,6 +697,8 @@
697 "send_error_minimum_value": "राशि का न्यूनतम मूल्य 0.01 है",
698 "send_estimated_fee": "अनुमानित शुल्क:",
699 "send_fee": "शुल्क:",
700 + "send_from_cake_wallet": "केक वॉलेट से भेजें",
701 + "send_from_external_wallet": "बाहरी बटुए से भेजें",
702 "send_name": "नाम",
703 "send_new": "नया",
704 "send_payment_id": "भुगतान ID (ऐच्छिक)",
@@ -1010,6 +1013,7 @@
1013 "you_now_have_debit_card": "अब आपके पास डेबिट कार्ड है",
1014 "you_pay": "आप भुगतान करते हैं",
1015 "you_will_get": "में बदलें",
1016 + "you_will_receive_estimated_amount": "आपको#अनुमानित ( प्राप्त होगा)",
1017 "you_will_send": "से रूपांतरित करें",
1018 "yy": "वाईवाई"
1019 }
\ No newline at end of file
res/values/strings_hr.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Molimo kopirajte ili zapišite svoj ID prikazan ispod.",
309 "exchange_result_write_down_trade_id": "Molimo kopirajte ili zapišite transakcijski ID za nastavak.",
310 "exchange_sync_alert_content": "Molimo pričekajte dok se Vaš novčanik ne sinkronizira.",
311 + "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.",
312 "expired": "Isteklo",
313 "expires": "Ističe",
314 "expiresOn": "Istječe",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "Minimalna vrijednost iznosa je 0.01",
696 "send_estimated_fee": "Procijenjena naknada:",
697 "send_fee": "Naknada:",
698 + "send_from_cake_wallet": "Pošaljite iz novčanika",
699 + "send_from_external_wallet": "Pošaljite iz vanjskog novčanika",
700 "send_name": "Ime",
701 "send_new": "Novi",
702 "send_payment_id": "ID plaćanja (nije obvezno)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "Sada imate debitnu karticu",
1012 "you_pay": "Vi plaćate",
1013 "you_will_get": "Razmijeni u",
1014 + "you_will_receive_estimated_amount": "Primit ćete(procijenjeno )",
1015 "you_will_send": "Razmijeni iz",
1016 "yy": "GG"
1017 }
\ No newline at end of file
res/values/strings_hy.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Խնդրում ենք պատճենել կամ գրել ձեր ID-ն վերևում",
309 "exchange_result_write_down_trade_id": "Խնդրում ենք պատճենել կամ գրել առևտրի ID-ն շարունակելու համար",
310 "exchange_sync_alert_content": "Խնդրում ենք սպասել մինչև ձեր հաշվեհամարը համաժամացվի",
311 + "exchange_trade_result_confirm": "Տորթի դրամապանակից ուղարկելու միջոցով ձեր դրամապանակից ${fetchingLabel} կուղարկեք ${from} անունով ${walletName}, ստորեւ նշված հասցեով: Կամ դուք կարող եք ձեր արտաքին դրամապանակից ուղարկել / QR կոդ, արտաքին դրամապանակի մանրամասների էջից ուղարկելու համար: \n\n Խնդրում ենք սեղմել կոճակներից կամ վերադառնալ, գումարները շարունակելու կամ վերադառնալու համար:",
312 "expired": "Վավերականությունը լրացել է",
313 "expires": "Վավերականությունը լրանում է",
314 "expiresOn": "Վավերականությունը լրանում է",
@@ -692,6 +693,8 @@
693 "send_error_minimum_value": "Քանակի նվազագույն արժեքը 0.01 է",
694 "send_estimated_fee": "Գնահատված վարձը՝",
695 "send_fee": "Վարձը՝",
696 + "send_from_cake_wallet": "Ուղարկել տորթի դրամապանակից",
697 + "send_from_external_wallet": "Ուղարկել արտաքին դրամապանակից",
698 "send_name": "Անվանում",
699 "send_new": "Նոր",
700 "send_payment_id": "Վճարման ID (կամավոր)",
@@ -1006,6 +1009,7 @@
1009 "you_now_have_debit_card": "Դուք այժմ ունեք դեբետային քարտ",
1010 "you_pay": "Դուք վճարում եք",
1011 "you_will_get": "Ստացեք",
1012 + "you_will_receive_estimated_amount": "Դուք կստանաք ( գնահատված )",
1013 "you_will_send": "Փոխանակեք",
1014 "yy": "ՏՏ"
1015 }
\ No newline at end of file
res/values/strings_id.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Silakan salin atau tulis ID Anda yang ditampilkan di atas.",
309 "exchange_result_write_down_trade_id": "Silakan salin atau tulis ID perdagangan untuk melanjutkan.",
310 "exchange_sync_alert_content": "Silakan tunggu sampai dompet Anda tersinkronisasi",
311 + "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.",
312 "expired": "Kedaluwarsa",
313 "expires": "Kadaluarsa",
314 "expiresOn": "Kadaluarsa pada",
@@ -697,6 +698,8 @@
698 "send_error_minimum_value": "Nilai minimum jumlah adalah 0.01",
699 "send_estimated_fee": "Biaya yang diperkirakan:",
700 "send_fee": "Biaya:",
701 + "send_from_cake_wallet": "Kirim dari Dompet Kue",
702 + "send_from_external_wallet": "Kirim dari dompet eksternal",
703 "send_name": "Nama",
704 "send_new": "Baru",
705 "send_payment_id": "ID Pembayaran (opsional)",
@@ -1011,6 +1014,7 @@
1014 "you_now_have_debit_card": "Anda sekarang memiliki kartu debit",
1015 "you_pay": "Anda Membayar",
1016 "you_will_get": "Konversi ke",
1017 + "you_will_receive_estimated_amount": "Anda akan menerima(estimasi )",
1018 "you_will_send": "Konversi dari",
1019 "yy": "YY"
1020 }
\ No newline at end of file
res/values/strings_it.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Copia o trascrivi il tuo ID mostrato in alto.",
309 "exchange_result_write_down_trade_id": "Copia o trascrivi l'ID dello scambio per continuare.",
310 "exchange_sync_alert_content": "Gentilmente aspetta che il tuo portafoglio venga sincronizzato",
311 + "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.",
312 "expired": "Scaduto",
313 "expires": "Scade",
314 "expiresOn": "Scade il",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "L'importo minimo è 0.01",
697 "send_estimated_fee": "Commissione stimata:",
698 "send_fee": "Commissione:",
699 + "send_from_cake_wallet": "Invia dal portafoglio Cake",
700 + "send_from_external_wallet": "Invia dal portafoglio esterno",
701 "send_name": "Nome",
702 "send_new": "Nuovo",
703 "send_payment_id": "ID Pagamento (opzionale)",
@@ -1010,6 +1013,7 @@
1013 "you_now_have_debit_card": "Ora hai una carta di debito",
1014 "you_pay": "Tu paghi",
1015 "you_will_get": "Converti a",
1016 + "you_will_receive_estimated_amount": "Riceverai(stimato )",
1017 "you_will_send": "Conveti da",
1018 "yy": "YY"
1019 }
\ No newline at end of file
res/values/strings_ja.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*上記のIDをコピーまたは書き留めてください.",
309 "exchange_result_write_down_trade_id": "続行するには、取引IDをコピーまたは書き留めてください.",
310 "exchange_sync_alert_content": "ウォレットが同期されるまでお待ちください",
311 + "exchange_trade_result_confirm": "Cake Walletから送信を押すことにより、${walletName}というウォレットから ${fetchingLabel} ${from}を以下に示すアドレスに送信します。または、外部ウォレットから外部ウォレットの詳細ページから送信のアドレス/ QRコードに送信することもできます。",
312 "expired": "期限切れ",
313 "expires": "Expires",
314 "expiresOn": "有効期限は次のとおりです",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "金額の最小値は0.01です",
697 "send_estimated_fee": "見積手数料:",
698 "send_fee": "費用:",
699 + "send_from_cake_wallet": "ケーキウォレットから送信します",
700 + "send_from_external_wallet": "外部ウォレットから送信します",
701 "send_name": "名前",
702 "send_new": "新着",
703 "send_payment_id": "支払いID (オプショナル)",
@@ -1009,6 +1012,7 @@
1012 "you_now_have_debit_card": "デビットカードができました",
1013 "you_pay": "あなたが支払う",
1014 "you_will_get": "に変換",
1015 + "you_will_receive_estimated_amount": "あなたは(推定)を受け取ります",
1016 "you_will_send": "から変換",
1017 "yy": "YY"
1018 }
\ No newline at end of file
res/values/strings_ko.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*위에 표시된 ID를 복사하거나 적어 두십시오.",
309 "exchange_result_write_down_trade_id": "계속하려면 거래 ID를 복사하거나 적어 두십시오..",
310 "exchange_sync_alert_content": "지갑이 동기화 될 때까지 기다리십시오",
311 + "exchange_trade_result_confirm": "Cake 지갑에서 보내기를 누르면 ${walletName}이라는 지갑에서 아래에 표시된 주소로 ${fetchingLabel} ${from}을 보내는 것입니다. 또는 외부 지갑에서 외부 지갑 세부 정보 페이지에서 주소 / QR 코드로 보낼 수 있습니다.",
312 "expired": "만료",
313 "expires": "만료",
314 "expiresOn": "만료 날짜",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "금액의 최소값은 0.01입니다",
696 "send_estimated_fee": "예상 수수료:",
697 "send_fee": "회비:",
698 + "send_from_cake_wallet": "케이크 지갑에서 보내십시오",
699 + "send_from_external_wallet": "외부 지갑에서 보내십시오",
700 "send_name": "이름",
701 "send_new": "새로운",
702 "send_payment_id": "지불 ID (optional)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "이제 직불카드가 있습니다.",
1012 "you_pay": "당신이 지불합니다",
1013 "you_will_get": "로 변환하다",
1014 + "you_will_receive_estimated_amount": "(추정 )을 받게됩니다.",
1015 "you_will_send": "다음에서 변환",
1016 "YY": "YY",
1017 "yy": "YY"
res/values/strings_my.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "* ကျေးဇူးပြု၍ အထက်ဖော်ပြပါ သင်၏ ID ကို ကော်ပီ သို့မဟုတ် ရေးမှတ်ပါ။",
309 "exchange_result_write_down_trade_id": "ရှေ့ဆက်ရန် ကုန်သွယ်မှု ID ကို ကူးယူ သို့မဟုတ် ချရေးပါ။",
310 "exchange_sync_alert_content": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်ထားသည့်အချိန်အထိ စောင့်ပါ။",
311 + "exchange_trade_result_confirm": "Cake Wallet မှ Send ကိုနှိပ်ခြင်းအားဖြင့်သင်သည် ${walletName} ဟုခေါ်သည့်သင်၏ပိုက်ဆံအိတ်မှ ${fetchingLabel} ကို ${from} ကိုအောက်တွင်ဖော်ပြထားသောလိပ်စာသို့ပို့လိမ့်မည်။ သို့မဟုတ်ပြင်ပပိုက်ဆံအိတ်အသေးစိတ်စာမျက်နှာမှ Send People ၏ Send People ၏ Send People မှသင်၏ပြင်ပပိုက်ဆံအိတ်မှလိပ်စာသို့သင်ပို့နိုင်သည်။ \n\n ဆက်လုပ်ရန်သို့မဟုတ်ပမာဏကိုပြောင်းလဲရန်ပြန်သွားပါ။",
312 "expired": "သက်တမ်းကုန်သွားပြီ",
313 "expires": "သက်တမ်းကုန်သည်။",
314 "expiresOn": "သက်တမ်းကုန်သည်။",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "ပမာဏ၏ အနည်းဆုံးတန်ဖိုးမှာ 0.01 ဖြစ်သည်။",
696 "send_estimated_fee": "ခန့်မှန်းကြေး-",
697 "send_fee": "အခကြေးငွေ-",
698 + "send_from_cake_wallet": "ကိတ်မုန့်ပိုက်ဆံအိတ်မှပေးပို့ပါ",
699 + "send_from_external_wallet": "ပြင်ပပိုက်ဆံအိတ်မှပေးပို့ပါ",
700 "send_name": "နာမည်",
701 "send_new": "အသစ်",
702 "send_payment_id": "ငွေပေးချေမှု ID (ချန်လှပ်ထား)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "ယခု သင့်တွင် ဒက်ဘစ်ကတ်တစ်ခုရှိသည်။",
1012 "you_pay": "သင်ပေးချေပါ။",
1013 "you_will_get": "သို့ပြောင်းပါ။",
1014 + "you_will_receive_estimated_amount": "သင် ( ခန့်မှန်းခြေ ) လက်ခံရရှိလိမ့်မည်",
1015 "you_will_send": "မှပြောင်းပါ။",
1016 "yy": "YY"
1017 }
\ No newline at end of file
res/values/strings_nl.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Kopieer of noteer uw hierboven getoonde ID.",
309 "exchange_result_write_down_trade_id": "Kopieer of noteer de handels-ID om door te gaan.",
310 "exchange_sync_alert_content": "Wacht tot uw portemonnee is gesynchroniseerd",
311 + "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.",
312 "expired": "Verlopen",
313 "expires": "Verloopt",
314 "expiresOn": "Verloopt op",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "Minimale waarde van bedrag is 0,01",
696 "send_estimated_fee": "Geschatte vergoeding:",
697 "send_fee": "Vergoeding:",
698 + "send_from_cake_wallet": "Stuur vanaf cake -portemonnee",
699 + "send_from_external_wallet": "Stuur vanuit een externe portemonnee",
700 "send_name": "Naam",
701 "send_new": "Nieuw",
702 "send_payment_id": "Betaling ID (facultatief)",
@@ -1009,6 +1012,7 @@
1012 "you_now_have_debit_card": "Je hebt nu een debetkaart",
1013 "you_pay": "U betaalt",
1014 "you_will_get": "Converteren naar",
1015 + "you_will_receive_estimated_amount": "U ontvangt(geschat )",
1016 "you_will_send": "Converteren van",
1017 "yy": "JJ"
1018 }
\ No newline at end of file
res/values/strings_pl.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Skopiuj lub zanotuj identyfikator transakcji pokazany powyżej.",
309 "exchange_result_write_down_trade_id": "Skopiuj lub zanotuj identyfikator transakcji (ID), aby kontynuować.",
310 "exchange_sync_alert_content": "Poczekaj, aż portfel zostanie zsynchronizowany",
311 + "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.",
312 "expired": "Przedawniony",
313 "expires": "Wygasa",
314 "expiresOn": "Upływa w dniu",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "Minimalna wartość to 0,01",
696 "send_estimated_fee": "Szacowana opłata:",
697 "send_fee": "Opłata:",
698 + "send_from_cake_wallet": "Wyślij z portfela ciasta",
699 + "send_from_external_wallet": "Wyślij z portfela zewnętrznego",
700 "send_name": "Imię",
701 "send_new": "Nowy",
702 "send_payment_id": "Identyfikator płatności (opcjonalny)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "Masz teraz kartę debetową",
1012 "you_pay": "Płacisz",
1013 "you_will_get": "Konwertuj na",
1014 + "you_will_receive_estimated_amount": "Otrzymasz(oszacowane )",
1015 "you_will_send": "Konwertuj z",
1016 "yy": "RR"
1017 }
\ No newline at end of file
res/values/strings_pt.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Copie ou anote seu ID mostrado acima.",
309 "exchange_result_write_down_trade_id": "Copie ou anote o ID da troca para continuar.",
310 "exchange_sync_alert_content": "Por favor, espere até que sua carteira seja sincronizada",
311 + "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.",
312 "expired": "Expirada",
313 "expires": "Expira",
314 "expiresOn": "Expira em",
@@ -696,6 +697,8 @@
697 "send_error_minimum_value": "O valor mínimo da quantia é 0,01",
698 "send_estimated_fee": "Taxa estimada:",
699 "send_fee": "Taxa:",
700 + "send_from_cake_wallet": "Enviar da carteira de bolo",
701 + "send_from_external_wallet": "Enviar da carteira externa",
702 "send_name": "Nome",
703 "send_new": "Novo",
704 "send_payment_id": "ID de pagamento (opcional)",
@@ -1011,6 +1014,7 @@
1014 "you_now_have_debit_card": "Agora você tem um cartão de débito",
1015 "you_pay": "Você paga",
1016 "you_will_get": "Converter para",
1017 + "you_will_receive_estimated_amount": "Você receberá(estimado )",
1018 "you_will_send": "Converter de",
1019 "yy": "aa"
1020 }
\ No newline at end of file
res/values/strings_ru.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Пожалуйста, скопируйте или запишите ID, указанный выше.",
309 "exchange_result_write_down_trade_id": "Пожалуйста, скопируйте или запишите ID сделки.",
310 "exchange_sync_alert_content": "Подождите, пока ваш кошелек синхронизируется",
311 + "exchange_trade_result_confirm": "Нажав отправить из кошелька для торта, вы отправите ${fetchingLabel} ${from} из своего кошелька под названием ${walletName} на адрес, показанный ниже. Или вы можете отправить из своего внешнего кошелька на адрес / QR -код на странице «Отправить с внешнего кошелька». \n\n Нажмите любую кнопки, чтобы продолжить или вернуться, чтобы изменить суммы.",
312 "expired": "Истекает",
313 "expires": "Истекает",
314 "expiresOn": "Годен до",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "Mинимальная сумма 0.01",
697 "send_estimated_fee": "Предполагаемая комиссия:",
698 "send_fee": "Комиссия:",
699 + "send_from_cake_wallet": "Отправить с кошелька для торта",
700 + "send_from_external_wallet": "Отправить с внешнего кошелька",
701 "send_name": "Имя",
702 "send_new": "Новый",
703 "send_payment_id": "ID платежа (опционально)",
@@ -1009,6 +1012,7 @@
1012 "you_now_have_debit_card": "Теперь у вас есть дебетовая карта",
1013 "you_pay": "Вы платите",
1014 "you_will_get": "Конвертировать в",
1015 + "you_will_receive_estimated_amount": "Вы получите(Оценку )",
1016 "you_will_send": "Конвертировать из",
1017 "yy": "ГГ"
1018 }
\ No newline at end of file
res/values/strings_th.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*โปรดคัดลอกหรือเขียนรหัสของคุณด้านบน",
309 "exchange_result_write_down_trade_id": "โปรดคัดลอกหรือบันทึก ID ของการซื้อขายเพื่อดำเนินการต่อไป",
310 "exchange_sync_alert_content": "โปรดรอจนกว่ากระเป๋าของคุณจะถูกซิงค์",
311 + "exchange_trade_result_confirm": "โดยการกดส่งจาก Cake Wallet คุณจะส่ง ${fetchingLabel} ${from} จากกระเป๋าเงินของคุณที่เรียกว่า ${walletName} ไปยังที่อยู่ที่แสดงด้านล่าง หรือคุณสามารถส่งจากกระเป๋าเงินภายนอกของคุณไปยังที่อยู่ / รหัส QR ในหน้าส่งจากรายละเอียดกระเป๋าเงินภายนอก \n\n โปรดกดปุ่มใดปุ่มหนึ่งเพื่อดำเนินการต่อหรือกลับไปเปลี่ยนจำนวนเงิน",
312 "expired": "หมดอายุ",
313 "expires": "หมดอายุ",
314 "expiresOn": "หมดอายุวันที่",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "จำนวนขั้นต่ำของจำนวนเงินคือ 0.01",
696 "send_estimated_fee": "ค่าธรรมเนียมที่คาดการณ์:",
697 "send_fee": "ค่าธรรมเนียม:",
698 + "send_from_cake_wallet": "ส่งจากกระเป๋าเงินเค้ก",
699 + "send_from_external_wallet": "ส่งจากกระเป๋าเงินภายนอก",
700 "send_name": "ชื่อ",
701 "send_new": "ใหม่",
702 "send_payment_id": "ID การชำระเงิน (ไม่จำเป็น)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "ขณะนี้คุณมีบัตรเดบิต",
1012 "you_pay": "คุณจ่าย",
1013 "you_will_get": "แปลงเป็น",
1014 + "you_will_receive_estimated_amount": "คุณจะได้รับ(โดยประมาณ )",
1015 "you_will_send": "แปลงจาก",
1016 "yy": "ปี"
1017 }
\ No newline at end of file
res/values/strings_tl.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Mangyaring kopyahin o isulat ang inyong ID na ipinapakita sa itaas.",
309 "exchange_result_write_down_trade_id": "Mangyaring kopyahin o isulat ang trade ID upang magpatuloy.",
310 "exchange_sync_alert_content": "Mangyaring maghintay hanggang ang iyong wallet ay naka-synchronize",
311 + "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.",
312 "expired": "Nag-expire na",
313 "expires": "Mag-e-expire",
314 "expiresOn": "Mag-e-expire sa",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "Ang minimum na halaga ay 0.01",
696 "send_estimated_fee": "Tinatayang fee:",
697 "send_fee": "Fee:",
698 + "send_from_cake_wallet": "Magpadala mula sa cake wallet",
699 + "send_from_external_wallet": "Magpadala mula sa panlabas na pitaka",
700 "send_name": "Pangalan",
701 "send_new": "Bago",
702 "send_payment_id": "Payment ID (opsyonal)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "Mayroon ka na ngayong debit card",
1012 "you_pay": "Magbayad ka",
1013 "you_will_get": "I-convert sa",
1014 + "you_will_receive_estimated_amount": "Makakatanggap ka ng(tinantyang)",
1015 "you_will_send": "I-convert mula sa",
1016 "yy": "YY"
1017 }
\ No newline at end of file
res/values/strings_tr.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Lütfen yukarıda gösterilen ID'ni kopyala veya bir yere yaz.",
309 "exchange_result_write_down_trade_id": "Devam etmek için lütfen ID'yi kopyala veya bir yere yaz.",
310 "exchange_sync_alert_content": "Lütfen cüzdanın senkronize olana kadar bekle",
311 + "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.",
312 "expired": "Süresi doldu",
313 "expires": "Son kullanma tarihi",
314 "expiresOn": "Tarihinde sona eriyor",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "Minimum tutar değeri 0.01'dir",
696 "send_estimated_fee": "Tahmini komisyon:",
697 "send_fee": "Komisyon:",
698 + "send_from_cake_wallet": "Kek cüzdanından gönder",
699 + "send_from_external_wallet": "Harici cüzdandan gönder",
700 "send_name": "İsim",
701 "send_new": "Yeni",
702 "send_payment_id": "Ödeme ID'si (isteğe bağlı)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "Artık bir ön ödemeli kartın var",
1012 "you_pay": "Şu kadar ödeyeceksin: ",
1013 "you_will_get": "Biçimine dönüştür:",
1014 + "you_will_receive_estimated_amount": "(Tahmini ) alacaksınız",
1015 "you_will_send": "Biçiminden dönüştür:",
1016 "yy": "YY"
1017 }
\ No newline at end of file
res/values/strings_uk.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*Будь ласка, скопіюйте або запишіть ID, вказаний вище.",
309 "exchange_result_write_down_trade_id": "Будь ласка, скопіюйте або запишіть ID операції.",
310 "exchange_sync_alert_content": "Зачекайте, поки ваш гаманець не синхронізується",
311 + "exchange_trade_result_confirm": "Натиснувши надсилання з гаманця тортів, ви будете відправляти ${fetchingLabel} ${from} зі свого гаманця під назвою ${walletName} на адресу, показану нижче. Або ви можете надіслати зі свого зовнішнього гаманця на адресу / QR -код на сторінці \"Надіслати з зовнішнього гаманця\".",
312 "expired": "Закінчується",
313 "expires": "Закінчується",
314 "expiresOn": "Термін дії закінчується",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "Мінімальна сума 0.01",
697 "send_estimated_fee": "Ймовірна комісія:",
698 "send_fee": "Комісія:",
699 + "send_from_cake_wallet": "Надіслати з гаманця торта",
700 + "send_from_external_wallet": "Надіслати із зовнішнього гаманця",
701 "send_name": "Ім'я",
702 "send_new": "Новий",
703 "send_payment_id": "ID платежу (опційно)",
@@ -1009,6 +1012,7 @@
1012 "you_now_have_debit_card": "Тепер у вас є дебетова картка",
1013 "you_pay": "Ви платите",
1014 "you_will_get": "Конвертувати в",
1015 + "you_will_receive_estimated_amount": "Ви отримаєте(оцінюється )",
1016 "you_will_send": "Конвертувати з",
1017 "yy": "YY"
1018 }
\ No newline at end of file
res/values/strings_ur.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*براہ کرم اوپر دکھائی گئی اپنی ID کاپی کریں یا لکھیں۔",
309 "exchange_result_write_down_trade_id": "جاری رکھنے کے لیے براہ کرم تجارتی ID کاپی کریں یا لکھیں۔",
310 "exchange_sync_alert_content": "براہ کرم اس وقت تک انتظار کریں جب تک آپ کا بٹوہ مطابقت پذیر نہ ہو جائے۔",
311 + "exchange_trade_result_confirm": "کیک پرس سے بھیجیں دبانے سے ، آپ اپنے بٹوے سے ${fetchingLabel} ${from} کہتے ہیں ${walletName} نیچے دیئے گئے پتے پر بھیج رہے ہوں گے۔ یا آپ اپنے بیرونی پرس سے بیرونی والیٹ کی تفصیلات کے صفحے پر بھیجنے والے ایڈریس \n\n QR کوڈ پر بھیج سکتے ہیں۔",
312 "expired": "میعاد ختم",
313 "expires": "میعاد ختم",
314 "expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ",
@@ -696,6 +697,8 @@
697 "send_error_minimum_value": "رقم کی کم از کم قیمت 0.01 ہے۔",
698 "send_estimated_fee": "تخمینی فیس:",
699 "send_fee": "فیس:",
700 + "send_from_cake_wallet": "کیک پرس سے بھیجیں",
701 + "send_from_external_wallet": "بیرونی پرس سے بھیجیں",
702 "send_name": "نام",
703 "send_new": "نئی",
704 "send_payment_id": "ادائیگی کی شناخت (اختیاری)",
@@ -1010,6 +1013,7 @@
1013 "you_now_have_debit_card": "اب آپ کے پاس ڈیبٹ کارڈ ہے۔",
1014 "you_pay": "تم ادا کرو",
1015 "you_will_get": "میں تبدیل کریں۔",
1016 + "you_will_receive_estimated_amount": "آپ(تخمینہ ) وصول کریں گے",
1017 "you_will_send": "سے تبدیل کریں۔",
1018 "yy": "YY"
1019 }
\ No newline at end of file
res/values/strings_vi.arb
+4
@@ -307,6 +307,7 @@
307 "exchange_result_write_down_ID": "*Vui lòng sao chép hoặc ghi lại ID hiển thị ở trên.",
308 "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.",
309 "exchange_sync_alert_content": "Vui lòng chờ cho đến khi ví của bạn được đồng bộ hóa",
310 + "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.",
311 "expired": "Đã hết hạn",
312 "expires": "Hết hạn",
313 "expiresOn": "Hết hạn vào",
@@ -691,6 +692,8 @@
692 "send_error_minimum_value": "Giá trị tối thiểu của số tiền là 0.01",
693 "send_estimated_fee": "Phí ước lượng:",
694 "send_fee": "Phí:",
695 + "send_from_cake_wallet": "Gửi từ ví bánh",
696 + "send_from_external_wallet": "Gửi từ ví bên ngoài",
697 "send_name": "Tên",
698 "send_new": "Mới",
699 "send_payment_id": "ID thanh toán (tùy chọn)",
@@ -1005,6 +1008,7 @@
1008 "you_now_have_debit_card": "Bạn hiện có một thẻ ghi nợ",
1009 "you_pay": "Bạn thanh toán",
1010 "you_will_get": "Chuyển đổi thành",
1011 + "you_will_receive_estimated_amount": "Bạn sẽ nhận được(ước tính )",
1012 "you_will_send": "Chuyển đổi từ",
1013 "yy": "YY"
1014 }
\ No newline at end of file
res/values/strings_yo.arb
+4
@@ -309,6 +309,7 @@
309 "exchange_result_write_down_ID": "*Ẹ jọ̀wọ́, ṣẹ̀dà àmì ìdánimọ̀ yín tó ṣàfihàn òun lókè.",
310 "exchange_result_write_down_trade_id": "Ẹ jọ̀wọ́, kọ àmì ìdánimọ̀ pàṣípààrọ̀ sílẹ̀ kí tẹ̀síwájú.",
311 "exchange_sync_alert_content": "Ẹ jọ̀wọ́ dúró kí a ti múdọ́gba àpamọ́wọ́ yín",
312 + "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ẹ.",
313 "expired": "Kíkú",
314 "expires": "Ó parí",
315 "expiresOn": "Ipari lori",
@@ -695,6 +696,8 @@
696 "send_error_minimum_value": "Ránṣẹ́ owó kò kéré dé 0.01",
697 "send_estimated_fee": "Iye àfikún l'a fojú díwọ̀n:",
698 "send_fee": "Owó àfikún:",
699 + "send_from_cake_wallet": "Firanṣẹ lati apamọwọ akara oyinbo",
700 + "send_from_external_wallet": "Firanṣẹ lati apamọwọ ita",
701 "send_name": "Orúkọ",
702 "send_new": "Títun",
703 "send_payment_id": "Àmì ìdánimọ̀ àránṣẹ́ (ìyàn nìyí)",
@@ -1009,6 +1012,7 @@
1012 "you_now_have_debit_card": "Ẹ ni káàdì ìrajà lọ́wọ́lọ́wọ́",
1013 "you_pay": "Ẹ sàn",
1014 "you_will_get": "Ṣe pàṣípààrọ̀ sí",
1015 + "you_will_receive_estimated_amount": "Iwọ yoo gba ( excimated )",
1016 "you_will_send": "Ṣe pàṣípààrọ̀ láti",
1017 "yy": "Ọd"
1018 }
\ No newline at end of file
res/values/strings_zh.arb
+4
@@ -308,6 +308,7 @@
308 "exchange_result_write_down_ID": "*请复制或写下您上面显示的ID.",
309 "exchange_result_write_down_trade_id": "请复制或写下交易编号以继续.",
310 "exchange_sync_alert_content": "请等待,直到您的钱包同步",
311 + "exchange_trade_result_confirm": "通过按Cake Wallet的发送发送,您将从钱包中发送 ${fetchingLabel} ${from}将###发送到下面所示的地址。或者,您可以从外部钱包${walletName} QR码从外部钱包详细信息页面发送到地址/ QR码。\n\n请按任何按钮继续或返回以更改金额。",
312 "expired": "已过期",
313 "expires": "过期",
314 "expiresOn": "到期",
@@ -694,6 +695,8 @@
695 "send_error_minimum_value": "最小金额为0.01",
696 "send_estimated_fee": "预估费用:",
697 "send_fee": "手续费:",
698 + "send_from_cake_wallet": "从蛋糕钱包发送",
699 + "send_from_external_wallet": "从外部钱包发送",
700 "send_name": "名称",
701 "send_new": "新建",
702 "send_payment_id": "付款编号 (可选的)",
@@ -1008,6 +1011,7 @@
1011 "you_now_have_debit_card": "你现在有一张借记卡",
1012 "you_pay": "你付钱",
1013 "you_will_get": "转换到",
1014 + "you_will_receive_estimated_amount": "您将收到(估计的)",
1015 "you_will_send": "转换自",
1016 "yy": "YY"
1017 }
\ No newline at end of file