From 6e04f8e34da83dafb467537cc7ddd052f7344ce0 Mon Sep 17 00:00:00 2001 From: Tritonn204 Date: Wed, 19 Mar 2025 13:07:14 -0500 Subject: [PATCH 1/2] Xelis updates. configured Unix line endings repo-wide --- lib/pages/exchange_view/send_from_view.dart | 4 +- lib/pages/pinpad_views/lock_screen_view.dart | 4 +- .../sub_widgets/favorite_card.dart | 4 +- .../sub_widgets/wallet_list_item.dart | 4 +- .../my_stack_view/coin_wallets_table.dart | 4 +- lib/utilities/test_node_connection.dart | 3 + lib/wallets/wallet/impl/xelis_wallet.dart | 82 +++-------- .../wallet/intermediate/lib_xelis_wallet.dart | 131 ++++++++---------- lib/widgets/wallet_card.dart | 4 +- pubspec.lock | 46 +++--- 10 files changed, 118 insertions(+), 168 deletions(-) diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 59cf20a47..7e97017a3 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -35,7 +35,7 @@ import '../../wallets/crypto_currency/crypto_currency.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/models/tx_data.dart'; import '../../wallets/wallet/impl/firo_wallet.dart'; -import '../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../wallets/wallet/intermediate/external_wallet.dart'; import '../../widgets/background.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; @@ -277,7 +277,7 @@ class _SendFromCardState extends ConsumerState { // access to this screen but this is needed to get past an error that // would occur only to lead to another error which is why xmr/wow wallets // don't have access to this screen currently - if (wallet is LibMoneroWallet) { + if (wallet is ExternalWallet) { await wallet.init(); await wallet.open(); } diff --git a/lib/pages/pinpad_views/lock_screen_view.dart b/lib/pages/pinpad_views/lock_screen_view.dart index 5d630ba4f..c7d6bb254 100644 --- a/lib/pages/pinpad_views/lock_screen_view.dart +++ b/lib/pages/pinpad_views/lock_screen_view.dart @@ -29,7 +29,7 @@ import '../../utilities/show_loading.dart'; import '../../utilities/show_node_tor_settings_mismatch.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; -import '../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../wallets/wallet/intermediate/external_wallet.dart'; import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/custom_buttons/blue_text_button.dart'; @@ -119,7 +119,7 @@ class _LockscreenViewState extends ConsumerState { } final Future loadFuture; - if (wallet is LibMoneroWallet) { + if (wallet is ExternalWallet) { loadFuture = wallet.init().then((value) async => await (wallet).open()); } else { diff --git a/lib/pages/wallets_view/sub_widgets/favorite_card.dart b/lib/pages/wallets_view/sub_widgets/favorite_card.dart index 26e11624a..d9f730804 100644 --- a/lib/pages/wallets_view/sub_widgets/favorite_card.dart +++ b/lib/pages/wallets_view/sub_widgets/favorite_card.dart @@ -27,7 +27,7 @@ import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; import '../../../wallets/crypto_currency/coins/firo.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../wallets/wallet/intermediate/external_wallet.dart'; import '../../../widgets/coin_card.dart'; import '../../../widgets/conditional_parent.dart'; import '../../wallet_view/wallet_view.dart'; @@ -132,7 +132,7 @@ class _FavoriteCardState extends ConsumerState { } final Future loadFuture; - if (wallet is LibMoneroWallet) { + if (wallet is ExternalWallet) { loadFuture = wallet.init().then((value) async => await (wallet).open()); } else { diff --git a/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart b/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart index 767770ba9..938baac71 100644 --- a/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart +++ b/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart @@ -25,7 +25,7 @@ import '../../../utilities/show_node_tor_settings_mismatch.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; -import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../wallets/wallet/intermediate/external_wallet.dart'; import '../../../widgets/dialogs/tor_warning_dialog.dart'; import '../../../widgets/rounded_white_container.dart'; import '../../wallet_view/wallet_view.dart'; @@ -99,7 +99,7 @@ class WalletListItem extends ConsumerWidget { } final Future loadFuture; - if (wallet is LibMoneroWallet) { + if (wallet is ExternalWallet) { loadFuture = wallet.init().then((value) async => await (wallet).open()); } else { diff --git a/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart b/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart index 8da907ca3..aaf1d1402 100644 --- a/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart +++ b/lib/pages_desktop_specific/my_stack_view/coin_wallets_table.dart @@ -21,7 +21,7 @@ import '../../utilities/show_loading.dart'; import '../../utilities/show_node_tor_settings_mismatch.dart'; import '../../utilities/util.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; -import '../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../wallets/wallet/intermediate/external_wallet.dart'; import '../../widgets/rounded_container.dart'; import '../../widgets/wallet_info_row/wallet_info_row.dart'; import 'wallet_view/desktop_wallet_view.dart'; @@ -101,7 +101,7 @@ class CoinWalletsTable extends ConsumerWidget { } final Future loadFuture; - if (wallet is LibMoneroWallet) { + if (wallet is ExternalWallet) { loadFuture = wallet .init() .then((value) async => await (wallet).open()); diff --git a/lib/utilities/test_node_connection.dart b/lib/utilities/test_node_connection.dart index a211dd97d..7e8616ac2 100644 --- a/lib/utilities/test_node_connection.dart +++ b/lib/utilities/test_node_connection.dart @@ -305,12 +305,15 @@ Future testNodeConnection({ final daemon = xelis_sdk.DaemonClient( endPoint: "${formData.host!}:${formData.port!}", secureWebSocket: formData.useSSL ?? false, + timeout: 5000 ); daemon.connect(); final xelis_sdk.GetInfoResult networkInfo = await daemon.getInfo(); testPassed = networkInfo.height != null; + daemon.disconnect(); + Logging.instance.i( "Xelis testNodeConnection result: \"${networkInfo.toString()}\"", ); diff --git a/lib/wallets/wallet/impl/xelis_wallet.dart b/lib/wallets/wallet/impl/xelis_wallet.dart index 0bb95e8e8..466755bae 100644 --- a/lib/wallets/wallet/impl/xelis_wallet.dart +++ b/lib/wallets/wallet/impl/xelis_wallet.dart @@ -4,9 +4,9 @@ import 'dart:math'; import 'package:isar/isar.dart'; import 'package:mutex/mutex.dart'; -import 'package:stack_wallet_backup/generate_password.dart'; import 'package:xelis_dart_sdk/xelis_dart_sdk.dart' as xelis_sdk; import 'package:xelis_flutter/src/api/wallet.dart' as x_wallet; +import 'package:stack_wallet_backup/generate_password.dart'; import '../../../models/balance.dart'; import '../../../models/isar/models/blockchain_data/address.dart'; @@ -31,28 +31,6 @@ class XelisWallet extends LibXelisWallet { @override int get isarTransactionVersion => 2; - @override - Future init({bool? isRestore}) async { - Logging.instance.d("Xelis: init"); - - if (isRestore == true) { - await _restoreWallet(); - return await super.init(); - } - - final String? walletExists = await secureStorageInterface.read( - key: "${walletId}_wallet", - ); - - if (walletExists == null) { - await _createNewWallet(); - } - - await open(); - - return await super.init(); - } - Future _createNewWallet() async { final String password = generatePassword(); @@ -61,39 +39,24 @@ class XelisWallet extends LibXelisWallet { key: Wallet.mnemonicPassphraseKey(walletId: info.walletId), value: password, ); - - await secureStorageInterface.write( - key: '${walletId}_wallet', - value: 'true', - ); - - await secureStorageInterface.write( - key: '_${walletId}_needs_creation', - value: 'true', - ); } - Future _restoreWallet() async { - final String password = generatePassword(); - - await secureStorageInterface.write( - key: Wallet.mnemonicPassphraseKey(walletId: info.walletId), - value: password, - ); - - await secureStorageInterface.write( - key: '${walletId}_wallet', - value: 'true', - ); + @override + Future init({bool? isRestore}) async { + Logging.instance.d("Xelis: init"); - await secureStorageInterface.write( - key: '_${walletId}_needs_restoration', - value: 'true', - ); + if (isRestore == true) { + await super.init(); + return await open(openType: XelisWalletOpenType.restore); + } - if (libXelisWallet != null) { - await super.exit(); + final bool walletExists = await LibXelisWallet.checkWalletExists(walletId); + if (!walletExists) { + await _createNewWallet(); + await open(openType: XelisWalletOpenType.create); } + + return await super.init(); } @override @@ -507,20 +470,10 @@ class XelisWallet extends LibXelisWallet { try { checkInitialized(); - // Use default address if recipients list is empty final recipients = txData.recipients?.isNotEmpty == true ? txData.recipients! - : [ - ( - address: - 'xel:xz9574c80c4xegnvurazpmxhw5dlg2n0g9qm60uwgt75uqyx3pcsqzzra9m', - amount: Amount.zeroWith( - fractionDigits: cryptoCurrency.fractionDigits, - ), - isChange: false, - ), - ]; + : throw ArgumentError('Address cannot be empty.'); // in the future, support for multiple recipients will work. final asset = assetId ?? xelis_sdk.xelisAsset; @@ -596,7 +549,7 @@ class XelisWallet extends LibXelisWallet { final defaultDecimals = cryptoCurrency.fractionDigits; final defaultFee = BigInt.from(0); - // Use default address if recipients list is empty + // Use default address if recipients list is empty to ensure basic fee estimates are readily available final effectiveRecipients = recipients.isNotEmpty ? recipients @@ -816,6 +769,9 @@ class XelisWallet extends LibXelisWallet { @override Future handleOnline() async { + await updateChainHeight(); + await updateBalance(); + await updateTransactions(); GlobalEventBus.instance.fire( WalletSyncStatusChangedEvent( WalletSyncStatus.synced, diff --git a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart index 92178d93e..62876565b 100644 --- a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart @@ -32,6 +32,11 @@ enum XelisTableSize { } } +enum XelisWalletOpenType { + create, + restore +} + class XelisTableState { final bool isGenerating; final XelisTableSize currentSize; @@ -329,7 +334,7 @@ abstract class LibXelisWallet } @override - Future open() async { + Future open({XelisWalletOpenType? openType}) async { bool wasNull = false; if (libXelisWallet == null) { @@ -345,80 +350,66 @@ abstract class LibXelisWallet await LibXelisWallet._initMutex.protect(() async { try { - final needsCreation = await secureStorageInterface.read( - key: '_${walletId}_needs_creation', - ); - - final needsRestoration = await secureStorageInterface.read( - key: '_${walletId}_needs_restoration', - ); - libXelisWallet = await syncMutex.protect(() async { - if (needsCreation == 'true') { - 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(), - ); - - await secureStorageInterface.delete( - key: '_${walletId}_needs_creation', - ); - - return wallet; - } else if (needsRestoration == 'true') { - 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(), - ); - - await secureStorageInterface.delete( - key: '_${walletId}_needs_restoration', - ); - - return wallet; - } else { - 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, - ); + 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 (_) { - // Logging.instance.log( + // Logging.instance.e( // "Failed to open/create wallet: $e\n$s", - // level: LogLevel.Error, // ); rethrow; } diff --git a/lib/widgets/wallet_card.dart b/lib/widgets/wallet_card.dart index 4981dafaf..ed49e5ebb 100644 --- a/lib/widgets/wallet_card.dart +++ b/lib/widgets/wallet_card.dart @@ -28,7 +28,7 @@ import '../utilities/util.dart'; import '../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../wallets/wallet/impl/ethereum_wallet.dart'; import '../wallets/wallet/impl/sub_wallets/eth_token_wallet.dart'; -import '../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../wallets/wallet/intermediate/external_wallet.dart'; import '../wallets/wallet/wallet.dart'; import 'conditional_parent.dart'; import 'desktop/primary_button.dart'; @@ -111,7 +111,7 @@ class SimpleWalletCard extends ConsumerWidget { if (context.mounted) { final Future loadFuture; - if (wallet is LibMoneroWallet) { + if (wallet is ExternalWallet) { loadFuture = wallet.init().then((value) async => await (wallet).open()); } else { loadFuture = wallet.init(); diff --git a/pubspec.lock b/pubspec.lock index 5df33ec99..8bdf56e80 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -50,10 +50,10 @@ packages: dependency: transitive description: name: args - sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.0" async: dependency: "direct main" description: @@ -223,10 +223,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573" + sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" url: "https://pub.dev" source: hosted - version: "2.4.14" + version: "2.4.15" build_runner_core: dependency: transitive description: @@ -247,10 +247,10 @@ packages: dependency: transitive description: name: built_value - sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2" + sha256: ea90e81dc4a25a043d9bee692d20ed6d1c4a1662a28c03a96417446c093ed6b4 url: "https://pub.dev" source: hosted - version: "8.9.3" + version: "8.9.5" calendar_date_picker2: dependency: "direct main" description: @@ -412,10 +412,10 @@ packages: dependency: transitive description: name: coverage - sha256: "88b0fddbe4c92910fefc09cc0248f5e7f0cd23e450ded4c28f16ab8ee8f83268" + sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" cross_file: dependency: transitive description: @@ -750,10 +750,10 @@ packages: dependency: "direct main" description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" file: dependency: transitive description: @@ -897,10 +897,10 @@ packages: dependency: transitive description: name: flutter_rust_bridge - sha256: "3292ad6085552987b8b3b9a7e5805567f4013372d302736b702801acb001ee00" + sha256: "5a5c7a5deeef2cc2ffe6076a33b0429f4a20ceac22a397297aed2b1eb067e611" url: "https://pub.dev" source: hosted - version: "2.7.1" + version: "2.9.0" flutter_secure_storage: dependency: "direct main" description: @@ -1454,10 +1454,10 @@ packages: dependency: transitive description: name: package_config - sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67" + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.2.0" package_info_plus: dependency: "direct main" description: @@ -1502,10 +1502,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" + sha256: "0ca7359dad67fd7063cb2892ab0c0737b2daafd807cf1acecd62374c8fae6c12" url: "https://pub.dev" source: hosted - version: "2.2.15" + version: "2.2.16" path_provider_foundation: dependency: transitive description: @@ -1662,10 +1662,10 @@ packages: dependency: transitive description: name: pub_semver - sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd" + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" pubspec_parse: dependency: transitive description: @@ -1782,10 +1782,10 @@ packages: dependency: transitive description: name: shelf_web_socket - sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -1845,10 +1845,10 @@ packages: dependency: transitive description: name: source_maps - sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" url: "https://pub.dev" source: hosted - version: "0.10.12" + version: "0.10.13" source_span: dependency: transitive description: @@ -2339,7 +2339,7 @@ packages: description: path: "." ref: "v0.1.0" - resolved-ref: "966469f2660226c33a1de77d1c5efee5459a2d4e" + resolved-ref: c685c5d3550cca414ec30d4b61259761f129dda6 url: "https://github.com/Tritonn204/xelis_flutter_ffi.git" source: git version: "0.1.0" From 8f5d17d026549579a395180cf412ef9e4f1eb6ef Mon Sep 17 00:00:00 2001 From: Tritonn204 Date: Wed, 19 Mar 2025 16:31:50 -0500 Subject: [PATCH 2/2] close on restore for all ExternalWallet instances --- .../restore_wallet_view/restore_wallet_view.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 82aef0d60..972012c00 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -50,7 +50,7 @@ import '../../../wallets/isar/models/wallet_info.dart'; import '../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../wallets/wallet/impl/monero_wallet.dart'; import '../../../wallets/wallet/impl/wownero_wallet.dart'; -import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart'; +import '../../../wallets/wallet/intermediate/external_wallet.dart'; import '../../../wallets/wallet/impl/xelis_wallet.dart'; import '../../../wallets/wallet/supporting/epiccash_wallet_info_extension.dart'; import '../../../wallets/wallet/wallet.dart'; @@ -391,7 +391,7 @@ class _RestoreWalletViewState extends ConsumerState { await wallet.recover(isRescan: false); - if (wallet is LibMoneroWallet) { + if (wallet is ExternalWallet) { await wallet.exit(); }