mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-11 17:06:30 +00:00
xmr/wow show tx spend key option
This commit is contained in:
parent
a74c565f9a
commit
cd068eefc7
3 changed files with 130 additions and 1 deletions
lib
pages/wallet_view/transaction_views/tx_v2
wallets/wallet/intermediate
widgets
|
@ -42,6 +42,7 @@ import '../../../../wallets/crypto_currency/intermediate/nano_currency.dart';
|
||||||
import '../../../../wallets/isar/models/spark_coin.dart';
|
import '../../../../wallets/isar/models/spark_coin.dart';
|
||||||
import '../../../../wallets/isar/providers/wallet_info_provider.dart';
|
import '../../../../wallets/isar/providers/wallet_info_provider.dart';
|
||||||
import '../../../../wallets/wallet/impl/epiccash_wallet.dart';
|
import '../../../../wallets/wallet/impl/epiccash_wallet.dart';
|
||||||
|
import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
|
||||||
import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart';
|
import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart';
|
||||||
import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
|
import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
|
||||||
import '../../../../widgets/background.dart';
|
import '../../../../widgets/background.dart';
|
||||||
|
@ -57,6 +58,7 @@ import '../../../../widgets/icon_widgets/copy_icon.dart';
|
||||||
import '../../../../widgets/icon_widgets/pencil_icon.dart';
|
import '../../../../widgets/icon_widgets/pencil_icon.dart';
|
||||||
import '../../../../widgets/rounded_white_container.dart';
|
import '../../../../widgets/rounded_white_container.dart';
|
||||||
import '../../../../widgets/stack_dialog.dart';
|
import '../../../../widgets/stack_dialog.dart';
|
||||||
|
import '../../../../widgets/tx_key_widget.dart';
|
||||||
import '../../sub_widgets/tx_icon.dart';
|
import '../../sub_widgets/tx_icon.dart';
|
||||||
import '../../wallet_view.dart';
|
import '../../wallet_view.dart';
|
||||||
import '../dialogs/cancelling_transaction_progress_dialog.dart';
|
import '../dialogs/cancelling_transaction_progress_dialog.dart';
|
||||||
|
@ -96,6 +98,7 @@ class _TransactionV2DetailsViewState
|
||||||
late final int minConfirms;
|
late final int minConfirms;
|
||||||
late final EthContract? ethContract;
|
late final EthContract? ethContract;
|
||||||
late final bool supportsRbf;
|
late final bool supportsRbf;
|
||||||
|
late final bool hasTxKeyProbably;
|
||||||
|
|
||||||
bool get isTokenTx => ethContract != null;
|
bool get isTokenTx => ethContract != null;
|
||||||
|
|
||||||
|
@ -180,10 +183,16 @@ class _TransactionV2DetailsViewState
|
||||||
_transaction = widget.transaction;
|
_transaction = widget.transaction;
|
||||||
walletId = widget.walletId;
|
walletId = widget.walletId;
|
||||||
|
|
||||||
|
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||||
|
|
||||||
|
hasTxKeyProbably = wallet is LibMoneroWallet &&
|
||||||
|
(_transaction.type == TransactionType.outgoing ||
|
||||||
|
_transaction.type == TransactionType.sentToSelf);
|
||||||
|
|
||||||
if (_transaction.type
|
if (_transaction.type
|
||||||
case TransactionType.sentToSelf || TransactionType.outgoing) {
|
case TransactionType.sentToSelf || TransactionType.outgoing) {
|
||||||
supportsRbf = _transaction.subType == TransactionSubType.none &&
|
supportsRbf = _transaction.subType == TransactionSubType.none &&
|
||||||
ref.read(pWallets).getWallet(walletId) is RbfInterface;
|
wallet is RbfInterface;
|
||||||
} else {
|
} else {
|
||||||
supportsRbf = false;
|
supportsRbf = false;
|
||||||
}
|
}
|
||||||
|
@ -1704,6 +1713,17 @@ class _TransactionV2DetailsViewState
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (hasTxKeyProbably)
|
||||||
|
isDesktop
|
||||||
|
? const _Divider()
|
||||||
|
: const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
if (hasTxKeyProbably)
|
||||||
|
TxKeyWidget(
|
||||||
|
walletId: walletId,
|
||||||
|
txid: _transaction.txid,
|
||||||
|
),
|
||||||
isDesktop
|
isDesktop
|
||||||
? const _Divider()
|
? const _Divider()
|
||||||
: const SizedBox(
|
: const SizedBox(
|
||||||
|
|
|
@ -164,6 +164,13 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
|
||||||
|
|
||||||
bool walletExists(String path);
|
bool walletExists(String path);
|
||||||
|
|
||||||
|
String getTxKeyFor({required String txid}) {
|
||||||
|
if (libMoneroWallet == null) {
|
||||||
|
throw Exception("Cannot get tx key in uninitialized libMoneroWallet");
|
||||||
|
}
|
||||||
|
return libMoneroWallet!.getTxKey(txid);
|
||||||
|
}
|
||||||
|
|
||||||
void _setListener() {
|
void _setListener() {
|
||||||
if (libMoneroWallet != null && libMoneroWallet!.getListeners().isEmpty) {
|
if (libMoneroWallet != null && libMoneroWallet!.getListeners().isEmpty) {
|
||||||
libMoneroWallet?.addListener(
|
libMoneroWallet?.addListener(
|
||||||
|
|
102
lib/widgets/tx_key_widget.dart
Normal file
102
lib/widgets/tx_key_widget.dart
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import '../pages/pinpad_views/pinpad_dialog.dart';
|
||||||
|
import '../pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart';
|
||||||
|
import '../pages_desktop_specific/password/request_desktop_auth_dialog.dart';
|
||||||
|
import '../providers/global/wallets_provider.dart';
|
||||||
|
import '../utilities/text_styles.dart';
|
||||||
|
import '../utilities/util.dart';
|
||||||
|
import '../wallets/wallet/intermediate/lib_monero_wallet.dart';
|
||||||
|
import 'custom_buttons/blue_text_button.dart';
|
||||||
|
import 'custom_buttons/simple_copy_button.dart';
|
||||||
|
import 'detail_item.dart';
|
||||||
|
|
||||||
|
class TxKeyWidget extends ConsumerStatefulWidget {
|
||||||
|
/// The [walletId] MUST be the id of a [LibMoneroWallet]!
|
||||||
|
const TxKeyWidget({
|
||||||
|
super.key,
|
||||||
|
required this.walletId,
|
||||||
|
required this.txid,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
final String txid;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<TxKeyWidget> createState() => _TxKeyWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TxKeyWidgetState extends ConsumerState<TxKeyWidget> {
|
||||||
|
String? _private;
|
||||||
|
|
||||||
|
bool _lock = false;
|
||||||
|
|
||||||
|
Future<void> _loadTxKey() async {
|
||||||
|
if (_lock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_lock = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final verified = await showDialog<String?>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => Util.isDesktop
|
||||||
|
? const RequestDesktopAuthDialog(title: "Show private view key")
|
||||||
|
: const PinpadDialog(
|
||||||
|
biometricsAuthenticationTitle: "Show private view key",
|
||||||
|
biometricsLocalizedReason:
|
||||||
|
"Authenticate to show private view key",
|
||||||
|
biometricsCancelButtonString: "CANCEL",
|
||||||
|
),
|
||||||
|
barrierDismissible: !Util.isDesktop,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (verified == "verified success" && mounted) {
|
||||||
|
final wallet =
|
||||||
|
ref.read(pWallets).getWallet(widget.walletId) as LibMoneroWallet;
|
||||||
|
|
||||||
|
_private = wallet.getTxKeyFor(txid: widget.txid);
|
||||||
|
if (_private!.isEmpty) {
|
||||||
|
_private = "Unavailable";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
setState(() {});
|
||||||
|
} else {
|
||||||
|
_private == null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_lock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DetailItemBase(
|
||||||
|
button: _private == null
|
||||||
|
? CustomTextButton(
|
||||||
|
text: "Show",
|
||||||
|
onTap: _loadTxKey,
|
||||||
|
enabled: _private == null,
|
||||||
|
)
|
||||||
|
: Util.isDesktop
|
||||||
|
? IconCopyButton(
|
||||||
|
data: _private!,
|
||||||
|
)
|
||||||
|
: SimpleCopyButton(
|
||||||
|
data: _private!,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
"Private view key",
|
||||||
|
style: STextStyles.itemSubtitle(context),
|
||||||
|
),
|
||||||
|
detail: SelectableText(
|
||||||
|
// TODO
|
||||||
|
_private ?? "*" * 52, // 52 is approx length
|
||||||
|
style: STextStyles.w500_14(context),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue