Transaction details (New UI) (#3070)

* merge * strings * layout fixes * add modal for tx details * add copy option * fix bottomWidget * fix bottomWidget * remove import * add rbf * add observer for rbf * post-review fixes * add mweb explorer * proper formatting for source address

malik1004x committed Mar 24, 2026 at 01:49 UTC a864655e2dd5e8d61ff0ef591a79271f8c4453c9
43 files changed +761 -809
cw_core/lib/wallet_type.dart
+15
@@ -25,6 +25,21 @@ const walletTypes = [
25 WalletType.bsc,
26 ];
27
28 +const electrumWalletTypes = [
29 + WalletType.bitcoin,
30 + WalletType.litecoin,
31 + WalletType.bitcoinCash,
32 + WalletType.dogecoin
33 +];
34 +
35 +const evmWalletTypes = [
36 + WalletType.ethereum,
37 + WalletType.polygon,
38 + WalletType.base,
39 + WalletType.arbitrum,
40 + WalletType.bsc
41 +];
42 +
43 @HiveType(typeId: WALLET_TYPE_TYPE_ID)
44 enum WalletType {
45 @HiveField(0)
lib/di.dart
+6
@@ -60,6 +60,7 @@ import 'package:cake_wallet/new-ui/pages/lightning_username_page.dart';
60 import 'package:cake_wallet/new-ui/pages/receive_page.dart';
61 import 'package:cake_wallet/new-ui/viewmodels/lightning_username/lightning_username_bloc.dart';
62 import 'package:cake_wallet/new-ui/widgets/addresses_page/address_label_input.dart';
63 +import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart';
64 import 'package:cake_wallet/new-ui/widgets/receive_page/receive_label_modal.dart';
65 import 'package:cake_wallet/new-ui/pages/swap_page.dart';
66 import 'package:cake_wallet/order/order.dart';
@@ -1419,6 +1420,11 @@ Future<void> setup({
1420 }
1421 );
1422
1423 + getIt.registerFactoryParam<TransactionDetailsModal, TransactionInfo, void>(
1424 + (transactionInfo, _) => TransactionDetailsModal(transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
1425 + param1: [transactionInfo, false]))
1426 + );
1427 +
1428 getIt.registerFactoryParam<TransactionDetailsPage, TransactionInfo, void>(
1429 (TransactionInfo transactionInfo, _) => TransactionDetailsPage(
1430 transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
lib/entities/new_ui_entities/list_item/list_item_regular_row.dart
+4
@@ -11,6 +11,8 @@ class ListItemRegularRow extends ListItem {
11 this.onTap,
12 this.trailingIconPath,
13 this.showArrow = true,
14 + this.bottomWidget,
15 + this.trailingWidget,
16 this.truncateTrailingText = false,
17 this.foregroundColor,
18 this.trailingIconSize
@@ -22,6 +24,8 @@ class ListItemRegularRow extends ListItem {
24 final String? trailingIconPath;
25 final VoidCallback? onTap;
26 final bool showArrow;
27 + final Widget? bottomWidget;
28 + final Widget? trailingWidget;
29 final bool truncateTrailingText;
30 final Color? foregroundColor;
31 final double? trailingIconSize;
lib/new-ui/widgets/coins_page/assets_history/history_section.dart
+6 -3
@@ -1,9 +1,11 @@
1 +import 'package:cake_wallet/di.dart';
2 import 'package:cake_wallet/generated/i18n.dart';
3 import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/anonpay_history_tile.dart';
4 import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/history_order_tile.dart';
5 import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/history_tile.dart';
6 import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/history_trade_tile.dart';
7 import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/payjoin_history_tile.dart';
8 +import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart';
9 import 'package:cake_wallet/routes.dart';
10 import 'package:cake_wallet/utils/date_formatter.dart';
11 import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
@@ -15,7 +17,6 @@ import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
17 import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
18 import 'package:cw_core/crypto_currency.dart';
19 import 'package:cw_core/sync_status.dart';
18 -import 'package:cw_core/utils/print_verbose.dart';
20 import 'package:flutter/material.dart';
21 import 'package:flutter_mobx/flutter_mobx.dart';
22 import 'package:intl/intl.dart';
@@ -70,8 +71,10 @@ class HistorySection extends StatelessWidget {
71 asset = CryptoCurrency.btcln;
72
73 return GestureDetector(
73 - onTap: () => Navigator.of(context)
74 - .pushNamed(Routes.transactionDetails, arguments: transaction),
74 + onTap: () {
75 + final page = getIt.get<TransactionDetailsModal>(param1: transaction);
76 + showModalBottomSheet(isScrollControlled:true,context: context, builder: (context) => page);
77 + },
78 child: HistoryTile(
79 title: item.formattedTitle + transactionType,
80 date: DateFormat('HH:mm').format(transaction.date),
lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart new
+226
@@ -0,0 +1,226 @@
1 +import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item.dart';
2 +import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
3 +import 'package:cake_wallet/generated/i18n.dart';
4 +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
5 +import 'package:cake_wallet/routes.dart';
6 +import 'package:cake_wallet/src/screens/transaction_details/confirmations_list_item.dart';
7 +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
8 +import 'package:cake_wallet/src/screens/transaction_details/address_list_item.dart';
9 +import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
10 +import 'package:cake_wallet/utils/address_formatter.dart';
11 +import 'package:cake_wallet/view_model/transaction_details_view_model.dart';
12 +import 'package:flutter/material.dart';
13 +import 'package:flutter/services.dart';
14 +import 'package:flutter_mobx/flutter_mobx.dart';
15 +
16 +class TransactionDetailsModal extends StatefulWidget {
17 + const TransactionDetailsModal({super.key, required this.transactionDetailsViewModel});
18 +
19 + final TransactionDetailsViewModel transactionDetailsViewModel;
20 +
21 + @override
22 + State<TransactionDetailsModal> createState() => _TransactionDetailsModalState();
23 +}
24 +
25 +class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
26 + final TextEditingController noteController = TextEditingController();
27 + final FocusNode noteFocusNode = FocusNode();
28 +
29 + @override
30 + void initState() {
31 + super.initState();
32 + noteController.text = widget.transactionDetailsViewModel.note;
33 +
34 + noteFocusNode.addListener(() {
35 + if (!noteFocusNode.hasFocus) {
36 + widget.transactionDetailsViewModel.updateNote(noteController.text);
37 + }
38 + });
39 + }
40 +
41 + @override
42 + Widget build(BuildContext context) {
43 + return DraggableScrollableSheet(
44 + expand: false,
45 + initialChildSize: 0.6,
46 + minChildSize: 0.25,
47 + maxChildSize: 0.9,
48 + snap: true,
49 + snapSizes: const [0.6, 0.9],
50 + builder: (context, controller) => SafeArea(
51 + bottom: false,
52 + child: Padding(
53 + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
54 + child: GestureDetector(
55 + onTap: FocusScope.of(context).unfocus,
56 + child: Container(
57 + decoration: BoxDecoration(
58 + color: Theme.of(context).colorScheme.surface,
59 + borderRadius: BorderRadius.vertical(top: Radius.circular(25))),
60 + child: Column(
61 + children: [
62 + ModalTopBar(
63 + title: S.of(context).transaction,
64 + leadingIcon: Icon(Icons.close),
65 + onLeadingPressed: Navigator.of(context).pop,
66 + ),
67 + Expanded(
68 + child: SingleChildScrollView(
69 + controller: controller,
70 + child: Column(
71 + children: [
72 + Image.asset(
73 + widget.transactionDetailsViewModel.transactionAsset.iconPath ??
74 + "",
75 + width: 64,
76 + height: 64),
77 + SizedBox(height: 10),
78 + Text(
79 + widget.transactionDetailsViewModel.formattedTitle +
80 + widget.transactionDetailsViewModel.formattedStatus,
81 + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
82 + ),
83 + Text(
84 + widget.transactionDetailsViewModel.transactionInfo
85 + .amountFormatted(),
86 + style: TextStyle(fontSize: 28),
87 + ),
88 + Padding(
89 + padding: const EdgeInsets.all(16.0),
90 + child: Column(
91 + spacing: 12,
92 + children: [
93 + NewListSections(sections: {
94 + "": widget.transactionDetailsViewModel.items
95 + .map((item) {
96 + if (item.value.isEmpty) return null;
97 +
98 + final shouldBuildBottomWidget =
99 + item.value.length > 25;
100 +
101 + return ListItemRegularRow(
102 + onTap: () {
103 + Clipboard.setData(
104 + ClipboardData(text: item.value));
105 + },
106 + showArrow: false,
107 + keyValue:
108 + ((item.key as ValueKey?)?.value as String?) ??
109 + item.title,
110 + label: item.title,
111 + trailingWidget: shouldBuildBottomWidget
112 + ? null
113 + : _buildTrailingWIdget(item),
114 + bottomWidget: shouldBuildBottomWidget
115 + ? _buildBottomWidget(item)
116 + : null);
117 + })
118 + .whereType<ListItem>()
119 + .toList(),
120 + }),
121 + Container(
122 + decoration: BoxDecoration(
123 + borderRadius: BorderRadius.circular(20),
124 + color: Theme.of(context).colorScheme.surfaceContainer),
125 + child: Padding(
126 + padding: const EdgeInsets.all(12.0),
127 + child: Column(
128 + spacing: 8,
129 + crossAxisAlignment: CrossAxisAlignment.start,
130 + children: [
131 + Text(S.of(context).note),
132 + TextField(
133 + focusNode: noteFocusNode,
134 + controller: noteController,
135 + decoration: InputDecoration(
136 + hintText: S.of(context).add_a_note,
137 + border: InputBorder.none,
138 + focusedBorder: InputBorder.none,
139 + enabledBorder: InputBorder.none,
140 + contentPadding: EdgeInsets.zero,
141 + isDense: true),
142 + )
143 + ],
144 + ),
145 + ),
146 + ),
147 + Observer(
148 + builder: (_) => NewListSections(sections: {
149 + "view tx": [
150 + ListItemRegularRow(
151 + keyValue: "view tx on",
152 + label: widget.transactionDetailsViewModel
153 + .explorerDescription,
154 + onTap: widget
155 + .transactionDetailsViewModel.launchExplorer,
156 + foregroundColor:
157 + Theme.of(context).colorScheme.primary,
158 + trailingIconPath: "assets/new-ui/link_arrow.svg",
159 + trailingIconSize: 8)
160 + ],
161 + if (widget.transactionDetailsViewModel.canReplaceByFee)
162 + "rbf": [
163 + ListItemRegularRow(
164 + keyValue: "replace by fee",
165 + label: S.of(context).bump_fee,
166 + onTap: () {
167 + Navigator.of(context)
168 + .pushNamed(Routes.bumpFeePage, arguments: [
169 + widget.transactionDetailsViewModel
170 + .transactionInfo,
171 + widget.transactionDetailsViewModel
172 + .rawTransaction
173 + ]);
174 + })
175 + ]
176 + }),
177 + )
178 + ],
179 + ),
180 + ),
181 + SizedBox(height: MediaQuery.of(context).viewPadding.bottom)
182 + ],
183 + ),
184 + ),
185 + )
186 + ],
187 + ),
188 + ),
189 + ),
190 + ),
191 + ));
192 + }
193 +
194 + Widget _buildTrailingWIdget(TransactionDetailsListItem item) {
195 + return switch (item.runtimeType) {
196 + ConfirmationsListItem => Row(
197 + children: [
198 + Text((item as ConfirmationsListItem).current.toString(),
199 + style: TextStyle(color: Theme.of(context).colorScheme.primary)),
200 + if (item.needed > 0)
201 + Text("/${item.needed}",
202 + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant))
203 + ],
204 + ),
205 + _ => Text(
206 + item.value,
207 + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
208 + )
209 + };
210 + }
211 +
212 + Widget _buildBottomWidget(TransactionDetailsListItem item) {
213 + return switch (item.runtimeType) {
214 + AddressListItem => AddressFormatter.buildSegmentedAddress(
215 + address: item.value,
216 + evenTextStyle: TextStyle(
217 + fontSize: 12,
218 + fontFamily: "IBM Plex Mono",
219 + color: Theme.of(context).colorScheme.onSurface)),
220 + _ => Text(
221 + item.value,
222 + style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),
223 + )
224 + };
225 + }
226 +}
lib/src/screens/transaction_details/address_list_item.dart new
+5
@@ -0,0 +1,5 @@
1 +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
2 +
3 +class AddressListItem extends TransactionDetailsListItem {
4 + AddressListItem({required super.title, required super.value, super.key});
5 +}
\ No newline at end of file
lib/src/screens/transaction_details/confirmations_list_item.dart new
+12
@@ -0,0 +1,12 @@
1 +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
2 +
3 +class ConfirmationsListItem extends TransactionDetailsListItem {
4 + late final int current;
5 + late final int needed;
6 +
7 + ConfirmationsListItem({required super.title, required super.value, super.key}) {
8 + final parts = value.split("/");
9 + current = int.tryParse(parts.first)??0;
10 + needed = int.tryParse(parts.last)??0;
11 + }
12 +}
\ No newline at end of file
lib/src/widgets/new_list_row/list_Item_style_wrapper.dart
+3 -3
@@ -7,14 +7,14 @@ class ListItemStyleWrapper extends StatelessWidget {
7 required this.isLastInSection,
8 required this.builder,
9 this.onTap,
10 - this.height = 50,
10 this.iconPath,
11 + this.height,
12 });
13
14 final String? iconPath;
15 final bool isFirstInSection;
16 final bool isLastInSection;
17 - final double height;
17 + final double? height;
18 final VoidCallback? onTap;
19 final Widget Function(BuildContext context, TextStyle textStyle, TextStyle labelStyle) builder;
20
@@ -59,7 +59,7 @@ class ListItemStyleWrapper extends StatelessWidget {
59 child: InkWell(
60 onTap: onTap,
61 child: Padding(
62 - padding: const EdgeInsets.symmetric(horizontal: 12),
62 + padding: EdgeInsets.symmetric(horizontal: 12, vertical: height == null ? 12 : 0),
63 child: builder(context, textStyle, labelStyle))))),
64 if(iconPath != null && isLastInSection == false) Container(
65 color: theme.colorScheme.surfaceContainer,
lib/src/widgets/new_list_row/list_item_regular_row_widget.dart
+68 -54
@@ -19,6 +19,8 @@ class ListItemRegularRowWidget extends StatelessWidget {
19 this.truncateTrailingText = false,
20 this.foregroundColor,
21 this.trailingIconSize,
22 + this.bottomWidget,
23 + this.trailingWidget
24 });
25
26 final String keyValue;
@@ -31,6 +33,8 @@ class ListItemRegularRowWidget extends StatelessWidget {
33 final bool isLastInSection;
34 final bool showArrow;
35 final String? trailingIconPath;
36 + final Widget? bottomWidget;
37 + final Widget? trailingWidget;
38 final bool truncateTrailingText;
39 final Color? foregroundColor;
40 final double? trailingIconSize;
@@ -38,74 +42,84 @@ class ListItemRegularRowWidget extends StatelessWidget {
42 @override
43 Widget build(BuildContext context) {
44 final theme = Theme.of(context);
41 - final trailingTextToShow = truncateTrailingText && trailingText != null && trailingText!.length > 20
42 - ? "${trailingText!.substring(0, 17)}..."
43 - : trailingText;
45 + final trailingTextToShow =
46 + truncateTrailingText && trailingText != null && trailingText!.length > 20
47 + ? "${trailingText!.substring(0, 17)}..."
48 + : trailingText;
49
50 return ListItemStyleWrapper(
51 onTap: onTap,
52 iconPath: iconPath,
53 isFirstInSection: isFirstInSection,
54 isLastInSection: isLastInSection,
50 - height: subtitle != null ? 64 : 50,
55 builder: (context, textStyle, labelStyle) {
52 - return Row(
53 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
56 + return Column(
57 + crossAxisAlignment: CrossAxisAlignment.start,
58 + mainAxisAlignment: MainAxisAlignment.center,
59 children: [
55 - Expanded(
56 - child: Row(
57 - children: [
58 - if(iconPath != null)
59 - Padding(
60 - padding: const EdgeInsets.only(right: 12.0),
61 - child: CakeImageWidget(imageUrl: iconPath!, width: 24,height: 24,)
62 - ),
63 - Flexible(
64 - child: Column(
65 - mainAxisAlignment: MainAxisAlignment.center,
66 - crossAxisAlignment: CrossAxisAlignment.start,
67 - children: [
68 - Text(label, style: foregroundColor == null ? textStyle : textStyle.copyWith(color: foregroundColor)),
69 - if (subtitle != null)
70 - Text(
71 - subtitle!,
72 - style: labelStyle.copyWith(fontSize: 12),
73 - ),
74 - ],
75 - ),
76 - ),
77 - ],
78 - ),
79 - ),
80 -
60 Row(
61 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
62 children: [
83 - if (trailingTextToShow != null)
84 - Padding(
85 - padding: const EdgeInsets.only(right: 8.0),
86 - child: Text(
87 - trailingTextToShow,
88 - style: labelStyle,
89 - ),
63 + Expanded(
64 + child: Row(
65 + children: [
66 + if (iconPath != null)
67 + Padding(
68 + padding: const EdgeInsets.only(right: 12.0),
69 + child: CakeImageWidget(imageUrl: iconPath!, width: 24,height: 24,)
70 + ),
71 + Flexible(
72 + child: Column(
73 + mainAxisAlignment: MainAxisAlignment.center,
74 + crossAxisAlignment: CrossAxisAlignment.start,
75 + children: [
76 + Text(label,
77 + style: foregroundColor == null
78 + ? textStyle
79 + : textStyle.copyWith(color: foregroundColor)),
80 + if (subtitle != null)
81 + Text(
82 + subtitle!,
83 + style: labelStyle.copyWith(fontSize: 12),
84 + ),
85 + ],
86 + ),
87 + ),
88 + ],
89 ),
91 - if(trailingIconPath != null)
92 - CakeImageWidget(imageUrl:
93 - trailingIconPath!,
94 - height: trailingIconSize ?? 18,
95 - width:trailingIconSize ?? 18,
96 - colorFilter: ColorFilter.mode(foregroundColor ?? Theme.of(context).colorScheme.onSurfaceVariant,BlendMode.srcIn),
97 - )
98 - else if(showArrow)
99 - CakeImageWidget(imageUrl:
100 - "assets/new-ui/arrow_forward.svg",
101 - height: 14,
102 - color: theme.colorScheme.onSurfaceVariant
103 - )
90 + ),
91 + Row(
92 + children: [
93 + if (trailingTextToShow != null)
94 + Padding(
95 + padding: const EdgeInsets.only(right: 8.0),
96 + child: Text(
97 + trailingTextToShow,
98 + style: labelStyle,
99 + ),
100 + ),
101 + if (trailingWidget != null)
102 + trailingWidget!
103 + else if (trailingIconPath != null)
104 + CakeImageWidget(imageUrl:
105 + trailingIconPath!,
106 + height: trailingIconSize ?? 18,
107 + width:trailingIconSize ?? 18,
108 + colorFilter: ColorFilter.mode(foregroundColor ?? Theme.of(context).colorScheme.onSurfaceVariant,BlendMode.srcIn),
109 + )
110 + else if (showArrow)
111 + CakeImageWidget(imageUrl:
112 + "assets/new-ui/arrow_forward.svg",
113 + height: 14,
114 + color: theme.colorScheme.onSurfaceVariant
115 + )
116 + ],
117 + ),
118 ],
119 ),
120 + if (bottomWidget != null) bottomWidget!
121 ],
122 );
108 - }
109 - );
123 + });
124 }
125 }
lib/src/widgets/new_list_row/list_item_text_field_widget.dart
+1
@@ -36,6 +36,7 @@ class _ListItemTextFieldWidgetState extends State<ListItemTextFieldWidget> {
36 return ListItemStyleWrapper(
37 isFirstInSection: widget.isFirstInSection,
38 isLastInSection: widget.isLastInSection,
39 + height:50,
40 builder: (context, textStyle, labelStyle) {
41 return Row(
42 children: [
lib/src/widgets/new_list_row/new_list_section.dart
+2
@@ -104,6 +104,8 @@ class NewListSections extends StatelessWidget {
104 truncateTrailingText: item.truncateTrailingText,
105 foregroundColor: item.foregroundColor,
106 trailingIconSize: item.trailingIconSize,
107 + trailingWidget: item.trailingWidget,
108 + bottomWidget: item.bottomWidget,
109 );
110 }
111
lib/view_model/transaction_details_view_model.dart
+319 -745
@@ -1,8 +1,13 @@
1 +import 'package:cake_wallet/reactions/wallet_connect.dart';
2 +import 'package:cake_wallet/solana/solana.dart';
3 +import 'package:cake_wallet/src/screens/transaction_details/address_list_item.dart';
4 +import 'package:cake_wallet/src/screens/transaction_details/confirmations_list_item.dart';
5 import 'package:cake_wallet/store/app_store.dart';
6 import 'package:cake_wallet/core/address_validator.dart';
7 import 'package:cake_wallet/tron/tron.dart';
4 -import 'package:cake_wallet/wownero/wownero.dart';
8 +import 'package:cake_wallet/zano/zano.dart';
9 import 'package:cw_core/crypto_currency.dart';
10 +import 'package:cw_core/currency_for_wallet_type.dart';
11 import 'package:cw_core/utils/print_verbose.dart';
12 import 'package:cw_core/wallet_base.dart';
13 import 'package:cw_core/transaction_info.dart';
@@ -13,10 +18,8 @@ import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
18 import 'package:cake_wallet/entities/transaction_description.dart';
19 import 'package:cake_wallet/generated/i18n.dart';
20 import 'package:cake_wallet/monero/monero.dart';
16 -import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart';
21 import 'package:cake_wallet/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart';
22 import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
19 -import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart';
23 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
24 import 'package:cake_wallet/src/screens/transaction_details/transaction_expandable_list_item.dart';
25 import 'package:cake_wallet/utils/date_formatter.dart';
@@ -26,12 +29,181 @@ import 'package:cw_core/transaction_direction.dart';
29 import 'package:cw_core/transaction_priority.dart';
30 import 'package:flutter/foundation.dart';
31 import 'package:hive/hive.dart';
29 -import 'package:intl/src/intl/date_format.dart';
32 import 'package:mobx/mobx.dart';
33 import 'package:url_launcher/url_launcher.dart';
34
35 part 'transaction_details_view_model.g.dart';
36
37 +bool _trueFunc(_) => true;
38 +
39 +bool isLightning(TransactionInfo tx) {
40 + printV(tx.additionalInfo);
41 + return (tx.additionalInfo["isLightning"] as bool?) ?? false;
42 +}
43 +
44 +class TxDetailRowDefinition {
45 + final String keyString;
46 + final String title;
47 + final String Function(TransactionDetailsViewModelBase) valueGetter;
48 + final bool Function(TransactionDetailsViewModelBase) applicable;
49 + final dynamic Function({
50 + required String title,
51 + required String value,
52 + required Key key,
53 + }) listItemBuilder;
54 +
55 + TxDetailRowDefinition(
56 + {required this.keyString,
57 + required this.title,
58 + required this.valueGetter,
59 + this.applicable = _trueFunc,
60 + this.listItemBuilder = StandartListItem.new});
61 +
62 + static final List<TxDetailRowDefinition> defs = [
63 + TxDetailRowDefinition(
64 + keyString: "standard_list_item_transaction_details_date_key",
65 + title: S.current.transaction_details_date,
66 + valueGetter: (vm) => DateFormatter.withCurrentLocal().format(vm.transactionInfo.date)),
67 +
68 +
69 + TxDetailRowDefinition(
70 + keyString: "standard_list_item_transaction_details_height_key",
71 + title: S.current.transaction_details_height,
72 + valueGetter: (vm) => vm.transactionInfo.height.toString(),
73 + applicable: (vm) => !([WalletType.solana, WalletType.tron].contains(vm.wallet.type) &&
74 + !isLightning(vm.transactionInfo))),
75 +
76 +
77 + TxDetailRowDefinition(
78 + keyString: "standard_list_item_transaction_details_fee_key",
79 + title: S.current.transaction_details_fee,
80 + valueGetter: (vm) => vm.transactionInfo.feeFormatted()!,
81 + applicable: (vm) =>
82 + vm.wallet.type != WalletType.nano &&
83 + (vm.transactionInfo.feeFormatted() ?? "").isNotEmpty),
84 +
85 +
86 + TxDetailRowDefinition(
87 + keyString: "standard_list_item_transaction_confirmations_key",
88 + title: S.current.confirmations,
89 + valueGetter: (vm) => "${vm.transactionInfo.confirmations}/${vm.neededConfirmations}",
90 + applicable: (vm) =>
91 + [...electrumWalletTypes, ...evmWalletTypes, WalletType.zcash, WalletType.monero]
92 + .contains(vm.wallet.type) &&
93 + !isLightning(vm.transactionInfo),
94 + listItemBuilder: ConfirmationsListItem.new),
95 +
96 +
97 + TxDetailRowDefinition(
98 + keyString: "standard_list_item_transaction_details_recipient_address_key",
99 + title: S.current.transaction_details_recipient_address,
100 + valueGetter: (vm) {
101 + vm.isRecipientAddressShown = true;
102 + switch (vm.wallet.type) {
103 + case WalletType.monero:
104 + return monero!.getTransactionAddress(
105 + vm.wallet,
106 + vm.transactionInfo.additionalInfo['accountIndex'] as int,
107 + vm.transactionInfo.additionalInfo['addressIndex'] as int);
108 + case WalletType.bitcoin:
109 + return (bitcoin!.getTransactionAddresses(vm.wallet, vm.transactionInfo) ?? [])
110 + .firstOrNull ??
111 + "";
112 + case WalletType.tron:
113 + return tron!.getTronBase58Address(vm.transactionInfo.to!, vm.wallet);
114 + default:
115 + return vm.transactionInfo.to!;
116 + }
117 + },
118 + applicable: (vm) =>
119 + vm.showRecipientAddress &&
120 + (vm.transactionInfo.to != null ||
121 + [WalletType.monero, WalletType.tron].contains(vm.wallet.type) ||
122 + vm.wallet.type == WalletType.bitcoin &&
123 + vm.transactionInfo.direction == TransactionDirection.incoming),
124 + listItemBuilder: AddressListItem.new),
125 +
126 +
127 + TxDetailRowDefinition(
128 + keyString: "standard_list_item_transaction_details_source_address_key",
129 + title: S.current.transaction_details_source_address,
130 + valueGetter: (vm) {
131 + switch (vm.wallet.type) {
132 + case WalletType.tron:
133 + return tron!.getTronBase58Address(vm.transactionInfo.from!, vm.wallet);
134 + default:
135 + return vm.transactionInfo.from!;
136 + }
137 + },
138 + applicable: (vm) => vm.transactionInfo.from != null,
139 + listItemBuilder: AddressListItem.new),
140 +
141 + TxDetailRowDefinition(
142 + keyString: "standard_list_item_address_label_key",
143 + title: S.current.address_label,
144 + valueGetter: (vm) => monero!.getSubaddressLabel(
145 + vm.wallet,
146 + vm.transactionInfo.additionalInfo['accountIndex'] as int,
147 + vm.transactionInfo.additionalInfo['addressIndex'] as int),
148 + applicable: (vm) => vm.wallet.type == WalletType.monero),
149 +
150 +
151 + TxDetailRowDefinition(
152 + keyString: "standard_list_item_transaction_key",
153 + title: S.current.transaction_key,
154 + valueGetter: (vm) {
155 + final descriptionKey =
156 + '${vm.transactionInfo.txHash}_${vm.wallet.walletAddresses.primaryAddress}';
157 +
158 + final description = vm.transactionDescriptionBox.values.firstWhere(
159 + (val) => val.id == descriptionKey || val.id == vm.transactionInfo.txHash,
160 + orElse: () => TransactionDescription(id: descriptionKey));
161 + return vm.transactionInfo.additionalInfo['key'] as String? ??
162 + description.transactionKey ??
163 + "";
164 + },
165 + applicable: (vm) => vm.wallet.type == WalletType.monero),
166 +
167 +
168 + TxDetailRowDefinition(
169 + keyString: "standard_list_item_transaction_confirmed_key",
170 + title: S.current.confirmed_tx,
171 + valueGetter: (vm) => (vm.transactionInfo.confirmations > 0).toString(),
172 + applicable: (vm) => vm.wallet.type == WalletType.nano),
173 +
174 +
175 + TxDetailRowDefinition(
176 + keyString: "standard_list_item_transaction_details_memo_key",
177 + title: S.current.memo,
178 + valueGetter: (vm) => vm.transactionInfo.additionalInfo['memo'] as String,
179 + applicable: (vm) =>
180 + vm.wallet.type == WalletType.zcash &&
181 + vm.transactionInfo.additionalInfo["memo"] != null),
182 +
183 +
184 + TxDetailRowDefinition(
185 + keyString: "standard_list_item_transaction_details_asset_id_key",
186 + title: "Asset ID",
187 + valueGetter: (vm) =>
188 + vm.transactionInfo.additionalInfo["assetId"] as String? ?? "Unknown asset id",
189 + applicable: (vm) => vm.wallet.type == WalletType.zano),
190 +
191 +
192 + TxDetailRowDefinition(
193 + keyString: "standard_list_item_transaction_details_comment_key",
194 + title: S.current.transaction_details_title,
195 + valueGetter: (vm) => vm.transactionInfo.additionalInfo['comment'] as String? ?? "",
196 + applicable: (vm) => vm.wallet.type == WalletType.zano),
197 +
198 +
199 + TxDetailRowDefinition(
200 + keyString: "standard_list_item_transaction_details_id_key",
201 + title: S.current.transaction_details_transaction_id,
202 + valueGetter: (vm) => vm.transactionInfo.txHash,
203 + ),
204 + ];
205 +}
206 +
207 class TransactionDetailsViewModel = TransactionDetailsViewModelBase
208 with _$TransactionDetailsViewModel;
209
@@ -49,61 +221,19 @@ abstract class TransactionDetailsViewModelBase with Store {
221 isRecipientAddressShown = false,
222 _appStore = appStore,
223 showRecipientAddress = appStore.settingsStore.shouldSaveRecipientAddress {
52 - final dateFormat = DateFormatter.withCurrentLocal();
224 final tx = transactionInfo;
225
55 - // TODO: can be cleaned further
56 - switch (wallet.type) {
57 - case WalletType.monero:
58 - _addMoneroListItems(tx, dateFormat);
59 - break;
60 - case WalletType.bitcoin:
61 - _addElectrumListItems(tx, dateFormat, CryptoCurrency.btc);
62 - if (!canReplaceByFee) _checkForRBF(tx);
63 - break;
64 - case WalletType.litecoin:
65 - _addLitecoinListItems(tx, dateFormat);
66 - case WalletType.bitcoinCash:
67 - _addElectrumListItems(tx, dateFormat, CryptoCurrency.bch);
68 - break;
69 - case WalletType.haven:
70 - _addHavenListItems(tx, dateFormat);
71 - break;
72 - case WalletType.ethereum:
73 - case WalletType.polygon:
74 - case WalletType.base:
75 - case WalletType.arbitrum:
76 - case WalletType.bsc:
77 - _addEVMListItems(tx, dateFormat);
78 - break;
79 - case WalletType.nano:
80 - _addNanoListItems(tx, dateFormat);
81 - break;
82 - case WalletType.solana:
83 - _addSolanaListItems(tx, dateFormat);
84 - break;
85 - case WalletType.tron:
86 - _addTronListItems(tx, dateFormat);
87 - break;
88 - case WalletType.wownero:
89 - _addWowneroListItems(tx, dateFormat);
90 - break;
91 - case WalletType.zano:
92 - _addZanoListItems(tx, dateFormat);
93 - break;
94 - case WalletType.decred:
95 - _addDecredListItems(tx, dateFormat);
96 - break;
97 - case WalletType.dogecoin:
98 - _addDogecoinListItems(tx, dateFormat);
99 - break;
100 - case WalletType.zcash:
101 - _addZcashListItems(tx, dateFormat);
102 - case WalletType.none:
103 - case WalletType.banano:
104 - break;
226 + for (final def in TxDetailRowDefinition.defs) {
227 + if (def.applicable(this)) {
228 + items.add(def.listItemBuilder(
229 + title: def.title,
230 + value: def.valueGetter(this),
231 + key: ValueKey(def.keyString)) as TransactionDetailsListItem);
232 + }
233 }
234
235 + _checkForRBF(tx);
236 +
237 final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
238 final description = transactionDescriptionBox.values.firstWhere(
239 (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
@@ -114,7 +244,7 @@ abstract class TransactionDetailsViewModelBase with Store {
244
245 if (recipientAddress?.isNotEmpty ?? false) {
246 items.add(
117 - StandartListItem(
247 + AddressListItem(
248 title: S.current.transaction_details_recipient_address,
249 value: recipientAddress!,
250 key: ValueKey('standard_list_item_${recipientAddress}_key'),
@@ -122,44 +252,28 @@ abstract class TransactionDetailsViewModelBase with Store {
252 );
253 }
254 }
255 + }
256
126 - final type = wallet.type;
127 -
128 - final isLightning = tx.additionalInfo["isLightning"] as bool? ?? false;
129 -
130 - if (!isLightning) {
131 - items.add(
132 - BlockExplorerListItem(
133 - title: S.current.view_in_block_explorer,
134 - value: _explorerDescription(type, wallet.chainId),
135 - onTap: () async {
136 - try {
137 - final uri = Uri.parse(_explorerUrl(type, tx.txHash, wallet.chainId));
138 - if (await canLaunchUrl(uri)) await launchUrl(
139 - uri, mode: LaunchMode.externalApplication);
140 - } catch (e) {}
141 - },
142 - key: ValueKey('block_explorer_list_item_${type.name}_wallet_type_key'),
143 - ),
144 - );
257 + void updateNote(String note) {
258 + final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
259 + final description = transactionDescriptionBox.values.firstWhere(
260 + (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
261 + orElse: () => TransactionDescription(id: descriptionKey));
262 +
263 + description.transactionNote = note;
264 +
265 + if (description.isInBox) {
266 + description.save();
267 + } else {
268 + transactionDescriptionBox.add(description);
269 }
270 + }
271
147 - items.add(
148 - TextFieldListItem(
149 - title: S.current.note_tap_to_change,
150 - value: description.note,
151 - onSubmitted: (value) {
152 - description.transactionNote = value;
153 -
154 - if (description.isInBox) {
155 - description.save();
156 - } else {
157 - transactionDescriptionBox.add(description);
158 - }
159 - },
160 - key: ValueKey('textfield_list_item_note_entry_key'),
161 - ),
162 - );
272 + String get note {
273 + final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
274 + final description = transactionDescriptionBox.values.firstWhereOrNull(
275 + (val) => val.id == descriptionKey || val.id == transactionInfo.txHash);
276 + return description?.transactionNote??"";
277 }
278
279 final TransactionInfo transactionInfo;
@@ -176,22 +290,128 @@ abstract class TransactionDetailsViewModelBase with Store {
290 String? rawTransaction;
291 TransactionPriority? transactionPriority;
292
293 + CryptoCurrency get transactionAsset {
294 + if (isEVMCompatibleChain(wallet.type)) {
295 + return evm!.assetOfTransaction(wallet, transactionInfo);
296 + }
297 +
298 + return switch (wallet.type) {
299 + WalletType.solana => solana!.assetOfTransaction(wallet, transactionInfo),
300 + WalletType.tron => tron!.assetOfTransaction(wallet, transactionInfo),
301 + WalletType.zano => zano!.assetOfTransaction(wallet, transactionInfo) ?? CryptoCurrency.zano,
302 + _ => walletTypeToCryptoCurrency(wallet.type)
303 + };
304 + }
305 +
306 +
307 + // TODO integrate these getters with the TransactionInfo object
308 + String get formattedPendingStatus {
309 + switch (wallet.type) {
310 + case WalletType.monero:
311 + case WalletType.haven:
312 + case WalletType.zano:
313 + if (transactionInfo.confirmations >= 0 && transactionInfo.confirmations < 10) {
314 + return ' (${transactionInfo.confirmations}/10)';
315 + }
316 + break;
317 + case WalletType.wownero:
318 + if (transactionInfo.confirmations >= 0 && transactionInfo.confirmations < 3) {
319 + return ' (${transactionInfo.confirmations}/3)';
320 + }
321 + break;
322 + case WalletType.litecoin:
323 + bool isPegIn = (transactionInfo.additionalInfo["isPegIn"] as bool?) ?? false;
324 + bool isPegOut = (transactionInfo.additionalInfo["isPegOut"] as bool?) ?? false;
325 + bool fromPegOut = (transactionInfo.additionalInfo["fromPegOut"] as bool?) ?? false;
326 + String str = '';
327 + if (transactionInfo.confirmations <= 0) {
328 + str = S.current.pending;
329 + }
330 + if ((isPegOut || fromPegOut) &&
331 + transactionInfo.confirmations >= 0 &&
332 + transactionInfo.confirmations < 6) {
333 + str = " (${transactionInfo.confirmations}/6)";
334 + }
335 + if (isPegIn) {
336 + str += " (Peg In)";
337 + }
338 + if (isPegOut) {
339 + str += " (Peg Out)";
340 + }
341 + return str;
342 + default:
343 + return '';
344 + }
345 +
346 + return '';
347 + }
348 +
349 + String get formattedStatus {
350 + if ([
351 + WalletType.monero,
352 + WalletType.haven,
353 + WalletType.wownero,
354 + WalletType.litecoin,
355 + WalletType.zano,
356 + ].contains(wallet.type)) {
357 + return formattedPendingStatus;
358 + }
359 +
360 + return transactionInfo.isPending ? S.current.pending : '';
361 + }
362 +
363 + int get neededConfirmations {
364 + switch (wallet.type) {
365 + case WalletType.monero:
366 + case WalletType.haven:
367 + case WalletType.zano:
368 + return 10;
369 + case WalletType.wownero:
370 + return 3;
371 + case WalletType.litecoin:
372 + bool isPegOut = (transactionInfo.additionalInfo["isPegOut"] as bool?) ?? false;
373 + bool fromPegOut = (transactionInfo.additionalInfo["fromPegOut"] as bool?) ?? false;
374 + if(isPegOut || fromPegOut)
375 + return 6;
376 + default:
377 + return 0;
378 + }
379 + return 0;
380 + }
381 +
382 +
383 +
384 + String get formattedTitle {
385 + if (transactionInfo.additionalInfo['autoShield'] == true) {
386 + return "Autoshield";
387 + }
388 + if (transactionInfo.direction == TransactionDirection.incoming) {
389 + return S.current.received;
390 + }
391 +
392 + return S.current.sent;
393 + }
394 +
395 @observable
396 bool canReplaceByFee;
397
182 - String _explorerUrl(WalletType type, String txId, int? chainId) {
183 - if (chainId != null) {
184 - final explorerUrl = evm!.getExplorerUrlForChainId(chainId);
398 + String get _explorerUrl {
399 +
400 + final txId = transactionInfo.id;
401 + if (wallet.chainId != null) {
402 + final explorerUrl = evm!.getExplorerUrlForChainId(wallet.chainId!);
403 if (explorerUrl != null) return '$explorerUrl/tx/${txId}';
404 }
405
188 - switch (type) {
406 + switch (wallet.type) {
407 case WalletType.monero:
408 return 'https://monero.com/tx/${txId}';
409 case WalletType.bitcoin:
410 return 'https://mempool.cakewallet.com/${wallet.isTestnet ? "testnet/" : ""}tx/${txId}';
411 case WalletType.litecoin:
194 - return 'https://blockchair.com/litecoin/transaction/${txId}';
412 + return bitcoin!.txIsMweb(transactionInfo)
413 + ? "https://www.mwebexplorer.com/blocks/block/${transactionInfo.height}"
414 + : 'https://blockchair.com/litecoin/transaction/${txId}';
415 case WalletType.bitcoinCash:
416 return 'https://blockchair.com/bitcoin-cash/transaction/${txId}';
417 case WalletType.haven:
@@ -229,390 +449,10 @@ abstract class TransactionDetailsViewModelBase with Store {
449 }
450 }
451
232 - String _explorerDescription(WalletType type, int? chainId) {
233 - if (chainId != null) {
234 - final explorerUrl = evm!.getExplorerUrlForChainId(chainId, showProtocol: false);
235 - if (explorerUrl != null) {
236 - return S.current.view_transaction_on + explorerUrl;
237 - }
238 - }
239 - switch (type) {
240 - case WalletType.monero:
241 - return S.current.view_transaction_on + 'Monero.com';
242 - case WalletType.bitcoin:
243 - return S.current.view_transaction_on + 'mempool.space';
244 - case WalletType.litecoin:
245 - case WalletType.bitcoinCash:
246 - case WalletType.dogecoin:
247 - return S.current.view_transaction_on + 'Blockchair.com';
248 - case WalletType.haven:
249 - return S.current.view_transaction_on + 'explorer.havenprotocol.org';
250 - case WalletType.ethereum:
251 - return S.current.view_transaction_on + 'etherscan.io';
252 - case WalletType.nano:
253 - return S.current.view_transaction_on + 'nanexplorer.com';
254 - case WalletType.banano:
255 - return S.current.view_transaction_on + 'nanexplorer.com';
256 - case WalletType.polygon:
257 - return S.current.view_transaction_on + 'polygonscan.com';
258 - case WalletType.bsc:
259 - return S.current.view_transaction_on + 'bscscan.com';
260 - case WalletType.solana:
261 - return S.current.view_transaction_on + 'solscan.io';
262 - case WalletType.tron:
263 - return S.current.view_transaction_on + 'tronscan.org';
264 - case WalletType.wownero:
265 - return S.current.view_transaction_on + 'Wownero.com';
266 - case WalletType.zano:
267 - return S.current.view_transaction_on + 'explorer.zano.org';
268 - case WalletType.decred:
269 - return S.current.view_transaction_on + 'dcrdata.decred.org';
270 - case WalletType.base:
271 - return S.current.view_transaction_on + 'basescan.org';
272 - case WalletType.arbitrum:
273 - return S.current.view_transaction_on + 'arbiscan.io';
274 - case WalletType.zcash:
275 - return S.current.view_transaction_on + 'blockchair.com';
276 - case WalletType.none:
277 - return '';
278 - }
279 - }
280 -
281 - void _addMoneroListItems(TransactionInfo tx, DateFormat dateFormat) {
282 - final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
283 - final description = transactionDescriptionBox.values.firstWhere(
284 - (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
285 - orElse: () => TransactionDescription(id: descriptionKey));
452 + String get explorerDescription => S.current.view_transaction_on + Uri.parse(_explorerUrl).host;
453
287 - final key = tx.additionalInfo['key'] as String? ?? description.transactionKey;
288 - final accountIndex = tx.additionalInfo['accountIndex'] as int;
289 - final addressIndex = tx.additionalInfo['addressIndex'] as int;
290 - final feeFormatted = tx.feeFormatted();
291 - final _items = [
292 - StandartListItem(
293 - title: S.current.transaction_details_transaction_id,
294 - value: tx.txHash,
295 - key: ValueKey('standard_list_item_transaction_details_id_key'),
296 - ),
297 - StandartListItem(
298 - title: S.current.transaction_details_date,
299 - value: dateFormat.format(tx.date),
300 - key: ValueKey('standard_list_item_transaction_details_date_key'),
301 - ),
302 - StandartListItem(
303 - title: S.current.transaction_details_height,
304 - value: '${tx.height}',
305 - key: ValueKey('standard_list_item_transaction_details_height_key'),
306 - ),
307 - StandartListItem(
308 - title: S.current.transaction_details_amount,
309 - value: tx.amountFormatted(),
310 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
311 - ),
312 - if (feeFormatted != null)
313 - StandartListItem(
314 - title: S.current.transaction_details_fee,
315 - value: feeFormatted,
316 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
317 - ),
318 - if (key?.isNotEmpty ?? false)
319 - StandartListItem(
320 - title: S.current.transaction_key,
321 - value: key!,
322 - key: ValueKey('standard_list_item_transaction_key'),
323 - ),
324 - ];
325 -
326 - if (tx.direction == TransactionDirection.incoming) {
327 - try {
328 - final address = monero!.getTransactionAddress(wallet, accountIndex, addressIndex);
329 - final label = monero!.getSubaddressLabel(wallet, accountIndex, addressIndex);
330 -
331 - if (address.isNotEmpty) {
332 - isRecipientAddressShown = true;
333 - _items.add(
334 - StandartListItem(
335 - title: S.current.transaction_details_recipient_address,
336 - value: address,
337 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
338 - ),
339 - );
340 - }
341 -
342 - if (label.isNotEmpty) {
343 - _items.add(StandartListItem(
344 - title: S.current.address_label,
345 - value: label,
346 - key: ValueKey('standard_list_item_address_label_key'),
347 - ));
348 - }
349 - } catch (e) {
350 - printV(e.toString());
351 - }
352 - }
353 -
354 - items.addAll(_items);
355 - }
356 -
357 - void _addElectrumListItems(
358 - TransactionInfo tx, DateFormat dateFormat, CryptoCurrency cryptoCurrency) {
359 - final isLightning = (tx.additionalInfo["isLightning"] as bool?) ?? false;
360 -
361 - final currency = isLightning ? CryptoCurrency.btcln : cryptoCurrency;
362 - final symbol = _appStore.amountParsingProxy.getCryptoSymbol(currency);
363 - final amountFormatted = _appStore.amountParsingProxy.getDisplayCryptoString(
364 - tx.amount, currency);
365 - final feeFormatted = (tx.fee != null)
366 - ? _appStore.amountParsingProxy.getDisplayCryptoString(tx.fee!, currency)
367 - : "";
368 -
369 - final _items = [
370 - StandartListItem(
371 - title: S.current.transaction_details_transaction_id,
372 - value: tx.txHash,
373 - key: ValueKey('standard_list_item_transaction_details_id_key'),
374 - ),
375 - StandartListItem(
376 - title: S.current.transaction_details_date,
377 - value: dateFormat.format(tx.date),
378 - key: ValueKey('standard_list_item_transaction_details_date_key'),
379 - ),
380 - if (!isLightning) ...[
381 - StandartListItem(
382 - title: S.current.confirmations,
383 - value: tx.confirmations.toString(),
384 - key: ValueKey('standard_list_item_transaction_confirmations_key'),
385 - ),
386 - StandartListItem(
387 - title: S.current.transaction_details_height,
388 - value: '${tx.height}',
389 - key: ValueKey('standard_list_item_transaction_details_height_key'),
390 - ),
391 - ],
392 - StandartListItem(
393 - title: S.current.transaction_details_amount,
394 - value: '$amountFormatted $symbol',
395 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
396 - ),
397 - if (tx.feeFormatted()?.isNotEmpty ?? false)
398 - StandartListItem(
399 - title: S.current.transaction_details_fee,
400 - value: '$feeFormatted $symbol',
401 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
402 - ),
403 - ];
404 -
405 - if (wallet.type == WalletType.bitcoin && tx.direction == TransactionDirection.incoming) {
406 - try {
407 - final addresses = bitcoin!.getTransactionAddresses(wallet, tx);
408 -
409 - if (addresses != null) {
410 - isRecipientAddressShown = true;
411 - for (final address in addresses) {
412 - _items.add(
413 - StandartListItem(
414 - title: S.current.transaction_details_recipient_address,
415 - value: address,
416 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
417 - ),
418 - );
419 - }
420 - }
421 - } catch (e) {
422 - printV(e.toString());
423 - }
424 - }
425 -
426 - items.addAll(_items);
427 - }
428 -
429 - void _addLitecoinListItems(TransactionInfo tx, DateFormat dateFormat) {
430 - _addElectrumListItems(tx, dateFormat, CryptoCurrency.ltc);
431 -
432 - bool isMweb = bitcoin!.txIsMweb(tx);
433 -
434 - final _items = [
435 - if (isMweb)
436 - BlockExplorerListItem(
437 - title: S.current.view_in_block_explorer,
438 - value: S.current.view_transaction_on + 'mwebexplorer.com',
439 - onTap: () async {
440 - try {
441 - final uri = Uri.parse('https://www.mwebexplorer.com/blocks/block/${tx.height}');
442 - if (await canLaunchUrl(uri))
443 - await launchUrl(uri, mode: LaunchMode.externalApplication);
444 - } catch (e) {}
445 - },
446 - key: ValueKey('block_explorer_list_item_mweb_wallet_type_key'),
447 - ),
448 - ];
449 -
450 - items.addAll(_items);
451 - }
452 -
453 - void _addHavenListItems(TransactionInfo tx, DateFormat dateFormat) {
454 - items.addAll([
455 - StandartListItem(
456 - title: S.current.transaction_details_transaction_id,
457 - value: tx.txHash,
458 - key: ValueKey('standard_list_item_transaction_details_id_key'),
459 - ),
460 - StandartListItem(
461 - title: S.current.transaction_details_date,
462 - value: dateFormat.format(tx.date),
463 - key: ValueKey('standard_list_item_transaction_details_date_key'),
464 - ),
465 - StandartListItem(
466 - title: S.current.transaction_details_height,
467 - value: '${tx.height}',
468 - key: ValueKey('standard_list_item_transaction_details_height_key'),
469 - ),
470 - StandartListItem(
471 - title: S.current.transaction_details_amount,
472 - value: tx.amountFormatted(),
473 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
474 - ),
475 - if (tx.feeFormatted()?.isNotEmpty ?? false)
476 - StandartListItem(
477 - title: S.current.transaction_details_fee,
478 - value: tx.feeFormatted()!,
479 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
480 - ),
481 - ]);
482 - }
483 -
484 - void _addEVMListItems(TransactionInfo tx, DateFormat dateFormat) {
485 - final _items = [
486 - StandartListItem(
487 - title: S.current.transaction_details_transaction_id,
488 - value: tx.txHash,
489 - key: ValueKey('standard_list_item_transaction_details_id_key'),
490 - ),
491 - StandartListItem(
492 - title: S.current.transaction_details_date,
493 - value: dateFormat.format(tx.date),
494 - key: ValueKey('standard_list_item_transaction_details_date_key'),
495 - ),
496 - StandartListItem(
497 - title: S.current.confirmations,
498 - value: tx.confirmations.toString(),
499 - key: ValueKey('standard_list_item_transaction_confirmations_key'),
500 - ),
501 - StandartListItem(
502 - title: S.current.transaction_details_height,
503 - value: '${tx.height}',
504 - key: ValueKey('standard_list_item_transaction_details_height_key'),
505 - ),
506 - StandartListItem(
507 - title: S.current.transaction_details_amount,
508 - value: tx.amountFormatted(),
509 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
510 - ),
511 - if (tx.feeFormatted()?.isNotEmpty ?? false)
512 - StandartListItem(
513 - title: S.current.transaction_details_fee,
514 - value: tx.feeFormatted()!,
515 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
516 - ),
517 - if (showRecipientAddress && tx.to != null)
518 - StandartListItem(
519 - title: S.current.transaction_details_recipient_address,
520 - value: tx.to!,
521 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
522 - ),
523 - if (tx.direction == TransactionDirection.incoming && tx.from != null)
524 - StandartListItem(
525 - title: S.current.transaction_details_source_address,
526 - value: tx.from!,
527 - key: ValueKey('standard_list_item_transaction_details_source_address_key'),
528 - ),
529 - ];
530 -
531 - items.addAll(_items);
532 - }
533 -
534 - void _addNanoListItems(TransactionInfo tx, DateFormat dateFormat) {
535 - final _items = [
536 - StandartListItem(
537 - title: S.current.transaction_details_transaction_id,
538 - value: tx.txHash,
539 - key: ValueKey('standard_list_item_transaction_details_id_key'),
540 - ),
541 - if (showRecipientAddress && tx.to != null)
542 - StandartListItem(
543 - title: S.current.transaction_details_recipient_address,
544 - value: tx.to!,
545 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
546 - ),
547 - if (showRecipientAddress && tx.from != null)
548 - StandartListItem(
549 - title: S.current.transaction_details_source_address,
550 - value: tx.from!,
551 - key: ValueKey('standard_list_item_transaction_details_source_address_key'),
552 - ),
553 - StandartListItem(
554 - title: S.current.transaction_details_amount,
555 - value: tx.amountFormatted(),
556 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
557 - ),
558 - StandartListItem(
559 - title: S.current.transaction_details_date,
560 - value: dateFormat.format(tx.date),
561 - key: ValueKey('standard_list_item_transaction_details_date_key'),
562 - ),
563 - StandartListItem(
564 - title: S.current.confirmed_tx,
565 - value: (tx.confirmations > 0).toString(),
566 - key: ValueKey('standard_list_item_transaction_confirmed_key'),
567 - ),
568 - StandartListItem(
569 - title: S.current.transaction_details_height,
570 - value: '${tx.height}',
571 - key: ValueKey('standard_list_item_transaction_details_height_key'),
572 - ),
573 - ];
574 -
575 - items.addAll(_items);
576 - }
577 -
578 - void _addSolanaListItems(TransactionInfo tx, DateFormat dateFormat) {
579 - final _items = [
580 - StandartListItem(
581 - title: S.current.transaction_details_transaction_id,
582 - value: tx.txHash.replaceAll(RegExp(r'_(incoming|outgoing)$'), ''),
583 - key: ValueKey('standard_list_item_transaction_details_id_key'),
584 - ),
585 - StandartListItem(
586 - title: S.current.transaction_details_date,
587 - value: dateFormat.format(tx.date),
588 - key: ValueKey('standard_list_item_transaction_details_date_key'),
589 - ),
590 - StandartListItem(
591 - title: S.current.transaction_details_amount,
592 - value: tx.amountFormatted(),
593 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
594 - ),
595 - if (tx.feeFormatted()?.isNotEmpty ?? false)
596 - StandartListItem(
597 - title: S.current.transaction_details_fee,
598 - value: tx.feeFormatted()!,
599 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
600 - ),
601 - if (showRecipientAddress && tx.to != null)
602 - StandartListItem(
603 - title: S.current.transaction_details_recipient_address,
604 - value: tx.to!,
605 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
606 - ),
607 - if (tx.from != null)
608 - StandartListItem(
609 - title: S.current.transaction_details_source_address,
610 - value: tx.from!,
611 - key: ValueKey('standard_list_item_transaction_details_source_address_key'),
612 - ),
613 - ];
614 -
615 - items.addAll(_items);
454 + void launchExplorer() {
455 + launchUrl(Uri.parse(_explorerUrl));
456 }
457
458 void addBumpFeesListItems(TransactionInfo tx, String rawTransaction) {
@@ -699,186 +539,8 @@ abstract class TransactionDetailsViewModelBase with Store {
539 }
540 }
541
702 - void _addTronListItems(TransactionInfo tx, DateFormat dateFormat) {
703 - final _items = [
704 - StandartListItem(
705 - title: S.current.transaction_details_transaction_id,
706 - value: tx.txHash,
707 - key: ValueKey('standard_list_item_transaction_details_id_key'),
708 - ),
709 - StandartListItem(
710 - title: S.current.transaction_details_date,
711 - value: dateFormat.format(tx.date),
712 - key: ValueKey('standard_list_item_transaction_details_date_key'),
713 - ),
714 - StandartListItem(
715 - title: S.current.transaction_details_amount,
716 - value: tx.amountFormatted(),
717 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
718 - ),
719 - if (tx.feeFormatted()?.isNotEmpty ?? false)
720 - StandartListItem(
721 - title: S.current.transaction_details_fee,
722 - value: tx.feeFormatted()!,
723 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
724 - ),
725 - if (showRecipientAddress && tx.to != null)
726 - StandartListItem(
727 - title: S.current.transaction_details_recipient_address,
728 - value: tron!.getTronBase58Address(tx.to!, wallet),
729 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
730 - ),
731 - if (tx.from != null)
732 - StandartListItem(
733 - title: S.current.transaction_details_source_address,
734 - value: tron!.getTronBase58Address(tx.from!, wallet),
735 - key: ValueKey('standard_list_item_transaction_details_source_address_key'),
736 - ),
737 - ];
542
739 - items.addAll(_items);
740 - }
543
742 - void _addDecredListItems(TransactionInfo tx, DateFormat dateFormat) {
743 - final _items = [
744 - StandartListItem(
745 - title: S.current.transaction_details_transaction_id,
746 - value: tx.txHash,
747 - key: ValueKey('standard_list_item_transaction_details_id_key'),
748 - ),
749 - StandartListItem(
750 - title: S.current.transaction_details_date,
751 - value: dateFormat.format(tx.date),
752 - key: ValueKey('standard_list_item_transaction_details_date_key'),
753 - ),
754 - StandartListItem(
755 - title: S.current.transaction_details_height,
756 - value: '${tx.height}',
757 - key: ValueKey('standard_list_item_transaction_details_height_key'),
758 - ),
759 - StandartListItem(
760 - title: S.current.transaction_details_amount,
761 - value: tx.amountFormatted(),
762 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
763 - ),
764 - if (tx.feeFormatted()?.isNotEmpty ?? false)
765 - StandartListItem(
766 - title: S.current.transaction_details_fee,
767 - value: tx.feeFormatted()!,
768 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
769 - ),
770 - if (showRecipientAddress && tx.to != null)
771 - StandartListItem(
772 - title: S.current.transaction_details_recipient_address,
773 - value: tx.to!,
774 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
775 - ),
776 - if (tx.from != null)
777 - StandartListItem(
778 - title: S.current.transaction_details_source_address,
779 - value: tx.from!,
780 - key: ValueKey('standard_list_item_transaction_details_source_address_key'),
781 - ),
782 - ];
783 -
784 - items.addAll(_items);
785 - }
786 -
787 - void _addZcashListItems(TransactionInfo tx, DateFormat dateFormat) {
788 - final memo = tx.additionalInfo['memo'] as String?;
789 -
790 - final _items = [
791 - StandartListItem(
792 - title: S.current.transaction_details_transaction_id,
793 - value: tx.txHash,
794 - key: ValueKey('standard_list_item_transaction_details_id_key'),
795 - ),
796 - if (tx.to != null)
797 - StandartListItem(
798 - title: S.current.transaction_details_recipient_address,
799 - value: tx.to!,
800 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
801 - ),
802 - StandartListItem(
803 - title: S.current.transaction_details_date,
804 - value: dateFormat.format(tx.date),
805 - key: ValueKey('standard_list_item_transaction_details_date_key'),
806 - ),
807 - StandartListItem(
808 - title: S.current.confirmations,
809 - value: tx.confirmations.toString(),
810 - key: ValueKey('standard_list_item_transaction_confirmations_key'),
811 - ),
812 - StandartListItem(
813 - title: S.current.transaction_details_height,
814 - value: '${tx.height ?? 0}',
815 - key: ValueKey('standard_list_item_transaction_details_height_key'),
816 - ),
817 - StandartListItem(
818 - title: S.current.transaction_details_amount,
819 - value: tx.amountFormatted(),
820 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
821 - ),
822 - if (tx.feeFormatted() != null && tx.feeFormatted()!.isNotEmpty)
823 - StandartListItem(
824 - title: S.current.transaction_details_fee,
825 - value: tx.feeFormatted()!,
826 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
827 - ),
828 - if (memo != null && memo.isNotEmpty)
829 - StandartListItem(
830 - title: S.current.memo,
831 - value: memo,
832 - key: ValueKey('standard_list_item_transaction_details_memo_key'),
833 - ),
834 - ];
835 - items.addAll(_items);
836 - }
837 -
838 - void _addDogecoinListItems(TransactionInfo tx, DateFormat dateFormat) {
839 - final _items = [
840 - StandartListItem(
841 - title: S.current.transaction_details_transaction_id,
842 - value: tx.txHash,
843 - key: ValueKey('standard_list_item_transaction_details_id_key'),
844 - ),
845 - StandartListItem(
846 - title: S.current.transaction_details_date,
847 - value: dateFormat.format(tx.date),
848 - key: ValueKey('standard_list_item_transaction_details_date_key'),
849 - ),
850 - StandartListItem(
851 - title: S.current.transaction_details_height,
852 - value: '${tx.height}',
853 - key: ValueKey('standard_list_item_transaction_details_height_key'),
854 - ),
855 - StandartListItem(
856 - title: S.current.transaction_details_amount,
857 - value: tx.amountFormatted(),
858 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
859 - ),
860 - if (tx.feeFormatted()?.isNotEmpty ?? false)
861 - StandartListItem(
862 - title: S.current.transaction_details_fee,
863 - value: tx.feeFormatted()!,
864 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
865 - ),
866 - if (showRecipientAddress && tx.to != null)
867 - StandartListItem(
868 - title: S.current.transaction_details_recipient_address,
869 - value: tx.to!,
870 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
871 - ),
872 - if (tx.from != null)
873 - StandartListItem(
874 - title: S.current.transaction_details_source_address,
875 - value: tx.from!,
876 - key: ValueKey('standard_list_item_transaction_details_source_address_key'),
877 - ),
878 - ];
879 -
880 - items.addAll(_items);
881 - }
544
545 @action
546 Future<void> _checkForRBF(TransactionInfo tx) async {
@@ -929,93 +591,5 @@ abstract class TransactionDetailsViewModelBase with Store {
591 ? ''
592 : sendViewModel.pendingTransactionFeeFiatAmount + ' ' + sendViewModel.fiat.title;
593
932 - void _addWowneroListItems(TransactionInfo tx, DateFormat dateFormat) {
933 - final key = tx.additionalInfo['key'] as String?;
934 - final accountIndex = tx.additionalInfo['accountIndex'] as int;
935 - final addressIndex = tx.additionalInfo['addressIndex'] as int;
936 - final feeFormatted = tx.feeFormatted();
937 - final _items = [
938 - StandartListItem(
939 - title: S.current.transaction_details_transaction_id,
940 - value: tx.txHash,
941 - key: ValueKey('standard_list_item_transaction_details_id_key'),
942 - ),
943 - StandartListItem(
944 - title: S.current.transaction_details_date,
945 - value: dateFormat.format(tx.date),
946 - key: ValueKey('standard_list_item_transaction_details_date_key'),
947 - ),
948 - StandartListItem(
949 - title: S.current.transaction_details_height,
950 - value: '${tx.height}',
951 - key: ValueKey('standard_list_item_transaction_details_height_key'),
952 - ),
953 - StandartListItem(
954 - title: S.current.transaction_details_amount,
955 - value: tx.amountFormatted(),
956 - key: ValueKey('standard_list_item_transaction_details_amount_key'),
957 - ),
958 - if (feeFormatted != null)
959 - StandartListItem(
960 - title: S.current.transaction_details_fee,
961 - value: feeFormatted,
962 - key: ValueKey('standard_list_item_transaction_details_fee_key'),
963 - ),
964 - if (key?.isNotEmpty ?? false)
965 - StandartListItem(
966 - title: S.current.transaction_key,
967 - value: key!,
968 - key: ValueKey('standard_list_item_transaction_key'),
969 - ),
970 - ];
971 -
972 - if (tx.direction == TransactionDirection.incoming) {
973 - try {
974 - final address = wownero!.getTransactionAddress(wallet, accountIndex, addressIndex);
975 - final label = wownero!.getSubaddressLabel(wallet, accountIndex, addressIndex);
976 -
977 - if (address.isNotEmpty) {
978 - isRecipientAddressShown = true;
979 - _items.add(
980 - StandartListItem(
981 - title: S.current.transaction_details_recipient_address,
982 - value: address,
983 - key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
984 - ),
985 - );
986 - }
987 -
988 - if (label.isNotEmpty) {
989 - _items.add(
990 - StandartListItem(
991 - title: S.current.address_label,
992 - value: label,
993 - key: ValueKey('standard_list_item_address_label_key'),
994 - ),
995 - );
996 - }
997 - } catch (e) {
998 - printV(e.toString());
999 - }
1000 - }
1001 -
1002 - items.addAll(_items);
1003 - }
594
1005 - void _addZanoListItems(TransactionInfo tx, DateFormat dateFormat) {
1006 - final comment = tx.additionalInfo['comment'] as String?;
1007 - items.addAll([
1008 - StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
1009 - StandartListItem(
1010 - title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
1011 - StandartListItem(
1012 - title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
1013 - StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
1014 - StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
1015 - if (tx.feeFormatted()?.isNotEmpty ?? false)
1016 - StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
1017 - if (comment != null && comment.isNotEmpty)
1018 - StandartListItem(title: S.current.transaction_details_title, value: comment),
1019 - ]);
1020 - }
595 }
res/pictures/link_arrow.svg
+1 -1
@@ -1,3 +1,3 @@
1 <svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
2 - <path d="M0.674022 8L0 7.32598L6.35165 0.968191H0.577203V0H8V7.4228H7.03181V1.64835L0.674022 8Z" fill="#91B0FF"/>
2 + <path d="M0.674022 8L0 7.32598L6.35165 0.968191H0.577203V0H8V7.4228H7.03181V1.64835L0.674022 8Z" fill="white"/>
3 </svg>
res/values/strings_ar.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "البطاقات النشطة",
14 "activeConnectionsPrompt": "ستظهر الاتصالات النشطة هنا",
15 "add": "إضافة",
16 + "add_a_note": "أضف ملاحظة",
17 "add_account": "إضافة حساب",
18 "add_contact": "إضافة جهة اتصال",
19 "add_contact_to_address_book": "هل ترغب في إضافة جهة الاتصال هذه إلى دفتر العناوين الخاص بك؟",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "لا يمكن لأيٍّ من المزوّدين المحدّدين إجراء هذه المبادلة",
681 "noNFTYet": "لا توجد رموز NFT بعد",
682 "normal": "عادي",
683 + "note": "ملحوظة",
684 "note_optional": "ملاحظة (اختيارية)",
685 "note_tap_to_change": "ملاحظة (اضغط للتغيير)",
686 "notification_permission_denied": "تم رفض إذن الإشعارات بشكل دائم. يُرجى تمكينه يدويًا من الإعدادات",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "غير مدفوع بالكامل",
1186 "trade_state_unpaid": "غير مدفوع",
1187 "trades": "الصفقات",
1188 + "transaction": "عملية",
1189 "transaction_commited": "تم تأكيد المعاملة",
1190 "transaction_cost": "تكلفة المعاملة",
1191 "transaction_details_amount": "الكمية",
res/values/strings_bg.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Активни карти",
14 "activeConnectionsPrompt": "Тук ще се показват активните връзки",
15 "add": "Добави",
16 + "add_a_note": "Добавете бележка",
17 "add_account": "Добавяне на акаунт",
18 "add_contact": "Добавяне на контакт",
19 "add_contact_to_address_book": "Желаете ли да добавите този контакт към адресната си книга?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Нито един от избраните доставчици не може да извърши този суап",
681 "noNFTYet": "Все още няма NFT",
682 "normal": "Нормален",
683 + "note": "Забележка",
684 "note_optional": "Бележка (незадължително)",
685 "note_tap_to_change": "Бележка (докоснете, за да промените)",
686 "notification_permission_denied": "Разрешението за известия е окончателно отказано. Моля, включете го ръчно в настройките.",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "Недоплатено",
1186 "trade_state_unpaid": "Неплатено",
1187 "trades": "Сделки",
1188 + "transaction": "Транзакция",
1189 "transaction_commited": "Транзакцията е потвърдена",
1190 "transaction_cost": "Разход за транзакция",
1191 "transaction_details_amount": "Сума",
res/values/strings_cs.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Aktivní karty",
14 "activeConnectionsPrompt": "Aktivní připojení se zobrazí zde",
15 "add": "Přidat",
16 + "add_a_note": "Přidejte poznámku",
17 "add_account": "Přidat účet",
18 "add_contact": "Přidat kontakt",
19 "add_contact_to_address_book": "Chcete přidat tento kontakt do svého adresáře?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Žádný z vybraných poskytovatelů nemůže tento swap provést",
681 "noNFTYet": "Zatím žádné NFT",
682 "normal": "Normální",
683 + "note": "Poznámka",
684 "note_optional": "Poznámka (nepovinné)",
685 "note_tap_to_change": "Poznámka (klepnutím změnit)",
686 "notification_permission_denied": "Oprávnění k oznámením bylo trvale zamítnuto, prosím ručně jej povolte v nastavení",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "Nedoplaceno",
1186 "trade_state_unpaid": "Nezaplaceno",
1187 "trades": "Obchody",
1188 + "transaction": "Transakce",
1189 "transaction_commited": "Transakce potvrzena",
1190 "transaction_cost": "Náklady transakce",
1191 "transaction_details_amount": "Částka",
res/values/strings_de.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Aktive Karten",
14 "activeConnectionsPrompt": "Aktive Verbindungen werden hier angezeigt",
15 "add": "Hinzufügen",
16 + "add_a_note": "Fügen Sie eine Notiz hinzu",
17 "add_account": "Konto hinzufügen",
18 "add_contact": "Kontakt hinzufügen",
19 "add_contact_to_address_book": "Möchten Sie diesen Kontakt zu Ihrem Adressbuch hinzufügen?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Keiner der ausgewählten Anbieter kann diesen Swap durchführen",
681 "noNFTYet": "Noch keine NFTs",
682 "normal": "Normal",
683 + "note": "Notiz",
684 "note_optional": "Notiz (optional)",
685 "note_tap_to_change": "Notiz (zum Ändern tippen)",
686 "notification_permission_denied": "Die Benachrichtigungsberechtigung wurde dauerhaft verweigert. Bitte aktivieren Sie sie manuell in den Einstellungen.",
@@ -1184,6 +1186,7 @@
1186 "trade_state_underpaid": "Unterbezahlt",
1187 "trade_state_unpaid": "Unbezahlt",
1188 "trades": "Trades",
1189 + "transaction": "Transaktion",
1190 "transaction_commited": "Transaktion übermittelt",
1191 "transaction_cost": "Transaktionskosten",
1192 "transaction_details_amount": "Betrag",
res/values/strings_en.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Active cards",
14 "activeConnectionsPrompt": "Active connections will appear here",
15 "add": "Add",
16 + "add_a_note": "Add a note",
17 "add_account": "Add Account",
18 "add_contact": "Add contact",
19 "add_contact_to_address_book": "Would you like to add this contact to your address book?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "None of the selected providers can make this swap",
681 "noNFTYet": "No NFTs yet",
682 "normal": "Normal",
683 + "note": "Note",
684 "note_optional": "Note (optional)",
685 "note_tap_to_change": "Note (tap to change)",
686 "notification_permission_denied": "Notification permission got permamently denied, please manually enable it in settings",
@@ -1184,6 +1186,7 @@
1186 "trade_state_underpaid": "Underpaid",
1187 "trade_state_unpaid": "Unpaid",
1188 "trades": "Trades",
1189 + "transaction": "Transaction",
1190 "transaction_commited": "Transaction commited",
1191 "transaction_cost": "Transaction Cost",
1192 "transaction_details_amount": "Amount",
res/values/strings_es.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Tarjetas activas",
14 "activeConnectionsPrompt": "Las conexiones activas aparecerán aquí",
15 "add": "Añadir",
16 + "add_a_note": "Añadir una nota",
17 "add_account": "Añadir cuenta",
18 "add_contact": "Agregar contacto",
19 "add_contact_to_address_book": "¿Te gustaría añadir este contacto a tu libreta de direcciones?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Ninguno de los proveedores seleccionados puede realizar este swap",
681 "noNFTYet": "Aún no hay NFT",
682 "normal": "Normal",
683 + "note": "Nota",
684 "note_optional": "Nota (opcional)",
685 "note_tap_to_change": "Nota (toca para cambiar)",
686 "notification_permission_denied": "El permiso de notificaciones se ha denegado permanentemente. Por favor, habilítalo manualmente en la configuración.",
@@ -1184,6 +1186,7 @@
1186 "trade_state_underpaid": "Pago insuficiente",
1187 "trade_state_unpaid": "No pagado",
1188 "trades": "Operaciones",
1189 + "transaction": "Transacción",
1190 "transaction_commited": "Transacción confirmada",
1191 "transaction_cost": "Costo de transacción",
1192 "transaction_details_amount": "Cantidad",
res/values/strings_fa.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "کارت‌های فعال",
14 "activeConnectionsPrompt": "اتصال‌های فعال اینجا نمایش داده می‌شوند",
15 "add": "افزودن",
16 + "add_a_note": "یک یادداشت اضافه کنید",
17 "add_account": "افزودن حساب",
18 "add_contact": "افزودن مخاطب",
19 "add_contact_to_address_book": "آیا می‌خواهید این مخاطب را به دفترچه آدرس خود اضافه کنید؟",
@@ -677,6 +678,7 @@
678 "none_of_selected_providers_can_exchange": "هیچ‌یک از ارائه‌دهندگان انتخاب‌شده نمی‌توانند این سواپ را انجام دهند",
679 "noNFTYet": "هنوز هیچ NFT‌ای وجود ندارد",
680 "normal": "عادی",
681 + "note": "توجه داشته باشید",
682 "note_optional": "یادداشت (اختیاری)",
683 "note_tap_to_change": "یادداشت (برای تغییر ضربه بزنید)",
684 "notification_permission_denied": "مجوز اعلان‌ها به‌طور دائمی رد شده است، لطفاً آن را به‌صورت دستی در تنظیمات فعال کنید",
@@ -1182,6 +1184,7 @@
1184 "trade_state_underpaid": "کم‌پرداخت",
1185 "trade_state_unpaid": "پرداخت‌نشده",
1186 "trades": "معاملات",
1187 + "transaction": "معامله",
1188 "transaction_commited": "تراکنش ثبت شد",
1189 "transaction_cost": "هزینه تراکنش",
1190 "transaction_details_amount": "مقدار",
res/values/strings_fr.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Cartes actives",
14 "activeConnectionsPrompt": "Les connexions actives apparaîtront ici",
15 "add": "Ajouter",
16 + "add_a_note": "Ajouter une note",
17 "add_account": "Ajouter un compte",
18 "add_contact": "Ajouter un contact",
19 "add_contact_to_address_book": "Souhaitez-vous ajouter ce contact à votre carnet d'adresses ?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Aucun des fournisseurs sélectionnés ne peut effectuer ce swap",
681 "noNFTYet": "Aucun NFT pour le moment",
682 "normal": "Normal",
683 + "note": "Note",
684 "note_optional": "Note (facultative)",
685 "note_tap_to_change": "Note (appuyez pour modifier)",
686 "notification_permission_denied": "L'autorisation des notifications a été refusée de manière permanente. Veuillez l'activer manuellement dans les paramètres.",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "Sous-payé",
1186 "trade_state_unpaid": "Impayé",
1187 "trades": "Trades",
1188 + "transaction": "Transaction",
1189 "transaction_commited": "Transaction validée",
1190 "transaction_cost": "Coût de transaction",
1191 "transaction_details_amount": "Montant",
res/values/strings_gn.arb
+3
@@ -12,6 +12,7 @@
12 "active_cards": "Tarjeta oĩva hag̃ua",
13 "activeConnectionsPrompt": "Umi jeikeha oĩva ojehechaukáta ko'ápe",
14 "add": "Emoĩve",
15 + "add_a_note": "Emoĩ peteĩ nóta",
16 "add_account": "Embojoapy cuenta",
17 "add_contact": "Emoĩve contacto",
18 "add_contact_to_address_book": "¿Reipotápa remoĩ ko contacto nde kundaharape?",
@@ -531,6 +532,7 @@
532 "none_of_selected_providers_can_exchange": "Ndaipóri umi proveedor ojeiporavóva apytépe ikatúva ojapo ko swap.",
533 "noNFTYet": "Ndaipóri NFT gueteri",
534 "normal": "Normal",
535 + "note": "Haipy",
536 "note_optional": "Jehaipy (opcional)",
537 "note_tap_to_change": "Jehaipy (eikutu emoambue hag̃ua)",
538 "nullURIError": "URI nulo",
@@ -951,6 +953,7 @@
953 "trade_state_underpaid": "Ojehepyme’ẽ mboyve",
954 "trade_state_unpaid": "Noñeme’ẽi",
955 "trades": "Ñemuha",
956 + "transaction": "Transacción rehegua",
957 "transaction_commited": "Transacción ojejapóma.",
958 "transaction_details_amount": "Hetakue",
959 "transaction_details_copied": "${title} ojekopia portapapélpe",
res/values/strings_ha.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Katunan da ke aiki",
14 "activeConnectionsPrompt": "Haɗe-haɗe masu aiki za su bayyana a nan",
15 "add": "Ƙara",
16 + "add_a_note": "Ƙara bayanin kula",
17 "add_account": "Ƙara Asusun",
18 "add_contact": "Ƙara tuntuɓa",
19 "add_contact_to_address_book": "Kuna so ku ƙara wannan tuntuɓa zuwa littafin adireshinku?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Babu ɗaya daga cikin masu ba da sabis da aka zaɓa da zai iya yin wannan musayar",
681 "noNFTYet": "Babu NFT tukuna",
682 "normal": "Na al’ada",
683 + "note": "Lura",
684 "note_optional": "Bayani (na zaɓi)",
685 "note_tap_to_change": "Bayanan kula (taɓa don canjawa)",
686 "notification_permission_denied": "An ƙi ba da izinin sanarwa har abada, don Allah ka kunna shi da hannu a cikin saituna",
@@ -1185,6 +1187,7 @@
1187 "trade_state_underpaid": "Ba a biya cikakke ba",
1188 "trade_state_unpaid": "Ba a biya ba",
1189 "trades": "Kasuwanci",
1190 + "transaction": "Ma'amala",
1191 "transaction_commited": "An tabbatar da ma'amala",
1192 "transaction_cost": "Kudin ma'amala",
1193 "transaction_details_amount": "Adadi",
res/values/strings_hi.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "सक्रिय कार्ड",
14 "activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे",
15 "add": "जोड़ें",
16 + "add_a_note": "एक नोट जोड़े",
17 "add_account": "अकाउंट जोड़ें",
18 "add_contact": "संपर्क जोड़ें",
19 "add_contact_to_address_book": "क्या आप इस संपर्क को अपनी पता पुस्तिका में जोड़ना चाहेंगे?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "चयनित प्रदाताओं में से कोई भी यह स्वैप नहीं कर सकता",
681 "noNFTYet": "अभी तक कोई NFT नहीं",
682 "normal": "सामान्य",
683 + "note": "टिप्पणी",
684 "note_optional": "नोट (वैकल्पिक)",
685 "note_tap_to_change": "नोट (बदलने के लिए टैप करें)",
686 "notification_permission_denied": "अधिसूचना की अनुमति स्थायी रूप से अस्वीकार कर दी गई है, कृपया इसे सेटिंग्स में जाकर मैन्युअल रूप से सक्षम करें",
@@ -1185,6 +1187,7 @@
1187 "trade_state_underpaid": "अपर्याप्त भुगतान",
1188 "trade_state_unpaid": "अवैतनिक",
1189 "trades": "ट्रेड्स",
1190 + "transaction": "लेन-देन",
1191 "transaction_commited": "लेन-देन कमिट हो गया",
1192 "transaction_cost": "लेनदेन लागत",
1193 "transaction_details_amount": "राशि",
res/values/strings_hr.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Aktivne kartice",
14 "activeConnectionsPrompt": "Ovdje će se prikazati aktivne veze",
15 "add": "Dodaj",
16 + "add_a_note": "Dodajte bilješku",
17 "add_account": "Dodaj račun",
18 "add_contact": "Dodaj kontakt",
19 "add_contact_to_address_book": "Želite li dodati ovaj kontakt u svoj adresar?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Nijedan od odabranih pružatelja ne može izvršiti ovu zamjenu",
681 "noNFTYet": "Još nema NFT-ova",
682 "normal": "Normalno",
683 + "note": "Bilješka",
684 "note_optional": "Napomena (nije obvezno)",
685 "note_tap_to_change": "Napomena (dodirnite za promjenu)",
686 "notification_permission_denied": "Dozvola za obavijesti trajno je odbijena, molimo ručno je omogućite u postavkama",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "Nedovoljno plaćeno",
1186 "trade_state_unpaid": "Neplaćeno",
1187 "trades": "Trgovanja",
1188 + "transaction": "Transakcija",
1189 "transaction_commited": "Transakcija potvrđena",
1190 "transaction_cost": "Trošak transakcije",
1191 "transaction_details_amount": "Iznos",
res/values/strings_hy.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Ակտիվ քարտեր",
14 "activeConnectionsPrompt": "Ակտիվ կապերը կհայտնվեն այստեղ",
15 "add": "Ավելացնել",
16 + "add_a_note": "Ավելացնել նշում",
17 "add_account": "Ավելացնել հաշիվ",
18 "add_contact": "Ավելացնել կոնտակտ",
19 "add_contact_to_address_book": "Ցանկանո՞ւմ եք այս կոնտակտը ավելացնել Ձեր հասցեագրքում:",
@@ -678,6 +679,7 @@
679 "none_of_selected_providers_can_exchange": "Ընտրված մատակարարներից ոչ մեկը չի կարող կատարել այս սվոփը",
680 "noNFTYet": "Դեռևս NFT-ներ չկան",
681 "normal": "Նորմալ",
682 + "note": "Նշում",
683 "note_optional": "Նշում (ըստ ցանկության)",
684 "note_tap_to_change": "Նշում (հպեք՝ փոխելու համար)",
685 "notification_permission_denied": "Ծանուցումների թույլտվությունը մշտապես մերժվել է, խնդրում ենք այն ձեռքով միացնել կարգավորումներում",
@@ -1181,6 +1183,7 @@
1183 "trade_state_underpaid": "Թերվճարված",
1184 "trade_state_unpaid": "Չվճարված",
1185 "trades": "Գործարքներ",
1186 + "transaction": "Գործարք",
1187 "transaction_commited": "Գործարքը հաստատվեց",
1188 "transaction_cost": "Գործարքի արժեք",
1189 "transaction_details_amount": "Գումար",
res/values/strings_id.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Kartu aktif",
14 "activeConnectionsPrompt": "Koneksi aktif akan muncul di sini",
15 "add": "Tambah",
16 + "add_a_note": "Tambahkan catatan",
17 "add_account": "Tambahkan Akun",
18 "add_contact": "Tambah kontak",
19 "add_contact_to_address_book": "Apakah Anda ingin menambahkan kontak ini ke buku alamat Anda?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Tidak ada penyedia yang dipilih yang dapat melakukan swap ini",
681 "noNFTYet": "Belum ada NFT",
682 "normal": "Normal",
683 + "note": "Catatan",
684 "note_optional": "Catatan (opsional)",
685 "note_tap_to_change": "Catatan (ketuk untuk mengubah)",
686 "notification_permission_denied": "Izin notifikasi ditolak secara permanen, mohon aktifkan secara manual di pengaturan",
@@ -1186,6 +1188,7 @@
1188 "trade_state_underpaid": "Kurang dibayar",
1189 "trade_state_unpaid": "Belum dibayar",
1190 "trades": "Perdagangan",
1191 + "transaction": "Transaksi",
1192 "transaction_commited": "Transaksi dikomit",
1193 "transaction_cost": "Biaya Transaksi",
1194 "transaction_details_amount": "Jumlah",
res/values/strings_it.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Carte attive",
14 "activeConnectionsPrompt": "Le connessioni attive appariranno qui",
15 "add": "Aggiungi",
16 + "add_a_note": "Aggiungi una nota",
17 "add_account": "Aggiungi account",
18 "add_contact": "Aggiungi contatto",
19 "add_contact_to_address_book": "Vuoi aggiungere questo contatto alla tua rubrica?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Nessuno dei provider selezionati può effettuare questo swap",
681 "noNFTYet": "Nessun NFT ancora",
682 "normal": "Normale",
683 + "note": "Nota",
684 "note_optional": "Nota (opzionale)",
685 "note_tap_to_change": "Nota (tocca per cambiare)",
686 "notification_permission_denied": "L'autorizzazione alle notifiche è stata negata in modo permanente, abilitala manualmente nelle impostazioni",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "Pagamento insufficiente",
1186 "trade_state_unpaid": "Non pagato",
1187 "trades": "Operazioni",
1188 + "transaction": "Transazione",
1189 "transaction_commited": "Transazione confermata",
1190 "transaction_cost": "Costo della transazione",
1191 "transaction_details_amount": "Importo",
res/values/strings_ja.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "有効なカード",
14 "activeConnectionsPrompt": "アクティブな接続はここに表示されます",
15 "add": "追加",
16 + "add_a_note": "メモを追加する",
17 "add_account": "アカウントを追加",
18 "add_contact": "連絡先を追加",
19 "add_contact_to_address_book": "この連絡先をアドレス帳に追加しますか?",
@@ -680,6 +681,7 @@
681 "none_of_selected_providers_can_exchange": "選択したプロバイダーはいずれもこのスワップを実行できません",
682 "noNFTYet": "NFTはまだありません",
683 "normal": "通常",
684 + "note": "注記",
685 "note_optional": "メモ(任意)",
686 "note_tap_to_change": "メモ(タップして変更)",
687 "notification_permission_denied": "通知の権限が永久に拒否されました。設定で手動で有効にしてください",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "支払い不足",
1186 "trade_state_unpaid": "未払い",
1187 "trades": "取引",
1188 + "transaction": "取引",
1189 "transaction_commited": "トランザクションがコミットされました",
1190 "transaction_cost": "取引手数料",
1191 "transaction_details_amount": "金額",
res/values/strings_ko.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "활성화된 카드",
14 "activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다",
15 "add": "추가",
16 + "add_a_note": "메모 추가",
17 "add_account": "계정 추가",
18 "add_contact": "연락처 추가",
19 "add_contact_to_address_book": "이 연락처를 주소록에 추가하시겠습니까?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "선택한 제공업체 중 이 스왑을 지원하는 곳이 없습니다",
681 "noNFTYet": "아직 NFT가 없습니다",
682 "normal": "일반",
683 + "note": "메모",
684 "note_optional": "메모(선택 사항)",
685 "note_tap_to_change": "메모 (탭하여 변경)",
686 "notification_permission_denied": "알림 권한이 영구적으로 거부되었습니다. 설정에서 수동으로 활성화해 주세요.",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "지불 부족",
1186 "trade_state_unpaid": "미결제",
1187 "trades": "거래",
1188 + "transaction": "거래",
1189 "transaction_commited": "트랜잭션이 커밋되었습니다",
1190 "transaction_cost": "거래 수수료",
1191 "transaction_details_amount": "금액",
res/values/strings_my.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "အသုံးပြုနေသောကတ်များ",
14 "activeConnectionsPrompt": "လက်ရှိ ချိတ်ဆက်မှုများကို ဤနေရာတွင် ပြသပါမည်",
15 "add": "ထည့်ရန်",
16 + "add_a_note": "မှတ်စုတစ်ခုထည့်ပါ။",
17 "add_account": "အကောင့်ထည့်ရန်",
18 "add_contact": "အဆက်အသွယ် ထည့်ရန်",
19 "add_contact_to_address_book": "ဒီအဆက်အသွယ်ကို သင့်လိပ်စာစာအုပ်ထဲ ထည့်ချင်ပါသလား။",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "ရွေးချယ်ထားသော ပံ့ပိုးပေးသူများထဲမှ မည်သူမျှ ဒီ swap ကို မလုပ်နိုင်ပါ",
681 "noNFTYet": "NFT မရှိသေးပါ",
682 "normal": "ပုံမှန်",
683 + "note": "မှတ်ချက်",
684 "note_optional": "မှတ်ချက် (မဖြည့်လည်းရသည်)",
685 "note_tap_to_change": "မှတ်ချက် (ပြောင်းလဲရန် နှိပ်ပါ)",
686 "notification_permission_denied": "အသိပေးချက်ခွင့်ပြုချက်ကို အပြီးတိုင် ငြင်းပယ်ထားပါသည်၊ ကျေးဇူးပြု၍ ချိန်ညှိချက်များတွင် လက်ဖြင့် ဖွင့်ပေးပါ",
@@ -1182,6 +1184,7 @@
1184 "trade_state_underpaid": "ပေးချေမှုမလုံလောက်ပါ",
1185 "trade_state_unpaid": "မပေးချေရသေး",
1186 "trades": "အရောင်းအဝယ်များ",
1187 + "transaction": "ငွေလွှဲခြင်း။",
1188 "transaction_commited": "ငွေလွှဲမှု အတည်ပြုပြီးပါပြီ",
1189 "transaction_cost": "ငွေလွှဲခ ကုန်ကျစရိတ်",
1190 "transaction_details_amount": "ပမာဏ",
res/values/strings_nl.arb
+6 -3
@@ -13,6 +13,7 @@
13 "active_cards": "Actieve kaarten",
14 "activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven",
15 "add": "Toevoegen",
16 + "add_a_note": "Voeg een notitie toe",
17 "add_account": "Account toevoegen",
18 "add_contact": "Contactpersoon toevoegen",
19 "add_contact_to_address_book": "Wil je dit contact toevoegen aan je adresboek?",
@@ -676,9 +677,10 @@
677 "none_of_selected_providers_can_exchange": "Geen van de geselecteerde providers kan deze swap maken",
678 "noNFTYet": "Nog geen NFT's",
679 "normal": "Normaal",
679 - "note_optional": "Opmerking (optioneel)",
680 - "note_tap_to_change": "Opmerking (tik om te wijzigen)",
681 - "notification_permission_denied": "Meldingstoestemming is permanent geweigerd, schakel deze handmatig in via de instellingen",
680 + "note": "Opmerking",
681 + "note_optional": "Notitie (optioneel)",
682 + "note_tap_to_change": "Notitie (tik om te wijzigen)",
683 + "notification_permission_denied": "Meldingstoestemming is permanent geweigerd. Schakel deze handmatig in via de instellingen.",
684 "nullURIError": "URI is null",
685 "offer_expires_in": "Aanbieding verloopt over: ",
686 "offline": "Offline",
@@ -1178,6 +1180,7 @@
1180 "trade_state_trading": "Handel",
1181 "trade_state_underpaid": "Te weinig betaald",
1182 "trade_state_unpaid": "Onbetaald",
1183 + "transaction": "Transactie",
1184 "trades": "Trades",
1185 "transaction_commited": "Transactie vastgelegd",
1186 "transaction_cost": "Transactiekosten",
res/values/strings_pl.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Aktywne karty",
14 "activeConnectionsPrompt": "Aktywne połączenia pojawią się tutaj",
15 "add": "Dodaj",
16 + "add_a_note": "Dodaj notatkę",
17 "add_account": "Dodaj konto",
18 "add_contact": "Dodaj kontakt",
19 "add_contact_to_address_book": "Czy chcesz dodać ten kontakt do swojej książki adresowej?",
@@ -678,6 +679,7 @@
679 "none_of_selected_providers_can_exchange": "Żaden z wybranych dostawców nie może wykonać tej wymiany",
680 "noNFTYet": "Brak NFT",
681 "normal": "Normalny",
682 + "note": "Notatka",
683 "note_optional": "Notatka (opcjonalnie)",
684 "note_tap_to_change": "Notatka (stuknij, aby zmienić)",
685 "notification_permission_denied": "Uprawnienie do powiadomień zostało trwale odrzucone. Włącz je ręcznie w ustawieniach.",
@@ -1181,6 +1183,7 @@
1183 "trade_state_underpaid": "Niedopłacone",
1184 "trade_state_unpaid": "Nieopłacone",
1185 "trades": "Transakcje",
1186 + "transaction": "Transakcja",
1187 "transaction_commited": "Transakcja zatwierdzona",
1188 "transaction_cost": "Koszt transakcji",
1189 "transaction_details_amount": "Kwota",
res/values/strings_pt.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Cartões ativos",
14 "activeConnectionsPrompt": "As conexões ativas aparecerão aqui",
15 "add": "Adicionar",
16 + "add_a_note": "Adicione uma nota",
17 "add_account": "Adicionar conta",
18 "add_contact": "Adicionar contato",
19 "add_contact_to_address_book": "Você gostaria de adicionar este contato ao seu catálogo de endereços?",
@@ -680,6 +681,7 @@
681 "none_of_selected_providers_can_exchange": "Nenhum dos provedores selecionados pode realizar esta troca",
682 "noNFTYet": "Ainda não há NFTs",
683 "normal": "Normal",
684 + "note": "Observação",
685 "note_optional": "Nota (opcional)",
686 "note_tap_to_change": "Nota (toque para mudar)",
687 "notification_permission_denied": "A permissão de notificações foi negada permanentemente. Ative-a manualmente nas configurações.",
@@ -1184,6 +1186,7 @@
1186 "trade_state_underpaid": "Pago insuficiente",
1187 "trade_state_unpaid": "Não pago",
1188 "trades": "Negociações",
1189 + "transaction": "Transação",
1190 "transaction_commited": "Transação confirmada",
1191 "transaction_cost": "Custo da transação",
1192 "transaction_details_amount": "Valor",
res/values/strings_ru.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Активные карты",
14 "activeConnectionsPrompt": "Здесь будут отображаться активные подключения",
15 "add": "Добавить",
16 + "add_a_note": "Добавить заметку",
17 "add_account": "Добавить аккаунт",
18 "add_contact": "Добавить контакт",
19 "add_contact_to_address_book": "Хотите добавить этот контакт в адресную книгу?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Ни один из выбранных провайдеров не может выполнить этот обмен",
681 "noNFTYet": "Пока нет NFT",
682 "normal": "Обычный",
683 + "note": "Примечание",
684 "note_optional": "Примечание (необязательно)",
685 "note_tap_to_change": "Примечание (нажмите, чтобы изменить)",
686 "notification_permission_denied": "Разрешение на уведомления было навсегда отклонено, пожалуйста, включите его вручную в настройках",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "Недоплачено",
1186 "trade_state_unpaid": "Не оплачено",
1187 "trades": "Сделки",
1188 + "transaction": "Сделка",
1189 "transaction_commited": "Транзакция подтверждена",
1190 "transaction_cost": "Стоимость транзакции",
1191 "transaction_details_amount": "Сумма",
res/values/strings_th.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "บัตรที่ใช้งานอยู่",
14 "activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะแสดงที่นี่",
15 "add": "เพิ่ม",
16 + "add_a_note": "เพิ่มบันทึก",
17 "add_account": "เพิ่มบัญชี",
18 "add_contact": "เพิ่มผู้ติดต่อ",
19 "add_contact_to_address_book": "คุณต้องการเพิ่มผู้ติดต่อนี้ลงในสมุดที่อยู่ของคุณหรือไม่?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "ไม่มีผู้ให้บริการที่เลือกไว้รายใดสามารถทำการสวอปนี้ได้",
681 "noNFTYet": "ยังไม่มี NFT",
682 "normal": "ปกติ",
683 + "note": "บันทึก",
684 "note_optional": "หมายเหตุ (ไม่จำเป็น)",
685 "note_tap_to_change": "หมายเหตุ (แตะเพื่อเปลี่ยน)",
686 "notification_permission_denied": "สิทธิ์การแจ้งเตือนถูกปฏิเสธอย่างถาวร โปรดเปิดใช้งานด้วยตนเองในการตั้งค่า",
@@ -1182,6 +1184,7 @@
1184 "trade_state_underpaid": "ชำระไม่ครบ",
1185 "trade_state_unpaid": "ยังไม่ได้ชำระ",
1186 "trades": "การเทรด",
1187 + "transaction": "ธุรกรรม",
1188 "transaction_commited": "ธุรกรรมถูกบันทึกแล้ว",
1189 "transaction_cost": "ค่าธรรมเนียมธุรกรรม",
1190 "transaction_details_amount": "จำนวน",
res/values/strings_tl.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Mga aktibong card",
14 "activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon",
15 "add": "Magdagdag",
16 + "add_a_note": "Magdagdag ng tala",
17 "add_account": "Magdagdag ng account",
18 "add_contact": "Magdagdag ng kontak",
19 "add_contact_to_address_book": "Gusto mo bang idagdag ang contact na ito sa iyong address book?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Wala sa mga napiling provider ang makakagawa ng swap na ito",
681 "noNFTYet": "Wala pang mga NFT",
682 "normal": "Normal",
683 + "note": "Tandaan",
684 "note_optional": "Tala (opsyonal)",
685 "note_tap_to_change": "Tala (i-tap para baguhin)",
686 "notification_permission_denied": "Permanenteng tinanggihan ang pahintulot para sa mga abiso. Pakipaganahin ito nang manu-mano sa mga setting.",
@@ -1182,6 +1184,7 @@
1184 "trade_state_underpaid": "Kulang ang bayad",
1185 "trade_state_unpaid": "Hindi bayad",
1186 "trades": "Mga Trade",
1187 + "transaction": "Transaksyon",
1188 "transaction_commited": "Nakumpirma ang transaksyon",
1189 "transaction_cost": "Gastos sa Transaksyon",
1190 "transaction_details_amount": "Halaga",
res/values/strings_tr.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Aktif kartlar",
14 "activeConnectionsPrompt": "Etkin bağlantılar burada görünecek",
15 "add": "Ekle",
16 + "add_a_note": "Not ekle",
17 "add_account": "Hesap Ekle",
18 "add_contact": "Kişi ekle",
19 "add_contact_to_address_book": "Bu kişiyi adres defterinize eklemek ister misiniz?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Seçilen sağlayıcıların hiçbiri bu takası gerçekleştiremez",
681 "noNFTYet": "Henüz NFT yok",
682 "normal": "Normal",
683 + "note": "Not",
684 "note_optional": "Not (isteğe bağlı)",
685 "note_tap_to_change": "Not (değiştirmek için dokunun)",
686 "notification_permission_denied": "Bildirim izni kalıcı olarak reddedildi, lütfen ayarlardan manuel olarak etkinleştirin",
@@ -1182,6 +1184,7 @@
1184 "trade_state_underpaid": "Eksik ödendi",
1185 "trade_state_unpaid": "Ödenmedi",
1186 "trades": "Alım satımlar",
1187 + "transaction": "İşlem",
1188 "transaction_commited": "İşlem onaylandı",
1189 "transaction_cost": "İşlem maliyeti",
1190 "transaction_details_amount": "Miktar",
res/values/strings_uk.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Активні картки",
14 "activeConnectionsPrompt": "Активні підключення з’являться тут",
15 "add": "Додати",
16 + "add_a_note": "Додайте примітку",
17 "add_account": "Додати акаунт",
18 "add_contact": "Додати контакт",
19 "add_contact_to_address_book": "Бажаєте додати цей контакт до своєї адресної книги?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "Жоден із вибраних провайдерів не може виконати цей своп",
681 "noNFTYet": "NFT ще немає",
682 "normal": "Звичайний",
683 + "note": "Примітка",
684 "note_optional": "Примітка (необов’язково)",
685 "note_tap_to_change": "Примітка (натисніть, щоб змінити)",
686 "notification_permission_denied": "Дозвіл на сповіщення було назавжди відхилено, будь ласка, увімкніть його вручну в налаштуваннях",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "Недоплачено",
1186 "trade_state_unpaid": "Не оплачено",
1187 "trades": "Угоди",
1188 + "transaction": "Транзакція",
1189 "transaction_commited": "Транзакцію підтверджено",
1190 "transaction_cost": "Вартість транзакції",
1191 "transaction_details_amount": "Сума",
res/values/strings_ur.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "فعال کارڈز",
14 "activeConnectionsPrompt": "فعال کنکشنز یہاں ظاہر ہوں گے",
15 "add": "شامل کریں",
16 + "add_a_note": "ایک نوٹ شامل کریں۔",
17 "add_account": "اکاؤنٹ شامل کریں",
18 "add_contact": "رابطہ شامل کریں",
19 "add_contact_to_address_book": "کیا آپ اس رابطے کو اپنی ایڈریس بک میں شامل کرنا چاہیں گے؟",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "منتخب کردہ فراہم کنندگان میں سے کوئی بھی یہ سواپ نہیں کر سکتا",
681 "noNFTYet": "ابھی تک کوئی NFTs نہیں",
682 "normal": "معمول",
683 + "note": "نوٹ",
684 "note_optional": "نوٹ (اختیاری)",
685 "note_tap_to_change": "نوٹ (تبدیل کرنے کے لیے ٹیپ کریں)",
686 "notification_permission_denied": "نوٹیفکیشن کی اجازت مستقل طور پر مسترد کر دی گئی ہے، براہِ کرم اسے سیٹنگز میں دستی طور پر فعال کریں",
@@ -1184,6 +1186,7 @@
1186 "trade_state_underpaid": "کم ادائیگی",
1187 "trade_state_unpaid": "غیر ادا شدہ",
1188 "trades": "تبادلے",
1189 + "transaction": "لین دین",
1190 "transaction_commited": "ٹرانزیکشن مکمل ہو گئی",
1191 "transaction_cost": "لین دین کی لاگت",
1192 "transaction_details_amount": "رقم",
res/values/strings_vi.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Thẻ đang hoạt động",
14 "activeConnectionsPrompt": "Các kết nối đang hoạt động sẽ hiển thị ở đây",
15 "add": "Thêm",
16 + "add_a_note": "Thêm ghi chú",
17 "add_account": "Thêm tài khoản",
18 "add_contact": "Thêm liên hệ",
19 "add_contact_to_address_book": "Bạn có muốn thêm liên hệ này vào sổ địa chỉ không?",
@@ -677,6 +678,7 @@
678 "none_of_selected_providers_can_exchange": "Không có nhà cung cấp nào trong số các nhà cung cấp đã chọn có thể thực hiện hoán đổi này",
679 "noNFTYet": "Chưa có NFT nào",
680 "normal": "Bình thường",
681 + "note": "Ghi chú",
682 "note_optional": "Ghi chú (tùy chọn)",
683 "note_tap_to_change": "Ghi chú (chạm để thay đổi)",
684 "notification_permission_denied": "Quyền thông báo đã bị từ chối vĩnh viễn, vui lòng bật thủ công trong cài đặt",
@@ -1179,6 +1181,7 @@
1181 "trade_state_underpaid": "Trả thiếu",
1182 "trade_state_unpaid": "Chưa thanh toán",
1183 "trades": "Giao dịch",
1184 + "transaction": "Giao dịch",
1185 "transaction_commited": "Giao dịch đã được xác nhận",
1186 "transaction_cost": "Chi phí giao dịch",
1187 "transaction_details_amount": "Số lượng",
res/values/strings_yo.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "Àwọn káàdì tó ń ṣiṣẹ́",
14 "activeConnectionsPrompt": "Awọn asopọ tó ń ṣiṣẹ yóò hàn níbí",
15 "add": "Fi kún",
16 + "add_a_note": "Fi akọsilẹ kun",
17 "add_account": "Ṣàfikún Àkántì",
18 "add_contact": "Ṣàfikún olubasọrọ",
19 "add_contact_to_address_book": "Ṣe o fẹ́ fi olubasọrọ yìí kún ìwé àdírẹ́sì rẹ?",
@@ -680,6 +681,7 @@
681 "none_of_selected_providers_can_exchange": "Ko si ọkan ninu awọn olupese tí a yàn tó lè ṣe paṣipaarọ yìí",
682 "noNFTYet": "Ko si NFT sibẹsibẹ",
683 "normal": "Deede",
684 + "note": "Akiyesi",
685 "note_optional": "Àkọsílẹ̀ (àṣàyàn)",
686 "note_tap_to_change": "Akọsilẹ (tẹ lati yí padà)",
687 "notification_permission_denied": "A ti kọ igbanilaaye iwifunni patapata, jọwọ mu un ṣiṣẹ lọ́wọ́ rẹ nínú àwọn eto",
@@ -1183,6 +1185,7 @@
1185 "trade_state_underpaid": "A san iye tó kéré ju",
1186 "trade_state_unpaid": "A kò tíì san",
1187 "trades": "Àwọn ìṣòwò",
1188 + "transaction": "Idunadura",
1189 "transaction_commited": "Idunadura ti fọwọsi",
1190 "transaction_cost": "Iye Iṣowo",
1191 "transaction_details_amount": "Iye",
res/values/strings_zh.arb
+3
@@ -13,6 +13,7 @@
13 "active_cards": "已激活的卡",
14 "activeConnectionsPrompt": "活跃连接将显示在此处",
15 "add": "添加",
16 + "add_a_note": "添加注释",
17 "add_account": "添加账户",
18 "add_contact": "添加联系人",
19 "add_contact_to_address_book": "您想将此联系人添加到地址簿吗?",
@@ -679,6 +680,7 @@
680 "none_of_selected_providers_can_exchange": "所选的提供商均无法完成此兑换",
681 "noNFTYet": "暂无 NFT",
682 "normal": "普通",
683 + "note": "笔记",
684 "note_optional": "备注(可选)",
685 "note_tap_to_change": "备注(轻触以更改)",
686 "notification_permission_denied": "通知权限已被永久拒绝,请在设置中手动启用",
@@ -1182,6 +1184,7 @@
1184 "trade_state_underpaid": "支付不足",
1185 "trade_state_unpaid": "未付款",
1186 "trades": "交易",
1187 + "transaction": "交易",
1188 "transaction_commited": "交易已提交",
1189 "transaction_cost": "交易费用",
1190 "transaction_details_amount": "金额",