tx-confirmation-options-on-dev [cw-1463] (#3289)

* add note and contact options to tx confirmation screen

* fix closing animation for confirm sheet

* fix note button for lightning

* sizing fix

* add local tx info for evm/sol/trx

* fix for xmr/zec

* merge

* fixes
This commit is contained in:
malik1004x
2026-06-04 11:32:19 +02:00
committed by GitHub
parent 1704bc5172
commit 5099fa3b9c
22 changed files with 458 additions and 65 deletions
@@ -326,6 +326,10 @@ abstract class DashboardViewModelBase with Store {
appStore.wallet!.transactionHistory.transactions.values.last.confirmations +
1;
} catch (_) {}
} else {
confirmations = appStore.wallet!.transactionHistory.transactions.values
.map((item) => item.isPending)
.fold(0, (val, pending) => pending ? val + 1 : val);
}
return length * confirmations;
}, _transactionDisposerCallback, delay: 300);
@@ -490,16 +494,23 @@ abstract class DashboardViewModelBase with Store {
}
// printV("Transaction disposer callback (relevantTxs: ${relevantTxs.length} current: ${transactions.length})");
// TODO(malik) update this in a saner way during the vm refactor
String _txIdentityString(String txHash, TransactionDirection direction) => "${txHash}_$direction";
String _txIdentityStringConfirmations(String txHash, TransactionDirection direction, int confirmations) => "${txHash}_${direction}_$confirmations";
String _txIdentityStringConfirmations(
String txHash, TransactionDirection direction, int confirmations, bool isPending) =>
"${txHash}_${direction}_${confirmations}_$isPending";
final existingKeys = transactions
.map((item) => _txIdentityStringConfirmations(item.transaction.txHash, item.transaction.direction, item.transaction.confirmations))
.map((item) => _txIdentityStringConfirmations(
item.transaction.txHash,
item.transaction.direction,
item.transaction.confirmations,
item.transaction.isPending))
.toSet();
final newTransactions = relevantTxs
.where((tx) => !existingKeys.contains(_txIdentityStringConfirmations(tx.txHash, tx.direction, tx.confirmations)))
.where((tx) => !existingKeys.contains(_txIdentityStringConfirmations(
tx.txHash, tx.direction, tx.confirmations, tx.isPending)))
.map((tx) => TransactionListItem(
transaction: tx,
balanceViewModel: balanceViewModel,
@@ -1291,6 +1302,10 @@ abstract class DashboardViewModelBase with Store {
appStore.wallet!.transactionHistory.transactions.values.last.confirmations +
1;
} catch (_) {}
} else {
confirmations = appStore.wallet!.transactionHistory.transactions.values
.map((item) => item.isPending)
.fold(0, (val, pending) => pending ? val + 1 : val);
}
return length * confirmations;
}, _transactionDisposerCallback, delay: 300);
@@ -218,7 +218,7 @@ class TransactionListItem extends ActionListItem with Keyable {
case WalletType.base:
case WalletType.arbitrum:
case WalletType.bsc:
final asset = evm!.assetOfTransaction(balanceViewModel.wallet, transaction);
final asset = assetOfTransaction;
final price = balanceViewModel.fiatConversionStore.prices[asset];
amount = calculateFiatAmountRaw(
cryptoAmount: evm!.formatterEVMAmountToDouble(transaction: transaction),
+63
View File
@@ -8,6 +8,7 @@ import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/core/open_crypto_pay/exceptions.dart';
import 'package:cake_wallet/core/open_crypto_pay/models.dart';
import 'package:cake_wallet/core/open_crypto_pay/open_cryptopay_service.dart';
import 'package:cake_wallet/core/utilities.dart';
import 'package:cake_wallet/core/validator.dart';
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/decred/decred.dart';
@@ -59,6 +60,7 @@ import 'package:cw_core/exceptions.dart';
import 'package:cw_core/lnurl.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coin_type.dart';
@@ -488,6 +490,25 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
bool get shouldDisplayTOTP2FAForSendsToInternalWallet =>
_settingsStore.shouldRequireTOTP2FAForSendsToInternalWallets;
@computed
TransactionInfo? get transactionInfo {
if(isEVMCompatibleChain(walletType)) {
return wallet.transactionHistory.transactions[pendingTransaction?.evmTxHashFromRawHex];
}
if (walletType == WalletType.monero) {
// monero tx history keys are in format txhash_amount_accountindex_addressindex
return wallet.transactionHistory.transactions[wallet.transactionHistory.transactions.keys
.firstWhereOrNull((item) => item.split("_").first == pendingTransaction?.id)];
}
if (walletType == WalletType.zcash) {
// zcash has a txHash getter, but the pendingTransaction id contains quotation marks for whatever reason?
final txIdNoQuotes = pendingTransaction?.id.replaceAll("\"", "");
return wallet.transactionHistory.transactions.values
.firstWhereOrNull((item) => item.txHash == txIdNoQuotes);
}
return wallet.transactionHistory.transactions[pendingTransaction?.id];
}
//* Still open to further optimize these checks
//* It works but can be made better
@action
@@ -1078,6 +1099,48 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
});
}
// FIXME(malik) ideally, this should be done wallet-side.
// it is required because evm, solana and tron don't actually save the transaction info when you send something.
// instead, they rely on the tx to eventually get fetched at sync time, which can take a while
if(isEVMWallet) {
wallet.transactionHistory.addOne(evm!.getTransactionInfo(
id: pendingTransaction!.evmTxHashFromRawHex!,
height: 0,
// FIXME(malik) this is even more critical given all the issues we had with decimal point parsing. with money it'll be easy
ethAmount: selectedCryptoCurrency.parseAmount(outputs.first.cryptoAmount),
ethFee: CryptoCurrency.eth.parseAmount(pendingTransaction!.feeFormattedValue),
tokenSymbol: selectedCryptoCurrency.title,
direction: TransactionDirection.outgoing,
isPending: true,
date: DateTime.now(),
confirmations: 0,
chainId: wallet.chainId ?? 0));
}
if(walletType == WalletType.solana) {
wallet.transactionHistory.addOne(solana!.getTransactionInfo(
id: pendingTransaction!.id,
blockTime: DateTime.now(),
tokenSymbol: selectedCryptoCurrency.title,
to: "",
from: "",
direction: TransactionDirection.outgoing,
solAmount: solana!.getPendingTransactionAmount(pendingTransaction!),
isPending: true,
txFee: solana!.getPendingTransactionFee(pendingTransaction!)));
}
if (walletType == WalletType.tron) {
wallet.transactionHistory.addOne(tron!.getTransactionInfo(
id: pendingTransaction!.id,
blockTime: DateTime.now(),
tokenSymbol: selectedCryptoCurrency.title,
direction: TransactionDirection.outgoing,
tronAmount: selectedCryptoCurrency.parseAmount(outputs.first.cryptoAmount),
isPending: true,
txFee: CryptoCurrency.trx.parseAmount(outputs.first.estimatedFee).toInt()));
}
if (pendingTransaction!.id.isNotEmpty) {
_addTransactionDescription();
}
@@ -127,6 +127,7 @@ class TxDetailRowDefinition {
.firstOrNull ??
"";
case WalletType.tron:
if(vm.transactionInfo.to != null)
ret = tron!.getTronBase58Address(vm.transactionInfo.to!, vm.wallet);
default:
break;
@@ -315,6 +316,7 @@ abstract class TransactionDetailsViewModelBase with Store {
TransactionPriority? transactionPriority;
CryptoCurrency get transactionAsset {
if (isEVMCompatibleChain(wallet.type)) {
return evm!.assetOfTransaction(wallet, transactionInfo);
}