mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
94 files changed, -5926 net lines. No stubs, no generators, no dead enum
values, no orphan switch branches. Removed for principled reasons (we
do not ship these chains) and to make the codebase smaller and friendlier
to contribute to.
What's gone:
- lib/{solana,tron,zano,decred,zcash,haven}/ directories
- lib/exchange/provider/jupiter_exchange_provider.dart (Solana-only)
- lib/entities/haven_seed_store.dart
- WalletType.{solana,tron,zano,decred,zcash,haven} enum values
(HiveField IDs are pinned: Wownero stays at 12, all surviving types
keep their IDs, so existing user-saved wallets deserialize unchanged)
- All ~70 lib/ files that imported the removed chain stubs or branched
on the removed WalletType values
- backupSeeds(Box<HavenSeedStore>) abstract method + Wownero implementation
- Jupiter exchange branches in send/exchange view models
- TronGrid usage settings, Zano alias lookups, Zcash transparent address
handling, Decred default-spv-nodes branches, Haven seed migration
What stays (intentional):
- CryptoCurrency.{xhv,sol,trx,dcr,zano,zec} enum entries in cw_core —
they're still used as exchange/swap currency identifiers in
address_validator.dart and elsewhere. The wallet types are gone but
the *currencies* are still tradeable through Trocador.
- cw_core/spl_token.dart and cw_core/tron_token.dart Hive adapters in
main.dart — the tokens still register as Hive types for backwards-
compat with any old box data.
- lib/buy/{moonpay,robinhood,onramper,dfx,kryptonim,meld}/ provider
source files (just stripped of solana/tron/etc references; providers
themselves remain dormant per provider_types.dart).
Pinned-ID note: WalletType enum now has gaps in @HiveField IDs (4, 10,
11, 13, 14, 18 removed). This is deliberate — re-using a freed ID later
would mis-deserialize old hive boxes. Don't renumber.
Bundled config / CI hasn't changed; configure.dart was already free of
these chains in commit 4eb7db0b7.
272 lines
8.3 KiB
Dart
272 lines
8.3 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:hash_wallet/core/universal_address_detector.dart';
|
|
import 'package:hash_wallet/evm/evm.dart';
|
|
import 'package:hash_wallet/reactions/wallet_connect.dart';
|
|
import 'package:hash_wallet/store/app_store.dart';
|
|
import 'package:cw_core/wallet_type.dart';
|
|
import 'package:cw_core/wallet_info.dart';
|
|
import 'package:cw_core/utils/print_verbose.dart';
|
|
import 'package:cw_core/currency_for_wallet_type.dart';
|
|
import 'package:cw_core/crypto_currency.dart';
|
|
import 'package:mobx/mobx.dart';
|
|
|
|
part 'payment_view_model.g.dart';
|
|
|
|
class PaymentViewModel = PaymentViewModelBase with _$PaymentViewModel;
|
|
|
|
abstract class PaymentViewModelBase with Store {
|
|
PaymentViewModelBase({required this.appStore});
|
|
|
|
final AppStore appStore;
|
|
|
|
@observable
|
|
WalletType? detectedWalletType;
|
|
|
|
@observable
|
|
AddressDetectionResult? _lastDetectionResult;
|
|
|
|
@computed
|
|
int? get detectedChainId {
|
|
if (detectedWalletType == null) return null;
|
|
|
|
if (!isEVMCompatibleChain(detectedWalletType!)) return null;
|
|
|
|
if (_lastDetectionResult?.chainId != null) {
|
|
return _lastDetectionResult!.chainId;
|
|
}
|
|
|
|
// If detected wallet type is EVM-compatible, get chainId from detected currency
|
|
if (_lastDetectionResult?.detectedCurrency != null) {
|
|
return getChainIdByCryptoCurrency(_lastDetectionResult!.detectedCurrency!);
|
|
}
|
|
|
|
return evm!.getChainIdByWalletType(detectedWalletType!);
|
|
}
|
|
|
|
@observable
|
|
bool isProcessing = false;
|
|
|
|
@computed
|
|
WalletType get currentWalletType => appStore.wallet!.type;
|
|
|
|
@computed
|
|
int? get currentChainId {
|
|
if (!isEVMCompatibleChain(currentWalletType)) return null;
|
|
|
|
return evm!.getSelectedChainId(appStore.wallet!);
|
|
}
|
|
|
|
/// Main entry point - detect address type and check compatibility
|
|
@action
|
|
Future<PaymentFlowResult> processAddress(String addressData) async {
|
|
try {
|
|
detectedWalletType = null;
|
|
isProcessing = true;
|
|
|
|
// Detect address type
|
|
final detectionResult = UniversalAddressDetector.detectAddress(addressData);
|
|
|
|
_lastDetectionResult = detectionResult;
|
|
detectedWalletType = detectionResult.detectedWalletType;
|
|
|
|
if (!detectionResult.isValid || detectedWalletType == null) {
|
|
return PaymentFlowResult.incompatible('Unable to detect address type');
|
|
}
|
|
|
|
final currentWallet = appStore.wallet;
|
|
|
|
if (currentWallet != null &&
|
|
currentWallet.type == detectedWalletType &&
|
|
!isEVMCompatibleChain(detectedWalletType!)) {
|
|
return PaymentFlowResult.currentWalletCompatible();
|
|
}
|
|
|
|
if (isEVMCompatibleChain(detectedWalletType!)) {
|
|
return PaymentFlowResult.evmNetworkSelection(detectionResult);
|
|
}
|
|
|
|
final compatibleWallets = await getWalletsByType(detectedWalletType!);
|
|
|
|
switch (compatibleWallets.length) {
|
|
case 0:
|
|
return PaymentFlowResult.noWallets(detectedWalletType!, detectionResult);
|
|
case 1:
|
|
return PaymentFlowResult.singleWallet(compatibleWallets.first, detectionResult);
|
|
default:
|
|
return PaymentFlowResult.multipleWallets(compatibleWallets, detectionResult);
|
|
}
|
|
} catch (e) {
|
|
printV('PaymentViewModel error: $e');
|
|
return PaymentFlowResult.error('Payment processing failed: $e');
|
|
} finally {
|
|
isProcessing = false;
|
|
}
|
|
}
|
|
|
|
@action
|
|
Future<void> selectChain() async {
|
|
if (detectedWalletType == null) return;
|
|
|
|
final node =
|
|
appStore.settingsStore.getCurrentNode(detectedWalletType!, chainId: detectedChainId);
|
|
|
|
await evm!.selectChain(appStore.wallet!, detectedChainId!, node: node);
|
|
}
|
|
|
|
Future<List<WalletInfo>> getWalletsByType(WalletType walletType) async {
|
|
return (await WalletInfo.getAll()).where((wallet) => wallet.type == walletType).toList();
|
|
}
|
|
|
|
Future<List<WalletInfo>> getEVMCompatibleWallets() async {
|
|
final allWallets = await WalletInfo.getAll();
|
|
return allWallets.where((wallet) => isEVMCompatibleChain(wallet.type)).toList();
|
|
}
|
|
}
|
|
|
|
class PaymentFlowResult {
|
|
final PaymentFlowType type;
|
|
final String? message;
|
|
final WalletInfo? wallet;
|
|
final int? chainId;
|
|
final List<WalletInfo> wallets;
|
|
final WalletType? walletType;
|
|
final AddressDetectionResult? addressDetectionResult;
|
|
|
|
PaymentFlowResult._({
|
|
required this.type,
|
|
this.message,
|
|
this.wallet,
|
|
this.chainId,
|
|
this.wallets = const [],
|
|
this.walletType,
|
|
this.addressDetectionResult,
|
|
});
|
|
|
|
/// EVM address detected - needs network selection
|
|
/// We'll also take note of the number of compatible wallets for EVM ecosystem
|
|
factory PaymentFlowResult.evmNetworkSelection(
|
|
AddressDetectionResult addressDetectionResult, {
|
|
List<WalletInfo>? compatibleWallets,
|
|
WalletInfo? wallet,
|
|
}) {
|
|
int? chainId = addressDetectionResult.chainId;
|
|
if (chainId == null && addressDetectionResult.detectedCurrency != null) {
|
|
chainId = getChainIdByCryptoCurrency(addressDetectionResult.detectedCurrency!);
|
|
}
|
|
if (chainId == null && addressDetectionResult.detectedWalletType != null) {
|
|
chainId = evm!.getChainIdByWalletType(addressDetectionResult.detectedWalletType!);
|
|
}
|
|
|
|
return PaymentFlowResult._(
|
|
type: PaymentFlowType.evmNetworkSelection,
|
|
addressDetectionResult: addressDetectionResult,
|
|
walletType: addressDetectionResult.detectedWalletType,
|
|
chainId: chainId,
|
|
wallets: compatibleWallets ?? [],
|
|
wallet: wallet,
|
|
);
|
|
}
|
|
|
|
/// Current wallet is compatible
|
|
factory PaymentFlowResult.currentWalletCompatible() =>
|
|
PaymentFlowResult._(type: PaymentFlowType.currentWalletCompatible);
|
|
|
|
/// Single compatible wallet available
|
|
factory PaymentFlowResult.singleWallet(
|
|
WalletInfo wallet,
|
|
AddressDetectionResult addressDetectionResult,
|
|
) {
|
|
int? chainId = addressDetectionResult.chainId;
|
|
if (chainId == null && addressDetectionResult.detectedCurrency != null) {
|
|
chainId = getChainIdByCryptoCurrency(addressDetectionResult.detectedCurrency!);
|
|
}
|
|
if (chainId == null) {
|
|
chainId = evm!.getChainIdByWalletType(wallet.type);
|
|
}
|
|
|
|
return PaymentFlowResult._(
|
|
type: PaymentFlowType.singleWallet,
|
|
wallet: wallet,
|
|
walletType: wallet.type,
|
|
chainId: chainId,
|
|
addressDetectionResult: addressDetectionResult,
|
|
);
|
|
}
|
|
|
|
/// Multiple compatible wallets available
|
|
factory PaymentFlowResult.multipleWallets(
|
|
List<WalletInfo> wallets,
|
|
AddressDetectionResult addressDetectionResult,
|
|
) {
|
|
int? chainId = addressDetectionResult.chainId;
|
|
if (chainId == null && addressDetectionResult.detectedCurrency != null) {
|
|
chainId = getChainIdByCryptoCurrency(addressDetectionResult.detectedCurrency!);
|
|
}
|
|
if (chainId == null) {
|
|
chainId = evm!.getChainIdByWalletType(wallets.first.type);
|
|
}
|
|
|
|
return PaymentFlowResult._(
|
|
type: PaymentFlowType.multipleWallets,
|
|
wallets: wallets,
|
|
walletType: wallets.first.type,
|
|
addressDetectionResult: addressDetectionResult,
|
|
chainId: chainId,
|
|
);
|
|
}
|
|
|
|
/// No compatible wallets available
|
|
factory PaymentFlowResult.noWallets(
|
|
WalletType walletType,
|
|
AddressDetectionResult addressDetectionResult,
|
|
) {
|
|
int? chainId = addressDetectionResult.chainId;
|
|
if (chainId == null && addressDetectionResult.detectedCurrency != null) {
|
|
chainId = getChainIdByCryptoCurrency(addressDetectionResult.detectedCurrency!);
|
|
}
|
|
if (chainId == null) {
|
|
chainId = evm!.getChainIdByWalletType(walletType);
|
|
}
|
|
|
|
return PaymentFlowResult._(
|
|
type: PaymentFlowType.noWallets,
|
|
walletType: walletType,
|
|
addressDetectionResult: addressDetectionResult,
|
|
chainId: chainId,
|
|
);
|
|
}
|
|
|
|
/// Error occurred
|
|
factory PaymentFlowResult.error(String message) =>
|
|
PaymentFlowResult._(type: PaymentFlowType.error, message: message);
|
|
|
|
/// Incompatible address
|
|
factory PaymentFlowResult.incompatible(String message) =>
|
|
PaymentFlowResult._(type: PaymentFlowType.incompatible, message: message);
|
|
|
|
CryptoCurrency? get detectedCurrency {
|
|
if (type == PaymentFlowType.evmNetworkSelection) {
|
|
return addressDetectionResult?.detectedCurrency;
|
|
}
|
|
if (walletType != null) {
|
|
if (isEVMCompatibleChain(walletType!)) {
|
|
return walletTypeToCryptoCurrency(walletType!, chainId: chainId);
|
|
}
|
|
|
|
return walletTypeToCryptoCurrency(walletType!);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
enum PaymentFlowType {
|
|
currentWalletCompatible,
|
|
singleWallet,
|
|
multipleWallets,
|
|
noWallets,
|
|
evmNetworkSelection,
|
|
error,
|
|
incompatible,
|
|
}
|