Transaction details (New UI) (#3070)
What changed, and why it matters
This commit is a user-interface redesign for the transaction details screen in the Cake Wallet cryptocurrency app. It replaces the old full-page transaction details with a new bottom-sheet modal, adds a copy-to-clipboard option for each detail row, and refactors how transaction detail rows are generated. There is no obvious security vulnerability in the changes, but the refactor is large and touches many wallet types, so small functional regressions are possible.
Treat as a routine UI refactor. Review the new `TxDetailRowDefinition` applicability logic to ensure no sensitive fields are shown for the wrong wallet type or direction, and verify that the `launchExplorer` URL construction still uses the correct tx id and cannot be influenced by user-controlled transaction data. No immediate security action is required.
Security signals we found
Large UI refactor with removal of many wallet-specific detail builders
New bottom sheet modal exposes transaction details including tx hash, addresses, amounts, fees, notes, and block explorer links
Copy-to-clipboard added for each detail row via `Clipboard.setData`
Block explorer URLs are still constructed from wallet type/chain id and opened with `launchUrl` in external application mode
Note persistence logic unchanged; still saved to Hive transaction description box keyed by txHash + primary address
No input validation, authentication, or permission changes observed
Evidence from the diff
The patch refactors transaction details presentation. A new TransactionDetailsModal is registered in the dependency injection graph and shown as a DraggableScrollableSheet bottom sheet. Detail rows are now generated declaratively via TxDetailRowDefinition.defs instead of per-wallet-type methods. It adds AddressListItem and ConfirmationsListItem subclasses, supports bottomWidget/trailingWidget in list rows, and moves explorer launching and note editing into the view model. The old per-wallet _add* methods are removed. No cryptographic, networking, or permission changes are present.
Changed components
lib/view_model/transaction_details_view_model.dartlib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dartlib/new-ui/widgets/coins_page/assets_history/history_section.dartlib/di.dartlib/src/widgets/new_list_row/list_item_regular_row_widget.dartlib/src/widgets/new_list_row/new_list_section.dartlib/src/widgets/new_list_row/list_Item_style_wrapper.dartlib/entities/new_ui_entities/list_item/list_item_regular_row.dartcw_core/lib/wallet_type.dartInspect captured patch +761 / −809
diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart
index 05ef1417..10a472d6 100644
--- a/cw_core/lib/wallet_type.dart
+++ b/cw_core/lib/wallet_type.dart
@@ -25,6 +25,21 @@ const walletTypes = [
WalletType.bsc,
];
+const electrumWalletTypes = [
+ WalletType.bitcoin,
+ WalletType.litecoin,
+ WalletType.bitcoinCash,
+ WalletType.dogecoin
+];
+
+const evmWalletTypes = [
+ WalletType.ethereum,
+ WalletType.polygon,
+ WalletType.base,
+ WalletType.arbitrum,
+ WalletType.bsc
+];
+
@HiveType(typeId: WALLET_TYPE_TYPE_ID)
enum WalletType {
@HiveField(0)
diff --git a/lib/di.dart b/lib/di.dart
index 156a3624..715c8866 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -60,6 +60,7 @@ import 'package:cake_wallet/new-ui/pages/lightning_username_page.dart';
import 'package:cake_wallet/new-ui/pages/receive_page.dart';
import 'package:cake_wallet/new-ui/viewmodels/lightning_username/lightning_username_bloc.dart';
import 'package:cake_wallet/new-ui/widgets/addresses_page/address_label_input.dart';
+import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart';
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_label_modal.dart';
import 'package:cake_wallet/new-ui/pages/swap_page.dart';
import 'package:cake_wallet/order/order.dart';
@@ -1419,6 +1420,11 @@ Future<void> setup({
}
);
+ getIt.registerFactoryParam<TransactionDetailsModal, TransactionInfo, void>(
+ (transactionInfo, _) => TransactionDetailsModal(transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
+ param1: [transactionInfo, false]))
+ );
+
getIt.registerFactoryParam<TransactionDetailsPage, TransactionInfo, void>(
(TransactionInfo transactionInfo, _) => TransactionDetailsPage(
transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
diff --git a/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart b/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart
index 1f23e2b0..a9ef260d 100644
--- a/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart
+++ b/lib/entities/new_ui_entities/list_item/list_item_regular_row.dart
@@ -11,6 +11,8 @@ class ListItemRegularRow extends ListItem {
this.onTap,
this.trailingIconPath,
this.showArrow = true,
+ this.bottomWidget,
+ this.trailingWidget,
this.truncateTrailingText = false,
this.foregroundColor,
this.trailingIconSize
@@ -22,6 +24,8 @@ class ListItemRegularRow extends ListItem {
final String? trailingIconPath;
final VoidCallback? onTap;
final bool showArrow;
+ final Widget? bottomWidget;
+ final Widget? trailingWidget;
final bool truncateTrailingText;
final Color? foregroundColor;
final double? trailingIconSize;
diff --git a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
index aa6672fd..a205ce0e 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
@@ -1,9 +1,11 @@
+import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/anonpay_history_tile.dart';
import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/history_order_tile.dart';
import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/history_tile.dart';
import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/history_trade_tile.dart';
import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/payjoin_history_tile.dart';
+import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/utils/date_formatter.dart';
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';
import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/sync_status.dart';
-import 'package:cw_core/utils/print_verbose.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:intl/intl.dart';
@@ -70,8 +71,10 @@ class HistorySection extends StatelessWidget {
asset = CryptoCurrency.btcln;
return GestureDetector(
- onTap: () => Navigator.of(context)
- .pushNamed(Routes.transactionDetails, arguments: transaction),
+ onTap: () {
+ final page = getIt.get<TransactionDetailsModal>(param1: transaction);
+ showModalBottomSheet(isScrollControlled:true,context: context, builder: (context) => page);
+ },
child: HistoryTile(
title: item.formattedTitle + transactionType,
date: DateFormat('HH:mm').format(transaction.date),
diff --git a/lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart b/lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart
new file mode 100644
index 00000000..fe7b15f0
--- /dev/null
+++ b/lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart
@@ -0,0 +1,226 @@
+import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item.dart';
+import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
+import 'package:cake_wallet/routes.dart';
+import 'package:cake_wallet/src/screens/transaction_details/confirmations_list_item.dart';
+import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
+import 'package:cake_wallet/src/screens/transaction_details/address_list_item.dart';
+import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
+import 'package:cake_wallet/utils/address_formatter.dart';
+import 'package:cake_wallet/view_model/transaction_details_view_model.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+
+class TransactionDetailsModal extends StatefulWidget {
+ const TransactionDetailsModal({super.key, required this.transactionDetailsViewModel});
+
+ final TransactionDetailsViewModel transactionDetailsViewModel;
+
+ @override
+ State<TransactionDetailsModal> createState() => _TransactionDetailsModalState();
+}
+
+class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
+ final TextEditingController noteController = TextEditingController();
+ final FocusNode noteFocusNode = FocusNode();
+
+ @override
+ void initState() {
+ super.initState();
+ noteController.text = widget.transactionDetailsViewModel.note;
+
+ noteFocusNode.addListener(() {
+ if (!noteFocusNode.hasFocus) {
+ widget.transactionDetailsViewModel.updateNote(noteController.text);
+ }
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return DraggableScrollableSheet(
+ expand: false,
+ initialChildSize: 0.6,
+ minChildSize: 0.25,
+ maxChildSize: 0.9,
+ snap: true,
+ snapSizes: const [0.6, 0.9],
+ builder: (context, controller) => SafeArea(
+ bottom: false,
+ child: Padding(
+ padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
+ child: GestureDetector(
+ onTap: FocusScope.of(context).unfocus,
+ child: Container(
+ decoration: BoxDecoration(
+ color: Theme.of(context).colorScheme.surface,
+ borderRadius: BorderRadius.vertical(top: Radius.circular(25))),
+ child: Column(
+ children: [
+ ModalTopBar(
+ title: S.of(context).transaction,
+ leadingIcon: Icon(Icons.close),
+ onLeadingPressed: Navigator.of(context).pop,
+ ),
+ Expanded(
+ child: SingleChildScrollView(
+ controller: controller,
+ child: Column(
+ children: [
+ Image.asset(
+ widget.transactionDetailsViewModel.transactionAsset.iconPath ??
+ "",
+ width: 64,
+ height: 64),
+ SizedBox(height: 10),
+ Text(
+ widget.transactionDetailsViewModel.formattedTitle +
+ widget.transactionDetailsViewModel.formattedStatus,
+ style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
+ ),
+ Text(
+ widget.transactionDetailsViewModel.transactionInfo
+ .amountFormatted(),
+ style: TextStyle(fontSize: 28),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ spacing: 12,
+ children: [
+ NewListSections(sections: {
+ "": widget.transactionDetailsViewModel.items
+ .map((item) {
+ if (item.value.isEmpty) return null;
+
+ final shouldBuildBottomWidget =
+ item.value.length > 25;
+
+ return ListItemRegularRow(
+ onTap: () {
+ Clipboard.setData(
+ ClipboardData(text: item.value));
+ },
+ showArrow: false,
+ keyValue:
+ ((item.key as ValueKey?)?.value as String?) ??
+ item.title,
+ label: item.title,
+ trailingWidget: shouldBuildBottomWidget
+ ? null
+ : _buildTrailingWIdget(item),
+ bottomWidget: shouldBuildBottomWidget
+ ? _buildBottomWidget(item)
+ : null);
+ })
+ .whereType<ListItem>()
+ .toList(),
+ }),
+ Container(
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(20),
+ color: Theme.of(context).colorScheme.surfaceContainer),
+ child: Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Column(
+ spacing: 8,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(S.of(context).note),
+ TextField(
+ focusNode: noteFocusNode,
+ controller: noteController,
+ decoration: InputDecoration(
+ hintText: S.of(context).add_a_note,
+ border: InputBorder.none,
+ focusedBorder: InputBorder.none,
+ enabledBorder: InputBorder.none,
+ contentPadding: EdgeInsets.zero,
+ isDense: true),
+ )
+ ],
+ ),
+ ),
+ ),
+ Observer(
+ builder: (_) => NewListSections(sections: {
+ "view tx": [
+ ListItemRegularRow(
+ keyValue: "view tx on",
+ label: widget.transactionDetailsViewModel
+ .explorerDescription,
+ onTap: widget
+ .transactionDetailsViewModel.launchExplorer,
+ foregroundColor:
+ Theme.of(context).colorScheme.primary,
+ trailingIconPath: "assets/new-ui/link_arrow.svg",
+ trailingIconSize: 8)
+ ],
+ if (widget.transactionDetailsViewModel.canReplaceByFee)
+ "rbf": [
+ ListItemRegularRow(
+ keyValue: "replace by fee",
+ label: S.of(context).bump_fee,
+ onTap: () {
+ Navigator.of(context)
+ .pushNamed(Routes.bumpFeePage, arguments: [
+ widget.transactionDetailsViewModel
+ .transactionInfo,
+ widget.transactionDetailsViewModel
+ .rawTransaction
+ ]);
+ })
+ ]
+ }),
+ )
+ ],
+ ),
+ ),
+ SizedBox(height: MediaQuery.of(context).viewPadding.bottom)
+ ],
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ ),
+ ));
+ }
+
+ Widget _buildTrailingWIdget(TransactionDetailsListItem item) {
+ return switch (item.runtimeType) {
+ ConfirmationsListItem => Row(
+ children: [
+ Text((item as ConfirmationsListItem).current.toString(),
+ style: TextStyle(color: Theme.of(context).colorScheme.primary)),
+ if (item.needed > 0)
+ Text("/${item.needed}",
+ style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant))
+ ],
+ ),
+ _ => Text(
+ item.value,
+ style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
+ )
+ };
+ }
+
+ Widget _buildBottomWidget(TransactionDetailsListItem item) {
+ return switch (item.runtimeType) {
+ AddressListItem => AddressFormatter.buildSegmentedAddress(
+ address: item.value,
+ evenTextStyle: TextStyle(
+ fontSize: 12,
+ fontFamily: "IBM Plex Mono",
+ color: Theme.of(context).colorScheme.onSurface)),
+ _ => Text(
+ item.value,
+ style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),
+ )
+ };
+ }
+}
diff --git a/lib/src/screens/transaction_details/address_list_item.dart b/lib/src/screens/transaction_details/address_list_item.dart
new file mode 100644
index 00000000..1e969f58
--- /dev/null
+++ b/lib/src/screens/transaction_details/address_list_item.dart
@@ -0,0 +1,5 @@
+import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
+
+class AddressListItem extends TransactionDetailsListItem {
+ AddressListItem({required super.title, required super.value, super.key});
+}
\ No newline at end of file
diff --git a/lib/src/screens/transaction_details/confirmations_list_item.dart b/lib/src/screens/transaction_details/confirmations_list_item.dart
new file mode 100644
index 00000000..a1c7d441
--- /dev/null
+++ b/lib/src/screens/transaction_details/confirmations_list_item.dart
@@ -0,0 +1,12 @@
+import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
+
+class ConfirmationsListItem extends TransactionDetailsListItem {
+ late final int current;
+ late final int needed;
+
+ ConfirmationsListItem({required super.title, required super.value, super.key}) {
+ final parts = value.split("/");
+ current = int.tryParse(parts.first)??0;
+ needed = int.tryParse(parts.last)??0;
+ }
+}
\ No newline at end of file
diff --git a/lib/src/widgets/new_list_row/list_Item_style_wrapper.dart b/lib/src/widgets/new_list_row/list_Item_style_wrapper.dart
index 1e4d5e70..88ebf59c 100644
--- a/lib/src/widgets/new_list_row/list_Item_style_wrapper.dart
+++ b/lib/src/widgets/new_list_row/list_Item_style_wrapper.dart
@@ -7,14 +7,14 @@ class ListItemStyleWrapper extends StatelessWidget {
required this.isLastInSection,
required this.builder,
this.onTap,
- this.height = 50,
this.iconPath,
+ this.height,
});
final String? iconPath;
final bool isFirstInSection;
final bool isLastInSection;
- final double height;
+ final double? height;
final VoidCallback? onTap;
final Widget Function(BuildContext context, TextStyle textStyle, TextStyle labelStyle) builder;
@@ -59,7 +59,7 @@ class ListItemStyleWrapper extends StatelessWidget {
child: InkWell(
onTap: onTap,
child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 12),
+ padding: EdgeInsets.symmetric(horizontal: 12, vertical: height == null ? 12 : 0),
child: builder(context, textStyle, labelStyle))))),
if(iconPath != null && isLastInSection == false) Container(
color: theme.colorScheme.surfaceContainer,
diff --git a/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart b/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart
index 7705cdca..e60dcfba 100644
--- a/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart
+++ b/lib/src/widgets/new_list_row/list_item_regular_row_widget.dart
@@ -19,6 +19,8 @@ class ListItemRegularRowWidget extends StatelessWidget {
this.truncateTrailingText = false,
this.foregroundColor,
this.trailingIconSize,
+ this.bottomWidget,
+ this.trailingWidget
});
final String keyValue;
@@ -31,6 +33,8 @@ class ListItemRegularRowWidget extends StatelessWidget {
final bool isLastInSection;
final bool showArrow;
final String? trailingIconPath;
+ final Widget? bottomWidget;
+ final Widget? trailingWidget;
final bool truncateTrailingText;
final Color? foregroundColor;
final double? trailingIconSize;
@@ -38,74 +42,84 @@ class ListItemRegularRowWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
- final trailingTextToShow = truncateTrailingText && trailingText != null && trailingText!.length > 20
- ? "${trailingText!.substring(0, 17)}..."
- : trailingText;
+ final trailingTextToShow =
+ truncateTrailingText && trailingText != null && trailingText!.length > 20
+ ? "${trailingText!.substring(0, 17)}..."
+ : trailingText;
return ListItemStyleWrapper(
onTap: onTap,
iconPath: iconPath,
isFirstInSection: isFirstInSection,
isLastInSection: isLastInSection,
- height: subtitle != null ? 64 : 50,
builder: (context, textStyle, labelStyle) {
- return Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
- Expanded(
- child: Row(
- children: [
- if(iconPath != null)
- Padding(
- padding: const EdgeInsets.only(right: 12.0),
- child: CakeImageWidget(imageUrl: iconPath!, width: 24,height: 24,)
- ),
- Flexible(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(label, style: foregroundColor == null ? textStyle : textStyle.copyWith(color: foregroundColor)),
- if (subtitle != null)
- Text(
- subtitle!,
- style: labelStyle.copyWith(fontSize: 12),
- ),
- ],
- ),
- ),
- ],
- ),
- ),
-
Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- if (trailingTextToShow != null)
- Padding(
- padding: const EdgeInsets.only(right: 8.0),
- child: Text(
- trailingTextToShow,
- style: labelStyle,
- ),
+ Expanded(
+ child: Row(
+ children: [
+ if (iconPath != null)
+ Padding(
+ padding: const EdgeInsets.only(right: 12.0),
+ child: CakeImageWidget(imageUrl: iconPath!, width: 24,height: 24,)
+ ),
+ Flexible(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(label,
+ style: foregroundColor == null
+ ? textStyle
+ : textStyle.copyWith(color: foregroundColor)),
+ if (subtitle != null)
+ Text(
+ subtitle!,
+ style: labelStyle.copyWith(fontSize: 12),
+ ),
+ ],
+ ),
+ ),
+ ],
),
- if(trailingIconPath != null)
- CakeImageWidget(imageUrl:
- trailingIconPath!,
- height: trailingIconSize ?? 18,
- width:trailingIconSize ?? 18,
- colorFilter: ColorFilter.mode(foregroundColor ?? Theme.of(context).colorScheme.onSurfaceVariant,BlendMode.srcIn),
- )
- else if(showArrow)
- CakeImageWidget(imageUrl:
- "assets/new-ui/arrow_forward.svg",
- height: 14,
- color: theme.colorScheme.onSurfaceVariant
- )
+ ),
+ Row(
+ children: [
+ if (trailingTextToShow != null)
+ Padding(
+ padding: const EdgeInsets.only(right: 8.0),
+ child: Text(
+ trailingTextToShow,
+ style: labelStyle,
+ ),
+ ),
+ if (trailingWidget != null)
+ trailingWidget!
+ else if (trailingIconPath != null)
+ CakeImageWidget(imageUrl:
+ trailingIconPath!,
+ height: trailingIconSize ?? 18,
+ width:trailingIconSize ?? 18,
+ colorFilter: ColorFilter.mode(foregroundColor ?? Theme.of(context).colorScheme.onSurfaceVariant,BlendMode.srcIn),
+ )
+ else if (showArrow)
+ CakeImageWidget(imageUrl:
+ "assets/new-ui/arrow_forward.svg",
+ height: 14,
+ color: theme.colorScheme.onSurfaceVariant
+ )
+ ],
+ ),
],
),
+ if (bottomWidget != null) bottomWidget!
],
);
- }
- );
+ });
}
}
diff --git a/lib/src/widgets/new_list_row/list_item_text_field_widget.dart b/lib/src/widgets/new_list_row/list_item_text_field_widget.dart
index 9b248c2d..fd66df2c 100644
--- a/lib/src/widgets/new_list_row/list_item_text_field_widget.dart
+++ b/lib/src/widgets/new_list_row/list_item_text_field_widget.dart
@@ -36,6 +36,7 @@ class _ListItemTextFieldWidgetState extends State<ListItemTextFieldWidget> {
return ListItemStyleWrapper(
isFirstInSection: widget.isFirstInSection,
isLastInSection: widget.isLastInSection,
+ height:50,
builder: (context, textStyle, labelStyle) {
return Row(
children: [
diff --git a/lib/src/widgets/new_list_row/new_list_section.dart b/lib/src/widgets/new_list_row/new_list_section.dart
index b36fc516..21893d81 100644
--- a/lib/src/widgets/new_list_row/new_list_section.dart
+++ b/lib/src/widgets/new_list_row/new_list_section.dart
@@ -104,6 +104,8 @@ class NewListSections extends StatelessWidget {
truncateTrailingText: item.truncateTrailingText,
foregroundColor: item.foregroundColor,
trailingIconSize: item.trailingIconSize,
+ trailingWidget: item.trailingWidget,
+ bottomWidget: item.bottomWidget,
);
}
diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart
index dc49babf..ed2c45e3 100644
--- a/lib/view_model/transaction_details_view_model.dart
+++ b/lib/view_model/transaction_details_view_model.dart
@@ -1,8 +1,13 @@
+import 'package:cake_wallet/reactions/wallet_connect.dart';
+import 'package:cake_wallet/solana/solana.dart';
+import 'package:cake_wallet/src/screens/transaction_details/address_list_item.dart';
+import 'package:cake_wallet/src/screens/transaction_details/confirmations_list_item.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/core/address_validator.dart';
import 'package:cake_wallet/tron/tron.dart';
-import 'package:cake_wallet/wownero/wownero.dart';
+import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/currency_for_wallet_type.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/transaction_info.dart';
@@ -13,10 +18,8 @@ import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/monero/monero.dart';
-import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart';
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart';
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
-import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart';
import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
import 'package:cake_wallet/src/screens/transaction_details/transaction_expandable_list_item.dart';
import 'package:cake_wallet/utils/date_formatter.dart';
@@ -26,12 +29,181 @@ import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
-import 'package:intl/src/intl/date_format.dart';
import 'package:mobx/mobx.dart';
import 'package:url_launcher/url_launcher.dart';
part 'transaction_details_view_model.g.dart';
+bool _trueFunc(_) => true;
+
+bool isLightning(TransactionInfo tx) {
+ printV(tx.additionalInfo);
+ return (tx.additionalInfo["isLightning"] as bool?) ?? false;
+}
+
+class TxDetailRowDefinition {
+ final String keyString;
+ final String title;
+ final String Function(TransactionDetailsViewModelBase) valueGetter;
+ final bool Function(TransactionDetailsViewModelBase) applicable;
+ final dynamic Function({
+ required String title,
+ required String value,
+ required Key key,
+ }) listItemBuilder;
+
+ TxDetailRowDefinition(
+ {required this.keyString,
+ required this.title,
+ required this.valueGetter,
+ this.applicable = _trueFunc,
+ this.listItemBuilder = StandartListItem.new});
+
+ static final List<TxDetailRowDefinition> defs = [
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_date_key",
+ title: S.current.transaction_details_date,
+ valueGetter: (vm) => DateFormatter.withCurrentLocal().format(vm.transactionInfo.date)),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_height_key",
+ title: S.current.transaction_details_height,
+ valueGetter: (vm) => vm.transactionInfo.height.toString(),
+ applicable: (vm) => !([WalletType.solana, WalletType.tron].contains(vm.wallet.type) &&
+ !isLightning(vm.transactionInfo))),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_fee_key",
+ title: S.current.transaction_details_fee,
+ valueGetter: (vm) => vm.transactionInfo.feeFormatted()!,
+ applicable: (vm) =>
+ vm.wallet.type != WalletType.nano &&
+ (vm.transactionInfo.feeFormatted() ?? "").isNotEmpty),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_confirmations_key",
+ title: S.current.confirmations,
+ valueGetter: (vm) => "${vm.transactionInfo.confirmations}/${vm.neededConfirmations}",
+ applicable: (vm) =>
+ [...electrumWalletTypes, ...evmWalletTypes, WalletType.zcash, WalletType.monero]
+ .contains(vm.wallet.type) &&
+ !isLightning(vm.transactionInfo),
+ listItemBuilder: ConfirmationsListItem.new),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_recipient_address_key",
+ title: S.current.transaction_details_recipient_address,
+ valueGetter: (vm) {
+ vm.isRecipientAddressShown = true;
+ switch (vm.wallet.type) {
+ case WalletType.monero:
+ return monero!.getTransactionAddress(
+ vm.wallet,
+ vm.transactionInfo.additionalInfo['accountIndex'] as int,
+ vm.transactionInfo.additionalInfo['addressIndex'] as int);
+ case WalletType.bitcoin:
+ return (bitcoin!.getTransactionAddresses(vm.wallet, vm.transactionInfo) ?? [])
+ .firstOrNull ??
+ "";
+ case WalletType.tron:
+ return tron!.getTronBase58Address(vm.transactionInfo.to!, vm.wallet);
+ default:
+ return vm.transactionInfo.to!;
+ }
+ },
+ applicable: (vm) =>
+ vm.showRecipientAddress &&
+ (vm.transactionInfo.to != null ||
+ [WalletType.monero, WalletType.tron].contains(vm.wallet.type) ||
+ vm.wallet.type == WalletType.bitcoin &&
+ vm.transactionInfo.direction == TransactionDirection.incoming),
+ listItemBuilder: AddressListItem.new),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_source_address_key",
+ title: S.current.transaction_details_source_address,
+ valueGetter: (vm) {
+ switch (vm.wallet.type) {
+ case WalletType.tron:
+ return tron!.getTronBase58Address(vm.transactionInfo.from!, vm.wallet);
+ default:
+ return vm.transactionInfo.from!;
+ }
+ },
+ applicable: (vm) => vm.transactionInfo.from != null,
+ listItemBuilder: AddressListItem.new),
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_address_label_key",
+ title: S.current.address_label,
+ valueGetter: (vm) => monero!.getSubaddressLabel(
+ vm.wallet,
+ vm.transactionInfo.additionalInfo['accountIndex'] as int,
+ vm.transactionInfo.additionalInfo['addressIndex'] as int),
+ applicable: (vm) => vm.wallet.type == WalletType.monero),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_key",
+ title: S.current.transaction_key,
+ valueGetter: (vm) {
+ final descriptionKey =
+ '${vm.transactionInfo.txHash}_${vm.wallet.walletAddresses.primaryAddress}';
+
+ final description = vm.transactionDescriptionBox.values.firstWhere(
+ (val) => val.id == descriptionKey || val.id == vm.transactionInfo.txHash,
+ orElse: () => TransactionDescription(id: descriptionKey));
+ return vm.transactionInfo.additionalInfo['key'] as String? ??
+ description.transactionKey ??
+ "";
+ },
+ applicable: (vm) => vm.wallet.type == WalletType.monero),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_confirmed_key",
+ title: S.current.confirmed_tx,
+ valueGetter: (vm) => (vm.transactionInfo.confirmations > 0).toString(),
+ applicable: (vm) => vm.wallet.type == WalletType.nano),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_memo_key",
+ title: S.current.memo,
+ valueGetter: (vm) => vm.transactionInfo.additionalInfo['memo'] as String,
+ applicable: (vm) =>
+ vm.wallet.type == WalletType.zcash &&
+ vm.transactionInfo.additionalInfo["memo"] != null),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_asset_id_key",
+ title: "Asset ID",
+ valueGetter: (vm) =>
+ vm.transactionInfo.additionalInfo["assetId"] as String? ?? "Unknown asset id",
+ applicable: (vm) => vm.wallet.type == WalletType.zano),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_comment_key",
+ title: S.current.transaction_details_title,
+ valueGetter: (vm) => vm.transactionInfo.additionalInfo['comment'] as String? ?? "",
+ applicable: (vm) => vm.wallet.type == WalletType.zano),
+
+
+ TxDetailRowDefinition(
+ keyString: "standard_list_item_transaction_details_id_key",
+ title: S.current.transaction_details_transaction_id,
+ valueGetter: (vm) => vm.transactionInfo.txHash,
+ ),
+ ];
+}
+
class TransactionDetailsViewModel = TransactionDetailsViewModelBase
with _$TransactionDetailsViewModel;
@@ -49,61 +221,19 @@ abstract class TransactionDetailsViewModelBase with Store {
isRecipientAddressShown = false,
_appStore = appStore,
showRecipientAddress = appStore.settingsStore.shouldSaveRecipientAddress {
- final dateFormat = DateFormatter.withCurrentLocal();
final tx = transactionInfo;
- // TODO: can be cleaned further
- switch (wallet.type) {
- case WalletType.monero:
- _addMoneroListItems(tx, dateFormat);
- break;
- case WalletType.bitcoin:
- _addElectrumListItems(tx, dateFormat, CryptoCurrency.btc);
- if (!canReplaceByFee) _checkForRBF(tx);
- break;
- case WalletType.litecoin:
- _addLitecoinListItems(tx, dateFormat);
- case WalletType.bitcoinCash:
- _addElectrumListItems(tx, dateFormat, CryptoCurrency.bch);
- break;
- case WalletType.haven:
- _addHavenListItems(tx, dateFormat);
- break;
- case WalletType.ethereum:
- case WalletType.polygon:
- case WalletType.base:
- case WalletType.arbitrum:
- case WalletType.bsc:
- _addEVMListItems(tx, dateFormat);
- break;
- case WalletType.nano:
- _addNanoListItems(tx, dateFormat);
- break;
- case WalletType.solana:
- _addSolanaListItems(tx, dateFormat);
- break;
- case WalletType.tron:
- _addTronListItems(tx, dateFormat);
- break;
- case WalletType.wownero:
- _addWowneroListItems(tx, dateFormat);
- break;
- case WalletType.zano:
- _addZanoListItems(tx, dateFormat);
- break;
- case WalletType.decred:
- _addDecredListItems(tx, dateFormat);
- break;
- case WalletType.dogecoin:
- _addDogecoinListItems(tx, dateFormat);
- break;
- case WalletType.zcash:
- _addZcashListItems(tx, dateFormat);
- case WalletType.none:
- case WalletType.banano:
- break;
+ for (final def in TxDetailRowDefinition.defs) {
+ if (def.applicable(this)) {
+ items.add(def.listItemBuilder(
+ title: def.title,
+ value: def.valueGetter(this),
+ key: ValueKey(def.keyString)) as TransactionDetailsListItem);
+ }
}
+ _checkForRBF(tx);
+
final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
final description = transactionDescriptionBox.values.firstWhere(
(val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
@@ -114,7 +244,7 @@ abstract class TransactionDetailsViewModelBase with Store {
if (recipientAddress?.isNotEmpty ?? false) {
items.add(
- StandartListItem(
+ AddressListItem(
title: S.current.transaction_details_recipient_address,
value: recipientAddress!,
key: ValueKey('standard_list_item_${recipientAddress}_key'),
@@ -122,44 +252,28 @@ abstract class TransactionDetailsViewModelBase with Store {
);
}
}
+ }
- final type = wallet.type;
-
- final isLightning = tx.additionalInfo["isLightning"] as bool? ?? false;
-
- if (!isLightning) {
- items.add(
- BlockExplorerListItem(
- title: S.current.view_in_block_explorer,
- value: _explorerDescription(type, wallet.chainId),
- onTap: () async {
- try {
- final uri = Uri.parse(_explorerUrl(type, tx.txHash, wallet.chainId));
- if (await canLaunchUrl(uri)) await launchUrl(
- uri, mode: LaunchMode.externalApplication);
- } catch (e) {}
- },
- key: ValueKey('block_explorer_list_item_${type.name}_wallet_type_key'),
- ),
- );
+ void updateNote(String note) {
+ final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
+ final description = transactionDescriptionBox.values.firstWhere(
+ (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
+ orElse: () => TransactionDescription(id: descriptionKey));
+
+ description.transactionNote = note;
+
+ if (description.isInBox) {
+ description.save();
+ } else {
+ transactionDescriptionBox.add(description);
}
+ }
- items.add(
- TextFieldListItem(
- title: S.current.note_tap_to_change,
- value: description.note,
- onSubmitted: (value) {
- description.transactionNote = value;
-
- if (description.isInBox) {
- description.save();
- } else {
- transactionDescriptionBox.add(description);
- }
- },
- key: ValueKey('textfield_list_item_note_entry_key'),
- ),
- );
+ String get note {
+ final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
+ final description = transactionDescriptionBox.values.firstWhereOrNull(
+ (val) => val.id == descriptionKey || val.id == transactionInfo.txHash);
+ return description?.transactionNote??"";
}
final TransactionInfo transactionInfo;
@@ -176,22 +290,128 @@ abstract class TransactionDetailsViewModelBase with Store {
String? rawTransaction;
TransactionPriority? transactionPriority;
+ CryptoCurrency get transactionAsset {
+ if (isEVMCompatibleChain(wallet.type)) {
+ return evm!.assetOfTransaction(wallet, transactionInfo);
+ }
+
+ return switch (wallet.type) {
+ WalletType.solana => solana!.assetOfTransaction(wallet, transactionInfo),
+ WalletType.tron => tron!.assetOfTransaction(wallet, transactionInfo),
+ WalletType.zano => zano!.assetOfTransaction(wallet, transactionInfo) ?? CryptoCurrency.zano,
+ _ => walletTypeToCryptoCurrency(wallet.type)
+ };
+ }
+
+
+ // TODO integrate these getters with the TransactionInfo object
+ String get formattedPendingStatus {
+ switch (wallet.type) {
+ case WalletType.monero:
+ case WalletType.haven:
+ case WalletType.zano:
+ if (transactionInfo.confirmations >= 0 && transactionInfo.confirmations < 10) {
+ return ' (${transactionInfo.confirmations}/10)';
+ }
+ break;
+ case WalletType.wownero:
+ if (transactionInfo.confirmations >= 0 && transactionInfo.confirmations < 3) {
+ return ' (${transactionInfo.confirmations}/3)';
+ }
+ break;
+ case WalletType.litecoin:
+ bool isPegIn = (transactionInfo.additionalInfo["isPegIn"] as bool?) ?? false;
+ bool isPegOut = (transactionInfo.additionalInfo["isPegOut"] as bool?) ?? false;
+ bool fromPegOut = (transactionInfo.additionalInfo["fromPegOut"] as bool?) ?? false;
+ String str = '';
+ if (transactionInfo.confirmations <= 0) {
+ str = S.current.pending;
+ }
+ if ((isPegOut || fromPegOut) &&
+ transactionInfo.confirmations >= 0 &&
+ transactionInfo.confirmations < 6) {
+ str = " (${transactionInfo.confirmations}/6)";
+ }
+ if (isPegIn) {
+ str += " (Peg In)";
+ }
+ if (isPegOut) {
+ str += " (Peg Out)";
+ }
+ return str;
+ default:
+ return '';
+ }
+
+ return '';
+ }
+
+ String get formattedStatus {
+ if ([
+ WalletType.monero,
+ WalletType.haven,
+ WalletType.wownero,
+ WalletType.litecoin,
+ WalletType.zano,
+ ].contains(wallet.type)) {
+ return formattedPendingStatus;
+ }
+
+ return transactionInfo.isPending ? S.current.pending : '';
+ }
+
+ int get neededConfirmations {
+ switch (wallet.type) {
+ case WalletType.monero:
+ case WalletType.haven:
+ case WalletType.zano:
+ return 10;
+ case WalletType.wownero:
+ return 3;
+ case WalletType.litecoin:
+ bool isPegOut = (transactionInfo.additionalInfo["isPegOut"] as bool?) ?? false;
+ bool fromPegOut = (transactionInfo.additionalInfo["fromPegOut"] as bool?) ?? false;
+ if(isPegOut || fromPegOut)
+ return 6;
+ default:
+ return 0;
+ }
+ return 0;
+ }
+
+
+
+ String get formattedTitle {
+ if (transactionInfo.additionalInfo['autoShield'] == true) {
+ return "Autoshield";
+ }
+ if (transactionInfo.direction == TransactionDirection.incoming) {
+ return S.current.received;
+ }
+
+ return S.current.sent;
+ }
+
@observable
bool canReplaceByFee;
- String _explorerUrl(WalletType type, String txId, int? chainId) {
- if (chainId != null) {
- final explorerUrl = evm!.getExplorerUrlForChainId(chainId);
+ String get _explorerUrl {
+
+ final txId = transactionInfo.id;
+ if (wallet.chainId != null) {
+ final explorerUrl = evm!.getExplorerUrlForChainId(wallet.chainId!);
if (explorerUrl != null) return '$explorerUrl/tx/${txId}';
}
- switch (type) {
+ switch (wallet.type) {
case WalletType.monero:
return 'https://monero.com/tx/${txId}';
case WalletType.bitcoin:
return 'https://mempool.cakewallet.com/${wallet.isTestnet ? "testnet/" : ""}tx/${txId}';
case WalletType.litecoin:
- return 'https://blockchair.com/litecoin/transaction/${txId}';
+ return bitcoin!.txIsMweb(transactionInfo)
+ ? "https://www.mwebexplorer.com/blocks/block/${transactionInfo.height}"
+ : 'https://blockchair.com/litecoin/transaction/${txId}';
case WalletType.bitcoinCash:
return 'https://blockchair.com/bitcoin-cash/transaction/${txId}';
case WalletType.haven:
@@ -229,390 +449,10 @@ abstract class TransactionDetailsViewModelBase with Store {
}
}
- String _explorerDescription(WalletType type, int? chainId) {
- if (chainId != null) {
- final explorerUrl = evm!.getExplorerUrlForChainId(chainId, showProtocol: false);
- if (explorerUrl != null) {
- return S.current.view_transaction_on + explorerUrl;
- }
- }
- switch (type) {
- case WalletType.monero:
- return S.current.view_transaction_on + 'Monero.com';
- case WalletType.bitcoin:
- return S.current.view_transaction_on + 'mempool.space';
- case WalletType.litecoin:
- case WalletType.bitcoinCash:
- case WalletType.dogecoin:
- return S.current.view_transaction_on + 'Blockchair.com';
- case WalletType.haven:
- return S.current.view_transaction_on + 'explorer.havenprotocol.org';
- case WalletType.ethereum:
- return S.current.view_transaction_on + 'etherscan.io';
- case WalletType.nano:
- return S.current.view_transaction_on + 'nanexplorer.com';
- case WalletType.banano:
- return S.current.view_transaction_on + 'nanexplorer.com';
- case WalletType.polygon:
- return S.current.view_transaction_on + 'polygonscan.com';
- case WalletType.bsc:
- return S.current.view_transaction_on + 'bscscan.com';
- case WalletType.solana:
- return S.current.view_transaction_on + 'solscan.io';
- case WalletType.tron:
- return S.current.view_transaction_on + 'tronscan.org';
- case WalletType.wownero:
- return S.current.view_transaction_on + 'Wownero.com';
- case WalletType.zano:
- return S.current.view_transaction_on + 'explorer.zano.org';
- case WalletType.decred:
- return S.current.view_transaction_on + 'dcrdata.decred.org';
- case WalletType.base:
- return S.current.view_transaction_on + 'basescan.org';
- case WalletType.arbitrum:
- return S.current.view_transaction_on + 'arbiscan.io';
- case WalletType.zcash:
- return S.current.view_transaction_on + 'blockchair.com';
- case WalletType.none:
- return '';
- }
- }
-
- void _addMoneroListItems(TransactionInfo tx, DateFormat dateFormat) {
- final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
- final description = transactionDescriptionBox.values.firstWhere(
- (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
- orElse: () => TransactionDescription(id: descriptionKey));
+ String get explorerDescription => S.current.view_transaction_on + Uri.parse(_explorerUrl).host;
- final key = tx.additionalInfo['key'] as String? ?? description.transactionKey;
- final accountIndex = tx.additionalInfo['accountIndex'] as int;
- final addressIndex = tx.additionalInfo['addressIndex'] as int;
- final feeFormatted = tx.feeFormatted();
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (feeFormatted != null)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: feeFormatted,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (key?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_key,
- value: key!,
- key: ValueKey('standard_list_item_transaction_key'),
- ),
- ];
-
- if (tx.direction == TransactionDirection.incoming) {
- try {
- final address = monero!.getTransactionAddress(wallet, accountIndex, addressIndex);
- final label = monero!.getSubaddressLabel(wallet, accountIndex, addressIndex);
-
- if (address.isNotEmpty) {
- isRecipientAddressShown = true;
- _items.add(
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: address,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- );
- }
-
- if (label.isNotEmpty) {
- _items.add(StandartListItem(
- title: S.current.address_label,
- value: label,
- key: ValueKey('standard_list_item_address_label_key'),
- ));
- }
- } catch (e) {
- printV(e.toString());
- }
- }
-
- items.addAll(_items);
- }
-
- void _addElectrumListItems(
- TransactionInfo tx, DateFormat dateFormat, CryptoCurrency cryptoCurrency) {
- final isLightning = (tx.additionalInfo["isLightning"] as bool?) ?? false;
-
- final currency = isLightning ? CryptoCurrency.btcln : cryptoCurrency;
- final symbol = _appStore.amountParsingProxy.getCryptoSymbol(currency);
- final amountFormatted = _appStore.amountParsingProxy.getDisplayCryptoString(
- tx.amount, currency);
- final feeFormatted = (tx.fee != null)
- ? _appStore.amountParsingProxy.getDisplayCryptoString(tx.fee!, currency)
- : "";
-
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- if (!isLightning) ...[
- StandartListItem(
- title: S.current.confirmations,
- value: tx.confirmations.toString(),
- key: ValueKey('standard_list_item_transaction_confirmations_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- ],
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: '$amountFormatted $symbol',
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: '$feeFormatted $symbol',
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- ];
-
- if (wallet.type == WalletType.bitcoin && tx.direction == TransactionDirection.incoming) {
- try {
- final addresses = bitcoin!.getTransactionAddresses(wallet, tx);
-
- if (addresses != null) {
- isRecipientAddressShown = true;
- for (final address in addresses) {
- _items.add(
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: address,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- );
- }
- }
- } catch (e) {
- printV(e.toString());
- }
- }
-
- items.addAll(_items);
- }
-
- void _addLitecoinListItems(TransactionInfo tx, DateFormat dateFormat) {
- _addElectrumListItems(tx, dateFormat, CryptoCurrency.ltc);
-
- bool isMweb = bitcoin!.txIsMweb(tx);
-
- final _items = [
- if (isMweb)
- BlockExplorerListItem(
- title: S.current.view_in_block_explorer,
- value: S.current.view_transaction_on + 'mwebexplorer.com',
- onTap: () async {
- try {
- final uri = Uri.parse('https://www.mwebexplorer.com/blocks/block/${tx.height}');
- if (await canLaunchUrl(uri))
- await launchUrl(uri, mode: LaunchMode.externalApplication);
- } catch (e) {}
- },
- key: ValueKey('block_explorer_list_item_mweb_wallet_type_key'),
- ),
- ];
-
- items.addAll(_items);
- }
-
- void _addHavenListItems(TransactionInfo tx, DateFormat dateFormat) {
- items.addAll([
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: tx.feeFormatted()!,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- ]);
- }
-
- void _addEVMListItems(TransactionInfo tx, DateFormat dateFormat) {
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.confirmations,
- value: tx.confirmations.toString(),
- key: ValueKey('standard_list_item_transaction_confirmations_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: tx.feeFormatted()!,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (showRecipientAddress && tx.to != null)
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: tx.to!,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- if (tx.direction == TransactionDirection.incoming && tx.from != null)
- StandartListItem(
- title: S.current.transaction_details_source_address,
- value: tx.from!,
- key: ValueKey('standard_list_item_transaction_details_source_address_key'),
- ),
- ];
-
- items.addAll(_items);
- }
-
- void _addNanoListItems(TransactionInfo tx, DateFormat dateFormat) {
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- if (showRecipientAddress && tx.to != null)
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: tx.to!,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- if (showRecipientAddress && tx.from != null)
- StandartListItem(
- title: S.current.transaction_details_source_address,
- value: tx.from!,
- key: ValueKey('standard_list_item_transaction_details_source_address_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.confirmed_tx,
- value: (tx.confirmations > 0).toString(),
- key: ValueKey('standard_list_item_transaction_confirmed_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- ];
-
- items.addAll(_items);
- }
-
- void _addSolanaListItems(TransactionInfo tx, DateFormat dateFormat) {
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash.replaceAll(RegExp(r'_(incoming|outgoing)$'), ''),
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: tx.feeFormatted()!,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (showRecipientAddress && tx.to != null)
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: tx.to!,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- if (tx.from != null)
- StandartListItem(
- title: S.current.transaction_details_source_address,
- value: tx.from!,
- key: ValueKey('standard_list_item_transaction_details_source_address_key'),
- ),
- ];
-
- items.addAll(_items);
+ void launchExplorer() {
+ launchUrl(Uri.parse(_explorerUrl));
}
void addBumpFeesListItems(TransactionInfo tx, String rawTransaction) {
@@ -699,186 +539,8 @@ abstract class TransactionDetailsViewModelBase with Store {
}
}
- void _addTronListItems(TransactionInfo tx, DateFormat dateFormat) {
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: tx.feeFormatted()!,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (showRecipientAddress && tx.to != null)
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: tron!.getTronBase58Address(tx.to!, wallet),
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- if (tx.from != null)
- StandartListItem(
- title: S.current.transaction_details_source_address,
- value: tron!.getTronBase58Address(tx.from!, wallet),
- key: ValueKey('standard_list_item_transaction_details_source_address_key'),
- ),
- ];
- items.addAll(_items);
- }
- void _addDecredListItems(TransactionInfo tx, DateFormat dateFormat) {
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: tx.feeFormatted()!,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (showRecipientAddress && tx.to != null)
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: tx.to!,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- if (tx.from != null)
- StandartListItem(
- title: S.current.transaction_details_source_address,
- value: tx.from!,
- key: ValueKey('standard_list_item_transaction_details_source_address_key'),
- ),
- ];
-
- items.addAll(_items);
- }
-
- void _addZcashListItems(TransactionInfo tx, DateFormat dateFormat) {
- final memo = tx.additionalInfo['memo'] as String?;
-
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- if (tx.to != null)
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: tx.to!,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.confirmations,
- value: tx.confirmations.toString(),
- key: ValueKey('standard_list_item_transaction_confirmations_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height ?? 0}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted() != null && tx.feeFormatted()!.isNotEmpty)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: tx.feeFormatted()!,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (memo != null && memo.isNotEmpty)
- StandartListItem(
- title: S.current.memo,
- value: memo,
- key: ValueKey('standard_list_item_transaction_details_memo_key'),
- ),
- ];
- items.addAll(_items);
- }
-
- void _addDogecoinListItems(TransactionInfo tx, DateFormat dateFormat) {
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: tx.feeFormatted()!,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (showRecipientAddress && tx.to != null)
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: tx.to!,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- if (tx.from != null)
- StandartListItem(
- title: S.current.transaction_details_source_address,
- value: tx.from!,
- key: ValueKey('standard_list_item_transaction_details_source_address_key'),
- ),
- ];
-
- items.addAll(_items);
- }
@action
Future<void> _checkForRBF(TransactionInfo tx) async {
@@ -929,93 +591,5 @@ abstract class TransactionDetailsViewModelBase with Store {
? ''
: sendViewModel.pendingTransactionFeeFiatAmount + ' ' + sendViewModel.fiat.title;
- void _addWowneroListItems(TransactionInfo tx, DateFormat dateFormat) {
- final key = tx.additionalInfo['key'] as String?;
- final accountIndex = tx.additionalInfo['accountIndex'] as int;
- final addressIndex = tx.additionalInfo['addressIndex'] as int;
- final feeFormatted = tx.feeFormatted();
- final _items = [
- StandartListItem(
- title: S.current.transaction_details_transaction_id,
- value: tx.txHash,
- key: ValueKey('standard_list_item_transaction_details_id_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_date,
- value: dateFormat.format(tx.date),
- key: ValueKey('standard_list_item_transaction_details_date_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_height,
- value: '${tx.height}',
- key: ValueKey('standard_list_item_transaction_details_height_key'),
- ),
- StandartListItem(
- title: S.current.transaction_details_amount,
- value: tx.amountFormatted(),
- key: ValueKey('standard_list_item_transaction_details_amount_key'),
- ),
- if (feeFormatted != null)
- StandartListItem(
- title: S.current.transaction_details_fee,
- value: feeFormatted,
- key: ValueKey('standard_list_item_transaction_details_fee_key'),
- ),
- if (key?.isNotEmpty ?? false)
- StandartListItem(
- title: S.current.transaction_key,
- value: key!,
- key: ValueKey('standard_list_item_transaction_key'),
- ),
- ];
-
- if (tx.direction == TransactionDirection.incoming) {
- try {
- final address = wownero!.getTransactionAddress(wallet, accountIndex, addressIndex);
- final label = wownero!.getSubaddressLabel(wallet, accountIndex, addressIndex);
-
- if (address.isNotEmpty) {
- isRecipientAddressShown = true;
- _items.add(
- StandartListItem(
- title: S.current.transaction_details_recipient_address,
- value: address,
- key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
- ),
- );
- }
-
- if (label.isNotEmpty) {
- _items.add(
- StandartListItem(
- title: S.current.address_label,
- value: label,
- key: ValueKey('standard_list_item_address_label_key'),
- ),
- );
- }
- } catch (e) {
- printV(e.toString());
- }
- }
-
- items.addAll(_items);
- }
- void _addZanoListItems(TransactionInfo tx, DateFormat dateFormat) {
- final comment = tx.additionalInfo['comment'] as String?;
- items.addAll([
- StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
- StandartListItem(
- title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
- StandartListItem(
- title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
- StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
- StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
- if (tx.feeFormatted()?.isNotEmpty ?? false)
- StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
- if (comment != null && comment.isNotEmpty)
- StandartListItem(title: S.current.transaction_details_title, value: comment),
- ]);
- }
}
diff --git a/res/pictures/link_arrow.svg b/res/pictures/link_arrow.svg
index feb8a607..3cd0ea17 100644
--- a/res/pictures/link_arrow.svg
+++ b/res/pictures/link_arrow.svg
@@ -1,3 +1,3 @@
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
- <path d="M0.674022 8L0 7.32598L6.35165 0.968191H0.577203V0H8V7.4228H7.03181V1.64835L0.674022 8Z" fill="#91B0FF"/>
+ <path d="M0.674022 8L0 7.32598L6.35165 0.968191H0.577203V0H8V7.4228H7.03181V1.64835L0.674022 8Z" fill="white"/>
</svg>
diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb
index ab480a48..6c0cb29f 100644
--- a/res/values/strings_ar.arb
+++ b/res/values/strings_ar.arb
@@ -13,6 +13,7 @@
"active_cards": "البطاقات النشطة",
"activeConnectionsPrompt": "ستظهر الاتصالات النشطة هنا",
"add": "إضافة",
+ "add_a_note": "أضف ملاحظة",
"add_account": "إضافة حساب",
"add_contact": "إضافة جهة اتصال",
"add_contact_to_address_book": "هل ترغب في إضافة جهة الاتصال هذه إلى دفتر العناوين الخاص بك؟",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "لا يمكن لأيٍّ من المزوّدين المحدّدين إجراء هذه المبادلة",
"noNFTYet": "لا توجد رموز NFT بعد",
"normal": "عادي",
+ "note": "ملحوظة",
"note_optional": "ملاحظة (اختيارية)",
"note_tap_to_change": "ملاحظة (اضغط للتغيير)",
"notification_permission_denied": "تم رفض إذن الإشعارات بشكل دائم. يُرجى تمكينه يدويًا من الإعدادات",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "غير مدفوع بالكامل",
"trade_state_unpaid": "غير مدفوع",
"trades": "الصفقات",
+ "transaction": "عملية",
"transaction_commited": "تم تأكيد المعاملة",
"transaction_cost": "تكلفة المعاملة",
"transaction_details_amount": "الكمية",
diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb
index d50474f4..0b1103e5 100644
--- a/res/values/strings_bg.arb
+++ b/res/values/strings_bg.arb
@@ -13,6 +13,7 @@
"active_cards": "Активни карти",
"activeConnectionsPrompt": "Тук ще се показват активните връзки",
"add": "Добави",
+ "add_a_note": "Добавете бележка",
"add_account": "Добавяне на акаунт",
"add_contact": "Добавяне на контакт",
"add_contact_to_address_book": "Желаете ли да добавите този контакт към адресната си книга?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Нито един от избраните доставчици не може да извърши този суап",
"noNFTYet": "Все още няма NFT",
"normal": "Нормален",
+ "note": "Забележка",
"note_optional": "Бележка (незадължително)",
"note_tap_to_change": "Бележка (докоснете, за да промените)",
"notification_permission_denied": "Разрешението за известия е окончателно отказано. Моля, включете го ръчно в настройките.",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "Недоплатено",
"trade_state_unpaid": "Неплатено",
"trades": "Сделки",
+ "transaction": "Транзакция",
"transaction_commited": "Транзакцията е потвърдена",
"transaction_cost": "Разход за транзакция",
"transaction_details_amount": "Сума",
diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb
index aebca6a9..2e93f2d8 100644
--- a/res/values/strings_cs.arb
+++ b/res/values/strings_cs.arb
@@ -13,6 +13,7 @@
"active_cards": "Aktivní karty",
"activeConnectionsPrompt": "Aktivní připojení se zobrazí zde",
"add": "Přidat",
+ "add_a_note": "Přidejte poznámku",
"add_account": "Přidat účet",
"add_contact": "Přidat kontakt",
"add_contact_to_address_book": "Chcete přidat tento kontakt do svého adresáře?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Žádný z vybraných poskytovatelů nemůže tento swap provést",
"noNFTYet": "Zatím žádné NFT",
"normal": "Normální",
+ "note": "Poznámka",
"note_optional": "Poznámka (nepovinné)",
"note_tap_to_change": "Poznámka (klepnutím změnit)",
"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 @@
"trade_state_underpaid": "Nedoplaceno",
"trade_state_unpaid": "Nezaplaceno",
"trades": "Obchody",
+ "transaction": "Transakce",
"transaction_commited": "Transakce potvrzena",
"transaction_cost": "Náklady transakce",
"transaction_details_amount": "Částka",
diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb
index f3b37917..4737c1d5 100644
--- a/res/values/strings_de.arb
+++ b/res/values/strings_de.arb
@@ -13,6 +13,7 @@
"active_cards": "Aktive Karten",
"activeConnectionsPrompt": "Aktive Verbindungen werden hier angezeigt",
"add": "Hinzufügen",
+ "add_a_note": "Fügen Sie eine Notiz hinzu",
"add_account": "Konto hinzufügen",
"add_contact": "Kontakt hinzufügen",
"add_contact_to_address_book": "Möchten Sie diesen Kontakt zu Ihrem Adressbuch hinzufügen?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Keiner der ausgewählten Anbieter kann diesen Swap durchführen",
"noNFTYet": "Noch keine NFTs",
"normal": "Normal",
+ "note": "Notiz",
"note_optional": "Notiz (optional)",
"note_tap_to_change": "Notiz (zum Ändern tippen)",
"notification_permission_denied": "Die Benachrichtigungsberechtigung wurde dauerhaft verweigert. Bitte aktivieren Sie sie manuell in den Einstellungen.",
@@ -1184,6 +1186,7 @@
"trade_state_underpaid": "Unterbezahlt",
"trade_state_unpaid": "Unbezahlt",
"trades": "Trades",
+ "transaction": "Transaktion",
"transaction_commited": "Transaktion übermittelt",
"transaction_cost": "Transaktionskosten",
"transaction_details_amount": "Betrag",
diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb
index f55ddf0f..f3f732c2 100644
--- a/res/values/strings_en.arb
+++ b/res/values/strings_en.arb
@@ -13,6 +13,7 @@
"active_cards": "Active cards",
"activeConnectionsPrompt": "Active connections will appear here",
"add": "Add",
+ "add_a_note": "Add a note",
"add_account": "Add Account",
"add_contact": "Add contact",
"add_contact_to_address_book": "Would you like to add this contact to your address book?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "None of the selected providers can make this swap",
"noNFTYet": "No NFTs yet",
"normal": "Normal",
+ "note": "Note",
"note_optional": "Note (optional)",
"note_tap_to_change": "Note (tap to change)",
"notification_permission_denied": "Notification permission got permamently denied, please manually enable it in settings",
@@ -1184,6 +1186,7 @@
"trade_state_underpaid": "Underpaid",
"trade_state_unpaid": "Unpaid",
"trades": "Trades",
+ "transaction": "Transaction",
"transaction_commited": "Transaction commited",
"transaction_cost": "Transaction Cost",
"transaction_details_amount": "Amount",
diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb
index 49ce3fc0..474a55b1 100644
--- a/res/values/strings_es.arb
+++ b/res/values/strings_es.arb
@@ -13,6 +13,7 @@
"active_cards": "Tarjetas activas",
"activeConnectionsPrompt": "Las conexiones activas aparecerán aquí",
"add": "Añadir",
+ "add_a_note": "Añadir una nota",
"add_account": "Añadir cuenta",
"add_contact": "Agregar contacto",
"add_contact_to_address_book": "¿Te gustaría añadir este contacto a tu libreta de direcciones?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Ninguno de los proveedores seleccionados puede realizar este swap",
"noNFTYet": "Aún no hay NFT",
"normal": "Normal",
+ "note": "Nota",
"note_optional": "Nota (opcional)",
"note_tap_to_change": "Nota (toca para cambiar)",
"notification_permission_denied": "El permiso de notificaciones se ha denegado permanentemente. Por favor, habilítalo manualmente en la configuración.",
@@ -1184,6 +1186,7 @@
"trade_state_underpaid": "Pago insuficiente",
"trade_state_unpaid": "No pagado",
"trades": "Operaciones",
+ "transaction": "Transacción",
"transaction_commited": "Transacción confirmada",
"transaction_cost": "Costo de transacción",
"transaction_details_amount": "Cantidad",
diff --git a/res/values/strings_fa.arb b/res/values/strings_fa.arb
index 5e1edfa7..0c405d4a 100644
--- a/res/values/strings_fa.arb
+++ b/res/values/strings_fa.arb
@@ -13,6 +13,7 @@
"active_cards": "کارتهای فعال",
"activeConnectionsPrompt": "اتصالهای فعال اینجا نمایش داده میشوند",
"add": "افزودن",
+ "add_a_note": "یک یادداشت اضافه کنید",
"add_account": "افزودن حساب",
"add_contact": "افزودن مخاطب",
"add_contact_to_address_book": "آیا میخواهید این مخاطب را به دفترچه آدرس خود اضافه کنید؟",
@@ -677,6 +678,7 @@
"none_of_selected_providers_can_exchange": "هیچیک از ارائهدهندگان انتخابشده نمیتوانند این سواپ را انجام دهند",
"noNFTYet": "هنوز هیچ NFTای وجود ندارد",
"normal": "عادی",
+ "note": "توجه داشته باشید",
"note_optional": "یادداشت (اختیاری)",
"note_tap_to_change": "یادداشت (برای تغییر ضربه بزنید)",
"notification_permission_denied": "مجوز اعلانها بهطور دائمی رد شده است، لطفاً آن را بهصورت دستی در تنظیمات فعال کنید",
@@ -1182,6 +1184,7 @@
"trade_state_underpaid": "کمپرداخت",
"trade_state_unpaid": "پرداختنشده",
"trades": "معاملات",
+ "transaction": "معامله",
"transaction_commited": "تراکنش ثبت شد",
"transaction_cost": "هزینه تراکنش",
"transaction_details_amount": "مقدار",
diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb
index 625bbde3..a97b59b1 100644
--- a/res/values/strings_fr.arb
+++ b/res/values/strings_fr.arb
@@ -13,6 +13,7 @@
"active_cards": "Cartes actives",
"activeConnectionsPrompt": "Les connexions actives apparaîtront ici",
"add": "Ajouter",
+ "add_a_note": "Ajouter une note",
"add_account": "Ajouter un compte",
"add_contact": "Ajouter un contact",
"add_contact_to_address_book": "Souhaitez-vous ajouter ce contact à votre carnet d'adresses ?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Aucun des fournisseurs sélectionnés ne peut effectuer ce swap",
"noNFTYet": "Aucun NFT pour le moment",
"normal": "Normal",
+ "note": "Note",
"note_optional": "Note (facultative)",
"note_tap_to_change": "Note (appuyez pour modifier)",
"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 @@
"trade_state_underpaid": "Sous-payé",
"trade_state_unpaid": "Impayé",
"trades": "Trades",
+ "transaction": "Transaction",
"transaction_commited": "Transaction validée",
"transaction_cost": "Coût de transaction",
"transaction_details_amount": "Montant",
diff --git a/res/values/strings_gn.arb b/res/values/strings_gn.arb
index 7c535a74..c63a8c55 100644
--- a/res/values/strings_gn.arb
+++ b/res/values/strings_gn.arb
@@ -12,6 +12,7 @@
"active_cards": "Tarjeta oĩva hag̃ua",
"activeConnectionsPrompt": "Umi jeikeha oĩva ojehechaukáta ko'ápe",
"add": "Emoĩve",
+ "add_a_note": "Emoĩ peteĩ nóta",
"add_account": "Embojoapy cuenta",
"add_contact": "Emoĩve contacto",
"add_contact_to_address_book": "¿Reipotápa remoĩ ko contacto nde kundaharape?",
@@ -531,6 +532,7 @@
"none_of_selected_providers_can_exchange": "Ndaipóri umi proveedor ojeiporavóva apytépe ikatúva ojapo ko swap.",
"noNFTYet": "Ndaipóri NFT gueteri",
"normal": "Normal",
+ "note": "Haipy",
"note_optional": "Jehaipy (opcional)",
"note_tap_to_change": "Jehaipy (eikutu emoambue hag̃ua)",
"nullURIError": "URI nulo",
@@ -951,6 +953,7 @@
"trade_state_underpaid": "Ojehepyme’ẽ mboyve",
"trade_state_unpaid": "Noñeme’ẽi",
"trades": "Ñemuha",
+ "transaction": "Transacción rehegua",
"transaction_commited": "Transacción ojejapóma.",
"transaction_details_amount": "Hetakue",
"transaction_details_copied": "${title} ojekopia portapapélpe",
diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb
index 4d57e1b1..3253c51d 100644
--- a/res/values/strings_ha.arb
+++ b/res/values/strings_ha.arb
@@ -13,6 +13,7 @@
"active_cards": "Katunan da ke aiki",
"activeConnectionsPrompt": "Haɗe-haɗe masu aiki za su bayyana a nan",
"add": "Ƙara",
+ "add_a_note": "Ƙara bayanin kula",
"add_account": "Ƙara Asusun",
"add_contact": "Ƙara tuntuɓa",
"add_contact_to_address_book": "Kuna so ku ƙara wannan tuntuɓa zuwa littafin adireshinku?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Babu ɗaya daga cikin masu ba da sabis da aka zaɓa da zai iya yin wannan musayar",
"noNFTYet": "Babu NFT tukuna",
"normal": "Na al’ada",
+ "note": "Lura",
"note_optional": "Bayani (na zaɓi)",
"note_tap_to_change": "Bayanan kula (taɓa don canjawa)",
"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 @@
"trade_state_underpaid": "Ba a biya cikakke ba",
"trade_state_unpaid": "Ba a biya ba",
"trades": "Kasuwanci",
+ "transaction": "Ma'amala",
"transaction_commited": "An tabbatar da ma'amala",
"transaction_cost": "Kudin ma'amala",
"transaction_details_amount": "Adadi",
diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb
index dc779052..105aa6c4 100644
--- a/res/values/strings_hi.arb
+++ b/res/values/strings_hi.arb
@@ -13,6 +13,7 @@
"active_cards": "सक्रिय कार्ड",
"activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे",
"add": "जोड़ें",
+ "add_a_note": "एक नोट जोड़े",
"add_account": "अकाउंट जोड़ें",
"add_contact": "संपर्क जोड़ें",
"add_contact_to_address_book": "क्या आप इस संपर्क को अपनी पता पुस्तिका में जोड़ना चाहेंगे?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "चयनित प्रदाताओं में से कोई भी यह स्वैप नहीं कर सकता",
"noNFTYet": "अभी तक कोई NFT नहीं",
"normal": "सामान्य",
+ "note": "टिप्पणी",
"note_optional": "नोट (वैकल्पिक)",
"note_tap_to_change": "नोट (बदलने के लिए टैप करें)",
"notification_permission_denied": "अधिसूचना की अनुमति स्थायी रूप से अस्वीकार कर दी गई है, कृपया इसे सेटिंग्स में जाकर मैन्युअल रूप से सक्षम करें",
@@ -1185,6 +1187,7 @@
"trade_state_underpaid": "अपर्याप्त भुगतान",
"trade_state_unpaid": "अवैतनिक",
"trades": "ट्रेड्स",
+ "transaction": "लेन-देन",
"transaction_commited": "लेन-देन कमिट हो गया",
"transaction_cost": "लेनदेन लागत",
"transaction_details_amount": "राशि",
diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb
index 4ca1ae54..d893c695 100644
--- a/res/values/strings_hr.arb
+++ b/res/values/strings_hr.arb
@@ -13,6 +13,7 @@
"active_cards": "Aktivne kartice",
"activeConnectionsPrompt": "Ovdje će se prikazati aktivne veze",
"add": "Dodaj",
+ "add_a_note": "Dodajte bilješku",
"add_account": "Dodaj račun",
"add_contact": "Dodaj kontakt",
"add_contact_to_address_book": "Želite li dodati ovaj kontakt u svoj adresar?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Nijedan od odabranih pružatelja ne može izvršiti ovu zamjenu",
"noNFTYet": "Još nema NFT-ova",
"normal": "Normalno",
+ "note": "Bilješka",
"note_optional": "Napomena (nije obvezno)",
"note_tap_to_change": "Napomena (dodirnite za promjenu)",
"notification_permission_denied": "Dozvola za obavijesti trajno je odbijena, molimo ručno je omogućite u postavkama",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "Nedovoljno plaćeno",
"trade_state_unpaid": "Neplaćeno",
"trades": "Trgovanja",
+ "transaction": "Transakcija",
"transaction_commited": "Transakcija potvrđena",
"transaction_cost": "Trošak transakcije",
"transaction_details_amount": "Iznos",
diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb
index f884ebdd..1607a382 100644
--- a/res/values/strings_hy.arb
+++ b/res/values/strings_hy.arb
@@ -13,6 +13,7 @@
"active_cards": "Ակտիվ քարտեր",
"activeConnectionsPrompt": "Ակտիվ կապերը կհայտնվեն այստեղ",
"add": "Ավելացնել",
+ "add_a_note": "Ավելացնել նշում",
"add_account": "Ավելացնել հաշիվ",
"add_contact": "Ավելացնել կոնտակտ",
"add_contact_to_address_book": "Ցանկանո՞ւմ եք այս կոնտակտը ավելացնել Ձեր հասցեագրքում:",
@@ -678,6 +679,7 @@
"none_of_selected_providers_can_exchange": "Ընտրված մատակարարներից ոչ մեկը չի կարող կատարել այս սվոփը",
"noNFTYet": "Դեռևս NFT-ներ չկան",
"normal": "Նորմալ",
+ "note": "Նշում",
"note_optional": "Նշում (ըստ ցանկության)",
"note_tap_to_change": "Նշում (հպեք՝ փոխելու համար)",
"notification_permission_denied": "Ծանուցումների թույլտվությունը մշտապես մերժվել է, խնդրում ենք այն ձեռքով միացնել կարգավորումներում",
@@ -1181,6 +1183,7 @@
"trade_state_underpaid": "Թերվճարված",
"trade_state_unpaid": "Չվճարված",
"trades": "Գործարքներ",
+ "transaction": "Գործարք",
"transaction_commited": "Գործարքը հաստատվեց",
"transaction_cost": "Գործարքի արժեք",
"transaction_details_amount": "Գումար",
diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb
index 99a58739..4276081d 100644
--- a/res/values/strings_id.arb
+++ b/res/values/strings_id.arb
@@ -13,6 +13,7 @@
"active_cards": "Kartu aktif",
"activeConnectionsPrompt": "Koneksi aktif akan muncul di sini",
"add": "Tambah",
+ "add_a_note": "Tambahkan catatan",
"add_account": "Tambahkan Akun",
"add_contact": "Tambah kontak",
"add_contact_to_address_book": "Apakah Anda ingin menambahkan kontak ini ke buku alamat Anda?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Tidak ada penyedia yang dipilih yang dapat melakukan swap ini",
"noNFTYet": "Belum ada NFT",
"normal": "Normal",
+ "note": "Catatan",
"note_optional": "Catatan (opsional)",
"note_tap_to_change": "Catatan (ketuk untuk mengubah)",
"notification_permission_denied": "Izin notifikasi ditolak secara permanen, mohon aktifkan secara manual di pengaturan",
@@ -1186,6 +1188,7 @@
"trade_state_underpaid": "Kurang dibayar",
"trade_state_unpaid": "Belum dibayar",
"trades": "Perdagangan",
+ "transaction": "Transaksi",
"transaction_commited": "Transaksi dikomit",
"transaction_cost": "Biaya Transaksi",
"transaction_details_amount": "Jumlah",
diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb
index 72ed9288..a0675f7f 100644
--- a/res/values/strings_it.arb
+++ b/res/values/strings_it.arb
@@ -13,6 +13,7 @@
"active_cards": "Carte attive",
"activeConnectionsPrompt": "Le connessioni attive appariranno qui",
"add": "Aggiungi",
+ "add_a_note": "Aggiungi una nota",
"add_account": "Aggiungi account",
"add_contact": "Aggiungi contatto",
"add_contact_to_address_book": "Vuoi aggiungere questo contatto alla tua rubrica?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Nessuno dei provider selezionati può effettuare questo swap",
"noNFTYet": "Nessun NFT ancora",
"normal": "Normale",
+ "note": "Nota",
"note_optional": "Nota (opzionale)",
"note_tap_to_change": "Nota (tocca per cambiare)",
"notification_permission_denied": "L'autorizzazione alle notifiche è stata negata in modo permanente, abilitala manualmente nelle impostazioni",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "Pagamento insufficiente",
"trade_state_unpaid": "Non pagato",
"trades": "Operazioni",
+ "transaction": "Transazione",
"transaction_commited": "Transazione confermata",
"transaction_cost": "Costo della transazione",
"transaction_details_amount": "Importo",
diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb
index 1597fb30..a6f4fd43 100644
--- a/res/values/strings_ja.arb
+++ b/res/values/strings_ja.arb
@@ -13,6 +13,7 @@
"active_cards": "有効なカード",
"activeConnectionsPrompt": "アクティブな接続はここに表示されます",
"add": "追加",
+ "add_a_note": "メモを追加する",
"add_account": "アカウントを追加",
"add_contact": "連絡先を追加",
"add_contact_to_address_book": "この連絡先をアドレス帳に追加しますか?",
@@ -680,6 +681,7 @@
"none_of_selected_providers_can_exchange": "選択したプロバイダーはいずれもこのスワップを実行できません",
"noNFTYet": "NFTはまだありません",
"normal": "通常",
+ "note": "注記",
"note_optional": "メモ(任意)",
"note_tap_to_change": "メモ(タップして変更)",
"notification_permission_denied": "通知の権限が永久に拒否されました。設定で手動で有効にしてください",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "支払い不足",
"trade_state_unpaid": "未払い",
"trades": "取引",
+ "transaction": "取引",
"transaction_commited": "トランザクションがコミットされました",
"transaction_cost": "取引手数料",
"transaction_details_amount": "金額",
diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb
index 6df7fd1b..e4effa00 100644
--- a/res/values/strings_ko.arb
+++ b/res/values/strings_ko.arb
@@ -13,6 +13,7 @@
"active_cards": "활성화된 카드",
"activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다",
"add": "추가",
+ "add_a_note": "메모 추가",
"add_account": "계정 추가",
"add_contact": "연락처 추가",
"add_contact_to_address_book": "이 연락처를 주소록에 추가하시겠습니까?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "선택한 제공업체 중 이 스왑을 지원하는 곳이 없습니다",
"noNFTYet": "아직 NFT가 없습니다",
"normal": "일반",
+ "note": "메모",
"note_optional": "메모(선택 사항)",
"note_tap_to_change": "메모 (탭하여 변경)",
"notification_permission_denied": "알림 권한이 영구적으로 거부되었습니다. 설정에서 수동으로 활성화해 주세요.",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "지불 부족",
"trade_state_unpaid": "미결제",
"trades": "거래",
+ "transaction": "거래",
"transaction_commited": "트랜잭션이 커밋되었습니다",
"transaction_cost": "거래 수수료",
"transaction_details_amount": "금액",
diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb
index a9785f5b..2a9bb18d 100644
--- a/res/values/strings_my.arb
+++ b/res/values/strings_my.arb
@@ -13,6 +13,7 @@
"active_cards": "အသုံးပြုနေသောကတ်များ",
"activeConnectionsPrompt": "လက်ရှိ ချိတ်ဆက်မှုများကို ဤနေရာတွင် ပြသပါမည်",
"add": "ထည့်ရန်",
+ "add_a_note": "မှတ်စုတစ်ခုထည့်ပါ။",
"add_account": "အကောင့်ထည့်ရန်",
"add_contact": "အဆက်အသွယ် ထည့်ရန်",
"add_contact_to_address_book": "ဒီအဆက်အသွယ်ကို သင့်လိပ်စာစာအုပ်ထဲ ထည့်ချင်ပါသလား။",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "ရွေးချယ်ထားသော ပံ့ပိုးပေးသူများထဲမှ မည်သူမျှ ဒီ swap ကို မလုပ်နိုင်ပါ",
"noNFTYet": "NFT မရှိသေးပါ",
"normal": "ပုံမှန်",
+ "note": "မှတ်ချက်",
"note_optional": "မှတ်ချက် (မဖြည့်လည်းရသည်)",
"note_tap_to_change": "မှတ်ချက် (ပြောင်းလဲရန် နှိပ်ပါ)",
"notification_permission_denied": "အသိပေးချက်ခွင့်ပြုချက်ကို အပြီးတိုင် ငြင်းပယ်ထားပါသည်၊ ကျေးဇူးပြု၍ ချိန်ညှိချက်များတွင် လက်ဖြင့် ဖွင့်ပေးပါ",
@@ -1182,6 +1184,7 @@
"trade_state_underpaid": "ပေးချေမှုမလုံလောက်ပါ",
"trade_state_unpaid": "မပေးချေရသေး",
"trades": "အရောင်းအဝယ်များ",
+ "transaction": "ငွေလွှဲခြင်း။",
"transaction_commited": "ငွေလွှဲမှု အတည်ပြုပြီးပါပြီ",
"transaction_cost": "ငွေလွှဲခ ကုန်ကျစရိတ်",
"transaction_details_amount": "ပမာဏ",
diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb
index 3d85f18f..a27007d9 100644
--- a/res/values/strings_nl.arb
+++ b/res/values/strings_nl.arb
@@ -13,6 +13,7 @@
"active_cards": "Actieve kaarten",
"activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven",
"add": "Toevoegen",
+ "add_a_note": "Voeg een notitie toe",
"add_account": "Account toevoegen",
"add_contact": "Contactpersoon toevoegen",
"add_contact_to_address_book": "Wil je dit contact toevoegen aan je adresboek?",
@@ -676,9 +677,10 @@
"none_of_selected_providers_can_exchange": "Geen van de geselecteerde providers kan deze swap maken",
"noNFTYet": "Nog geen NFT's",
"normal": "Normaal",
- "note_optional": "Opmerking (optioneel)",
- "note_tap_to_change": "Opmerking (tik om te wijzigen)",
- "notification_permission_denied": "Meldingstoestemming is permanent geweigerd, schakel deze handmatig in via de instellingen",
+ "note": "Opmerking",
+ "note_optional": "Notitie (optioneel)",
+ "note_tap_to_change": "Notitie (tik om te wijzigen)",
+ "notification_permission_denied": "Meldingstoestemming is permanent geweigerd. Schakel deze handmatig in via de instellingen.",
"nullURIError": "URI is null",
"offer_expires_in": "Aanbieding verloopt over: ",
"offline": "Offline",
@@ -1178,6 +1180,7 @@
"trade_state_trading": "Handel",
"trade_state_underpaid": "Te weinig betaald",
"trade_state_unpaid": "Onbetaald",
+ "transaction": "Transactie",
"trades": "Trades",
"transaction_commited": "Transactie vastgelegd",
"transaction_cost": "Transactiekosten",
diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb
index e80a7d3b..ba93ddd3 100644
--- a/res/values/strings_pl.arb
+++ b/res/values/strings_pl.arb
@@ -13,6 +13,7 @@
"active_cards": "Aktywne karty",
"activeConnectionsPrompt": "Aktywne połączenia pojawią się tutaj",
"add": "Dodaj",
+ "add_a_note": "Dodaj notatkę",
"add_account": "Dodaj konto",
"add_contact": "Dodaj kontakt",
"add_contact_to_address_book": "Czy chcesz dodać ten kontakt do swojej książki adresowej?",
@@ -678,6 +679,7 @@
"none_of_selected_providers_can_exchange": "Żaden z wybranych dostawców nie może wykonać tej wymiany",
"noNFTYet": "Brak NFT",
"normal": "Normalny",
+ "note": "Notatka",
"note_optional": "Notatka (opcjonalnie)",
"note_tap_to_change": "Notatka (stuknij, aby zmienić)",
"notification_permission_denied": "Uprawnienie do powiadomień zostało trwale odrzucone. Włącz je ręcznie w ustawieniach.",
@@ -1181,6 +1183,7 @@
"trade_state_underpaid": "Niedopłacone",
"trade_state_unpaid": "Nieopłacone",
"trades": "Transakcje",
+ "transaction": "Transakcja",
"transaction_commited": "Transakcja zatwierdzona",
"transaction_cost": "Koszt transakcji",
"transaction_details_amount": "Kwota",
diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb
index d2823434..981ab987 100644
--- a/res/values/strings_pt.arb
+++ b/res/values/strings_pt.arb
@@ -13,6 +13,7 @@
"active_cards": "Cartões ativos",
"activeConnectionsPrompt": "As conexões ativas aparecerão aqui",
"add": "Adicionar",
+ "add_a_note": "Adicione uma nota",
"add_account": "Adicionar conta",
"add_contact": "Adicionar contato",
"add_contact_to_address_book": "Você gostaria de adicionar este contato ao seu catálogo de endereços?",
@@ -680,6 +681,7 @@
"none_of_selected_providers_can_exchange": "Nenhum dos provedores selecionados pode realizar esta troca",
"noNFTYet": "Ainda não há NFTs",
"normal": "Normal",
+ "note": "Observação",
"note_optional": "Nota (opcional)",
"note_tap_to_change": "Nota (toque para mudar)",
"notification_permission_denied": "A permissão de notificações foi negada permanentemente. Ative-a manualmente nas configurações.",
@@ -1184,6 +1186,7 @@
"trade_state_underpaid": "Pago insuficiente",
"trade_state_unpaid": "Não pago",
"trades": "Negociações",
+ "transaction": "Transação",
"transaction_commited": "Transação confirmada",
"transaction_cost": "Custo da transação",
"transaction_details_amount": "Valor",
diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb
index 416377e8..99496d87 100644
--- a/res/values/strings_ru.arb
+++ b/res/values/strings_ru.arb
@@ -13,6 +13,7 @@
"active_cards": "Активные карты",
"activeConnectionsPrompt": "Здесь будут отображаться активные подключения",
"add": "Добавить",
+ "add_a_note": "Добавить заметку",
"add_account": "Добавить аккаунт",
"add_contact": "Добавить контакт",
"add_contact_to_address_book": "Хотите добавить этот контакт в адресную книгу?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Ни один из выбранных провайдеров не может выполнить этот обмен",
"noNFTYet": "Пока нет NFT",
"normal": "Обычный",
+ "note": "Примечание",
"note_optional": "Примечание (необязательно)",
"note_tap_to_change": "Примечание (нажмите, чтобы изменить)",
"notification_permission_denied": "Разрешение на уведомления было навсегда отклонено, пожалуйста, включите его вручную в настройках",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "Недоплачено",
"trade_state_unpaid": "Не оплачено",
"trades": "Сделки",
+ "transaction": "Сделка",
"transaction_commited": "Транзакция подтверждена",
"transaction_cost": "Стоимость транзакции",
"transaction_details_amount": "Сумма",
diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb
index fc986ff8..3c62489d 100644
--- a/res/values/strings_th.arb
+++ b/res/values/strings_th.arb
@@ -13,6 +13,7 @@
"active_cards": "บัตรที่ใช้งานอยู่",
"activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะแสดงที่นี่",
"add": "เพิ่ม",
+ "add_a_note": "เพิ่มบันทึก",
"add_account": "เพิ่มบัญชี",
"add_contact": "เพิ่มผู้ติดต่อ",
"add_contact_to_address_book": "คุณต้องการเพิ่มผู้ติดต่อนี้ลงในสมุดที่อยู่ของคุณหรือไม่?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "ไม่มีผู้ให้บริการที่เลือกไว้รายใดสามารถทำการสวอปนี้ได้",
"noNFTYet": "ยังไม่มี NFT",
"normal": "ปกติ",
+ "note": "บันทึก",
"note_optional": "หมายเหตุ (ไม่จำเป็น)",
"note_tap_to_change": "หมายเหตุ (แตะเพื่อเปลี่ยน)",
"notification_permission_denied": "สิทธิ์การแจ้งเตือนถูกปฏิเสธอย่างถาวร โปรดเปิดใช้งานด้วยตนเองในการตั้งค่า",
@@ -1182,6 +1184,7 @@
"trade_state_underpaid": "ชำระไม่ครบ",
"trade_state_unpaid": "ยังไม่ได้ชำระ",
"trades": "การเทรด",
+ "transaction": "ธุรกรรม",
"transaction_commited": "ธุรกรรมถูกบันทึกแล้ว",
"transaction_cost": "ค่าธรรมเนียมธุรกรรม",
"transaction_details_amount": "จำนวน",
diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb
index 2893fdc4..4e8e9799 100644
--- a/res/values/strings_tl.arb
+++ b/res/values/strings_tl.arb
@@ -13,6 +13,7 @@
"active_cards": "Mga aktibong card",
"activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon",
"add": "Magdagdag",
+ "add_a_note": "Magdagdag ng tala",
"add_account": "Magdagdag ng account",
"add_contact": "Magdagdag ng kontak",
"add_contact_to_address_book": "Gusto mo bang idagdag ang contact na ito sa iyong address book?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Wala sa mga napiling provider ang makakagawa ng swap na ito",
"noNFTYet": "Wala pang mga NFT",
"normal": "Normal",
+ "note": "Tandaan",
"note_optional": "Tala (opsyonal)",
"note_tap_to_change": "Tala (i-tap para baguhin)",
"notification_permission_denied": "Permanenteng tinanggihan ang pahintulot para sa mga abiso. Pakipaganahin ito nang manu-mano sa mga setting.",
@@ -1182,6 +1184,7 @@
"trade_state_underpaid": "Kulang ang bayad",
"trade_state_unpaid": "Hindi bayad",
"trades": "Mga Trade",
+ "transaction": "Transaksyon",
"transaction_commited": "Nakumpirma ang transaksyon",
"transaction_cost": "Gastos sa Transaksyon",
"transaction_details_amount": "Halaga",
diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb
index f2753f94..a0ef9832 100644
--- a/res/values/strings_tr.arb
+++ b/res/values/strings_tr.arb
@@ -13,6 +13,7 @@
"active_cards": "Aktif kartlar",
"activeConnectionsPrompt": "Etkin bağlantılar burada görünecek",
"add": "Ekle",
+ "add_a_note": "Not ekle",
"add_account": "Hesap Ekle",
"add_contact": "Kişi ekle",
"add_contact_to_address_book": "Bu kişiyi adres defterinize eklemek ister misiniz?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Seçilen sağlayıcıların hiçbiri bu takası gerçekleştiremez",
"noNFTYet": "Henüz NFT yok",
"normal": "Normal",
+ "note": "Not",
"note_optional": "Not (isteğe bağlı)",
"note_tap_to_change": "Not (değiştirmek için dokunun)",
"notification_permission_denied": "Bildirim izni kalıcı olarak reddedildi, lütfen ayarlardan manuel olarak etkinleştirin",
@@ -1182,6 +1184,7 @@
"trade_state_underpaid": "Eksik ödendi",
"trade_state_unpaid": "Ödenmedi",
"trades": "Alım satımlar",
+ "transaction": "İşlem",
"transaction_commited": "İşlem onaylandı",
"transaction_cost": "İşlem maliyeti",
"transaction_details_amount": "Miktar",
diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb
index fc280695..7b48fc38 100644
--- a/res/values/strings_uk.arb
+++ b/res/values/strings_uk.arb
@@ -13,6 +13,7 @@
"active_cards": "Активні картки",
"activeConnectionsPrompt": "Активні підключення з’являться тут",
"add": "Додати",
+ "add_a_note": "Додайте примітку",
"add_account": "Додати акаунт",
"add_contact": "Додати контакт",
"add_contact_to_address_book": "Бажаєте додати цей контакт до своєї адресної книги?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "Жоден із вибраних провайдерів не може виконати цей своп",
"noNFTYet": "NFT ще немає",
"normal": "Звичайний",
+ "note": "Примітка",
"note_optional": "Примітка (необов’язково)",
"note_tap_to_change": "Примітка (натисніть, щоб змінити)",
"notification_permission_denied": "Дозвіл на сповіщення було назавжди відхилено, будь ласка, увімкніть його вручну в налаштуваннях",
@@ -1183,6 +1185,7 @@
"trade_state_underpaid": "Недоплачено",
"trade_state_unpaid": "Не оплачено",
"trades": "Угоди",
+ "transaction": "Транзакція",
"transaction_commited": "Транзакцію підтверджено",
"transaction_cost": "Вартість транзакції",
"transaction_details_amount": "Сума",
diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb
index e8de667a..e7dec923 100644
--- a/res/values/strings_ur.arb
+++ b/res/values/strings_ur.arb
@@ -13,6 +13,7 @@
"active_cards": "فعال کارڈز",
"activeConnectionsPrompt": "فعال کنکشنز یہاں ظاہر ہوں گے",
"add": "شامل کریں",
+ "add_a_note": "ایک نوٹ شامل کریں۔",
"add_account": "اکاؤنٹ شامل کریں",
"add_contact": "رابطہ شامل کریں",
"add_contact_to_address_book": "کیا آپ اس رابطے کو اپنی ایڈریس بک میں شامل کرنا چاہیں گے؟",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "منتخب کردہ فراہم کنندگان میں سے کوئی بھی یہ سواپ نہیں کر سکتا",
"noNFTYet": "ابھی تک کوئی NFTs نہیں",
"normal": "معمول",
+ "note": "نوٹ",
"note_optional": "نوٹ (اختیاری)",
"note_tap_to_change": "نوٹ (تبدیل کرنے کے لیے ٹیپ کریں)",
"notification_permission_denied": "نوٹیفکیشن کی اجازت مستقل طور پر مسترد کر دی گئی ہے، براہِ کرم اسے سیٹنگز میں دستی طور پر فعال کریں",
@@ -1184,6 +1186,7 @@
"trade_state_underpaid": "کم ادائیگی",
"trade_state_unpaid": "غیر ادا شدہ",
"trades": "تبادلے",
+ "transaction": "لین دین",
"transaction_commited": "ٹرانزیکشن مکمل ہو گئی",
"transaction_cost": "لین دین کی لاگت",
"transaction_details_amount": "رقم",
diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb
index 63efd82e..f51cde32 100644
--- a/res/values/strings_vi.arb
+++ b/res/values/strings_vi.arb
@@ -13,6 +13,7 @@
"active_cards": "Thẻ đang hoạt động",
"activeConnectionsPrompt": "Các kết nối đang hoạt động sẽ hiển thị ở đây",
"add": "Thêm",
+ "add_a_note": "Thêm ghi chú",
"add_account": "Thêm tài khoản",
"add_contact": "Thêm liên hệ",
"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 @@
"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",
"noNFTYet": "Chưa có NFT nào",
"normal": "Bình thường",
+ "note": "Ghi chú",
"note_optional": "Ghi chú (tùy chọn)",
"note_tap_to_change": "Ghi chú (chạm để thay đổi)",
"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 @@
"trade_state_underpaid": "Trả thiếu",
"trade_state_unpaid": "Chưa thanh toán",
"trades": "Giao dịch",
+ "transaction": "Giao dịch",
"transaction_commited": "Giao dịch đã được xác nhận",
"transaction_cost": "Chi phí giao dịch",
"transaction_details_amount": "Số lượng",
diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb
index 177a2422..a544aa8e 100644
--- a/res/values/strings_yo.arb
+++ b/res/values/strings_yo.arb
@@ -13,6 +13,7 @@
"active_cards": "Àwọn káàdì tó ń ṣiṣẹ́",
"activeConnectionsPrompt": "Awọn asopọ tó ń ṣiṣẹ yóò hàn níbí",
"add": "Fi kún",
+ "add_a_note": "Fi akọsilẹ kun",
"add_account": "Ṣàfikún Àkántì",
"add_contact": "Ṣàfikún olubasọrọ",
"add_contact_to_address_book": "Ṣe o fẹ́ fi olubasọrọ yìí kún ìwé àdírẹ́sì rẹ?",
@@ -680,6 +681,7 @@
"none_of_selected_providers_can_exchange": "Ko si ọkan ninu awọn olupese tí a yàn tó lè ṣe paṣipaarọ yìí",
"noNFTYet": "Ko si NFT sibẹsibẹ",
"normal": "Deede",
+ "note": "Akiyesi",
"note_optional": "Àkọsílẹ̀ (àṣàyàn)",
"note_tap_to_change": "Akọsilẹ (tẹ lati yí padà)",
"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 @@
"trade_state_underpaid": "A san iye tó kéré ju",
"trade_state_unpaid": "A kò tíì san",
"trades": "Àwọn ìṣòwò",
+ "transaction": "Idunadura",
"transaction_commited": "Idunadura ti fọwọsi",
"transaction_cost": "Iye Iṣowo",
"transaction_details_amount": "Iye",
diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb
index e8fc8f72..6a3a19fd 100644
--- a/res/values/strings_zh.arb
+++ b/res/values/strings_zh.arb
@@ -13,6 +13,7 @@
"active_cards": "已激活的卡",
"activeConnectionsPrompt": "活跃连接将显示在此处",
"add": "添加",
+ "add_a_note": "添加注释",
"add_account": "添加账户",
"add_contact": "添加联系人",
"add_contact_to_address_book": "您想将此联系人添加到地址簿吗?",
@@ -679,6 +680,7 @@
"none_of_selected_providers_can_exchange": "所选的提供商均无法完成此兑换",
"noNFTYet": "暂无 NFT",
"normal": "普通",
+ "note": "笔记",
"note_optional": "备注(可选)",
"note_tap_to_change": "备注(轻触以更改)",
"notification_permission_denied": "通知权限已被永久拒绝,请在设置中手动启用",
@@ -1182,6 +1184,7 @@
"trade_state_underpaid": "支付不足",
"trade_state_unpaid": "未付款",
"trades": "交易",
+ "transaction": "交易",
"transaction_commited": "交易已提交",
"transaction_cost": "交易费用",
"transaction_details_amount": "金额",
Why this scored 22/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.