mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
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:
+6
-4
@@ -1417,10 +1417,12 @@ Future<void> setup({
|
||||
}
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<TransactionDetailsModal, TransactionInfo, void>(
|
||||
(transactionInfo, _) => TransactionDetailsModal(transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
|
||||
param1: [transactionInfo, false]))
|
||||
);
|
||||
getIt.registerFactoryParam<TransactionDetailsModal, TransactionInfo, bool?>(
|
||||
(transactionInfo, highlightNoteField) => TransactionDetailsModal(
|
||||
transactionDetailsViewModel:
|
||||
getIt.get<TransactionDetailsViewModel>(param1: [transactionInfo, false]),
|
||||
highlightNoteField: highlightNoteField ?? false,
|
||||
));
|
||||
|
||||
getIt.registerFactoryParam<TransactionDetailsPage, TransactionInfo, void>(
|
||||
(TransactionInfo transactionInfo, _) => TransactionDetailsPage(
|
||||
|
||||
@@ -143,6 +143,39 @@ class CWEVM extends EVM {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionInfo getTransactionInfo(
|
||||
|
||||
{
|
||||
required String id,
|
||||
required int height,
|
||||
required BigInt ethAmount,
|
||||
required BigInt ethFee,
|
||||
required String tokenSymbol,
|
||||
int exponent = 18,
|
||||
required TransactionDirection direction,
|
||||
required bool isPending,
|
||||
required DateTime date,
|
||||
required int confirmations,
|
||||
String? to,
|
||||
String? from,
|
||||
String? evmSignatureName,
|
||||
String? contractAddress,
|
||||
required int chainId,
|
||||
}) =>
|
||||
EVMChainTransactionInfo(id: id,
|
||||
height: height,
|
||||
ethAmount: ethAmount,
|
||||
ethFee: ethFee,
|
||||
tokenSymbol: tokenSymbol,
|
||||
direction: direction,
|
||||
isPending: isPending,
|
||||
date: date,
|
||||
confirmations: confirmations,
|
||||
to: to,
|
||||
from: from,
|
||||
chainId: chainId);
|
||||
|
||||
@override
|
||||
int formatterEVMParseAmount(String amount) => EVMChainFormatter.parseEVMChainAmount(amount);
|
||||
|
||||
@@ -432,6 +465,13 @@ class CWEVM extends EVM {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
BigInt getPendingTransactionFee(PendingTransaction tx) => (tx as PendingEVMChainTransaction).fee;
|
||||
|
||||
@override
|
||||
String getPendingTransactionAmount(PendingTransaction tx) => (tx as PendingEVMChainTransaction).amount;
|
||||
|
||||
// Registry helper methods
|
||||
static final EvmChainRegistry _registry = EvmChainRegistry();
|
||||
|
||||
|
||||
@@ -1315,7 +1315,7 @@ class _NewSendPageState extends State<NewSendPage> {
|
||||
// height: MediaQuery.of(context).size.height*0.4,
|
||||
child: ModalNavigator(
|
||||
parentContext: modalContext,
|
||||
heightMode: ModalHeightModes.autoLock,
|
||||
heightMode: ModalHeightModes.natural,
|
||||
rootPage: Material(
|
||||
child: NewPicker(
|
||||
title: S.of(context).set_fees,
|
||||
|
||||
@@ -16,9 +16,10 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class TransactionDetailsModal extends StatefulWidget {
|
||||
const TransactionDetailsModal({super.key, required this.transactionDetailsViewModel});
|
||||
const TransactionDetailsModal({super.key, required this.transactionDetailsViewModel, this.highlightNoteField = false});
|
||||
|
||||
final TransactionDetailsViewModel transactionDetailsViewModel;
|
||||
final bool highlightNoteField;
|
||||
|
||||
@override
|
||||
State<TransactionDetailsModal> createState() => _TransactionDetailsModalState();
|
||||
@@ -38,6 +39,10 @@ class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
|
||||
widget.transactionDetailsViewModel.updateNote(noteController.text);
|
||||
}
|
||||
});
|
||||
|
||||
if(widget.highlightNoteField) {
|
||||
noteFocusNode.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -2,17 +2,25 @@ import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/core/address_validator.dart';
|
||||
import 'package:cake_wallet/core/utilities.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/contact.dart';
|
||||
import 'package:cake_wallet/entities/contact_record.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/animated_dropdown.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/send_page/send_confirm_bottom_widget.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cake_wallet/utils/address_formatter.dart';
|
||||
import 'package:cake_wallet/view_model/send/send_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@@ -31,12 +39,14 @@ class SendConfirmSheet extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SendConfirmSheetState extends State<SendConfirmSheet> {
|
||||
bool _committed = false;
|
||||
|
||||
void initState() {
|
||||
super.initState();
|
||||
reaction((context) => widget.sendViewModel.state, (state) {
|
||||
if (state is TransactionCommitted) {
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
if (mounted) Navigator.of(context).maybePop();
|
||||
reaction((_)=>widget.sendViewModel.state, (state){
|
||||
if(state is TransactionCommitted) {
|
||||
setState(() {
|
||||
_committed = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -60,33 +70,48 @@ class _SendConfirmSheetState extends State<SendConfirmSheet> {
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Observer(
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
final commited = widget.sendViewModel.state is TransactionCommitted;
|
||||
return Stack(
|
||||
fit: StackFit.loose,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
return AnimatedSize(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOutCubic,
|
||||
alignment: Alignment.topCenter,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
heightFactor: _committed ? 0.0 : 1.0,
|
||||
child: AnimatedSlide(
|
||||
offset: commited ? Offset.zero : const Offset(1, 0),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOutCubic,
|
||||
child: const TransactionCommitedScreen(),
|
||||
)),
|
||||
AnimatedSlide(
|
||||
offset: commited ? const Offset(-1, 0) : Offset.zero,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOutCubic,
|
||||
child: SendTransactionDetails(
|
||||
sendViewModel: widget.sendViewModel,
|
||||
isPage: widget.isPage,
|
||||
title: widget.title,
|
||||
iconPath: widget.iconPath),
|
||||
),
|
||||
],
|
||||
offset: _committed ? const Offset(-1, 0) : Offset.zero,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOutCubic,
|
||||
child: SendTransactionDetails(
|
||||
sendViewModel: widget.sendViewModel,
|
||||
isPage: widget.isPage,
|
||||
title: widget.title,
|
||||
iconPath: widget.iconPath,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
heightFactor: _committed ? 1.0 : 0.0,
|
||||
child: AnimatedSlide(
|
||||
offset: _committed ? Offset.zero : const Offset(1, 0),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOutCubic,
|
||||
child: TransactionCommitedScreen(
|
||||
sendViewModel: widget.sendViewModel,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -178,7 +203,7 @@ class SendTransactionDetails extends StatelessWidget {
|
||||
}),
|
||||
sendViewModel.selectedCryptoCurrency)
|
||||
: sendViewModel.amountParsingProxy.getDisplayCryptoAmount(
|
||||
formatAmount(transaction.amountFormatted), sendViewModel.selectedCryptoCurrency);
|
||||
formatAmount(transaction.amountFormatted), sendViewModel.selectedCryptoCurrency).withMaxDecimals(8);
|
||||
|
||||
final fee =
|
||||
"${(transaction == null) ? sendViewModel.amountParsingProxy.getDisplayCryptoStringFromBigInt(sumByBigInt(
|
||||
@@ -404,29 +429,150 @@ class SendTransactionDetails extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class TransactionCommitedScreen extends StatelessWidget {
|
||||
const TransactionCommitedScreen({super.key});
|
||||
class TransactionCommitedScreen extends StatefulWidget {
|
||||
const TransactionCommitedScreen({super.key, this.sendViewModel});
|
||||
|
||||
final SendViewModel? sendViewModel;
|
||||
|
||||
@override
|
||||
State<TransactionCommitedScreen> createState() => _TransactionCommitedScreenState();
|
||||
}
|
||||
|
||||
class _TransactionCommitedScreenState extends State<TransactionCommitedScreen> {
|
||||
bool _isNoteButtonLoading = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 24.0),
|
||||
child: Column(
|
||||
return Observer(
|
||||
builder: (_) => Column(
|
||||
spacing: 12,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
SizedBox(height: 12,),
|
||||
Text(
|
||||
S.of(context).transaction_sent_new,
|
||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
|
||||
),
|
||||
Image.asset(width: 256, height: 256, "assets/images/birthday_cake.png")
|
||||
SizedBox(),
|
||||
CakeImageWidget(width: 200, height: 200, imageUrl: "assets/new-ui/birthday_cake.svg"),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: Column(
|
||||
spacing: 12,
|
||||
children: [
|
||||
if (widget.sendViewModel != null)
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
if (!(widget.sendViewModel!.checkIfAddressIsAContact(
|
||||
widget.sendViewModel!.outputs.first.address)) &&
|
||||
!(widget.sendViewModel!.outputs.first.isParsedAddress))
|
||||
TransactionCommittedScreenActionButton(
|
||||
text: S.of(context).save_contact,
|
||||
iconPath: "assets/new-ui/save_contact.svg",
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(Routes.addressBookAddContact,
|
||||
arguments: ContactRecord(
|
||||
CakeHive.box<Contact>(Contact.boxName),
|
||||
Contact(
|
||||
name: "",
|
||||
address: widget.sendViewModel!.outputs.first.address,
|
||||
type: widget.sendViewModel!.wallet.currency)));
|
||||
}),
|
||||
// lightning has to be hacked in here as it doesn't get added to tx history for a few secs after committing.
|
||||
if (widget.sendViewModel!.transactionInfo != null ||
|
||||
widget.sendViewModel!.currency == CryptoCurrency.btcln)
|
||||
TransactionCommittedScreenActionButton(
|
||||
text: S.of(context).add_a_note,
|
||||
iconPath: "assets/new-ui/add_note.svg",
|
||||
isLoading: _isNoteButtonLoading,
|
||||
onTap: () async {
|
||||
setState(() {
|
||||
_isNoteButtonLoading = true;
|
||||
});
|
||||
|
||||
// for ln, we want to show the button and just have it wait until it appears in tx history
|
||||
// for other currs this is instant
|
||||
await asyncWhen((_) => widget.sendViewModel!.transactionInfo != null);
|
||||
|
||||
setState(() {
|
||||
_isNoteButtonLoading = false;
|
||||
});
|
||||
|
||||
final page = getIt.get<TransactionDetailsModal>(
|
||||
param1: widget.sendViewModel!.transactionInfo!, param2: true);
|
||||
showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (context) => page);
|
||||
}),
|
||||
],
|
||||
),
|
||||
NewPrimaryButton(
|
||||
onPressed: Navigator.of(context).maybePop,
|
||||
text: S.of(context).done,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary),
|
||||
SizedBox(height: 12,)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TransactionCommittedScreenActionButton extends StatelessWidget {
|
||||
const TransactionCommittedScreenActionButton(
|
||||
{super.key,
|
||||
required this.text,
|
||||
required this.iconPath,
|
||||
required this.onTap,
|
||||
this.isLoading = false});
|
||||
|
||||
final String text;
|
||||
final String iconPath;
|
||||
final VoidCallback onTap;
|
||||
final bool isLoading;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Flexible(
|
||||
child: GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
color: Theme.of(context).colorScheme.surfaceContainer),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 10,
|
||||
children: [
|
||||
isLoading
|
||||
? CupertinoActivityIndicator()
|
||||
: CakeImageWidget(
|
||||
imageUrl: iconPath,
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context).colorScheme.primary, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.w500),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
class MultiSendAddressPreview extends StatefulWidget {
|
||||
const MultiSendAddressPreview(
|
||||
|
||||
@@ -409,4 +409,33 @@ class CWSolana extends Solana {
|
||||
await Future.wait(tokenChecks);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionInfo getTransactionInfo({
|
||||
required String id,
|
||||
required DateTime blockTime,
|
||||
required String to,
|
||||
required String from,
|
||||
String? tokenSymbol,
|
||||
required TransactionDirection direction,
|
||||
required double solAmount,
|
||||
required bool isPending,
|
||||
required double txFee,
|
||||
}) =>
|
||||
SolanaTransactionInfo(
|
||||
id: id,
|
||||
blockTime: blockTime,
|
||||
to: to,
|
||||
from: from,
|
||||
tokenSymbol: tokenSymbol ?? "SOL",
|
||||
direction: direction,
|
||||
solAmount: solAmount,
|
||||
isPending: isPending,
|
||||
txFee: txFee);
|
||||
|
||||
@override
|
||||
double getPendingTransactionAmount(PendingTransaction tx) => (tx as PendingSolanaTransaction).amount;
|
||||
|
||||
@override
|
||||
double getPendingTransactionFee(PendingTransaction tx) => (tx as PendingSolanaTransaction).fee;
|
||||
}
|
||||
|
||||
@@ -153,4 +153,32 @@ class CWTron extends Tron {
|
||||
return tronWallet.tronTokenCurrencies
|
||||
.any((element) => element.contractAddress == contractAddress);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionInfo getTransactionInfo({
|
||||
required String id,
|
||||
required BigInt tronAmount,
|
||||
int? txFee,
|
||||
String? tokenSymbol,
|
||||
required TransactionDirection direction,
|
||||
required DateTime blockTime,
|
||||
String? to,
|
||||
String? from,
|
||||
required bool isPending,
|
||||
}) =>
|
||||
TronTransactionInfo(id: id,
|
||||
tronAmount: tronAmount,
|
||||
tokenSymbol: tokenSymbol ?? "TRX",
|
||||
txFee: txFee,
|
||||
direction: direction,
|
||||
blockTime: blockTime,
|
||||
to: to,
|
||||
from: from,
|
||||
isPending: isPending);
|
||||
|
||||
@override
|
||||
String getPendingTransactionAmount(PendingTransaction tx) => (tx as PendingTronTransaction).amount;
|
||||
|
||||
@override
|
||||
String getPendingTransactionFee(PendingTransaction tx) => (tx as PendingTronTransaction).amount;
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user