Files
hash-wallet/lib/view_model/settings/other_settings_view_model.dart
T
jwinterm dd449f2594 Merge upstream Cake Wallet v6.5.0
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.
2026-10-24 23:49:29 -04:00

201 lines
6.4 KiB
Dart

import 'dart:io';
import 'package:hash_wallet/bitcoin/bitcoin.dart';
import 'package:hash_wallet/entities/auto_generate_subaddress_status.dart';
import 'package:hash_wallet/entities/priority_for_wallet_type.dart';
import 'package:hash_wallet/store/settings_store.dart';
import 'package:hash_wallet/utils/package_info.dart';
import 'package:hash_wallet/view_model/send/send_view_model.dart';
import 'package:collection/collection.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:mobx/mobx.dart';
part 'other_settings_view_model.g.dart';
class OtherSettingsViewModel = OtherSettingsViewModelBase with _$OtherSettingsViewModel;
abstract class OtherSettingsViewModelBase with Store {
OtherSettingsViewModelBase(this._settingsStore, this._wallet, this.sendViewModel)
: walletType = _wallet.type,
chainId = _wallet.chainId,
currentVersion = '' {
PackageInfo.fromPlatform()
.then((PackageInfo packageInfo) => currentVersion = packageInfo.version);
final priority = _settingsStore.getPriority(_wallet.type, chainId: _wallet.chainId);
final priorities = priorityForWalletType(_wallet.type);
if (!priorities.contains(priority) && priorities.isNotEmpty) {
_settingsStore.setPriority(_wallet.type, priorities.first, chainId: _wallet.chainId);
}
}
final WalletType walletType;
final int? chainId;
final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet;
@observable
String currentVersion;
final SettingsStore _settingsStore;
final SendViewModel sendViewModel;
bool get hasSignVerify => _wallet.canSignMessages;
@computed
TransactionPriority get transactionPriority {
final priority = _settingsStore.getPriority(walletType, chainId: chainId);
if (priority == null) {
throw Exception('Unexpected type ${walletType.toString()}');
}
return priority;
}
@computed
bool get isAutoGenerateSubaddressesEnabled =>
_settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled;
@action
void setAutoGenerateSubaddresses(bool value) {
_wallet.isEnabledAutoGenerateSubaddress = value;
_settingsStore.autoGenerateSubaddressStatus =
value ? AutoGenerateSubaddressStatus.enabled : AutoGenerateSubaddressStatus.disabled;
}
bool get isAutoGenerateSubaddressesVisible => [
WalletType.monero,
WalletType.wownero,
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
WalletType.dogecoin,
].contains(_wallet.type);
@computed
bool get isMoneroWallet => _wallet.type == WalletType.monero;
@computed
bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress;
@computed
bool get changeRepresentativeEnabled =>
[WalletType.nano, WalletType.banano].contains(_wallet.type);
@computed
bool get changeHardwareWalletTypeEnabled => [
HardwareWalletType.cupcake,
HardwareWalletType.coldcard,
HardwareWalletType.seedsigner,
].contains(_wallet.hardwareWalletType);
@computed
bool get displayTransactionPriority => !(changeRepresentativeEnabled ||
[
WalletType.arbitrum,
].contains(_wallet.type));
String getDisplayPriority(dynamic priority) {
final _priority = priority as TransactionPriority;
if ([
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
WalletType.dogecoin,
].contains(_wallet.type)) {
final rate = bitcoin!.getFeeRate(_wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate);
}
return priority.toString();
}
String getDisplayBitcoinPriority(dynamic priority, int customValue) {
final _priority = priority as TransactionPriority;
if ([
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
WalletType.dogecoin,
].contains(_wallet.type)) {
final rate = bitcoin!.getFeeRate(_wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue);
}
return priority.toString();
}
void onDisplayPrioritySelected(TransactionPriority priority) =>
_settingsStore.setPriority(walletType, priority, chainId: chainId);
void onDisplayBitcoinPrioritySelected(TransactionPriority priority, double customValue) {
if (_wallet.type == WalletType.bitcoin) {
_settingsStore.customBitcoinFeeRate = customValue.round();
}
_settingsStore.setPriority(_wallet.type, priority, chainId: _wallet.chainId);
}
@action
Future<void> onHardwareWalletTypeChanged(HardwareWalletType hwType) async {
_wallet.walletInfo.hardwareWalletType = hwType;
await _wallet.walletInfo.save();
}
@computed
double get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate.toDouble();
@action
void setShouldSaveRecipientAddress(bool value) =>
_settingsStore.shouldSaveRecipientAddress = value;
@computed
bool get showCiBuildOverlay => _settingsStore.showCiBuildOverlay;
@action
void setShowCiBuildOverlay(bool value) => _settingsStore.showCiBuildOverlay = value;
int? get customPriorityItemIndex {
final priorities = priorityForWalletType(walletType);
final customItem = priorities
.firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom());
return customItem != null ? priorities.indexOf(customItem) : null;
}
int? get maxCustomFeeRate {
if (_wallet.type == WalletType.bitcoin) {
return bitcoin!.getMaxCustomFeeRate(_wallet);
}
return null;
}
bool get hasPayjoin => _wallet.hasPayjoinSupport;
bool get hasLightning => _wallet.hasLightningSupport;
Future<File?> getLightningLog() async {
final path = await pathForWalletDir(name: _wallet.name, type: walletType);
final logFile = File("$path/lightning.log");
if (await logFile.exists()) return logFile;
return null;
}
Future<File?> getPayjoinLog() async {
final path = await pathForWalletDir(name: _wallet.name, type: walletType);
final logFile = File("$path/payjoin.log");
if (await logFile.exists()) return logFile;
return null;
}
}