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": "金额",