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.
175 lines
5.3 KiB
Dart
175 lines
5.3 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:hash_wallet/core/wallet_loading_service.dart';
|
|
import 'package:hash_wallet/entities/wallet_group.dart';
|
|
import 'package:hash_wallet/entities/wallet_manager.dart';
|
|
import 'package:hash_wallet/reactions/wallet_utils.dart';
|
|
import 'package:hash_wallet/store/app_store.dart';
|
|
import 'package:hash_wallet/view_model/wallet_list/wallet_list_item.dart';
|
|
import 'package:hash_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
|
import 'package:hash_wallet/wallet_types.g.dart';
|
|
import 'package:cw_core/wallet_info.dart';
|
|
import 'package:cw_core/wallet_type.dart';
|
|
import 'package:mobx/mobx.dart';
|
|
|
|
part 'wallet_groups_display_view_model.g.dart';
|
|
|
|
class WalletGroupsDisplayViewModel = WalletGroupsDisplayViewModelBase
|
|
with _$WalletGroupsDisplayViewModel;
|
|
|
|
abstract class WalletGroupsDisplayViewModelBase with Store {
|
|
WalletGroupsDisplayViewModelBase(
|
|
this._appStore,
|
|
this._walletLoadingService,
|
|
this._walletManager,
|
|
this.walletListViewModel, {
|
|
required this.type,
|
|
}) : isFetchingMnemonic = false {
|
|
reaction((_) => _appStore.wallet, (_) => unawaited(updateWalletInfoSourceList()));
|
|
unawaited(updateWalletInfoSourceList());
|
|
}
|
|
|
|
final WalletType type;
|
|
final AppStore _appStore;
|
|
final WalletManager _walletManager;
|
|
final WalletLoadingService _walletLoadingService;
|
|
final WalletListViewModel walletListViewModel;
|
|
|
|
@observable
|
|
ObservableList<WalletGroup> multiWalletGroups = ObservableList<WalletGroup>();
|
|
|
|
@observable
|
|
ObservableList<WalletInfo> singleWalletsList = ObservableList<WalletInfo>();
|
|
|
|
@observable
|
|
WalletGroup? selectedWalletGroup;
|
|
|
|
@observable
|
|
WalletInfo? selectedSingleWallet;
|
|
|
|
@observable
|
|
bool isFetchingMnemonic;
|
|
|
|
@computed
|
|
bool get hasNoFilteredWallet {
|
|
return singleWalletsList.isEmpty && multiWalletGroups.isEmpty;
|
|
}
|
|
|
|
@action
|
|
Future<String?> getSelectedWalletMnemonic() async {
|
|
WalletListItem walletToUse;
|
|
|
|
bool isGroupSelected = selectedWalletGroup != null;
|
|
|
|
if (isGroupSelected) {
|
|
walletToUse = convertWalletInfoToWalletListItem(selectedWalletGroup!.wallets.first);
|
|
} else {
|
|
walletToUse = convertWalletInfoToWalletListItem(selectedSingleWallet!);
|
|
}
|
|
|
|
try {
|
|
isFetchingMnemonic = true;
|
|
final wallet = await _walletLoadingService.load(
|
|
walletToUse.type,
|
|
walletToUse.name,
|
|
);
|
|
|
|
return wallet.seed;
|
|
} catch (e) {
|
|
return null;
|
|
} finally {
|
|
isFetchingMnemonic = false;
|
|
}
|
|
}
|
|
|
|
@action
|
|
void selectWalletGroup(WalletGroup walletGroup) {
|
|
selectedWalletGroup = walletGroup;
|
|
selectedSingleWallet = null;
|
|
}
|
|
|
|
@action
|
|
void selectSingleWallet(WalletInfo singleWallet) {
|
|
selectedSingleWallet = singleWallet;
|
|
selectedWalletGroup = null;
|
|
}
|
|
|
|
@action
|
|
Future<void> updateWalletInfoSourceList() async {
|
|
List<WalletGroup> wallets = [];
|
|
|
|
multiWalletGroups.clear();
|
|
singleWalletsList.clear();
|
|
|
|
await _walletManager.updateWalletGroups();
|
|
|
|
final walletGroups = List<WalletGroup>.from(_walletManager.walletGroups);
|
|
|
|
// Iterate through the wallet groups to filter and categorize wallets
|
|
for (var group in walletGroups) {
|
|
// Handle group wallet filtering
|
|
bool shouldExcludeGroup = false;
|
|
for (final wallet in group.wallets) {
|
|
// Check for non-BIP39 wallet types
|
|
bool isNonBIP39Wallet = !isBIP39Wallet(wallet.type);
|
|
|
|
// Check for nano derivation type
|
|
final di = await wallet.getDerivationInfo();
|
|
bool isNanoDerivationType =
|
|
wallet.type == WalletType.nano && di.derivationType == DerivationType.nano;
|
|
|
|
// Check for electrum derivation type
|
|
bool isElectrumDerivationType =
|
|
(wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) &&
|
|
di.derivationType == DerivationType.electrum;
|
|
|
|
// Check that selected wallet type is not present already in group
|
|
bool isSameTypeAsSelectedWallet = wallet.type == type;
|
|
|
|
bool isNonSeedWallet = wallet.isNonSeedWallet;
|
|
|
|
bool isNotBip39CoinWallet =
|
|
wallet.type == WalletType.monero &&
|
|
di.derivationType != DerivationType.bip39;
|
|
|
|
bool isNotDecredBip39Wallet = false;
|
|
|
|
// Exclude if any of these conditions are true
|
|
shouldExcludeGroup = shouldExcludeGroup ||
|
|
isNonBIP39Wallet ||
|
|
isNanoDerivationType ||
|
|
isElectrumDerivationType ||
|
|
isSameTypeAsSelectedWallet ||
|
|
isNonSeedWallet ||
|
|
isNotBip39CoinWallet ||
|
|
isNotDecredBip39Wallet;
|
|
}
|
|
|
|
if (shouldExcludeGroup) continue;
|
|
|
|
// If the group passes the filters, add it to the wallets list
|
|
wallets.add(group);
|
|
}
|
|
|
|
for (var group in wallets) {
|
|
if (group.wallets.length == 1) {
|
|
singleWalletsList.add(group.wallets.first);
|
|
} else {
|
|
multiWalletGroups.add(group);
|
|
}
|
|
}
|
|
}
|
|
|
|
WalletListItem convertWalletInfoToWalletListItem(WalletInfo info) {
|
|
return WalletListItem(
|
|
name: info.name,
|
|
type: info.type,
|
|
key: info.id,
|
|
isCurrent: info.name == _appStore.wallet?.name && info.type == _appStore.wallet?.type,
|
|
isEnabled: availableWalletTypes.contains(info.type),
|
|
isTestnet: info.network?.toLowerCase().contains('testnet') ?? false,
|
|
isHardware: info.isHardwareWallet,
|
|
);
|
|
}
|
|
}
|