mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-21 06:18:42 +02:00
feat: initial hive -> SQLite (#2502)
* feat: initial hive -> SQLite Includes migration script and initial work done to remove dependency on hive generators. Also contains some refactoring to make sync code async. Features new dev screen that lists all SQLite tables Aspects that need testing: - backups (from this version, and from previous versions as well) - wallet loading / wallet list - almost everything else - renaming - deletion - sorting in wallet list - wallet groups - wallet seed/keys - wallet switching - wallet creation / restore - all methods - wallet address page - hardware wallet connection (and prompts from mall screens) - contacts - advanced settings in wallet creation - derivation paths - some minor wownero fixes - base, hardware wallets * fix: build errors * fix: Bad state: No element in backup restore * address comments from review * fix: HardwareWalletType
This commit is contained in:
@@ -4,8 +4,8 @@ class CWBase extends Base {
|
||||
@override
|
||||
List<String> getBaseWordList(String language) => EVMChainMnemonics.englishWordlist;
|
||||
|
||||
WalletService createBaseWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) =>
|
||||
BaseWalletService(walletInfoSource, isDirect, client: BaseClient());
|
||||
WalletService createBaseWalletService(bool isDirect) =>
|
||||
BaseWalletService(isDirect, client: BaseClient());
|
||||
|
||||
@override
|
||||
WalletCredentials createBaseNewWalletCredentials({
|
||||
@@ -216,14 +216,15 @@ class CWBase extends Base {
|
||||
|
||||
|
||||
@override
|
||||
void setHardwareWalletService(WalletBase wallet, HardwareWalletService service) {
|
||||
Future<void> setHardwareWalletService(WalletBase wallet, HardwareWalletService service) async {
|
||||
if (service is EVMChainLedgerService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials).setLedgerConnection(
|
||||
service.ledgerConnection, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
service.ledgerConnection, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
} else if (service is EVMChainBitboxService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmBitboxCredentials)
|
||||
.setBitbox(service.manager, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
.setBitbox(service.manager, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
}
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -260,17 +260,14 @@ class CWBitcoin extends Bitcoin {
|
||||
}
|
||||
|
||||
WalletService createBitcoinWalletService(
|
||||
Box<WalletInfo> walletInfoSource,
|
||||
Box<UnspentCoinsInfo> unspentCoinSource,
|
||||
Box<PayjoinSession> payjoinSessionSource,
|
||||
bool isDirect) {
|
||||
return BitcoinWalletService(
|
||||
walletInfoSource, unspentCoinSource, payjoinSessionSource, isDirect);
|
||||
return BitcoinWalletService(unspentCoinSource, payjoinSessionSource, isDirect);
|
||||
}
|
||||
|
||||
WalletService createLitecoinWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
|
||||
return LitecoinWalletService(walletInfoSource, unspentCoinSource, isDirect);
|
||||
WalletService createLitecoinWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
|
||||
return LitecoinWalletService(unspentCoinSource, isDirect);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -537,7 +534,7 @@ class CWBitcoin extends Bitcoin {
|
||||
}
|
||||
|
||||
@override
|
||||
void setHardwareWalletService(WalletBase wallet, HardwareWalletService service) {
|
||||
Future<void> setHardwareWalletService(WalletBase wallet, HardwareWalletService service) async {
|
||||
(wallet as ElectrumWallet).hardwareWalletService = service;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,8 @@ class CWBitcoinCash extends BitcoinCash {
|
||||
String getCashAddrFormat(String address) => AddressUtils.getCashAddrFormat(address);
|
||||
|
||||
@override
|
||||
WalletService createBitcoinCashWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
|
||||
return BitcoinCashWalletService(walletInfoSource, unspentCoinSource, isDirect);
|
||||
WalletService createBitcoinCashWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
|
||||
return BitcoinCashWalletService(unspentCoinSource, isDirect);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -24,7 +24,7 @@ import 'package:cake_wallet/wallet_types.g.dart';
|
||||
import 'package:cake_backup/backup.dart' as cake_backup;
|
||||
|
||||
class $BackupService {
|
||||
$BackupService(this._secureStorage, this.walletInfoSource, this.transactionDescriptionBox,
|
||||
$BackupService(this._secureStorage, this.transactionDescriptionBox,
|
||||
this.keyService, this.sharedPreferences)
|
||||
: cipher = Cryptography.instance.chacha20Poly1305Aead(),
|
||||
correctWallets = <WalletInfo>[];
|
||||
@@ -37,7 +37,6 @@ class $BackupService {
|
||||
final Cipher cipher;
|
||||
final SecureStorage _secureStorage;
|
||||
final SharedPreferences sharedPreferences;
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
final Box<TransactionDescription> transactionDescriptionBox;
|
||||
final KeyService keyService;
|
||||
List<WalletInfo> correctWallets;
|
||||
@@ -110,27 +109,14 @@ class $BackupService {
|
||||
}
|
||||
|
||||
Future<void> verifyWallets() async {
|
||||
final walletInfoSource = await reloadHiveWalletInfoBox();
|
||||
correctWallets =
|
||||
walletInfoSource.values.where((info) => availableWalletTypes.contains(info.type)).toList();
|
||||
await performHiveMigration(); // for backups made before sqlite migration
|
||||
correctWallets = (await WalletInfo.getAll()).where((info) => availableWalletTypes.contains(info.type)).toList();
|
||||
|
||||
if (correctWallets.isEmpty) {
|
||||
throw Exception('Correct wallets not detected');
|
||||
printV('Correct wallets not detected');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Box<WalletInfo>> reloadHiveWalletInfoBox() async {
|
||||
final appDir = await getAppDir();
|
||||
await CakeHive.close();
|
||||
CakeHive.init(appDir.path);
|
||||
|
||||
if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) {
|
||||
CakeHive.registerAdapter(WalletInfoAdapter());
|
||||
}
|
||||
|
||||
return await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
}
|
||||
|
||||
Future<void> importTransactionDescriptionDump() async {
|
||||
final appDir = await getAppDir();
|
||||
final transactionDescriptionFile = File('${appDir.path}/~_transaction_descriptions_dump');
|
||||
@@ -191,12 +177,16 @@ class $BackupService {
|
||||
String currentWalletName = data[PreferencesKey.currentWalletName] as String;
|
||||
int currentWalletType = data[PreferencesKey.currentWalletType] as int;
|
||||
|
||||
final isCorrentCurrentWallet = correctWallets
|
||||
final isCorrectCurrentWallet = correctWallets
|
||||
.any((info) => info.name == currentWalletName && info.type.index == currentWalletType);
|
||||
|
||||
if (!isCorrentCurrentWallet) {
|
||||
currentWalletName = correctWallets.first.name;
|
||||
currentWalletType = serializeToInt(correctWallets.first.type);
|
||||
try {
|
||||
if (!isCorrectCurrentWallet) {
|
||||
currentWalletName = correctWallets.first.name;
|
||||
currentWalletType = serializeToInt(correctWallets.first.type);
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
if (DeviceInfo.instance.isDesktop) {
|
||||
@@ -283,7 +273,7 @@ class $BackupService {
|
||||
Future<Uint8List> exportKeychainDumpV2(String password,
|
||||
{String keychainSalt = secrets.backupKeychainSalt}) async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final wallets = await Future.wait(walletInfoSource.values.map((walletInfo) async {
|
||||
final wallets = await Future.wait((await WalletInfo.getAll()).map((walletInfo) async {
|
||||
try {
|
||||
return {
|
||||
'name': walletInfo.name,
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:crypto/crypto.dart';
|
||||
import 'package:cw_core/root_dir.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
enum BackupVersion {
|
||||
@@ -143,7 +144,7 @@ class BackupMetadata {
|
||||
}
|
||||
|
||||
class BackupServiceV3 extends $BackupService {
|
||||
BackupServiceV3(super.secureStorage, super.walletInfoSource, super.transactionDescriptionBox, super.keyService, super.sharedPreferences);
|
||||
BackupServiceV3(super.secureStorage, super.transactionDescriptionBox, super.keyService, super.sharedPreferences);
|
||||
|
||||
static BackupVersion get currentVersion => BackupVersion.v3;
|
||||
|
||||
@@ -317,7 +318,6 @@ class BackupServiceV3 extends $BackupService {
|
||||
|
||||
Future<void> verifyHardwareWallets(String password,
|
||||
{String keychainSalt = secrets.backupKeychainSalt}) async {
|
||||
final walletInfoSource = await reloadHiveWalletInfoBox();
|
||||
final appDir = await getAppDir();
|
||||
final keychainDumpFile = File('${appDir.path}/~_keychain_dump');
|
||||
final decryptedKeychainDumpFileData = await decryptV2(
|
||||
@@ -334,10 +334,7 @@ class BackupServiceV3 extends $BackupService {
|
||||
|
||||
for (final expectedHardwareWallet in expectedHardwareWallets) {
|
||||
final info = expectedHardwareWallet as Map<String, dynamic>;
|
||||
final actualWalletInfo = walletInfoSource.values
|
||||
.where((e) =>
|
||||
e.name == info['name'] && e.type.toString() == info['type'])
|
||||
.firstOrNull;
|
||||
final actualWalletInfo = await WalletInfo.get(info['name'] as String, WalletType.values.firstWhere((e) => e.toString() == info['type'] as String));
|
||||
if (actualWalletInfo != null &&
|
||||
info["hardwareWalletType"] !=
|
||||
actualWalletInfo.hardwareWalletType?.index) {
|
||||
|
||||
@@ -16,8 +16,7 @@ class WalletCreationService {
|
||||
{required WalletType initialType,
|
||||
required this.keyService,
|
||||
required this.sharedPreferences,
|
||||
required this.settingsStore,
|
||||
required this.walletInfoSource})
|
||||
required this.settingsStore})
|
||||
: type = initialType {
|
||||
changeWalletType(type: type);
|
||||
}
|
||||
@@ -26,7 +25,6 @@ class WalletCreationService {
|
||||
final SharedPreferences sharedPreferences;
|
||||
final SettingsStore settingsStore;
|
||||
final KeyService keyService;
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
WalletService? _service;
|
||||
|
||||
static const _isNewMoneroWalletPasswordUpdated = true;
|
||||
@@ -36,23 +34,23 @@ class WalletCreationService {
|
||||
_service = getIt.get<WalletService>(param1: type);
|
||||
}
|
||||
|
||||
bool exists(String name) {
|
||||
Future<bool> exists(String name) async {
|
||||
final walletName = name.toLowerCase();
|
||||
return walletInfoSource.values.any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
|
||||
return (await WalletInfo.getAll()).any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
|
||||
}
|
||||
|
||||
bool typeExists(WalletType type) {
|
||||
return walletInfoSource.values.any((walletInfo) => walletInfo.type == type);
|
||||
Future<bool> typeExists(WalletType type) async {
|
||||
return (await WalletInfo.getAll()).any((walletInfo) => walletInfo.type == type);
|
||||
}
|
||||
|
||||
void checkIfExists(String name) {
|
||||
if (exists(name)) {
|
||||
Future<void> checkIfExists(String name) async {
|
||||
if (await exists(name)) {
|
||||
throw Exception('Wallet with name ${name} already exists!');
|
||||
}
|
||||
}
|
||||
|
||||
Future<WalletBase> create(WalletCredentials credentials, {bool? isTestnet}) async {
|
||||
checkIfExists(credentials.name);
|
||||
await checkIfExists(credentials.name);
|
||||
|
||||
if (credentials.password == null) {
|
||||
credentials.password = generateWalletPassword();
|
||||
@@ -84,12 +82,12 @@ class WalletCreationService {
|
||||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
case WalletType.dogecoin:
|
||||
case WalletType.nano:
|
||||
return true;
|
||||
case WalletType.monero:
|
||||
case WalletType.wownero:
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
case WalletType.zano:
|
||||
case WalletType.decred:
|
||||
|
||||
@@ -74,7 +74,7 @@ class WalletLoadingService {
|
||||
} catch (error, stack) {
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
final isLedgerError = await ExceptionHandler.isLedgerError(error);
|
||||
if (isLedgerError || requireHardwareWalletConnection(type, name)) rethrow;
|
||||
if (isLedgerError || await requireHardwareWalletConnection(type, name)) rethrow;
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||
|
||||
|
||||
@@ -87,9 +87,8 @@ class WalletLoadingService {
|
||||
}
|
||||
|
||||
// try opening another wallet that is not corrupted to give user access to the app
|
||||
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
WalletBase? wallet;
|
||||
for (var walletInfo in walletInfoSource.values) {
|
||||
for (var walletInfo in await WalletInfo.getAll()) {
|
||||
try {
|
||||
final walletService = walletServiceFactory.call(walletInfo.type);
|
||||
final walletPassword = await keyService.getWalletPassword(walletName: walletInfo.name);
|
||||
@@ -195,8 +194,8 @@ class WalletLoadingService {
|
||||
return "\n\n$type ($name): ${await walletService.getSeeds(name, password, type)}";
|
||||
}
|
||||
|
||||
bool requireHardwareWalletConnection(WalletType type, String name) {
|
||||
Future<bool> requireHardwareWalletConnection(WalletType type, String name) async {
|
||||
final walletService = walletServiceFactory.call(type);
|
||||
return walletService.requireHardwareWalletConnection(name);
|
||||
return await walletService.requireHardwareWalletConnection(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,8 @@ class CWDecred extends Decred {
|
||||
DecredRestoreWalletFromPubkeyCredentials(name: name, pubkey: pubkey, password: password);
|
||||
|
||||
@override
|
||||
WalletService createDecredWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
|
||||
return DecredWalletService(walletInfoSource, unspentCoinSource);
|
||||
WalletService createDecredWalletService(Box<UnspentCoinsInfo> unspentCoinSource) {
|
||||
return DecredWalletService(unspentCoinSource);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -53,7 +52,7 @@ class CWDecred extends Decred {
|
||||
.toList(),
|
||||
priority: priority as DecredTransactionPriority);
|
||||
|
||||
List<AddressInfo> getAddressInfos(Object wallet) {
|
||||
List<WalletInfoAddressInfo> getAddressInfos(Object wallet) {
|
||||
final decredWallet = wallet as DecredWallet;
|
||||
return decredWallet.walletAddresses.getAddressInfos();
|
||||
}
|
||||
|
||||
+24
-43
@@ -2,7 +2,6 @@ import 'dart:async' show Timer;
|
||||
|
||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
import 'package:cake_wallet/anonpay/anonpay_api.dart';
|
||||
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
||||
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
||||
import 'package:cake_wallet/anypay/anypay_api.dart';
|
||||
import 'package:cake_wallet/base/base.dart';
|
||||
@@ -301,7 +300,6 @@ import 'package:cake_wallet/view_model/wallet_switcher_view_model.dart';
|
||||
final getIt = GetIt.instance;
|
||||
|
||||
var _isSetupFinished = false;
|
||||
late Box<WalletInfo> _walletInfoSource;
|
||||
late Box<Node> _nodeSource;
|
||||
late Box<Node> _powNodeSource;
|
||||
late Box<Contact> _contactSource;
|
||||
@@ -315,7 +313,6 @@ late Box<PayjoinSession> _payjoinSessionSource;
|
||||
late Box<AnonpayInvoiceInfo> _anonpayInvoiceInfoSource;
|
||||
|
||||
Future<void> setup({
|
||||
required Box<WalletInfo> walletInfoSource,
|
||||
required Box<Node> nodeSource,
|
||||
required Box<Node> powNodeSource,
|
||||
required Box<Contact> contactSource,
|
||||
@@ -330,7 +327,6 @@ Future<void> setup({
|
||||
required SecureStorage secureStorage,
|
||||
required GlobalKey<NavigatorState> navigatorKey,
|
||||
}) async {
|
||||
_walletInfoSource = walletInfoSource;
|
||||
_nodeSource = nodeSource;
|
||||
_powNodeSource = powNodeSource;
|
||||
_contactSource = contactSource;
|
||||
@@ -432,7 +428,7 @@ Future<void> setup({
|
||||
keyService: getIt.get<KeyService>(),
|
||||
sharedPreferences: getIt.get<SharedPreferences>(),
|
||||
settingsStore: getIt.get<SettingsStore>(),
|
||||
walletInfoSource: _walletInfoSource));
|
||||
));
|
||||
|
||||
getIt.registerFactoryParam<AdvancedPrivacySettingsViewModel, WalletType, void>(
|
||||
(type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get<SettingsStore>()));
|
||||
@@ -446,17 +442,17 @@ Future<void> setup({
|
||||
(newWalletArgs, _) => WalletNewVM(
|
||||
getIt.get<AppStore>(),
|
||||
getIt.get<WalletCreationService>(param1:newWalletArgs.type),
|
||||
_walletInfoSource,
|
||||
getIt.get<AdvancedPrivacySettingsViewModel>(param1: newWalletArgs.type),
|
||||
getIt.get<SeedSettingsViewModel>(),
|
||||
newWalletArguments: newWalletArgs,));
|
||||
newWalletArguments: newWalletArgs,
|
||||
));
|
||||
|
||||
|
||||
getIt.registerFactory<NewWalletTypeViewModel>(() => NewWalletTypeViewModel(_walletInfoSource));
|
||||
final walletList = await WalletInfo.getAll();
|
||||
getIt.registerFactory<NewWalletTypeViewModel>(() => NewWalletTypeViewModel(walletList.isNotEmpty));
|
||||
|
||||
getIt.registerFactory<WalletManager>(
|
||||
() => WalletManager(
|
||||
_walletInfoSource,
|
||||
getIt.get<SharedPreferences>(),
|
||||
),
|
||||
);
|
||||
@@ -535,7 +531,6 @@ Future<void> setup({
|
||||
hardwareWalletVM,
|
||||
getIt.get<AppStore>(),
|
||||
getIt.get<WalletCreationService>(param1: type),
|
||||
_walletInfoSource,
|
||||
getIt.get<SeedSettingsViewModel>(),
|
||||
type: type));
|
||||
|
||||
@@ -560,7 +555,6 @@ Future<void> setup({
|
||||
getIt.get<ContactListViewModel>(),
|
||||
getIt.get<UnspentCoinsListViewModel>(),
|
||||
getIt.get<FeesViewModel>(),
|
||||
_walletInfoSource,
|
||||
getIt.get<FiatConversionStore>(),
|
||||
),
|
||||
);
|
||||
@@ -639,7 +633,7 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactory<AuthPage>(instanceName: 'login', () {
|
||||
return AuthPage(getIt.get<AuthViewModel>(), closable: false,
|
||||
onAuthenticationFinished: (isAuthenticated, AuthPageState authPageState) {
|
||||
onAuthenticationFinished: (isAuthenticated, AuthPageState authPageState) async {
|
||||
if (!isAuthenticated) {
|
||||
return;
|
||||
}
|
||||
@@ -680,7 +674,7 @@ Future<void> setup({
|
||||
);
|
||||
} else {
|
||||
// wallet is already loaded:
|
||||
if (appStore.wallet != null || requireHardwareWalletConnection()) {
|
||||
if (appStore.wallet != null || await requireHardwareWalletConnection()) {
|
||||
// goes to the dashboard:
|
||||
authStore.allowed();
|
||||
// trigger any deep links:
|
||||
@@ -847,8 +841,7 @@ Future<void> setup({
|
||||
: null,
|
||||
coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.nonMweb,
|
||||
getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom),
|
||||
getIt.get<FeesViewModel>(),
|
||||
_walletInfoSource,
|
||||
getIt.get<FeesViewModel>()
|
||||
),
|
||||
);
|
||||
|
||||
@@ -867,7 +860,6 @@ Future<void> setup({
|
||||
if (DeviceInfo.instance.isMobile) {
|
||||
getIt.registerFactory(
|
||||
() => WalletListViewModel(
|
||||
_walletInfoSource,
|
||||
getIt.get<AppStore>(),
|
||||
getIt.get<WalletLoadingService>(),
|
||||
getIt.get<WalletManager>(),
|
||||
@@ -878,7 +870,6 @@ Future<void> setup({
|
||||
// from multiple places at the same time (Wallets DropDown, Wallets List in settings)
|
||||
getIt.registerLazySingleton(
|
||||
() => WalletListViewModel(
|
||||
_walletInfoSource,
|
||||
getIt.get<AppStore>(),
|
||||
getIt.get<WalletLoadingService>(),
|
||||
getIt.get<WalletManager>(),
|
||||
@@ -890,7 +881,7 @@ Future<void> setup({
|
||||
(Function(BuildContext)? onWalletLoaded, _) => WalletListPage(
|
||||
walletListViewModel: getIt.get<WalletListViewModel>(),
|
||||
authService: getIt.get<AuthService>(),
|
||||
onWalletLoaded: onWalletLoaded,
|
||||
onWalletLoaded: onWalletLoaded as Future<void> Function(BuildContext)?,
|
||||
));
|
||||
|
||||
getIt.registerFactoryParam<WalletEditViewModel, WalletListViewModel, void>(
|
||||
@@ -1034,7 +1025,7 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactoryParam<ContactListViewModel, CryptoCurrency?, void>(
|
||||
(CryptoCurrency? cur, _) =>
|
||||
ContactListViewModel(_contactSource, _walletInfoSource, cur, getIt.get<SettingsStore>()));
|
||||
ContactListViewModel(_contactSource, walletList, cur, getIt.get<SettingsStore>()));
|
||||
|
||||
getIt.registerFactoryParam<ContactListPage, CryptoCurrency?, void>((CryptoCurrency? cur, _) =>
|
||||
ContactListPage(getIt.get<ContactListViewModel>(param1: cur), getIt.get<AuthService>()));
|
||||
@@ -1190,62 +1181,53 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactory(() => PaymentViewModel(
|
||||
appStore: getIt.get<AppStore>(),
|
||||
walletInfoSource: _walletInfoSource,
|
||||
));
|
||||
|
||||
getIt.registerFactory(() => WalletSwitcherViewModel(
|
||||
appStore: getIt.get<AppStore>(),
|
||||
walletLoadingService: getIt.get<WalletLoadingService>(),
|
||||
walletInfoSource: _walletInfoSource,
|
||||
));
|
||||
|
||||
getIt.registerFactoryParam<WalletService, WalletType, void>((WalletType param1, __) {
|
||||
switch (param1) {
|
||||
case WalletType.monero:
|
||||
return monero!.createMoneroWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
return monero!.createMoneroWalletService(_unspentCoinsInfoSource);
|
||||
case WalletType.bitcoin:
|
||||
return bitcoin!.createBitcoinWalletService(
|
||||
_walletInfoSource,
|
||||
_unspentCoinsInfoSource,
|
||||
_payjoinSessionSource,
|
||||
SettingsStoreBase.walletPasswordDirectInput,
|
||||
);
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.createLitecoinWalletService(
|
||||
_walletInfoSource,
|
||||
_unspentCoinsInfoSource,
|
||||
SettingsStoreBase.walletPasswordDirectInput,
|
||||
);
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.createEthereumWalletService(
|
||||
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return ethereum!.createEthereumWalletService(SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.bitcoinCash:
|
||||
return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource,
|
||||
_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return bitcoinCash!.createBitcoinCashWalletService(_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.dogecoin:
|
||||
return dogecoin!.createDogeCoinWalletService(_walletInfoSource,
|
||||
_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return dogecoin!.createDogeCoinWalletService(_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
return nano!.createNanoWalletService(_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return nano!.createNanoWalletService(SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonWalletService(
|
||||
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return polygon!.createPolygonWalletService(SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.solana:
|
||||
return solana!.createSolanaWalletService(
|
||||
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return solana!.createSolanaWalletService(SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.tron:
|
||||
return tron!.createTronWalletService(_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return tron!.createTronWalletService(SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.wownero:
|
||||
return wownero!.createWowneroWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
return wownero!.createWowneroWalletService(_unspentCoinsInfoSource);
|
||||
case WalletType.zano:
|
||||
return zano!.createZanoWalletService(_walletInfoSource);
|
||||
return zano!.createZanoWalletService();
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
return decred!.createDecredWalletService(_unspentCoinsInfoSource);
|
||||
case WalletType.base:
|
||||
return base!.createBaseWalletService(_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
return base!.createBaseWalletService(SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.haven:
|
||||
return HavenWalletService(_walletInfoSource);
|
||||
return HavenWalletService();
|
||||
case WalletType.none:
|
||||
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
|
||||
}
|
||||
@@ -1275,7 +1257,6 @@ Future<void> setup({
|
||||
return WalletRestoreViewModel(
|
||||
getIt.get<AppStore>(),
|
||||
getIt.get<WalletCreationService>(param1: type),
|
||||
_walletInfoSource,
|
||||
getIt.get<SeedSettingsViewModel>(),
|
||||
type: type,
|
||||
restoredWallet: restoredWallet,
|
||||
@@ -1351,7 +1332,7 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactory(() => CakeFeaturesViewModel(getIt.get<CakePayService>()));
|
||||
|
||||
getIt.registerFactory(() => BackupServiceV3(getIt.get<SecureStorage>(), _walletInfoSource,
|
||||
getIt.registerFactory(() => BackupServiceV3(getIt.get<SecureStorage>(),
|
||||
_transactionDescriptionBox,
|
||||
getIt.get<KeyService>(), getIt.get<SharedPreferences>()));
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@ part of 'dogecoin.dart';
|
||||
class CWDogeCoin extends DogeCoin {
|
||||
|
||||
@override
|
||||
WalletService createDogeCoinWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
|
||||
return DogeCoinWalletService(walletInfoSource, unspentCoinSource, isDirect);
|
||||
WalletService createDogeCoinWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
|
||||
return DogeCoinWalletService(unspentCoinSource, isDirect);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:cake_wallet/core/secure_storage.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/haven_seed_store.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||
import 'package:cw_core/root_dir.dart';
|
||||
@@ -21,6 +22,7 @@ import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/entities/contact.dart';
|
||||
import 'package:cake_wallet/entities/fs_migration.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_info_legacy.dart' as wiLegacy;
|
||||
import 'package:cake_wallet/exchange/trade.dart';
|
||||
import 'package:encrypt/encrypt.dart' as encrypt;
|
||||
import 'package:collection/collection.dart';
|
||||
@@ -55,12 +57,11 @@ Future<void> defaultSettingsMigration(
|
||||
required SecureStorage secureStorage,
|
||||
required Box<Node> nodes,
|
||||
required Box<Node> powNodes,
|
||||
required Box<WalletInfo> walletInfoSource,
|
||||
required Box<Trade> tradeSource,
|
||||
required Box<Contact> contactSource,
|
||||
required Box<HavenSeedStore> havenSeedStore}) async {
|
||||
if (Platform.isIOS) {
|
||||
await ios_migrate_v1(walletInfoSource, tradeSource, contactSource);
|
||||
await ios_migrate_v1(tradeSource, contactSource);
|
||||
}
|
||||
|
||||
// check current nodes for nullability regardless of the version
|
||||
@@ -69,7 +70,7 @@ Future<void> defaultSettingsMigration(
|
||||
final isNewInstall =
|
||||
sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
|
||||
|
||||
await _validateWalletInfoBoxData(walletInfoSource);
|
||||
await _validateWalletInfoBoxData();
|
||||
|
||||
await sharedPreferences.setBool(PreferencesKey.isNewInstall, isNewInstall);
|
||||
|
||||
@@ -162,7 +163,7 @@ Future<void> defaultSettingsMigration(
|
||||
break;
|
||||
|
||||
case 5:
|
||||
await addAddressesForMoneroWallets(walletInfoSource);
|
||||
await addAddressesForMoneroWallets();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
@@ -323,7 +324,7 @@ Future<void> defaultSettingsMigration(
|
||||
await updateNanoNodeList(nodes: nodes);
|
||||
break;
|
||||
case 32:
|
||||
await updateBtcNanoWalletInfos(walletInfoSource);
|
||||
await updateBtcNanoWalletInfos();
|
||||
break;
|
||||
case 33:
|
||||
await addWalletNodeList(nodes: nodes, type: WalletType.tron);
|
||||
@@ -361,7 +362,7 @@ Future<void> defaultSettingsMigration(
|
||||
// await replaceTronDefaultNode(sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
break;
|
||||
case 38:
|
||||
await fixBtcDerivationPaths(walletInfoSource);
|
||||
await fixBtcDerivationPaths();
|
||||
break;
|
||||
case 39:
|
||||
_fixNodesUseSSLFlag(nodes);
|
||||
@@ -738,7 +739,7 @@ Future<void> _updateMoneroPriority(SharedPreferences sharedPreferences) async {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _validateWalletInfoBoxData(Box<WalletInfo> walletInfoSource) async {
|
||||
Future<void> _validateWalletInfoBoxData() async {
|
||||
try {
|
||||
final root = await getAppDir();
|
||||
|
||||
@@ -780,7 +781,7 @@ Future<void> _validateWalletInfoBoxData(Box<WalletInfo> walletInfoSource) async
|
||||
}
|
||||
|
||||
final id = prefix + '_' + name;
|
||||
final exist = walletInfoSource.values.any((el) => el.id == id);
|
||||
final exist = (await WalletInfo.getAll()).any((el) => el.id == id);
|
||||
|
||||
if (exist) {
|
||||
continue;
|
||||
@@ -799,7 +800,7 @@ Future<void> _validateWalletInfoBoxData(Box<WalletInfo> walletInfoSource) async
|
||||
showIntroCakePayCard: false,
|
||||
);
|
||||
|
||||
walletInfoSource.add(walletInfo);
|
||||
await walletInfo.save();
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
@@ -967,8 +968,8 @@ Future<void> updateNodeTypes({required Box<Node> nodes}) async {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> addAddressesForMoneroWallets(Box<WalletInfo> walletInfoSource) async {
|
||||
final moneroWalletsInfo = walletInfoSource.values.where((info) => info.type == WalletType.monero);
|
||||
Future<void> addAddressesForMoneroWallets() async {
|
||||
final moneroWalletsInfo = (await WalletInfo.getAll()).where((info) => info.type == WalletType.monero);
|
||||
moneroWalletsInfo.forEach((info) async {
|
||||
try {
|
||||
final walletPath = await pathForWallet(name: info.name, type: WalletType.monero);
|
||||
@@ -1016,32 +1017,34 @@ Future<void> changeTransactionPriorityAndFeeRateKeys(SharedPreferences sharedPre
|
||||
bitcoin!.getMediumTransactionPriority().serialize());
|
||||
}
|
||||
|
||||
Future<void> fixBtcDerivationPaths(Box<WalletInfo> walletsInfoSource) async {
|
||||
for (WalletInfo walletInfo in walletsInfoSource.values) {
|
||||
Future<void> fixBtcDerivationPaths() async {
|
||||
for (WalletInfo walletInfo in await WalletInfo.getAll()) {
|
||||
if (walletInfo.type == WalletType.bitcoin ||
|
||||
walletInfo.type == WalletType.bitcoinCash ||
|
||||
walletInfo.type == WalletType.litecoin) {
|
||||
if (walletInfo.derivationInfo?.derivationPath == "m/0'/0") {
|
||||
walletInfo.derivationInfo!.derivationPath = "m/0'";
|
||||
final derivationInfo = await walletInfo.getDerivationInfo();
|
||||
if (derivationInfo?.derivationPath == "m/0'/0") {
|
||||
derivationInfo!.derivationPath = "m/0'";
|
||||
await walletInfo.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateBtcNanoWalletInfos(Box<WalletInfo> walletsInfoSource) async {
|
||||
for (WalletInfo walletInfo in walletsInfoSource.values) {
|
||||
if (walletInfo.type == WalletType.nano || walletInfo.type == WalletType.bitcoin) {
|
||||
walletInfo.derivationInfo = DerivationInfo(
|
||||
derivationPath: walletInfo.derivationPath,
|
||||
derivationType: walletInfo.derivationType,
|
||||
address: walletInfo.address,
|
||||
transactionsCount: walletInfo.restoreHeight,
|
||||
);
|
||||
await walletInfo.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
Future<void> updateBtcNanoWalletInfos() async {}
|
||||
// Future<void> updateBtcNanoWalletInfos() async {
|
||||
// for (WalletInfo walletInfo in await WalletInfo.getAll()) {
|
||||
// if (walletInfo.type == WalletType.nano || walletInfo.type == WalletType.bitcoin) {
|
||||
// final derivationInfo = await walletInfo.getDerivationInfo();
|
||||
// derivationInfo = DerivationInfo(
|
||||
// derivationPath: derivationInfo?.derivationPath,
|
||||
// derivationType: derivationInfo?.derivationType,
|
||||
// address: walletInfo.address,
|
||||
// transactionsCount: walletInfo.restoreHeight,
|
||||
// );
|
||||
// await walletInfo.save();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<void> checkCurrentNodes(
|
||||
Box<Node> nodeSource, Box<Node> powNodeSource, SharedPreferences sharedPreferences) async {
|
||||
|
||||
@@ -29,8 +29,7 @@ Future<void> migrate_android_v1() async {
|
||||
await android_migrate_wallets(appDocDir: appDocDir);
|
||||
}
|
||||
|
||||
Future<void> ios_migrate_v1(
|
||||
Box<WalletInfo> walletInfoSource, Box<Trade> tradeSource, Box<Contact> contactSource) async {
|
||||
Future<void> ios_migrate_v1(Box<Trade> tradeSource, Box<Contact> contactSource) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
if (prefs.getBool('ios_migration_v1_completed') ?? false) {
|
||||
@@ -40,7 +39,7 @@ Future<void> ios_migrate_v1(
|
||||
await ios_migrate_user_defaults();
|
||||
await ios_migrate_pin();
|
||||
await ios_migrate_wallet_passwords();
|
||||
await ios_migrate_wallet_info(walletInfoSource);
|
||||
await ios_migrate_wallet_info();
|
||||
await ios_migrate_trades_list(tradeSource);
|
||||
await ios_migrate_address_book(contactSource);
|
||||
|
||||
@@ -278,7 +277,7 @@ Future<void> android_migrate_wallets({required Directory appDocDir}) async {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> ios_migrate_wallet_info(Box<WalletInfo> walletsInfoSource) async {
|
||||
Future<void> ios_migrate_wallet_info() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
if (prefs.getBool('ios_migration_wallet_info_completed') ?? false) {
|
||||
@@ -289,6 +288,7 @@ Future<void> ios_migrate_wallet_info(Box<WalletInfo> walletsInfoSource) async {
|
||||
final appDocDir = await getApplicationDocumentsDirectory();
|
||||
final walletsDir = Directory('${appDocDir.path}/wallets');
|
||||
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
|
||||
final walletsInfo = await WalletInfo.getAll();
|
||||
final infoRecords = moneroWalletsDir
|
||||
.listSync()
|
||||
.map((item) {
|
||||
@@ -307,7 +307,7 @@ Future<void> ios_migrate_wallet_info(Box<WalletInfo> walletsInfoSource) async {
|
||||
final timestamp = dateAsDouble.toInt() * 1000;
|
||||
final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
|
||||
final id = walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
|
||||
final exist = walletsInfoSource.values.firstWhereOrNull((el) => el.id == id) != null;
|
||||
final exist = walletsInfo.firstWhereOrNull((el) => el.id == id) != null;
|
||||
|
||||
if (exist) {
|
||||
return null;
|
||||
@@ -334,7 +334,9 @@ Future<void> ios_migrate_wallet_info(Box<WalletInfo> walletsInfoSource) async {
|
||||
.where((el) => el != null)
|
||||
.whereType<WalletInfo>()
|
||||
.toList();
|
||||
await walletsInfoSource.addAll(infoRecords);
|
||||
for (final info in infoRecords) {
|
||||
await info.save();
|
||||
}
|
||||
await prefs.setBool('ios_migration_wallet_info_completed', true);
|
||||
} catch (e) {
|
||||
printV(e.toString());
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
bool requireHardwareWalletConnection() {
|
||||
Future<bool> requireHardwareWalletConnection() async {
|
||||
final name = getIt
|
||||
.get<SharedPreferences>()
|
||||
.getString(PreferencesKey.currentWalletName);
|
||||
@@ -21,5 +21,5 @@ bool requireHardwareWalletConnection() {
|
||||
|
||||
final type = deserializeFromInt(typeRaw);
|
||||
final walletLoadingService = getIt.get<WalletLoadingService>();
|
||||
return walletLoadingService.requireHardwareWalletConnection(type, name);
|
||||
return await walletLoadingService.requireHardwareWalletConnection(type, name);
|
||||
}
|
||||
|
||||
@@ -8,17 +8,16 @@ import 'package:hive/hive.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class WalletManager {
|
||||
WalletManager(this._walletInfoSource, this._sharedPreferences);
|
||||
WalletManager(this._sharedPreferences);
|
||||
|
||||
final Box<WalletInfo> _walletInfoSource;
|
||||
final SharedPreferences _sharedPreferences;
|
||||
|
||||
final List<WalletGroup> walletGroups = [];
|
||||
|
||||
void updateWalletGroups() {
|
||||
Future<void> updateWalletGroups() async {
|
||||
walletGroups.clear();
|
||||
|
||||
for (final walletInfo in _walletInfoSource.values) {
|
||||
for (final walletInfo in await WalletInfo.getAll()) {
|
||||
final groupKey = _resolveGroupKey(walletInfo);
|
||||
final group = _getOrCreateGroup(groupKey);
|
||||
group.wallets.add(walletInfo);
|
||||
@@ -115,7 +114,7 @@ class WalletManager {
|
||||
// If the openedWallet already has an hash, then there is nothing to do
|
||||
if (walletInfo.hashedWalletIdentifier != null &&
|
||||
walletInfo.hashedWalletIdentifier!.isNotEmpty) {
|
||||
updateWalletGroups(); // Still skeptical of calling this here. Looking for a better spot.
|
||||
await updateWalletGroups(); // Still skeptical of calling this here. Looking for a better spot.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,7 +122,7 @@ class WalletManager {
|
||||
final oldGroupKey = _resolveGroupKey(walletInfo); // parentAddress fallback
|
||||
|
||||
// Find all wallets that share this old group key (i.e the old group)
|
||||
final oldGroupWallets = _walletInfoSource.values.where((w) {
|
||||
final oldGroupWallets = (await WalletInfo.getAll()).where((w) {
|
||||
final key = w.hashedWalletIdentifier != null && w.hashedWalletIdentifier!.isNotEmpty
|
||||
? w.hashedWalletIdentifier
|
||||
: (w.parentAddress ?? w.address);
|
||||
@@ -150,7 +149,7 @@ class WalletManager {
|
||||
}
|
||||
|
||||
// Finally, we rebuild the groups so that these wallets are now in the new group
|
||||
updateWalletGroups();
|
||||
await updateWalletGroups();
|
||||
}
|
||||
|
||||
/// Copy an old group name to the new group key, then remove the old key.
|
||||
|
||||
@@ -4,8 +4,8 @@ class CWEthereum extends Ethereum {
|
||||
@override
|
||||
List<String> getEthereumWordList(String language) => EVMChainMnemonics.englishWordlist;
|
||||
|
||||
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) =>
|
||||
EthereumWalletService(walletInfoSource, isDirect, client: EthereumClient());
|
||||
WalletService createEthereumWalletService(bool isDirect) =>
|
||||
EthereumWalletService(isDirect, client: EthereumClient());
|
||||
|
||||
@override
|
||||
WalletCredentials createEthereumNewWalletCredentials({
|
||||
@@ -181,18 +181,19 @@ class CWEthereum extends Ethereum {
|
||||
String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
|
||||
|
||||
@override
|
||||
void setHardwareWalletService(WalletBase wallet, HardwareWalletService service) {
|
||||
Future<void> setHardwareWalletService(WalletBase wallet, HardwareWalletService service) async {
|
||||
if (service is EVMChainLedgerService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials).setLedgerConnection(
|
||||
service.ledgerConnection, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
service.ledgerConnection, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
} else if (service is EVMChainBitboxService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmBitboxCredentials)
|
||||
.setBitbox(service.manager, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
.setBitbox(service.manager, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
} else if (service is EVMChainTrezorService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmTrezorCredentials)
|
||||
.setTrezorConnect(service.connect, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
.setTrezorConnect(service.connect, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
HardwareWalletService getLedgerHardwareWalletService(ledger.LedgerConnection connection) =>
|
||||
EVMChainLedgerService(connection);
|
||||
|
||||
@@ -12,16 +12,15 @@ import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
class HavenWalletService extends WalletService {
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
HavenWalletService(this.walletInfoSource);
|
||||
HavenWalletService();
|
||||
|
||||
@override
|
||||
WalletType getType() => WalletType.haven;
|
||||
|
||||
@override
|
||||
Future<void> remove(String wallet) async {
|
||||
final path = await pathForWalletDir(name: wallet, type: WalletType.haven);
|
||||
final path = await pathForWalletDir(name: wallet, type: getType());
|
||||
|
||||
final file = Directory(path);
|
||||
final isExist = file.existsSync();
|
||||
@@ -30,9 +29,11 @@ class HavenWalletService extends WalletService {
|
||||
await file.delete(recursive: true);
|
||||
}
|
||||
|
||||
final walletInfo = walletInfoSource.values
|
||||
.firstWhere((info) => info.id == WalletBase.idFor(wallet, getType()));
|
||||
await walletInfoSource.delete(walletInfo.key);
|
||||
final walletInfo = await WalletInfo.get(wallet, getType());
|
||||
if (walletInfo == null) {
|
||||
throw Exception('Wallet not found');
|
||||
}
|
||||
await WalletInfo.delete(walletInfo);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1032,7 +1032,7 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations {
|
||||
@override
|
||||
// TODO: implement backButtonLabel
|
||||
String get backButtonLabel => "backButtonLabel";
|
||||
|
||||
|
||||
@override
|
||||
// TODO: implement cancelButtonLabel
|
||||
String get cancelButtonLabel => "cancelButtonLabel";
|
||||
|
||||
+8
-23
@@ -47,8 +47,9 @@ import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/utils/proxy_logger/memory_proxy_logger.dart';
|
||||
import 'package:cw_core/utils/proxy_wrapper.dart';
|
||||
import 'package:cw_core/utils/tor/abstract.dart';
|
||||
import 'package:cw_core/db/sqlite.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/utils/tor/abstract.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -86,12 +87,16 @@ Future<void> runAppWithZone({Key? topLevelKey}) async {
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
await FlutterDaemon().unmarkBackgroundSync();
|
||||
await initDb();
|
||||
|
||||
try {
|
||||
CakeTor.instance = await CakeTorInstance.getInstance();
|
||||
} catch (e) {
|
||||
printV("Failed to initialize tor: $e");
|
||||
}
|
||||
|
||||
await initializeAppAtRoot();
|
||||
|
||||
if (kDebugMode) {
|
||||
@@ -164,22 +169,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
|
||||
CakeHive.registerAdapter(AddressInfoAdapter());
|
||||
}
|
||||
|
||||
if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) {
|
||||
CakeHive.registerAdapter(WalletInfoAdapter());
|
||||
}
|
||||
|
||||
if (!CakeHive.isAdapterRegistered(DERIVATION_TYPE_TYPE_ID)) {
|
||||
CakeHive.registerAdapter(DerivationTypeAdapter());
|
||||
}
|
||||
|
||||
if (!CakeHive.isAdapterRegistered(DERIVATION_INFO_TYPE_ID)) {
|
||||
CakeHive.registerAdapter(DerivationInfoAdapter());
|
||||
}
|
||||
|
||||
if (!CakeHive.isAdapterRegistered(HARDWARE_WALLET_TYPE_TYPE_ID)) {
|
||||
CakeHive.registerAdapter(HardwareWalletTypeAdapter());
|
||||
}
|
||||
|
||||
if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) {
|
||||
CakeHive.registerAdapter(WalletTypeAdapter());
|
||||
}
|
||||
@@ -227,6 +216,7 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
|
||||
if (!CakeHive.isAdapterRegistered(TronToken.typeId)) {
|
||||
CakeHive.registerAdapter(TronTokenAdapter());
|
||||
}
|
||||
await performHiveMigration();
|
||||
|
||||
final secureStorage = secureStorageShared;
|
||||
final transactionDescriptionsBoxKey =
|
||||
@@ -242,7 +232,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
|
||||
encryptionKey: transactionDescriptionsBoxKey);
|
||||
final trades = await CakeHive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
|
||||
final orders = await CakeHive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
|
||||
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
final templates = await CakeHive.openBox<Template>(Template.boxName);
|
||||
final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
||||
final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
|
||||
@@ -259,7 +248,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
|
||||
sharedPreferences: await SharedPreferences.getInstance(),
|
||||
nodes: nodes,
|
||||
powNodes: powNodes,
|
||||
walletInfoSource: walletInfoSource,
|
||||
contactSource: contacts,
|
||||
tradesSource: trades,
|
||||
ordersSource: orders,
|
||||
@@ -281,7 +269,6 @@ Future<void> initialSetup({
|
||||
required SharedPreferences sharedPreferences,
|
||||
required Box<Node> nodes,
|
||||
required Box<Node> powNodes,
|
||||
required Box<WalletInfo> walletInfoSource,
|
||||
required Box<Contact> contactSource,
|
||||
required Box<Trade> tradesSource,
|
||||
required Box<Order> ordersSource,
|
||||
@@ -294,21 +281,19 @@ Future<void> initialSetup({
|
||||
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
|
||||
required Box<PayjoinSession> payjoinSessionSource,
|
||||
required Box<HavenSeedStore> havenSeedStore,
|
||||
int initialMigrationVersion = 15,
|
||||
required int initialMigrationVersion,
|
||||
}) async {
|
||||
LanguageService.loadLocaleList();
|
||||
await defaultSettingsMigration(
|
||||
secureStorage: secureStorage,
|
||||
version: initialMigrationVersion,
|
||||
sharedPreferences: sharedPreferences,
|
||||
walletInfoSource: walletInfoSource,
|
||||
contactSource: contactSource,
|
||||
tradeSource: tradesSource,
|
||||
nodes: nodes,
|
||||
powNodes: powNodes,
|
||||
havenSeedStore: havenSeedStore);
|
||||
await setup(
|
||||
walletInfoSource: walletInfoSource,
|
||||
nodeSource: nodes,
|
||||
powNodeSource: powNodes,
|
||||
contactSource: contactSource,
|
||||
|
||||
@@ -346,9 +346,8 @@ class CWMonero extends Monero {
|
||||
}
|
||||
|
||||
@override
|
||||
WalletService createMoneroWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) =>
|
||||
MoneroWalletService(walletInfoSource, unspentCoinSource);
|
||||
WalletService createMoneroWalletService(Box<UnspentCoinsInfo> unspentCoinSource) =>
|
||||
MoneroWalletService(unspentCoinSource);
|
||||
|
||||
@override
|
||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
|
||||
@@ -416,9 +415,9 @@ class CWMonero extends Monero {
|
||||
}
|
||||
|
||||
@override
|
||||
void setLedgerConnection(Object wallet, ledger.LedgerConnection connection) {
|
||||
Future<void> setLedgerConnection(Object wallet, ledger.LedgerConnection connection) async {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
moneroWallet.setLedgerConnection(connection);
|
||||
await moneroWallet.setLedgerConnection(connection);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -75,8 +75,8 @@ class CWNano extends Nano {
|
||||
}
|
||||
|
||||
@override
|
||||
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) {
|
||||
return NanoWalletService(walletInfoSource, isDirect);
|
||||
WalletService createNanoWalletService(bool isDirect) {
|
||||
return NanoWalletService(isDirect);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -4,8 +4,8 @@ class CWPolygon extends Polygon {
|
||||
@override
|
||||
List<String> getPolygonWordList(String language) => EVMChainMnemonics.englishWordlist;
|
||||
|
||||
WalletService createPolygonWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) =>
|
||||
PolygonWalletService(walletInfoSource, isDirect, client: PolygonClient());
|
||||
WalletService createPolygonWalletService(bool isDirect) =>
|
||||
PolygonWalletService(isDirect, client: PolygonClient());
|
||||
|
||||
@override
|
||||
WalletCredentials createPolygonNewWalletCredentials({
|
||||
@@ -206,16 +206,16 @@ class CWPolygon extends Polygon {
|
||||
);
|
||||
|
||||
@override
|
||||
void setHardwareWalletService(WalletBase wallet, HardwareWalletService service) {
|
||||
Future<void> setHardwareWalletService(WalletBase wallet, HardwareWalletService service) async {
|
||||
if (service is EVMChainLedgerService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials).setLedgerConnection(
|
||||
service.ledgerConnection, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
service.ledgerConnection, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
} else if (service is EVMChainBitboxService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmBitboxCredentials)
|
||||
.setBitbox(service.manager, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
.setBitbox(service.manager, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
} else if (service is EVMChainTrezorService) {
|
||||
((wallet as EVMChainWallet).evmChainPrivateKey as EvmTrezorCredentials)
|
||||
.setTrezorConnect(service.connect, wallet.walletInfo.derivationInfo?.derivationPath);
|
||||
.setTrezorConnect(service.connect, (await wallet.walletInfo.getDerivationInfo()).derivationPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void startAuthenticationStateChange(
|
||||
if (state == AuthenticationState.installed &&
|
||||
!SettingsStoreBase.walletPasswordDirectInput) {
|
||||
try {
|
||||
if (!requireHardwareWalletConnection()) await loadCurrentWallet();
|
||||
if (!(await requireHardwareWalletConnection())) await loadCurrentWallet();
|
||||
} catch (error, stack) {
|
||||
loginError = error;
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
@@ -56,7 +56,7 @@ void startAuthenticationStateChange(
|
||||
if ([AuthenticationState.allowed, AuthenticationState.allowedCreate]
|
||||
.contains(state)) {
|
||||
if (state == AuthenticationState.allowed &&
|
||||
requireHardwareWalletConnection()) {
|
||||
(await requireHardwareWalletConnection())) {
|
||||
await navigatorKey.currentState!.pushNamedAndRemoveUntil(
|
||||
Routes.connectDevices,
|
||||
(route) => false,
|
||||
|
||||
@@ -99,9 +99,7 @@ void startCurrentWalletChangeReaction(
|
||||
if (wallet.walletInfo.address.isEmpty) {
|
||||
wallet.walletInfo.address = wallet.walletAddresses.address;
|
||||
|
||||
if (wallet.walletInfo.isInBox) {
|
||||
await wallet.walletInfo.save();
|
||||
}
|
||||
await wallet.walletInfo.save();
|
||||
}
|
||||
} catch (e) {
|
||||
printV(e.toString());
|
||||
|
||||
@@ -4,8 +4,8 @@ class CWSolana extends Solana {
|
||||
@override
|
||||
List<String> getSolanaWordList(String language) => SolanaMnemonics.englishWordlist;
|
||||
|
||||
WalletService createSolanaWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) =>
|
||||
SolanaWalletService(walletInfoSource, isDirect);
|
||||
WalletService createSolanaWalletService(bool isDirect) =>
|
||||
SolanaWalletService(isDirect);
|
||||
|
||||
@override
|
||||
WalletCredentials createSolanaNewWalletCredentials({
|
||||
|
||||
@@ -17,6 +17,7 @@ import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
|
||||
class ContactListPage extends BasePage {
|
||||
@@ -150,7 +151,9 @@ class _ContactPageBodyState extends State<ContactPageBody> with SingleTickerProv
|
||||
child: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
_buildWalletContacts(context),
|
||||
Observer(
|
||||
builder: (final BuildContext context) => _buildWalletContacts(context),
|
||||
),
|
||||
ContactListBody(
|
||||
contactListViewModel: widget.contactListViewModel,
|
||||
tabController: _tabController,
|
||||
|
||||
@@ -351,7 +351,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
_formProcessing = false;
|
||||
return;
|
||||
}
|
||||
if (_walletNewVM.nameExists(_walletNewVM.name)) {
|
||||
if (await _walletNewVM.nameExists(_walletNewVM.name)) {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
|
||||
@@ -258,7 +258,7 @@ class WalletRestorePage extends BasePage {
|
||||
return;
|
||||
}
|
||||
|
||||
if (walletRestoreViewModel.nameExists(name)) {
|
||||
if (await walletRestoreViewModel.nameExists(name)) {
|
||||
showNameExistsAlert(formContext!);
|
||||
_formProcessing = false;
|
||||
return;
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dev/moneroc_cache_debug.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/setting_priority_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
@@ -11,6 +12,7 @@ import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_core/db/sqlite.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
@@ -144,6 +146,16 @@ class OtherSettingsPage extends BasePage {
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] browse sqlite db',
|
||||
handler: (BuildContext context) async {
|
||||
final data = await dumpDb();
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => JsonExplorerPage(data: data, title: 'sqlite db')),
|
||||
);
|
||||
}
|
||||
),
|
||||
Spacer(),
|
||||
SettingsVersionCell(
|
||||
title: S.of(context).version(_otherSettingsViewModel.currentVersion),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:another_flushbar/flushbar.dart';
|
||||
import 'package:cake_wallet/core/wallet_name_validator.dart';
|
||||
import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
|
||||
@@ -10,6 +12,7 @@ import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
@@ -86,7 +89,7 @@ class WalletEditPage extends BasePage {
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
if (!pageArguments.isWalletGroup &&
|
||||
pageArguments.walletNewVM!
|
||||
await pageArguments.walletNewVM!
|
||||
.nameExists(walletEditViewModel.newName)) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
@@ -217,9 +220,12 @@ class WalletEditPage extends BasePage {
|
||||
}
|
||||
|
||||
Future<void> hideProgressText() async {
|
||||
await Future.delayed(Duration(milliseconds: 50), () {
|
||||
_progressBar?.dismiss();
|
||||
_progressBar = null;
|
||||
});
|
||||
try {
|
||||
await Future.delayed(Duration(milliseconds: 250));
|
||||
await _progressBar?.dismiss();
|
||||
} catch (e) {
|
||||
printV(e);
|
||||
}
|
||||
_progressBar = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:another_flushbar/flushbar.dart';
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/new_wallet_arguments.dart';
|
||||
@@ -27,6 +29,7 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||
import 'package:cw_core/currency_for_wallet_type.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
@@ -40,17 +43,26 @@ class WalletListPage extends BasePage {
|
||||
|
||||
final WalletListViewModel walletListViewModel;
|
||||
final AuthService authService;
|
||||
final Function(BuildContext)? onWalletLoaded;
|
||||
final Future<void> Function(BuildContext)? onWalletLoaded;
|
||||
|
||||
@override
|
||||
String get title => S.current.wallets;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletListBody(
|
||||
Widget body(BuildContext context) => Observer(
|
||||
builder: (_) {
|
||||
if (walletListViewModel.singleWalletsList.isEmpty && walletListViewModel.multiWalletGroups.isEmpty) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
return WalletListBody(
|
||||
walletListViewModel: walletListViewModel,
|
||||
authService: authService,
|
||||
onWalletLoaded: onWalletLoaded ?? (context) => Navigator.of(context).pop(),
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
@@ -459,7 +471,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||
|
||||
try {
|
||||
final requireHardwareWalletConnection =
|
||||
widget.walletListViewModel.requireHardwareWalletConnection(wallet);
|
||||
await widget.walletListViewModel.requireHardwareWalletConnection(wallet);
|
||||
if (requireHardwareWalletConnection) {
|
||||
bool didConnect = false;
|
||||
await Navigator.of(context).pushNamed(
|
||||
@@ -489,22 +501,20 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||
buttonAction: () => Navigator.of(context).pop()),
|
||||
);
|
||||
}
|
||||
|
||||
changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
|
||||
await widget.walletListViewModel.loadWallet(wallet);
|
||||
await hideProgressText();
|
||||
// only pop the wallets route in mobile as it will go back to dashboard page
|
||||
// in desktop platforms the navigation tree is different
|
||||
if (responsiveLayoutUtil.shouldRenderMobileUI) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (this.mounted) {
|
||||
if (requireHardwareWalletConnection) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
widget.onWalletLoaded.call(context);
|
||||
}
|
||||
});
|
||||
// await Future.delayed(Duration(seconds: 1));
|
||||
// if (!this.mounted) return;
|
||||
if (!context.mounted) return;
|
||||
if (requireHardwareWalletConnection) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
await widget.onWalletLoaded.call(context);
|
||||
}
|
||||
unawaited(hideProgressText());
|
||||
} catch (e) {
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
final err = e.toString();
|
||||
|
||||
@@ -52,76 +52,79 @@ class _WalletSwitcherContent extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Observer(
|
||||
builder: (_) {
|
||||
final wallets = viewModel.getWallets(filterWalletType);
|
||||
|
||||
if (viewModel.isProcessing) {
|
||||
return Container(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
height: 400,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: StandardList(
|
||||
itemCount: wallets.length,
|
||||
itemBuilder: (context, index) {
|
||||
final wallet = wallets[index];
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
viewModel.selectWallet(wallet);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 60,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
walletTypeToCryptoCurrency(wallet.type).iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
wallet.name,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
letterSpacing: 0.0,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
return FutureBuilder(
|
||||
future: viewModel.getWallets(filterWalletType),
|
||||
builder: (context, snapshot) => Observer(
|
||||
builder: (_) {
|
||||
final List<WalletInfo> wallets = (snapshot.data ?? []);
|
||||
|
||||
if (viewModel.isProcessing) {
|
||||
return Container(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
height: 400,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: StandardList(
|
||||
itemCount: wallets.length,
|
||||
itemBuilder: (context, index) {
|
||||
final wallet = wallets[index];
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
viewModel.selectWallet(wallet);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 60,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
walletTypeToCryptoCurrency(wallet.type).iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
wallet.name,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
letterSpacing: 0.0,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@ abstract class AppStoreBase with Store {
|
||||
getIt.get<WalletKitService>().create();
|
||||
await getIt.get<WalletKitService>().init();
|
||||
}
|
||||
getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name);
|
||||
getIt
|
||||
await getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name);
|
||||
await getIt
|
||||
.get<SharedPreferences>()
|
||||
.setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type));
|
||||
}
|
||||
|
||||
@@ -243,9 +243,7 @@ abstract class YatStoreBase with Store {
|
||||
|
||||
walletInfo!.yatEid = emoji;
|
||||
|
||||
if (walletInfo!.isInBox) {
|
||||
walletInfo!.save();
|
||||
}
|
||||
walletInfo!.save();
|
||||
} catch (e) {
|
||||
printV(e.toString());
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ class CWTron extends Tron {
|
||||
List<String> getTronWordList(String language) => EVMChainMnemonics.englishWordlist;
|
||||
|
||||
@override
|
||||
WalletService createTronWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) =>
|
||||
TronWalletService(walletInfoSource, client: TronClient(), isDirect: isDirect);
|
||||
WalletService createTronWalletService(bool isDirect) =>
|
||||
TronWalletService(client: TronClient(), isDirect: isDirect);
|
||||
|
||||
@override
|
||||
WalletCredentials createTronNewWalletCredentials({
|
||||
|
||||
@@ -290,6 +290,8 @@ class ExceptionHandler {
|
||||
"core/key_service.dart:14",
|
||||
"Wallet is null",
|
||||
"Wrong Device Status: 0x5515 (UNKNOWN)",
|
||||
|
||||
"FocusScopeNode was used after being disposed",
|
||||
];
|
||||
|
||||
static Future<void> _addDeviceInfo(File file) async {
|
||||
|
||||
@@ -10,11 +10,10 @@ import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
class TokenUtilities {
|
||||
static Future<List<Erc20Token>> loadAllUniqueEvmTokens(
|
||||
Box<WalletInfo> walletInfoSource,
|
||||
) async {
|
||||
final evmWallets = walletInfoSource.values.where(
|
||||
(w) => isEVMCompatibleChain(w.type),
|
||||
static Future<List<Erc20Token>> loadAllUniqueEvmTokens() async {
|
||||
final allWi = await WalletInfo.getAll();
|
||||
final evmWallets = allWi.where(
|
||||
(w) => isEVMCompatibleChain(w.type),
|
||||
);
|
||||
|
||||
final seen = <String>{};
|
||||
@@ -35,10 +34,9 @@ class TokenUtilities {
|
||||
return unique;
|
||||
}
|
||||
|
||||
static Future<List<SPLToken>> loadAllUniqueSolTokens(
|
||||
Box<WalletInfo> walletInfoSource,
|
||||
) async {
|
||||
final solWallets = walletInfoSource.values.where(
|
||||
static Future<List<SPLToken>> loadAllUniqueSolTokens() async {
|
||||
final allWi = await WalletInfo.getAll();
|
||||
final solWallets = allWi.where(
|
||||
(w) => w.type == WalletType.solana,
|
||||
);
|
||||
|
||||
@@ -57,10 +55,9 @@ class TokenUtilities {
|
||||
return unique;
|
||||
}
|
||||
|
||||
static Future<List<TronToken>> loadAllUniqueTronTokens(
|
||||
Box<WalletInfo> walletInfoSource,
|
||||
) async {
|
||||
final tronWallets = walletInfoSource.values.where(
|
||||
static Future<List<TronToken>> loadAllUniqueTronTokens() async {
|
||||
final allWi = await WalletInfo.getAll();
|
||||
final tronWallets = allWi.where(
|
||||
(w) => w.type == WalletType.tron,
|
||||
);
|
||||
|
||||
@@ -82,7 +79,6 @@ class TokenUtilities {
|
||||
/// - Tron: match by contractAddress
|
||||
static Future<CryptoCurrency?> findTokenByAddress({
|
||||
required WalletType walletType,
|
||||
required Box<WalletInfo> walletInfoSource,
|
||||
required String address,
|
||||
}) async {
|
||||
final lower = address.toLowerCase();
|
||||
@@ -90,19 +86,19 @@ class TokenUtilities {
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
case WalletType.base:
|
||||
final tokens = await loadAllUniqueEvmTokens(walletInfoSource);
|
||||
final tokens = await loadAllUniqueEvmTokens();
|
||||
for (final t in tokens) {
|
||||
if (t.contractAddress.toLowerCase() == lower) return t;
|
||||
}
|
||||
return null;
|
||||
case WalletType.solana:
|
||||
final solTokens = await loadAllUniqueSolTokens(walletInfoSource);
|
||||
final solTokens = await loadAllUniqueSolTokens();
|
||||
for (final t in solTokens) {
|
||||
if (t.mintAddress.toLowerCase() == lower) return t;
|
||||
}
|
||||
return null;
|
||||
case WalletType.tron:
|
||||
final tronTokens = await loadAllUniqueTronTokens(walletInfoSource);
|
||||
final tronTokens = await loadAllUniqueTronTokens();
|
||||
for (final t in tronTokens) {
|
||||
if (t.contractAddress.toLowerCase() == lower) return t;
|
||||
}
|
||||
|
||||
@@ -22,16 +22,22 @@ class ContactListViewModel = ContactListViewModelBase with _$ContactListViewMode
|
||||
|
||||
abstract class ContactListViewModelBase with Store {
|
||||
ContactListViewModelBase(
|
||||
this.contactSource, this.walletInfoSource, this._currency, this.settingsStore)
|
||||
this.contactSource, List<WalletInfo> wallets, this._currency, this.settingsStore)
|
||||
: contacts = ObservableList<ContactRecord>(),
|
||||
walletContacts = [],
|
||||
isAutoGenerateEnabled =
|
||||
settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.enabled {
|
||||
walletInfoSource.values.forEach((info) {
|
||||
unawaited(_init());
|
||||
}
|
||||
|
||||
Future<void> _init() async {
|
||||
final walletInfos = await WalletInfo.getAll();
|
||||
for (final info in walletInfos) {
|
||||
final addressInfos = await info.getAddressInfos();
|
||||
final addresses = await info.getAddresses();
|
||||
if ([WalletType.monero, WalletType.wownero, WalletType.haven].contains(info.type) &&
|
||||
info.addressInfos != null) {
|
||||
for (var key in info.addressInfos!.keys) {
|
||||
final value = info.addressInfos![key];
|
||||
addressInfos.isNotEmpty) {
|
||||
for (var key in addressInfos.keys) {
|
||||
final value = addressInfos[key];
|
||||
final address = value?.first;
|
||||
if (address != null) {
|
||||
final name = _createName(info.name, address.label, key: key);
|
||||
@@ -42,7 +48,7 @@ abstract class ContactListViewModelBase with Store {
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if (info.addresses?.isNotEmpty == true && info.addresses!.length > 1) {
|
||||
} else if (addresses.isNotEmpty == true && addresses.length > 1) {
|
||||
if ([WalletType.monero, WalletType.wownero, WalletType.haven, WalletType.decred]
|
||||
.contains(info.type)) {
|
||||
final address = info.address;
|
||||
@@ -53,7 +59,7 @@ abstract class ContactListViewModelBase with Store {
|
||||
walletTypeToCryptoCurrency(info.type),
|
||||
));
|
||||
} else {
|
||||
info.addresses!.forEach((address, label) {
|
||||
addresses.forEach((address, label) {
|
||||
if (label.isEmpty) {
|
||||
return;
|
||||
}
|
||||
@@ -78,13 +84,14 @@ abstract class ContactListViewModelBase with Store {
|
||||
walletTypeToCryptoCurrency(info.type),
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_subscription = contactSource.bindToListWithTransform(
|
||||
contacts, (Contact contact) => ContactRecord(contactSource, contact),
|
||||
initialFire: true);
|
||||
|
||||
setOrderType(settingsStore.contactListOrder);
|
||||
walletContacts = walletContacts.toList(); // rebuild
|
||||
}
|
||||
|
||||
String _createName(String walletName, String label, {int? key = null}) {
|
||||
@@ -97,9 +104,9 @@ abstract class ContactListViewModelBase with Store {
|
||||
|
||||
final bool isAutoGenerateEnabled;
|
||||
final Box<Contact> contactSource;
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
final ObservableList<ContactRecord> contacts;
|
||||
final List<WalletContact> walletContacts;
|
||||
@observable
|
||||
List<WalletContact> walletContacts = [];
|
||||
final CryptoCurrency? _currency;
|
||||
StreamSubscription<BoxEvent>? _subscription;
|
||||
final SettingsStore settingsStore;
|
||||
|
||||
@@ -1098,8 +1098,8 @@ abstract class DashboardViewModelBase with Store {
|
||||
void setSyncAll(bool value) => settingsStore.currentSyncAll = value;
|
||||
|
||||
Future<List<String>> checkForHavenWallets() async {
|
||||
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
return walletInfoSource.values
|
||||
final walletInfos = await WalletInfo.getAll();
|
||||
return walletInfos
|
||||
.where((element) => element.type == WalletType.haven)
|
||||
.map((e) => e.name)
|
||||
.toList();
|
||||
@@ -1112,10 +1112,9 @@ abstract class DashboardViewModelBase with Store {
|
||||
.loadString('assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt');
|
||||
final vulnerableSeeds = vulnerableSeedsString.split("\n");
|
||||
|
||||
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
|
||||
List<String> affectedWallets = [];
|
||||
for (var walletInfo in walletInfoSource.values) {
|
||||
final walletInfos = await WalletInfo.getAll();
|
||||
for (var walletInfo in walletInfos) {
|
||||
if (walletInfo.type == WalletType.bitcoin) {
|
||||
final password = await keyService.getWalletPassword(walletName: walletInfo.name);
|
||||
final path = await pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||
|
||||
@@ -44,6 +44,7 @@ import 'package:cake_wallet/utils/token_utilities.dart';
|
||||
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/erc20_token.dart';
|
||||
@@ -82,7 +83,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
this.contactListViewModel,
|
||||
this.unspentCoinsListViewModel,
|
||||
this.feesViewModel,
|
||||
this.walletInfoSource,
|
||||
this.fiatConversionStore,
|
||||
) : _cryptoNumberFormat = NumberFormat(),
|
||||
isSendAllEnabled = false,
|
||||
@@ -369,8 +369,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
final FeesViewModel feesViewModel;
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@observable
|
||||
double bestRate = 0.0;
|
||||
|
||||
@@ -1096,7 +1094,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
@action
|
||||
Future<void> _injectUserEthTokensIntoCurrencyLists() async {
|
||||
final userTokens = await TokenUtilities.loadAllUniqueEvmTokens(walletInfoSource);
|
||||
final userTokens = await TokenUtilities.loadAllUniqueEvmTokens();
|
||||
|
||||
final toAddReceive = <CryptoCurrency>[];
|
||||
final toAddDeposit = <CryptoCurrency>[];
|
||||
@@ -1134,7 +1132,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
@action
|
||||
Future<void> _injectUserSplTokensIntoCurrencyLists() async {
|
||||
final userTokens = await TokenUtilities.loadAllUniqueSolTokens(walletInfoSource);
|
||||
final userTokens = await TokenUtilities.loadAllUniqueSolTokens();
|
||||
|
||||
final toAddReceive = <CryptoCurrency>[];
|
||||
final toAddDeposit = <CryptoCurrency>[];
|
||||
@@ -1162,7 +1160,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
@action
|
||||
Future<void> _injectUserTronTokensIntoCurrencyLists() async {
|
||||
final userTokens = await TokenUtilities.loadAllUniqueTronTokens(walletInfoSource);
|
||||
final userTokens = await TokenUtilities.loadAllUniqueTronTokens();
|
||||
|
||||
final toAddReceive = <CryptoCurrency>[];
|
||||
final toAddDeposit = <CryptoCurrency>[];
|
||||
|
||||
@@ -98,15 +98,15 @@ abstract class BitboxViewModelBase extends HardwareWalletViewModel with Store {
|
||||
}
|
||||
|
||||
@override
|
||||
void initWallet(WalletBase wallet) {
|
||||
Future<void> initWallet(WalletBase wallet) async {
|
||||
switch (wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return bitcoin!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return ethereum!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
case WalletType.polygon:
|
||||
return polygon!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return polygon!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
default:
|
||||
throw Exception('Unexpected wallet type: ${wallet.type}');
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ abstract class HardwareWalletViewModel {
|
||||
|
||||
HardwareWalletService getHardwareWalletService(WalletType type);
|
||||
|
||||
void initWallet(WalletBase wallet);
|
||||
Future<void> initWallet(WalletBase wallet);
|
||||
|
||||
String? interpretErrorCode(String error) => null;
|
||||
}
|
||||
|
||||
@@ -178,18 +178,18 @@ abstract class LedgerViewModelBase extends HardwareWalletViewModel with Store {
|
||||
sdk.LedgerConnection get connection => _connection!;
|
||||
|
||||
@override
|
||||
void initWallet(WalletBase wallet) {
|
||||
Future<void> initWallet(WalletBase wallet) async {
|
||||
switch (wallet.type) {
|
||||
case WalletType.monero:
|
||||
return monero!.setLedgerConnection(wallet, connection);
|
||||
case WalletType.bitcoin:
|
||||
return bitcoin!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return bitcoin!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return bitcoin!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return ethereum!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
case WalletType.polygon:
|
||||
return polygon!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return polygon!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
default:
|
||||
throw Exception('Unexpected wallet type: ${wallet.type}');
|
||||
}
|
||||
|
||||
@@ -66,15 +66,15 @@ abstract class TrezorViewModelBase extends HardwareWalletViewModel with Store {
|
||||
}
|
||||
|
||||
@override
|
||||
void initWallet(WalletBase wallet) {
|
||||
Future<void> initWallet(WalletBase wallet) async {
|
||||
switch (wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return bitcoin!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return ethereum!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
case WalletType.polygon:
|
||||
return polygon!.setHardwareWalletService(wallet, getHardwareWalletService(wallet.type));
|
||||
return polygon!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
|
||||
default:
|
||||
throw Exception('Unexpected wallet type: ${wallet.type}');
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'new_wallet_type_view_model.g.dart';
|
||||
@@ -7,10 +5,7 @@ part 'new_wallet_type_view_model.g.dart';
|
||||
class NewWalletTypeViewModel = NewWalletTypeViewModelBase with _$NewWalletTypeViewModel;
|
||||
|
||||
abstract class NewWalletTypeViewModelBase with Store {
|
||||
NewWalletTypeViewModelBase(this._walletInfoSource);
|
||||
NewWalletTypeViewModelBase(this.hasExisitingWallet);
|
||||
|
||||
@computed
|
||||
bool get hasExisitingWallet => _walletInfoSource.isNotEmpty;
|
||||
|
||||
final Box<WalletInfo> _walletInfoSource;
|
||||
final bool hasExisitingWallet;
|
||||
}
|
||||
|
||||
@@ -15,11 +15,9 @@ class PaymentViewModel = PaymentViewModelBase with _$PaymentViewModel;
|
||||
abstract class PaymentViewModelBase with Store {
|
||||
PaymentViewModelBase({
|
||||
required this.appStore,
|
||||
required this.walletInfoSource,
|
||||
});
|
||||
|
||||
final AppStore appStore;
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@observable
|
||||
WalletType? detectedWalletType;
|
||||
@@ -52,7 +50,7 @@ abstract class PaymentViewModelBase with Store {
|
||||
return PaymentFlowResult.currentWalletCompatible();
|
||||
}
|
||||
|
||||
final compatibleWallets = getWalletsByType(detectedWalletType!);
|
||||
final compatibleWallets = await getWalletsByType(detectedWalletType!);
|
||||
|
||||
switch (compatibleWallets.length) {
|
||||
case 0:
|
||||
@@ -70,8 +68,8 @@ abstract class PaymentViewModelBase with Store {
|
||||
}
|
||||
}
|
||||
|
||||
List<WalletInfo> getWalletsByType(WalletType walletType) {
|
||||
return walletInfoSource.values.where((wallet) => wallet.type == walletType).toList();
|
||||
Future<List<WalletInfo>> getWalletsByType(WalletType walletType) async {
|
||||
return (await WalletInfo.getAll()).where((wallet) => wallet.type == walletType).toList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,11 +45,11 @@ abstract class RestoreFromBackupViewModelBase with Store {
|
||||
|
||||
try {
|
||||
await backupService.importBackupFile(file, password);
|
||||
} catch (e) {
|
||||
} catch (e, s) {
|
||||
if (e.toString().contains("unknown_backup_version")) {
|
||||
state = FailureState('This is not a valid backup file, please make sure you have selected the correct one');
|
||||
} else {
|
||||
state = FailureState(e.toString());
|
||||
state = FailureState(e.toString() + "\n" + s.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,8 +100,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
this.transactionDescriptionBox,
|
||||
this.hardwareWalletViewModel,
|
||||
this.unspentCoinsListViewModel,
|
||||
this.feesViewModel,
|
||||
this.walletInfoSource, {
|
||||
this.feesViewModel, {
|
||||
this.coinTypeToSpendFrom = UnspentCoinType.nonMweb,
|
||||
}) : state = InitialExecutionState(),
|
||||
currencies = appStore.wallet!.balance.keys.toList(),
|
||||
@@ -130,8 +129,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
|
||||
ObservableList<Output> outputs;
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@observable
|
||||
UnspentCoinType coinTypeToSpendFrom;
|
||||
|
||||
@@ -1214,7 +1211,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
Future<void> fetchTokenForContractAddress(String contractAddress) async {
|
||||
final token = await TokenUtilities.findTokenByAddress(
|
||||
walletType: wallet.type,
|
||||
walletInfoSource: walletInfoSource,
|
||||
address: contractAddress,
|
||||
);
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
@action
|
||||
Future<void> onHardwareWalletTypeChanged(HardwareWalletType hwType) async {
|
||||
_wallet.walletInfo.hardwareWalletType = hwType;
|
||||
return _wallet.walletInfo.save();
|
||||
await _wallet.walletInfo.save();
|
||||
}
|
||||
|
||||
@computed
|
||||
|
||||
@@ -26,7 +26,7 @@ part 'wallet_creation_vm.g.dart';
|
||||
class WalletCreationVM = WalletCreationVMBase with _$WalletCreationVM;
|
||||
|
||||
abstract class WalletCreationVMBase with Store {
|
||||
WalletCreationVMBase(this._appStore, this._walletInfoSource, this.walletCreationService,
|
||||
WalletCreationVMBase(this._appStore, this.walletCreationService,
|
||||
this.seedSettingsViewModel,
|
||||
{required this.type, required this.isRecovery})
|
||||
: state = InitialExecutionState(),
|
||||
@@ -54,7 +54,6 @@ abstract class WalletCreationVMBase with Store {
|
||||
WalletType type;
|
||||
final bool isRecovery;
|
||||
final WalletCreationService walletCreationService;
|
||||
final Box<WalletInfo> _walletInfoSource;
|
||||
final AppStore _appStore;
|
||||
final SeedSettingsViewModel seedSettingsViewModel;
|
||||
|
||||
@@ -62,9 +61,9 @@ abstract class WalletCreationVMBase with Store {
|
||||
[WalletType.monero, WalletType.wownero].contains(type) &&
|
||||
(Polyseed.isValidSeed(seed) || (seed.split(" ").length == 14));
|
||||
|
||||
bool nameExists(String name) => walletCreationService.exists(name);
|
||||
Future<bool> nameExists(String name) => walletCreationService.exists(name);
|
||||
|
||||
bool typeExists(WalletType type) => walletCreationService.typeExists(type);
|
||||
Future<bool> typeExists(WalletType type) => walletCreationService.typeExists(type);
|
||||
|
||||
Future<void> create({dynamic options}) async {
|
||||
final type = this.type;
|
||||
@@ -88,6 +87,13 @@ abstract class WalletCreationVMBase with Store {
|
||||
|
||||
final credentials = getCredentials(options);
|
||||
|
||||
final di = ((credentials.derivationInfo?.derivationPath??"") == "")
|
||||
? getDefaultCreateDerivation()
|
||||
: credentials.derivationInfo;
|
||||
|
||||
final diId = await di!.save();
|
||||
credentials.derivationInfo = di;
|
||||
|
||||
final walletInfo = WalletInfo.external(
|
||||
id: WalletBase.idFor(name, type),
|
||||
name: name,
|
||||
@@ -98,19 +104,21 @@ abstract class WalletCreationVMBase with Store {
|
||||
path: path,
|
||||
dirPath: dirPath,
|
||||
address: '',
|
||||
showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven,
|
||||
derivationInfo: credentials.derivationInfo ?? getDefaultCreateDerivation(),
|
||||
showIntroCakePayCard: (!await walletCreationService.typeExists(type)) && type != WalletType.haven,
|
||||
derivationInfoId: diId,
|
||||
hardwareWalletType: credentials.hardwareWalletType,
|
||||
);
|
||||
|
||||
credentials.walletInfo = walletInfo;
|
||||
// await walletInfo.save();
|
||||
printV("derivationInfo: ${(await walletInfo.getDerivationInfo()).toJson()}");
|
||||
final wallet = await process(credentials);
|
||||
|
||||
final isNonSeedWallet = isRecovery ? wallet.seed == null : false;
|
||||
walletInfo.isNonSeedWallet = isNonSeedWallet;
|
||||
walletInfo.hashedWalletIdentifier = createHashedWalletIdentifier(wallet);
|
||||
walletInfo.address = wallet.walletAddresses.address;
|
||||
await _walletInfoSource.add(walletInfo);
|
||||
await walletInfo.save();
|
||||
await _appStore.changeCurrentWallet(wallet);
|
||||
_appStore.authenticationStore.allowedCreate();
|
||||
state = ExecutedSuccessfullyState();
|
||||
@@ -125,7 +133,7 @@ abstract class WalletCreationVMBase with Store {
|
||||
}
|
||||
}
|
||||
|
||||
DerivationInfo? getDefaultCreateDerivation() {
|
||||
DerivationInfo getDefaultCreateDerivation() {
|
||||
final useBip39ForBitcoin = seedSettingsViewModel.bitcoinSeedType.type == DerivationType.bip39;
|
||||
final useBip39ForNano = seedSettingsViewModel.nanoSeedType.type == DerivationType.bip39;
|
||||
switch (type) {
|
||||
@@ -155,7 +163,7 @@ abstract class WalletCreationVMBase with Store {
|
||||
}
|
||||
return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
|
||||
default:
|
||||
return null;
|
||||
return DerivationInfo(derivationType: DerivationType.unknown);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
import 'package:cake_wallet/entities/wallet_group.dart';
|
||||
import 'package:cake_wallet/entities/wallet_manager.dart';
|
||||
@@ -6,7 +8,6 @@ import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
||||
import 'package:cake_wallet/wallet_types.g.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
@@ -23,11 +24,9 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
this._walletManager,
|
||||
this.walletListViewModel, {
|
||||
required this.type,
|
||||
}) : isFetchingMnemonic = false,
|
||||
multiWalletGroups = ObservableList<WalletGroup>(),
|
||||
singleWalletsList = ObservableList<WalletInfo>() {
|
||||
reaction((_) => _appStore.wallet, (_) => updateWalletInfoSourceList());
|
||||
updateWalletInfoSourceList();
|
||||
}) : isFetchingMnemonic = false {
|
||||
reaction((_) => _appStore.wallet, (_) => unawaited(updateWalletInfoSourceList()));
|
||||
unawaited(updateWalletInfoSourceList());
|
||||
}
|
||||
|
||||
final WalletType type;
|
||||
@@ -37,10 +36,10 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
final WalletListViewModel walletListViewModel;
|
||||
|
||||
@observable
|
||||
ObservableList<WalletGroup> multiWalletGroups;
|
||||
ObservableList<WalletGroup> multiWalletGroups = ObservableList<WalletGroup>();
|
||||
|
||||
@observable
|
||||
ObservableList<WalletInfo> singleWalletsList;
|
||||
ObservableList<WalletInfo> singleWalletsList = ObservableList<WalletInfo>();
|
||||
|
||||
@observable
|
||||
WalletGroup? selectedWalletGroup;
|
||||
@@ -97,31 +96,33 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
}
|
||||
|
||||
@action
|
||||
void updateWalletInfoSourceList() {
|
||||
Future<void> updateWalletInfoSourceList() async {
|
||||
List<WalletGroup> wallets = [];
|
||||
|
||||
multiWalletGroups.clear();
|
||||
singleWalletsList.clear();
|
||||
|
||||
_walletManager.updateWalletGroups();
|
||||
await _walletManager.updateWalletGroups();
|
||||
|
||||
final walletGroups = _walletManager.walletGroups;
|
||||
|
||||
// Iterate through the wallet groups to filter and categorize wallets
|
||||
for (var group in walletGroups) {
|
||||
// Handle group wallet filtering
|
||||
bool shouldExcludeGroup = group.wallets.any((wallet) {
|
||||
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 &&
|
||||
wallet.derivationInfo?.derivationType == DerivationType.nano;
|
||||
di.derivationType == DerivationType.nano;
|
||||
|
||||
// Check for electrum derivation type
|
||||
bool isElectrumDerivationType =
|
||||
(wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) &&
|
||||
wallet.derivationInfo?.derivationType == DerivationType.electrum;
|
||||
di.derivationType == DerivationType.electrum;
|
||||
|
||||
// Check that selected wallet type is not present already in group
|
||||
bool isSameTypeAsSelectedWallet = wallet.type == type;
|
||||
@@ -129,16 +130,17 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
bool isNonSeedWallet = wallet.isNonSeedWallet;
|
||||
|
||||
bool isNotMoneroBip39Wallet = wallet.type == WalletType.monero &&
|
||||
wallet.derivationInfo?.derivationType != DerivationType.bip39;
|
||||
di.derivationType != DerivationType.bip39;
|
||||
|
||||
// Exclude if any of these conditions are true
|
||||
return isNonBIP39Wallet ||
|
||||
isNanoDerivationType ||
|
||||
isElectrumDerivationType ||
|
||||
isSameTypeAsSelectedWallet ||
|
||||
isNonSeedWallet ||
|
||||
isNotMoneroBip39Wallet;
|
||||
});
|
||||
shouldExcludeGroup = shouldExcludeGroup ||
|
||||
isNonBIP39Wallet ||
|
||||
isNanoDerivationType ||
|
||||
isElectrumDerivationType ||
|
||||
isSameTypeAsSelectedWallet ||
|
||||
isNonSeedWallet ||
|
||||
isNotMoneroBip39Wallet;
|
||||
}
|
||||
|
||||
if (shouldExcludeGroup) continue;
|
||||
|
||||
@@ -159,7 +161,7 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
return WalletListItem(
|
||||
name: info.name,
|
||||
type: info.type,
|
||||
key: info.key,
|
||||
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,
|
||||
|
||||
@@ -33,10 +33,9 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
|
||||
this.hardwareWalletVM,
|
||||
AppStore appStore,
|
||||
WalletCreationService walletCreationService,
|
||||
Box<WalletInfo> walletInfoSource,
|
||||
SeedSettingsViewModel seedSettingsViewModel,
|
||||
{required WalletType type})
|
||||
: super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel,
|
||||
: super(appStore, walletCreationService, seedSettingsViewModel,
|
||||
type: type, isRecovery: true);
|
||||
|
||||
@observable
|
||||
@@ -57,8 +56,8 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
|
||||
@action
|
||||
Future<void> getNextAvailableAccounts(int limit) async {
|
||||
try {
|
||||
List<HardwareAccountData> accounts = await hardwareWalletVM
|
||||
.getHardwareWalletService(type)
|
||||
final service = await hardwareWalletVM.getHardwareWalletService(type);
|
||||
List<HardwareAccountData> accounts = await service
|
||||
.getAvailableAccounts(index: _nextIndex, limit: limit);
|
||||
|
||||
availableAccounts.addAll(accounts);
|
||||
|
||||
@@ -46,7 +46,7 @@ abstract class WalletEditViewModelBase with Store {
|
||||
state = WalletEditRenamePending();
|
||||
|
||||
if (isWalletGroup) {
|
||||
_walletManager.updateWalletGroups();
|
||||
await _walletManager.updateWalletGroups();
|
||||
|
||||
_walletManager.setGroupName(walletGroupKey!, newName);
|
||||
} else {
|
||||
|
||||
@@ -2,12 +2,12 @@ import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
import 'package:cake_wallet/entities/wallet_group.dart';
|
||||
import 'package:cake_wallet/entities/wallet_list_order_types.dart';
|
||||
import 'package:cake_wallet/entities/wallet_manager.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cake_wallet/wallet_types.g.dart';
|
||||
|
||||
part 'wallet_list_view_model.g.dart';
|
||||
@@ -16,7 +16,6 @@ class WalletListViewModel = WalletListViewModelBase with _$WalletListViewModel;
|
||||
|
||||
abstract class WalletListViewModelBase with Store {
|
||||
WalletListViewModelBase(
|
||||
this._walletInfoSource,
|
||||
this._appStore,
|
||||
this._walletLoadingService,
|
||||
this._walletManager,
|
||||
@@ -25,7 +24,6 @@ abstract class WalletListViewModelBase with Store {
|
||||
singleWalletsList = ObservableList<WalletListItem>(),
|
||||
expansionTileStateTrack = ObservableMap<int, bool>() {
|
||||
setOrderType(_appStore.settingsStore.walletListOrder);
|
||||
reaction((_) => _appStore.wallet, (_) => updateList());
|
||||
updateList();
|
||||
}
|
||||
|
||||
@@ -63,12 +61,11 @@ abstract class WalletListViewModelBase with Store {
|
||||
|
||||
final AppStore _appStore;
|
||||
final WalletManager _walletManager;
|
||||
final Box<WalletInfo> _walletInfoSource;
|
||||
final WalletLoadingService _walletLoadingService;
|
||||
|
||||
WalletType get currentWalletType => _appStore.wallet!.type;
|
||||
|
||||
bool requireHardwareWalletConnection(WalletListItem walletItem) =>
|
||||
Future<bool> requireHardwareWalletConnection(WalletListItem walletItem) async =>
|
||||
_walletLoadingService.requireHardwareWalletConnection(
|
||||
walletItem.type, walletItem.name);
|
||||
|
||||
@@ -87,50 +84,62 @@ abstract class WalletListViewModelBase with Store {
|
||||
|
||||
bool get ascending => _appStore.settingsStore.walletListAscending;
|
||||
|
||||
|
||||
bool isUpdating = false;
|
||||
@action
|
||||
void updateList() {
|
||||
wallets.clear();
|
||||
multiWalletGroups.clear();
|
||||
singleWalletsList.clear();
|
||||
|
||||
for (var info in _walletInfoSource.values) {
|
||||
wallets.add(convertWalletInfoToWalletListItem(info));
|
||||
Future<void> updateList() async {
|
||||
if (isUpdating) {
|
||||
return;
|
||||
}
|
||||
isUpdating = true;
|
||||
try {
|
||||
wallets.clear();
|
||||
multiWalletGroups.clear();
|
||||
singleWalletsList.clear();
|
||||
|
||||
//========== Split into shared seed groups and single wallets list
|
||||
_walletManager.updateWalletGroups();
|
||||
final list = await WalletInfo.getAll();
|
||||
|
||||
final walletGroupsFromManager = _walletManager.walletGroups;
|
||||
|
||||
for (var group in walletGroupsFromManager) {
|
||||
if (group.wallets.length == 1) {
|
||||
singleWalletsList.add(convertWalletInfoToWalletListItem(group.wallets.first));
|
||||
continue;
|
||||
for (var info in list) {
|
||||
wallets.add(convertWalletInfoToWalletListItem(info));
|
||||
}
|
||||
|
||||
multiWalletGroups.add(group);
|
||||
//========== Split into shared seed groups and single wallets list
|
||||
await _walletManager.updateWalletGroups();
|
||||
|
||||
final walletGroupsFromManager = _walletManager.walletGroups;
|
||||
|
||||
for (var group in walletGroupsFromManager) {
|
||||
if (group.wallets.length == 1) {
|
||||
singleWalletsList.add(convertWalletInfoToWalletListItem(group.wallets.first));
|
||||
continue;
|
||||
}
|
||||
|
||||
multiWalletGroups.add(group);
|
||||
}
|
||||
} finally {
|
||||
isUpdating = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> reorderAccordingToWalletList() async {
|
||||
if (wallets.isEmpty) {
|
||||
updateList();
|
||||
await updateList();
|
||||
return;
|
||||
}
|
||||
|
||||
_appStore.settingsStore.walletListOrder = FilterListOrderType.Custom;
|
||||
|
||||
// make a copy of the walletInfoSource:
|
||||
List<WalletInfo> walletInfoSourceCopy = _walletInfoSource.values.toList();
|
||||
// delete all wallets from walletInfoSource:
|
||||
await _walletInfoSource.clear();
|
||||
List<WalletInfo> wiList = await WalletInfo.getAll();
|
||||
|
||||
// Reorder single wallets using the singleWalletsList
|
||||
int oldI = 0;
|
||||
for (WalletListItem wallet in singleWalletsList) {
|
||||
for (int i = 0; i < walletInfoSourceCopy.length; i++) {
|
||||
if (walletInfoSourceCopy[i].name == wallet.name) {
|
||||
await _walletInfoSource.add(walletInfoSourceCopy[i]);
|
||||
walletInfoSourceCopy.removeAt(i);
|
||||
for (int i = 0; i < wiList.length; i++) {
|
||||
if (wiList[i].id == wallet.key) {
|
||||
oldI++;
|
||||
wiList[i].sortOrder = oldI;
|
||||
await wiList[i].save();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -139,10 +148,11 @@ abstract class WalletListViewModelBase with Store {
|
||||
// Reorder wallets within multi-wallet groups
|
||||
for (WalletGroup group in multiWalletGroups) {
|
||||
for (WalletInfo walletInfo in group.wallets) {
|
||||
for (int i = 0; i < walletInfoSourceCopy.length; i++) {
|
||||
if (walletInfoSourceCopy[i].name == walletInfo.name) {
|
||||
await _walletInfoSource.add(walletInfoSourceCopy[i]);
|
||||
walletInfoSourceCopy.removeAt(i);
|
||||
for (int i = 0; i < wiList.length; i++) {
|
||||
if (wiList[i].name == walletInfo.name) {
|
||||
wiList[i].sortOrder = i+oldI;
|
||||
await wiList[i].save();
|
||||
wiList.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -150,47 +160,52 @@ abstract class WalletListViewModelBase with Store {
|
||||
}
|
||||
|
||||
// Rebuild the list of wallets and groups
|
||||
updateList();
|
||||
await updateList();
|
||||
}
|
||||
|
||||
Future<void> sortGroupByType() async {
|
||||
// sort the wallets by type:
|
||||
List<WalletInfo> walletInfoSourceCopy = _walletInfoSource.values.toList();
|
||||
await _walletInfoSource.clear();
|
||||
List<WalletInfo> wiList = await WalletInfo.getAll();
|
||||
if (ascending) {
|
||||
walletInfoSourceCopy
|
||||
.sort((a, b) => a.type.toString().compareTo(b.type.toString()));
|
||||
wiList.sort((a, b) => a.type.toString().compareTo(b.type.toString()));
|
||||
} else {
|
||||
walletInfoSourceCopy
|
||||
.sort((a, b) => b.type.toString().compareTo(a.type.toString()));
|
||||
wiList.sort((a, b) => b.type.toString().compareTo(a.type.toString()));
|
||||
}
|
||||
await _walletInfoSource.addAll(walletInfoSourceCopy);
|
||||
updateList();
|
||||
for (int i = 0; i < wiList.length; i++) {
|
||||
wiList[i].sortOrder = i;
|
||||
await wiList[i].save();
|
||||
}
|
||||
await updateList();
|
||||
}
|
||||
|
||||
Future<void> sortAlphabetically() async {
|
||||
// sort the wallets alphabetically:
|
||||
List<WalletInfo> walletInfoSourceCopy = _walletInfoSource.values.toList();
|
||||
await _walletInfoSource.clear();
|
||||
List<WalletInfo> wiList = await WalletInfo.getAll();
|
||||
if (ascending) {
|
||||
walletInfoSourceCopy.sort((a, b) => a.name.compareTo(b.name));
|
||||
wiList.sort((a, b) => a.name.compareTo(b.name));
|
||||
} else {
|
||||
walletInfoSourceCopy.sort((a, b) => b.name.compareTo(a.name));
|
||||
wiList.sort((a, b) => b.name.compareTo(a.name));
|
||||
}
|
||||
await _walletInfoSource.addAll(walletInfoSourceCopy);
|
||||
updateList();
|
||||
for (int i = 0; i < wiList.length; i++) {
|
||||
wiList[i].sortOrder = i;
|
||||
await wiList[i].save();
|
||||
}
|
||||
await updateList();
|
||||
}
|
||||
|
||||
Future<void> sortByCreationDate() async {
|
||||
// sort the wallets by creation date:
|
||||
List<WalletInfo> walletInfoSourceCopy = _walletInfoSource.values.toList();
|
||||
await _walletInfoSource.clear();
|
||||
List<WalletInfo> wiList = await WalletInfo.getAll();
|
||||
if (ascending) {
|
||||
walletInfoSourceCopy.sort((a, b) => a.date.compareTo(b.date));
|
||||
wiList.sort((a, b) => a.date.compareTo(b.date));
|
||||
} else {
|
||||
walletInfoSourceCopy.sort((a, b) => b.date.compareTo(a.date));
|
||||
wiList.sort((a, b) => b.date.compareTo(a.date));
|
||||
}
|
||||
await _walletInfoSource.addAll(walletInfoSourceCopy);
|
||||
for (int i = 0; i < wiList.length; i++) {
|
||||
wiList[i].sortOrder = i;
|
||||
await wiList[i].save();
|
||||
}
|
||||
|
||||
updateList();
|
||||
}
|
||||
|
||||
@@ -223,7 +238,7 @@ abstract class WalletListViewModelBase with Store {
|
||||
return WalletListItem(
|
||||
name: info.name,
|
||||
type: info.type,
|
||||
key: info.key,
|
||||
key: info.id,
|
||||
isCurrent: info.name == _appStore.wallet?.name &&
|
||||
info.type == _appStore.wallet?.type,
|
||||
isEnabled: availableWalletTypes.contains(info.type),
|
||||
|
||||
@@ -34,12 +34,11 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
WalletNewVMBase(
|
||||
AppStore appStore,
|
||||
WalletCreationService walletCreationService,
|
||||
Box<WalletInfo> walletInfoSource,
|
||||
this.advancedPrivacySettingsViewModel,
|
||||
SeedSettingsViewModel seedSettingsViewModel, {
|
||||
required this.newWalletArguments,
|
||||
}) : selectedMnemonicLanguage = '',
|
||||
super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel,
|
||||
super(appStore, walletCreationService, seedSettingsViewModel,
|
||||
type: newWalletArguments!.type, isRecovery: false);
|
||||
|
||||
final NewWalletArguments? newWalletArguments;
|
||||
|
||||
@@ -24,7 +24,6 @@ import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'wallet_restore_view_model.g.dart';
|
||||
@@ -33,12 +32,12 @@ class WalletRestoreViewModel = WalletRestoreViewModelBase with _$WalletRestoreVi
|
||||
|
||||
abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
WalletRestoreViewModelBase(AppStore appStore, WalletCreationService walletCreationService,
|
||||
Box<WalletInfo> walletInfoSource, SeedSettingsViewModel seedSettingsViewModel,
|
||||
SeedSettingsViewModel seedSettingsViewModel,
|
||||
{required WalletType type, this.restoredWallet, this.hardwareWalletType})
|
||||
: isButtonEnabled = restoredWallet != null,
|
||||
hasPassphrase = false,
|
||||
mode = restoredWallet?.restoreMode ?? WalletRestoreMode.seed,
|
||||
super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel,
|
||||
super(appStore, walletCreationService, seedSettingsViewModel,
|
||||
type: type, isRecovery: true) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'wallet_switcher_view_model.g.dart';
|
||||
@@ -16,12 +15,10 @@ abstract class WalletSwitcherViewModelBase with Store {
|
||||
WalletSwitcherViewModelBase({
|
||||
required this.appStore,
|
||||
required this.walletLoadingService,
|
||||
required this.walletInfoSource,
|
||||
});
|
||||
|
||||
final AppStore appStore;
|
||||
final WalletLoadingService walletLoadingService;
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@observable
|
||||
WalletInfo? selectedWallet;
|
||||
@@ -30,12 +27,13 @@ abstract class WalletSwitcherViewModelBase with Store {
|
||||
bool isProcessing = false;
|
||||
|
||||
@action
|
||||
List<WalletInfo> getWallets(WalletType? walletType) {
|
||||
Future<List<WalletInfo>> getWallets(WalletType? walletType) async {
|
||||
final wiList = await WalletInfo.getAll();
|
||||
if (walletType == null) {
|
||||
return walletInfoSource.values.toList();
|
||||
return wiList;
|
||||
}
|
||||
|
||||
return walletInfoSource.values.where((wallet) => wallet.type == walletType).toList();
|
||||
return wiList.where((wallet) => wallet.type == walletType).toList();
|
||||
}
|
||||
|
||||
@action
|
||||
|
||||
@@ -315,9 +315,8 @@ class CWWownero extends Wownero {
|
||||
}
|
||||
|
||||
@override
|
||||
WalletService createWowneroWalletService(
|
||||
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) =>
|
||||
WowneroWalletService(walletInfoSource, unspentCoinSource);
|
||||
WalletService createWowneroWalletService(Box<UnspentCoinsInfo> unspentCoinSource) =>
|
||||
WowneroWalletService(unspentCoinSource);
|
||||
|
||||
@override
|
||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
|
||||
|
||||
@@ -109,8 +109,8 @@ class CWZano extends Zano {
|
||||
// }
|
||||
|
||||
@override
|
||||
WalletService createZanoWalletService(Box<WalletInfo> walletInfoSource) {
|
||||
return ZanoWalletService(walletInfoSource);
|
||||
WalletService createZanoWalletService() {
|
||||
return ZanoWalletService();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user