diff --git a/lib/wallets/wallet/impl/xelis_wallet.dart b/lib/wallets/wallet/impl/xelis_wallet.dart index 8be779fc8..a57f03a02 100644 --- a/lib/wallets/wallet/impl/xelis_wallet.dart +++ b/lib/wallets/wallet/impl/xelis_wallet.dart @@ -19,6 +19,8 @@ import '../../../services/event_bus/events/global/wallet_sync_status_changed_eve import '../../../services/event_bus/global_event_bus.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/logger.dart'; +import '../../../utilities/stack_file_system.dart'; + import '../../crypto_currency/crypto_currency.dart'; import '../../models/tx_data.dart'; import '../intermediate/lib_xelis_wallet.dart'; @@ -31,7 +33,46 @@ class XelisWallet extends LibXelisWallet { @override int get isarTransactionVersion => 2; + Future<void> _restoreWallet() async { + final tablePath = await getPrecomputedTablesPath(); + final tableState = await getTableState(); + final xelisDir = await StackFileSystem.applicationXelisDirectory(); + final String name = walletId; + final String directory = xelisDir.path; + final password = await secureStorageInterface.read( + key: Wallet.mnemonicPassphraseKey(walletId: info.walletId), + ); + + final mnemonic = await getMnemonic(); + final seedLength = mnemonic.trim().split(" ").length; + + invalidSeedLengthCheck(seedLength); + + Logging.instance.i("Xelis: recovering wallet"); + final wallet = await x_wallet.createXelisWallet( + name: name, + directory: directory, + password: password!, + seed: mnemonic.trim(), + network: cryptoCurrency.network.xelisNetwork, + precomputedTablesPath: tablePath, + l1Low: tableState.currentSize.isLow, + ); + + await secureStorageInterface.write( + key: Wallet.mnemonicKey(walletId: walletId), + value: mnemonic.trim(), + ); + + libXelisWallet = wallet; + } + Future<void> _createNewWallet() async { + final tablePath = await getPrecomputedTablesPath(); + final tableState = await getTableState(); + final xelisDir = await StackFileSystem.applicationXelisDirectory(); + final String name = walletId; + final String directory = xelisDir.path; final String password = generatePassword(); Logging.instance.d("Xelis: storing password"); @@ -39,21 +80,82 @@ class XelisWallet extends LibXelisWallet { key: Wallet.mnemonicPassphraseKey(walletId: info.walletId), value: password, ); + + final wallet = await x_wallet.createXelisWallet( + name: name, + directory: directory, + password: password!, + network: cryptoCurrency.network.xelisNetwork, + precomputedTablesPath: tablePath, + l1Low: tableState.currentSize.isLow, + ); + + final mnemonic = await wallet.getSeed(); + await secureStorageInterface.write( + key: Wallet.mnemonicKey(walletId: walletId), + value: mnemonic.trim(), + ); + + libXelisWallet = wallet; } @override Future<void> init({bool? isRestore}) async { Logging.instance.d("Xelis: init"); - if (isRestore == true) { - await super.init(); - return await open(openType: XelisWalletOpenType.restore); - } + if (libXelisWallet == null) { + if (isRestore == true) { + await _restoreWallet(); + } else { + final bool walletExists = await LibXelisWallet.checkWalletExists(walletId); + if (!walletExists) { + await _createNewWallet(); + } else { + Logging.instance.i("Xelis: opening existing wallet"); + final tablePath = await getPrecomputedTablesPath(); + final tableState = await getTableState(); + final xelisDir = await StackFileSystem.applicationXelisDirectory(); + final String name = walletId; + final String directory = xelisDir.path; + final password = await secureStorageInterface.read( + key: Wallet.mnemonicPassphraseKey(walletId: info.walletId), + ); - final bool walletExists = await LibXelisWallet.checkWalletExists(walletId); - if (!walletExists) { - await _createNewWallet(); - await open(openType: XelisWalletOpenType.create); + libXelisWallet = await x_wallet.openXelisWallet( + name: name, + directory: directory, + password: password!, + network: cryptoCurrency.network.xelisNetwork, + precomputedTablesPath: tablePath, + l1Low: tableState.currentSize.isLow, + ); + } + } + + if (await isTableUpgradeAvailable()) { + unawaited(updateTablesToDesiredSize()); + } + + final newReceivingAddress = + await getCurrentReceivingAddress() ?? + Address( + walletId: walletId, + derivationIndex: 0, + derivationPath: null, + value: libXelisWallet!.getAddressStr(), + publicKey: [], + type: AddressType.xelis, + subType: AddressSubType.receiving, + ); + + await mainDB.updateOrPutAddresses([newReceivingAddress]); + + if (info.cachedReceivingAddress != newReceivingAddress.value) { + await info.updateReceivingAddress( + newAddress: newReceivingAddress.value, + isar: mainDB.isar, + ); + } } return await super.init(); @@ -97,7 +199,7 @@ class XelisWallet extends LibXelisWallet { } catch (_) { await handleOffline(); return false; - } + } } final _balanceUpdateMutex = Mutex(); diff --git a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart index 78caa6c87..e494d68db 100644 --- a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart @@ -331,119 +331,15 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> @override Future<void> open({XelisWalletOpenType? openType}) async { - bool wasNull = false; - - if (libXelisWallet == null) { - wasNull = true; - final tablePath = await getPrecomputedTablesPath(); - final tableState = await getTableState(); - final xelisDir = await StackFileSystem.applicationXelisDirectory(); - final String name = walletId; - final String directory = xelisDir.path; - final password = await secureStorageInterface.read( - key: Wallet.mnemonicPassphraseKey(walletId: info.walletId), - ); - - await LibXelisWallet._initMutex.protect(() async { - try { - libXelisWallet = await syncMutex.protect(() async { - switch (openType) { - case XelisWalletOpenType.create: - Logging.instance.i("Xelis: creating new wallet"); - final wallet = await x_wallet.createXelisWallet( - name: name, - directory: directory, - password: password!, - network: cryptoCurrency.network.xelisNetwork, - precomputedTablesPath: tablePath, - l1Low: tableState.currentSize.isLow, - ); - - final mnemonic = await wallet.getSeed(); - await secureStorageInterface.write( - key: Wallet.mnemonicKey(walletId: walletId), - value: mnemonic.trim(), - ); - - return wallet; - - case XelisWalletOpenType.restore: - final mnemonic = await getMnemonic(); - final seedLength = mnemonic.trim().split(" ").length; - - invalidSeedLengthCheck(seedLength); - - Logging.instance.i("Xelis: recovering wallet"); - final wallet = await x_wallet.createXelisWallet( - name: name, - directory: directory, - password: password!, - seed: mnemonic.trim(), - network: cryptoCurrency.network.xelisNetwork, - precomputedTablesPath: tablePath, - l1Low: tableState.currentSize.isLow, - ); - - await secureStorageInterface.write( - key: Wallet.mnemonicKey(walletId: walletId), - value: mnemonic.trim(), - ); - - return wallet; - - case null: - Logging.instance.i("Xelis: opening existing wallet"); - return await x_wallet.openXelisWallet( - name: name, - directory: directory, - password: password!, - network: cryptoCurrency.network.xelisNetwork, - precomputedTablesPath: tablePath, - l1Low: tableState.currentSize.isLow, - ); - } - }); - } catch (e, s) { - Logging.instance.e( - "Rethrowing failed $runtimeType open(openType: $openType)", - error: e, - stackTrace: s, - ); - rethrow; - } - }); - - Logging.instance.i("Xelis: Checking for upgradability"); - if (await isTableUpgradeAvailable()) { - Logging.instance.i("Xelis: Generating large tables in background"); - unawaited(updateTablesToDesiredSize()); - } - } - - final newReceivingAddress = - await getCurrentReceivingAddress() ?? - Address( - walletId: walletId, - derivationIndex: 0, - derivationPath: null, - value: libXelisWallet!.getAddressStr(), - publicKey: [], - type: AddressType.xelis, - subType: AddressSubType.receiving, - ); - await mainDB.updateOrPutAddresses([newReceivingAddress]); - - if (info.cachedReceivingAddress != newReceivingAddress.value) { - await info.updateReceivingAddress( - newAddress: newReceivingAddress.value, - isar: mainDB.isar, - ); - } - - if (wasNull) { + try { await connect(); + } catch (e) { + // Logging.instance.log( + // "Failed to start sync: $e", + // level: LogLevel.Error, + // ); + rethrow; } - unawaited(refresh()); } @@ -457,10 +353,6 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> _eventSubscription = null; await libXelisWallet?.offlineMode(); - await libXelisWallet?.close(); - libXelisWallet?.dispose(); - libXelisWallet = null; - await super.exit(); }); } @@ -511,6 +403,8 @@ extension XelisTableManagement on LibXelisWallet { await setTableState(state.copyWith(isGenerating: true)); try { + Logging.instance.i("Xelis: Generating large tables in background"); + final tablePath = await getPrecomputedTablesPath(); await x_wallet.updateTables( precomputedTablesPath: tablePath,