mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-29 06:38:45 +01:00
Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535 upstream commits, including the Monero silent-open fix, Monero on Trezor, Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9. Merged with both sides normalized first (import rename, 100-column format), which took the conflict count from 614 paths to 322. The procedure is now scripts/upstream_sync.sh. Kept from Hash Bags: - WalletType enum order and Hive IDs. SQLite stores WalletType.index and our order differs from upstream's; taking theirs would reread saved wallets as other chains. Our frozen adapter keeps the shipped IDs. - The 1.0.2 legacy PIN and wallet-password decode and self-heal. - Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out. - Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me), converted to upstream's isDefault node-list key; Wownero is back in the node reset list. - Privacy: address resolvers limited to domain-anchored sources again; prices.neroswap.com for fiat; upstream's charts tab, which reads prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false. - Lightning stays behind FeatureFlag.isLightningEnabled, including upstream's new post-seed Lightning username step. - Our icon pipeline, branding and bundle identifiers. Twelve new upstream widget tests are skipped: test and code are unchanged from v6.5.0 apart from renames (not rerun on a pristine upstream checkout; upstream's top_bar_test does not compile against its own TopBar). flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped; flutter build bundle compiles. Built with Flutter 3.41.9.
218 lines
6.8 KiB
Dart
218 lines
6.8 KiB
Dart
import 'package:hash_wallet/entities/balance_display_mode.dart';
|
|
import 'package:hash_wallet/entities/fiat_currency.dart';
|
|
import 'package:hash_wallet/evm/evm.dart';
|
|
import 'package:hash_wallet/generated/i18n.dart';
|
|
import 'package:hash_wallet/reactions/wallet_connect.dart';
|
|
import 'package:hash_wallet/store/app_store.dart';
|
|
import 'package:cw_core/crypto_amount_format.dart';
|
|
import 'package:cw_core/crypto_currency.dart';
|
|
import 'package:cw_core/transaction_direction.dart';
|
|
import 'package:cw_core/transaction_info.dart';
|
|
import 'package:hash_wallet/view_model/dashboard/action_list_item.dart';
|
|
import 'package:hash_wallet/entities/calculate_fiat_amount_raw.dart';
|
|
import 'package:hash_wallet/view_model/dashboard/balance_view_model.dart';
|
|
import 'package:cw_core/keyable.dart';
|
|
import 'package:cw_core/wallet_type.dart';
|
|
|
|
class TransactionListItem extends ActionListItem with Keyable {
|
|
TransactionListItem({
|
|
required this.transaction,
|
|
required this.balanceViewModel,
|
|
required AppStore appStore,
|
|
required super.key,
|
|
}) : _appStore = appStore;
|
|
|
|
final TransactionInfo transaction;
|
|
final BalanceViewModel balanceViewModel;
|
|
final AppStore _appStore;
|
|
|
|
double get price => balanceViewModel.price;
|
|
|
|
FiatCurrency get fiatCurrency => _appStore.settingsStore.fiatCurrency;
|
|
|
|
BalanceDisplayMode get displayMode => balanceViewModel.displayMode;
|
|
|
|
@override
|
|
dynamic get keyIndex => transaction.id;
|
|
|
|
bool get hasTokens => isEVMCompatibleChain(balanceViewModel.wallet.type);
|
|
|
|
String get formattedCryptoAmount {
|
|
if (displayMode == BalanceDisplayMode.hiddenBalance) return '---';
|
|
if (balanceViewModel.wallet.type == WalletType.bitcoin) {
|
|
return _appStore.amountParsingProxy
|
|
.asDisplayStringWithSymbol(transaction.amount)
|
|
.withLocalSeperator(_appStore.settingsStore.languageCode);
|
|
}
|
|
|
|
return transaction.amount.toStringWithSymbol(fractionalDigits: 8);
|
|
}
|
|
|
|
String get formattedTitle {
|
|
|
|
if (transaction.additionalInfo['isIronwoodMigration'] == true) {
|
|
return 'Migration';
|
|
}
|
|
if (transaction.additionalInfo['isAutoShield'] == true) {
|
|
if (transaction.isPending) {
|
|
final status = formattedStatus;
|
|
final baseString = S.current.shielding;
|
|
return status.isNotEmpty ? "$baseString $status" : "$baseString...";
|
|
}
|
|
return S.current.shielding;
|
|
}
|
|
if (transaction.isPending) {
|
|
final status = formattedStatus;
|
|
final baseString = transaction.direction == TransactionDirection.incoming
|
|
? S.current.receiving
|
|
: S.current.sending;
|
|
return status.isNotEmpty ? "$baseString $status" : "$baseString...";
|
|
}
|
|
|
|
if (transaction.direction == TransactionDirection.incoming) {
|
|
return S.current.received;
|
|
}
|
|
|
|
return S.current.sent;
|
|
}
|
|
|
|
int get neededConfirmations {
|
|
switch (balanceViewModel.wallet.type) {
|
|
case WalletType.monero:
|
|
return 10;
|
|
case WalletType.wownero:
|
|
return 3;
|
|
case WalletType.litecoin:
|
|
bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false;
|
|
bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false;
|
|
if (isPegOut || fromPegOut) return 6;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
String get formattedPendingStatus {
|
|
switch (balanceViewModel.wallet.type) {
|
|
case WalletType.monero:
|
|
if (transaction.confirmations >= 0 && transaction.confirmations < 10) {
|
|
return ' (${transaction.confirmations}/10)';
|
|
}
|
|
break;
|
|
case WalletType.wownero:
|
|
if (transaction.confirmations >= 0 && transaction.confirmations < 3) {
|
|
return ' (${transaction.confirmations}/3)';
|
|
}
|
|
break;
|
|
case WalletType.litecoin:
|
|
bool isPegIn = (transaction.additionalInfo["isPegIn"] as bool?) ?? false;
|
|
bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false;
|
|
bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false;
|
|
String str = '';
|
|
if (transaction.confirmations <= 0) {
|
|
str = S.current.pending;
|
|
}
|
|
if ((isPegOut || fromPegOut) &&
|
|
transaction.confirmations >= 0 &&
|
|
transaction.confirmations < 6) {
|
|
str = " (${transaction.confirmations}/6)";
|
|
}
|
|
if (isPegIn) {
|
|
str += " (Mask)";
|
|
}
|
|
if (isPegOut) {
|
|
str += " (Unmask)";
|
|
}
|
|
return str;
|
|
default:
|
|
return '';
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
String get formattedStatus {
|
|
if ([
|
|
WalletType.monero,
|
|
WalletType.wownero,
|
|
WalletType.litecoin,
|
|
].contains(balanceViewModel.wallet.type)) {
|
|
return formattedPendingStatus;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
String get formattedType {
|
|
if (transaction.evmSignatureName == 'approval') {
|
|
return ' (${transaction.evmSignatureName})';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
CryptoCurrency? get assetOfTransaction {
|
|
try {
|
|
if (isEVMCompatibleChain(balanceViewModel.wallet.type)) {
|
|
final asset = evm!.assetOfTransaction(balanceViewModel.wallet, transaction);
|
|
return asset;
|
|
}
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
String get formattedFiatAmount {
|
|
var amount = '';
|
|
|
|
switch (balanceViewModel.wallet.type) {
|
|
case WalletType.monero:
|
|
case WalletType.wownero:
|
|
case WalletType.bitcoin:
|
|
case WalletType.litecoin:
|
|
case WalletType.bitcoinCash:
|
|
case WalletType.dogecoin:
|
|
case WalletType.nano:
|
|
amount = calculateFiatAmountRaw(
|
|
cryptoAmount: double.parse(transaction.amount.toString()),
|
|
price: price,
|
|
).withLocalSeperator(_appStore.settingsStore.languageCode);
|
|
case WalletType.ethereum:
|
|
case WalletType.polygon:
|
|
case WalletType.base:
|
|
case WalletType.arbitrum:
|
|
case WalletType.bsc:
|
|
final asset = assetOfTransaction;
|
|
final price = balanceViewModel.fiatConversionStore.prices[asset];
|
|
amount = calculateFiatAmountRaw(
|
|
cryptoAmount: double.parse(transaction.amount.toString()),
|
|
price: price,
|
|
).withLocalSeperator(_appStore.settingsStore.languageCode);
|
|
break;
|
|
case WalletType.none:
|
|
case WalletType.banano:
|
|
break;
|
|
}
|
|
|
|
transaction.changeFiatAmount(amount);
|
|
return displayMode == BalanceDisplayMode.hiddenBalance
|
|
? '---'
|
|
: fiatCurrency.title + ' ' + transaction.fiatAmount();
|
|
}
|
|
|
|
@override
|
|
DateTime get date => transaction.date;
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (other is TransactionListItem) {
|
|
return other.transaction.txHash == transaction.txHash &&
|
|
other.transaction.confirmations == transaction.confirmations &&
|
|
other.transaction.isPending == transaction.isPending &&
|
|
other.transaction.direction == transaction.direction;
|
|
}
|
|
return false;
|
|
}
|
|
}
|