diff --git a/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart b/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart index 3dd8678a2..470bd483b 100644 --- a/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart +++ b/lib/models/isar/models/blockchain_data/v2/transaction_v2.dart @@ -6,7 +6,6 @@ import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart' import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; -import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/extensions/extensions.dart'; import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; @@ -79,7 +78,7 @@ class TransactionV2 { return confirmations >= minimumConfirms; } - Amount getFee({required Coin coin}) { + Amount getFee({required int fractionDigits}) { // check for override fee final fee = _getOverrideFee(); if (fee != null) { @@ -92,44 +91,47 @@ class TransactionV2 { .map((e) => e.value) .reduce((value, element) => value += element); - return Amount(rawValue: inSum - outSum, fractionDigits: coin.decimals); + return Amount(rawValue: inSum - outSum, fractionDigits: fractionDigits); } - Amount getAmountReceivedInThisWallet({required Coin coin}) { + Amount getAmountReceivedInThisWallet({required int fractionDigits}) { final outSum = outputs .where((e) => e.walletOwns) .fold(BigInt.zero, (p, e) => p + e.value); - return Amount(rawValue: outSum, fractionDigits: coin.decimals); + return Amount(rawValue: outSum, fractionDigits: fractionDigits); } - Amount getAmountSparkSelfMinted({required Coin coin}) { + Amount getAmountSparkSelfMinted({required int fractionDigits}) { final outSum = outputs.where((e) { final op = e.scriptPubKeyHex.substring(0, 2).toUint8ListFromHex.first; return e.walletOwns && (op == OP_SPARKMINT); }).fold(BigInt.zero, (p, e) => p + e.value); - return Amount(rawValue: outSum, fractionDigits: coin.decimals); + return Amount(rawValue: outSum, fractionDigits: fractionDigits); } - Amount getAmountSentFromThisWallet({required Coin coin}) { + Amount getAmountSentFromThisWallet({required int fractionDigits}) { final inSum = inputs .where((e) => e.walletOwns) .fold(BigInt.zero, (p, e) => p + e.value); - final amount = Amount( + Amount amount = Amount( rawValue: inSum, - fractionDigits: coin.decimals, + fractionDigits: fractionDigits, ) - getAmountReceivedInThisWallet( - coin: coin, - ) - - getFee(coin: coin); + fractionDigits: fractionDigits, + ); + + if (subType != TransactionSubType.ethToken) { + amount = amount - getFee(fractionDigits: fractionDigits); + } // negative amounts are likely an error or can happen with coins such as eth // that don't use the btc style inputs/outputs if (amount.raw < BigInt.zero) { - return Amount.zeroWith(fractionDigits: coin.decimals); + return Amount.zeroWith(fractionDigits: fractionDigits); } return amount; diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart index c9b6b202f..c67a8bf8f 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart @@ -843,6 +843,9 @@ class _DesktopTransactionCardRowState late final TransactionV2 _transaction; late final String walletId; late final int minConfirms; + late final EthContract? ethContract; + + bool get isTokenTx => ethContract != null; String whatIsIt(TransactionV2 tx, int height) => tx.statusLabel( currentChainHeight: height, @@ -858,6 +861,15 @@ class _DesktopTransactionCardRowState .cryptoCurrency .minConfirms; _transaction = widget.transaction; + + if (_transaction.subType == TransactionSubType.ethToken) { + ethContract = ref + .read(mainDBProvider) + .getEthContractSync(_transaction.contractAddress!); + } else { + ethContract == null; + } + super.initState(); } @@ -892,19 +904,22 @@ class _DesktopTransactionCardRowState final currentHeight = ref.watch(pWalletChainHeight(walletId)); final Amount amount; - + final fractionDigits = ethContract?.decimals ?? coin.decimals; if (_transaction.subType == TransactionSubType.cashFusion) { - amount = _transaction.getAmountReceivedInThisWallet(coin: coin); + amount = _transaction.getAmountReceivedInThisWallet( + fractionDigits: fractionDigits); } else { switch (_transaction.type) { case TransactionType.outgoing: - amount = _transaction.getAmountSentFromThisWallet(coin: coin); + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits); break; case TransactionType.incoming: case TransactionType.sentToSelf: if (_transaction.subType == TransactionSubType.sparkMint) { - amount = _transaction.getAmountSparkSelfMinted(coin: coin); + amount = _transaction.getAmountSparkSelfMinted( + fractionDigits: fractionDigits); } else if (_transaction.subType == TransactionSubType.sparkSpend) { final changeAddress = (ref.watch(pWallets).getWallet(walletId) as SparkInterface) @@ -917,12 +932,14 @@ class _DesktopTransactionCardRowState fractionDigits: coin.decimals, ); } else { - amount = _transaction.getAmountReceivedInThisWallet(coin: coin); + amount = _transaction.getAmountReceivedInThisWallet( + fractionDigits: fractionDigits); } break; case TransactionType.unknown: - amount = _transaction.getAmountSentFromThisWallet(coin: coin); + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits); break; } } @@ -1005,7 +1022,7 @@ class _DesktopTransactionCardRowState Expanded( flex: 6, child: Text( - "$prefix${ref.watch(pAmountFormatter(coin)).format(amount)}", + "$prefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", style: STextStyles.desktopTextExtraExtraSmall(context).copyWith( color: Theme.of(context).extension()!.textDark, diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart index f9561b740..d4c47e0fd 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_card.dart @@ -112,18 +112,23 @@ class _TransactionCardStateV2 extends ConsumerState { final Amount amount; + final fractionDigits = tokenContract?.decimals ?? coin.decimals; + if (_transaction.subType == TransactionSubType.cashFusion) { - amount = _transaction.getAmountReceivedInThisWallet(coin: coin); + amount = _transaction.getAmountReceivedInThisWallet( + fractionDigits: fractionDigits); } else { switch (_transaction.type) { case TransactionType.outgoing: - amount = _transaction.getAmountSentFromThisWallet(coin: coin); + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits); break; case TransactionType.incoming: case TransactionType.sentToSelf: if (_transaction.subType == TransactionSubType.sparkMint) { - amount = _transaction.getAmountSparkSelfMinted(coin: coin); + amount = _transaction.getAmountSparkSelfMinted( + fractionDigits: fractionDigits); } else if (_transaction.subType == TransactionSubType.sparkSpend) { final changeAddress = (ref.watch(pWallets).getWallet(walletId) as SparkInterface) @@ -136,12 +141,14 @@ class _TransactionCardStateV2 extends ConsumerState { fractionDigits: coin.decimals, ); } else { - amount = _transaction.getAmountReceivedInThisWallet(coin: coin); + amount = _transaction.getAmountReceivedInThisWallet( + fractionDigits: fractionDigits); } break; case TransactionType.unknown: - amount = _transaction.getAmountSentFromThisWallet(coin: coin); + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits); break; } } diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index 74b016893..54714bfb6 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -17,11 +17,13 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart'; +import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart'; import 'package:stackwallet/pages/wallet_view/transaction_views/dialogs/cancelling_transaction_progress_dialog.dart'; import 'package:stackwallet/pages/wallet_view/transaction_views/edit_note_view.dart'; import 'package:stackwallet/pages/wallet_view/wallet_view.dart'; +import 'package:stackwallet/providers/db/main_db_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/themes/stack_colors.dart'; @@ -84,6 +86,9 @@ class _TransactionV2DetailsViewState late final String amountPrefix; late final String unit; late final int minConfirms; + late final EthContract? ethContract; + + bool get isTokenTx => ethContract != null; late final List<({List addresses, Amount amount})> data; @@ -96,10 +101,24 @@ class _TransactionV2DetailsViewState walletId = widget.walletId; coin = widget.coin; + + if (_transaction.subType == TransactionSubType.ethToken) { + ethContract = ref + .read(mainDBProvider) + .getEthContractSync(_transaction.contractAddress!); + + unit = ethContract!.symbol; + } else { + ethContract == null; + unit = coin.ticker; + } + minConfirms = ref.read(pWallets).getWallet(walletId).cryptoCurrency.minConfirms; - fee = _transaction.getFee(coin: coin); + final fractionDigits = ethContract?.decimals ?? coin.decimals; + + fee = _transaction.getFee(fractionDigits: fractionDigits); if (_transaction.subType == TransactionSubType.cashFusion || _transaction.type == TransactionType.sentToSelf) { @@ -108,18 +127,18 @@ class _TransactionV2DetailsViewState amountPrefix = _transaction.type == TransactionType.outgoing ? "-" : "+"; } - unit = coin.ticker; - if (_transaction.isEpiccashTransaction) { switch (_transaction.type) { case TransactionType.outgoing: case TransactionType.unknown: - amount = _transaction.getAmountSentFromThisWallet(coin: coin); + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits); break; case TransactionType.incoming: case TransactionType.sentToSelf: - amount = _transaction.getAmountReceivedInThisWallet(coin: coin); + amount = _transaction.getAmountReceivedInThisWallet( + fractionDigits: fractionDigits); break; } data = _transaction.outputs @@ -129,7 +148,8 @@ class _TransactionV2DetailsViewState )) .toList(); } else if (_transaction.subType == TransactionSubType.cashFusion) { - amount = _transaction.getAmountReceivedInThisWallet(coin: coin); + amount = _transaction.getAmountReceivedInThisWallet( + fractionDigits: fractionDigits); data = _transaction.outputs .where((e) => e.walletOwns) .map((e) => ( @@ -140,7 +160,8 @@ class _TransactionV2DetailsViewState } else { switch (_transaction.type) { case TransactionType.outgoing: - amount = _transaction.getAmountSentFromThisWallet(coin: coin); + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits); data = _transaction.outputs .where((e) => !e.walletOwns) .map((e) => ( @@ -154,7 +175,8 @@ class _TransactionV2DetailsViewState case TransactionType.incoming: case TransactionType.sentToSelf: if (_transaction.subType == TransactionSubType.sparkMint) { - amount = _transaction.getAmountSparkSelfMinted(coin: coin); + amount = _transaction.getAmountSparkSelfMinted( + fractionDigits: fractionDigits); } else if (_transaction.subType == TransactionSubType.sparkSpend) { final changeAddress = (ref.read(pWallets).getWallet(walletId) as SparkInterface) @@ -167,7 +189,8 @@ class _TransactionV2DetailsViewState fractionDigits: coin.decimals, ); } else { - amount = _transaction.getAmountReceivedInThisWallet(coin: coin); + amount = _transaction.getAmountReceivedInThisWallet( + fractionDigits: fractionDigits); } data = _transaction.outputs .where((e) => e.walletOwns) @@ -180,7 +203,8 @@ class _TransactionV2DetailsViewState break; case TransactionType.unknown: - amount = _transaction.getAmountSentFromThisWallet(coin: coin); + amount = _transaction.getAmountSentFromThisWallet( + fractionDigits: fractionDigits); data = _transaction.inputs .where((e) => e.walletOwns) .map((e) => ( @@ -515,7 +539,7 @@ class _TransactionV2DetailsViewState : CrossAxisAlignment.start, children: [ SelectableText( - "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount)}", + "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", style: isDesktop ? STextStyles .desktopTextExtraExtraSmall( diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index 7a3f0a7b8..d5319221b 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -105,21 +105,6 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { await mainDB.updateOrPutAddresses([address]); } - // delete - @override - Future
getCurrentReceivingAddress() async { - return Address( - walletId: walletId, - value: - checksumEthereumAddress("0x6Cc3006944070B32D80107D51d843a66EaC00686"), - publicKey: [], // maybe store address bytes here? seems a waste of space though - derivationIndex: 0, - derivationPath: DerivationPath()..value = "$hdPathEthereum/0", - type: AddressType.ethereum, - subType: AddressSubType.receiving, - ); - } - // ==================== Overrides ============================================ @override diff --git a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart index 22fcd3e59..11c981ab4 100644 --- a/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart +++ b/lib/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart @@ -407,13 +407,17 @@ class EthTokenWallet extends Wallet { for (final tuple in data) { // ignore all non Transfer events (for now) if (tuple.tx.topics[0] == kTransferEventSignature) { - final Amount txFee = tuple.extra.gasUsed * tuple.extra.gasPrice; - final amount = Amount( rawValue: tuple.tx.data.toBigIntFromHex, fractionDigits: tokenContract.decimals, ); + if (amount.raw == BigInt.zero) { + // probably don't need to show this + continue; + } + + final Amount txFee = tuple.extra.gasUsed * tuple.extra.gasPrice; final addressFrom = _addressFromTopic( tuple.tx.topics[1], ); @@ -451,7 +455,28 @@ class EthTokenWallet extends Wallet { final List outputs = []; final List inputs = []; - // TODO: ins outs + OutputV2 output = OutputV2.isarCantDoRequiredInDefaultConstructor( + scriptPubKeyHex: "00", + valueStringSats: amount.raw.toString(), + addresses: [ + addressTo, + ], + walletOwns: addressTo == addressString, + ); + InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor( + scriptSigHex: null, + sequence: null, + outpoint: null, + addresses: [addressFrom], + valueStringSats: amount.raw.toString(), + witness: null, + innerRedeemScriptAsm: null, + coinbase: null, + walletOwns: addressFrom == addressString, + ); + + outputs.add(output); + inputs.add(input); final txn = TransactionV2( walletId: walletId,