What changed, and why it matters
This commit refactors how the Xelis wallet code keeps track of an open wallet. Previously, the wallet library internally cached wallets by their string ID and looked them up by that ID for every operation. Now, the wallet object itself is returned and stored directly, and most operations use that stored object instead of the ID. The change also removes duplicate-wallet checks and makes the interface constructor a constant. There is no direct evidence this fixes a known exploit, but it removes a class of bugs where the wrong wallet could be targeted if the ID-to-wallet mapping got out of sync.
Review the new `wallet!` assertions to ensure `wallet` is always set before use; consider making the non-null contract explicit through the type system or initialization checks. Verify that removing the duplicate-wallet guards does not allow accidental wallet overwrite or reuse of stale handles. Confirm the `const` interface implementation does not break stateful behavior elsewhere.
Security signals we found
Removed string-based wallet lookup cache in favor of direct opaque handle
Removed duplicate-wallet overwrite guards on create/open
Added null-check-based initialization guard (`wallet == null`) replacing map membership check
Added exception handling in daemon connection test to avoid crashes/leaks
Multiple call sites changed from `walletId` to `wallet!`, introducing potential runtime null-dereference if wallet not initialized
Evidence from the diff
The patch changes the Xelis wallet FFI/interface layer from a string-keyed in-memory cache (Map<String, x_wallet.XelisWallet>) to an opaque wallet handle (OpaqueXelisWallet) returned by createXelisWallet/openXelisWallet and held by the wallet class. LibXelisInterface methods now accept OpaqueXelisWallet instead of String walletId. The implementation removes walletInstanceExists, removes overwrite guards on create/open, and removes the lazy-initialized _xelisSeedSearch field. testDaemonConnection now catches exceptions and returns false instead of propagating. The interface class gains a const constructor. These are architectural/robustness changes rather than a targeted security patch.
Changed components
lib/wallets/wallet/impl/xelis_wallet.dartlib/wallets/wallet/intermediate/lib_xelis_wallet.dartlib/wl_gen/interfaces/lib_xelis_interface.darttool/wl_templates/XEL_lib_xelis_interface_impl.template.dartInspect captured patch +156 / −132
diff --git a/lib/wallets/wallet/impl/xelis_wallet.dart b/lib/wallets/wallet/impl/xelis_wallet.dart
index d36b831..9a4fd10 100644
--- a/lib/wallets/wallet/impl/xelis_wallet.dart
+++ b/lib/wallets/wallet/impl/xelis_wallet.dart
@@ -49,7 +49,7 @@ class XelisWallet extends LibXelisWallet {
invalidSeedLengthCheck(seedLength);
Logging.instance.i("Xelis: recovering wallet");
- await libXelis.createXelisWallet(
+ final wallet = await libXelis.createXelisWallet(
walletId,
name: name,
directory: directory,
@@ -65,6 +65,8 @@ class XelisWallet extends LibXelisWallet {
value: mnemonic,
);
+ this.wallet = wallet;
+
await _finishInit();
}
@@ -82,7 +84,7 @@ class XelisWallet extends LibXelisWallet {
value: password,
);
- await libXelis.createXelisWallet(
+ final wallet = await libXelis.createXelisWallet(
walletId,
name: name,
directory: directory,
@@ -92,12 +94,14 @@ class XelisWallet extends LibXelisWallet {
l1Low: tableState.currentSize.isLow,
);
- final mnemonic = await libXelis.getSeed(walletId);
+ final mnemonic = await libXelis.getSeed(wallet);
await secureStorageInterface.write(
key: Wallet.mnemonicKey(walletId: walletId),
value: mnemonic.trim(),
);
+ this.wallet = wallet;
+
await _finishInit();
}
@@ -112,7 +116,7 @@ class XelisWallet extends LibXelisWallet {
key: Wallet.mnemonicPassphraseKey(walletId: info.walletId),
);
- await libXelis.openXelisWallet(
+ wallet = await libXelis.openXelisWallet(
walletId,
name: name,
directory: directory,
@@ -136,7 +140,7 @@ class XelisWallet extends LibXelisWallet {
walletId: walletId,
derivationIndex: 0,
derivationPath: null,
- value: libXelis.getAddress(walletId),
+ value: libXelis.getAddress(wallet!),
publicKey: [],
type: AddressType.xelis,
subType: AddressSubType.receiving,
@@ -168,7 +172,7 @@ class XelisWallet extends LibXelisWallet {
walletId,
);
- if (!libXelis.walletInstanceExists(walletId)) {
+ if (wallet == null) {
if (isRestore == true) {
await _restoreWallet();
} else {
@@ -224,7 +228,7 @@ class XelisWallet extends LibXelisWallet {
@override
Future<bool> pingCheck() async {
try {
- await libXelis.getDaemonInfo(walletId);
+ await libXelis.getDaemonInfo(wallet!);
await handleOnline();
return true;
} catch (_) {
@@ -239,11 +243,11 @@ class XelisWallet extends LibXelisWallet {
Future<void> updateBalance({int? newBalance}) async {
await _balanceUpdateMutex.protect(() async {
try {
- if (await libXelis.hasXelisBalance(walletId)) {
+ if (await libXelis.hasXelisBalance(wallet!)) {
final BigInt xelBalance = newBalance != null
? BigInt.from(newBalance)
: await libXelis.getXelisBalanceRaw(
- walletId,
+ wallet!,
); // in the future, use getAssetBalances and handle each
final balance = Balance(
total: Amount(
@@ -274,7 +278,7 @@ class XelisWallet extends LibXelisWallet {
}
Future<int> _fetchChainHeight() async {
- final infoString = await libXelis.getDaemonInfo(walletId);
+ final infoString = await libXelis.getDaemonInfo(wallet!);
final Map<String, dynamic> nodeInfo = (json.decode(infoString) as Map)
.cast();
@@ -304,9 +308,9 @@ class XelisWallet extends LibXelisWallet {
@override
Future<void> updateNode() async {
try {
- final bool online = await libXelis.isOnline(walletId);
+ final bool online = await libXelis.isOnline(wallet!);
if (online == true) {
- await libXelis.offlineMode(walletId);
+ await libXelis.offlineMode(wallet!);
}
await super.connect();
} catch (e, s) {
@@ -333,7 +337,7 @@ class XelisWallet extends LibXelisWallet {
walletId: walletId,
derivationIndex: 0,
derivationPath: null,
- value: libXelis.getAddress(walletId),
+ value: libXelis.getAddress(wallet!),
publicKey: [],
type: AddressType.xelis,
subType: AddressSubType.receiving,
@@ -356,10 +360,10 @@ class XelisWallet extends LibXelisWallet {
firstBlock -= 10;
}
} else {
- await libXelis.rescan(walletId, topoheight: BigInt.from(pruningHeight));
+ await libXelis.rescan(wallet!, topoheight: BigInt.from(pruningHeight));
}
- final txList = objTransactions ?? (await libXelis.allHistory(walletId));
+ final txList = objTransactions ?? (await libXelis.allHistory(wallet!));
final List<TransactionV2> txns = [];
@@ -395,7 +399,7 @@ class XelisWallet extends LibXelisWallet {
txType = TransactionType.incoming;
final int decimals = await libXelis.getAssetDecimals(
- walletId,
+ wallet!,
asset: libXelis.xelisAsset,
);
@@ -418,7 +422,7 @@ class XelisWallet extends LibXelisWallet {
txType = TransactionType.outgoing;
final int decimals = await libXelis.getAssetDecimals(
- walletId,
+ wallet!,
asset: burn.asset,
);
@@ -460,7 +464,7 @@ class XelisWallet extends LibXelisWallet {
for (final transfer in incoming.transfers) {
final int decimals = await libXelis.getAssetDecimals(
- walletId,
+ wallet!,
asset: transfer.asset,
);
@@ -639,7 +643,7 @@ class XelisWallet extends LibXelisWallet {
);
// Check balance using raw method
- final xelBalance = await libXelis.getXelisBalanceRaw(walletId);
+ final xelBalance = await libXelis.getXelisBalanceRaw(wallet!);
final balance = Amount(
rawValue: xelBalance,
fractionDigits: cryptoCurrency.fractionDigits,
@@ -657,13 +661,13 @@ class XelisWallet extends LibXelisWallet {
// Check if we have enough for both transfers and fee
if (totalSendAmount + boostedFee > balance) {
final requiredAmt = await libXelis.formatCoin(
- walletId,
+ wallet!,
atomicAmount: (totalSendAmount + boostedFee).raw,
assetHash: asset,
);
final availableAmt = await libXelis.formatCoin(
- walletId,
+ wallet!,
atomicAmount: xelBalance,
assetHash: asset,
);
@@ -722,7 +726,7 @@ class XelisWallet extends LibXelisWallet {
try {
final amt = double.parse(
await libXelis.formatCoin(
- walletId,
+ wallet!,
atomicAmount: recipient.amount.raw,
assetHash: asset,
),
@@ -753,12 +757,9 @@ class XelisWallet extends LibXelisWallet {
}),
);
- final decimals = await libXelis.getAssetDecimals(
- walletId,
- asset: asset,
- );
+ final decimals = await libXelis.getAssetDecimals(wallet!, asset: asset);
final estimatedFee = double.parse(
- await libXelis.estimateFees(walletId, transfers: transfers),
+ await libXelis.estimateFees(wallet!, transfers: transfers),
);
final rawFee = (estimatedFee * pow(10, decimals)).round();
return Amount(
@@ -807,7 +808,7 @@ class XelisWallet extends LibXelisWallet {
final amt = double.parse(
await libXelis.formatCoin(
- walletId,
+ wallet!,
atomicAmount: sendAmount.raw,
assetHash: asset,
),
@@ -815,7 +816,7 @@ class XelisWallet extends LibXelisWallet {
// Create a transfer transaction
final txJson = await libXelis.createTransfersTransaction(
- walletId,
+ wallet!,
transfers: [
WrappedTransfer(
floatAmount: amt,
@@ -830,7 +831,7 @@ class XelisWallet extends LibXelisWallet {
final txHash = txMap['hash'] as String;
// Broadcast the transaction
- await libXelis.broadcastTransaction(walletId, txHash: txHash);
+ await libXelis.broadcastTransaction(wallet!, txHash: txHash);
return await updateSentCachedTxData(
txData: txData.copyWith(txid: txHash),
@@ -981,7 +982,7 @@ class XelisWallet extends LibXelisWallet {
Future<void> refresh({int? topoheight}) async {
await refreshMutex.protect(() async {
try {
- final bool online = await libXelis.isOnline(walletId);
+ final bool online = await libXelis.isOnline(wallet!);
if (online == true) {
await updateChainHeight(topoheight: topoheight);
await updateBalance();
diff --git a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart
index 4cec5e1..6b276c2 100644
--- a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart
+++ b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart
@@ -26,8 +26,10 @@ abstract class LibXelisWallet<T extends ElectrumCurrency>
int pruningHeight = 0;
+ OpaqueXelisWallet? wallet;
+
void checkInitialized() {
- if (!libXelis.walletInstanceExists(walletId)) {
+ if (wallet == null) {
throw StateError('libXelisWallet not initialized');
}
}
@@ -93,11 +95,11 @@ abstract class LibXelisWallet<T extends ElectrumCurrency>
final node = getCurrentNode();
try {
checkInitialized();
- _eventSubscription = libXelis.eventsStream(walletId).listen(handleEvent);
+ _eventSubscription = libXelis.eventsStream(wallet!).listen(handleEvent);
Logging.instance.i("Connecting to node: ${node.host}:${node.port}");
await libXelis.onlineMode(
- walletId,
+ wallet!,
daemonAddress: "${node.host}:${node.port}",
);
await super.refresh();
@@ -167,7 +169,9 @@ abstract class LibXelisWallet<T extends ElectrumCurrency>
await _eventSubscription?.cancel();
_eventSubscription = null;
- await libXelis.offlineMode(walletId);
+ if (wallet != null) {
+ await libXelis.offlineMode(wallet!);
+ }
await super.exit();
});
} finally {
diff --git a/lib/wl_gen/interfaces/lib_xelis_interface.dart b/lib/wl_gen/interfaces/lib_xelis_interface.dart
index 1fc28f8..ecf76a4 100644
--- a/lib/wl_gen/interfaces/lib_xelis_interface.dart
+++ b/lib/wl_gen/interfaces/lib_xelis_interface.dart
@@ -6,9 +6,9 @@ import '../../wallets/crypto_currency/crypto_currency.dart';
export '../generated/lib_xelis_interface_impl.dart';
abstract class LibXelisInterface {
- String get xelisAsset;
+ const LibXelisInterface();
- bool walletInstanceExists(String walletId);
+ String get xelisAsset;
Future<void> initRustLib();
@@ -22,19 +22,22 @@ abstract class LibXelisInterface {
bool validateSeedWord(String word);
- Stream<Event> eventsStream(String walletId);
+ Stream<Event> eventsStream(OpaqueXelisWallet wallet);
- Future<void> onlineMode(String walletId, {required String daemonAddress});
- Future<void> offlineMode(String walletId);
+ Future<void> onlineMode(
+ OpaqueXelisWallet wallet, {
+ required String daemonAddress,
+ });
+ Future<void> offlineMode(OpaqueXelisWallet wallet);
Future<void> updateTables({
required String precomputedTablesPath,
required bool l1Low,
});
- Future<String> getSeed(String walletId);
+ Future<String> getSeed(OpaqueXelisWallet wallet);
- Future<void> createXelisWallet(
+ Future<OpaqueXelisWallet> createXelisWallet(
String walletId, {
required String name,
required String directory,
@@ -46,7 +49,7 @@ abstract class LibXelisInterface {
bool? l1Low,
});
- Future<void> openXelisWallet(
+ Future<OpaqueXelisWallet> openXelisWallet(
String walletId, {
required String name,
required String directory,
@@ -56,45 +59,58 @@ abstract class LibXelisInterface {
bool? l1Low,
});
- String getAddress(String walletId);
+ String getAddress(OpaqueXelisWallet wallet);
- Future<String> getDaemonInfo(String walletId);
+ Future<String> getDaemonInfo(OpaqueXelisWallet wallet);
- Future<bool> isOnline(String walletId);
+ Future<bool> isOnline(OpaqueXelisWallet wallet);
- Future<void> rescan(String walletId, {required BigInt topoheight});
+ Future<void> rescan(OpaqueXelisWallet wallet, {required BigInt topoheight});
- Future<List<TransactionEntryWrapper>> allHistory(String walletId);
+ Future<List<TransactionEntryWrapper>> allHistory(OpaqueXelisWallet wallet);
- Future<void> broadcastTransaction(String walletId, {required String txHash});
+ Future<void> broadcastTransaction(
+ OpaqueXelisWallet wallet, {
+ required String txHash,
+ });
Future<String> estimateFees(
- String walletId, {
+ OpaqueXelisWallet wallet, {
required List<WrappedTransfer> transfers,
});
Future<String> createTransfersTransaction(
- String walletId, {
+ OpaqueXelisWallet wallet, {
required List<WrappedTransfer> transfers,
});
Future<String> formatCoin(
- String walletId, {
+ OpaqueXelisWallet wallet, {
required BigInt atomicAmount,
String? assetHash,
});
- Future<int> getAssetDecimals(String walletId, {required String asset});
+ Future<int> getAssetDecimals(
+ OpaqueXelisWallet wallet, {
+ required String asset,
+ });
- Future<BigInt> getXelisBalanceRaw(String walletId);
+ Future<BigInt> getXelisBalanceRaw(OpaqueXelisWallet wallet);
- Future<bool> hasXelisBalance(String walletId);
+ Future<bool> hasXelisBalance(OpaqueXelisWallet wallet);
Future<bool> testDaemonConnection(String endPoint, bool useSSL);
}
// =============================================================================
// ============== stupid =======================================================
+
+final class OpaqueXelisWallet {
+ final Object _value;
+ const OpaqueXelisWallet(this._value);
+ T get<T>() => _value as T;
+}
+
class WrappedTransfer {
final double floatAmount;
final String strAddress;
diff --git a/tool/wl_templates/XEL_lib_xelis_interface_impl.template.dart b/tool/wl_templates/XEL_lib_xelis_interface_impl.template.dart
index 5380ddf..75941a3 100644
--- a/tool/wl_templates/XEL_lib_xelis_interface_impl.template.dart
+++ b/tool/wl_templates/XEL_lib_xelis_interface_impl.template.dart
@@ -24,17 +24,18 @@ LibXelisInterface _getInterface() => throw Exception("XEL not enabled!");
//END_OFF
//ON
-LibXelisInterface _getInterface() => _LibXelisInterfaceImpl();
+LibXelisInterface _getInterface() => const _LibXelisInterfaceImpl();
+
+extension _OpaqueXelisWalletExt on OpaqueXelisWallet {
+ x_wallet.XelisWallet get actual => get();
+}
final class _LibXelisInterfaceImpl extends LibXelisInterface {
- final Map<String, x_wallet.XelisWallet> _wallets = {};
+ const _LibXelisInterfaceImpl();
@override
String get xelisAsset => xelis_sdk.xelisAsset;
- @override
- bool walletInstanceExists(String walletId) => _wallets[walletId] != null;
-
@override
Future<void> initRustLib() => xelis_rust.RustLib.init();
@@ -98,19 +99,16 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
bool isAddressValid({required String address}) =>
x_utils.isAddressValid(strAddress: address);
- x_seed.SearchEngine? _xelisSeedSearch;
@override
bool validateSeedWord(String word) {
- _xelisSeedSearch ??= x_seed.SearchEngine.init(
+ return x_seed.SearchEngine.init(
languageIndex: BigInt.from(0),
- );
-
- return _xelisSeedSearch!.search(query: word).isNotEmpty;
+ ).search(query: word).isNotEmpty;
}
@override
- Stream<Event> eventsStream(String walletId) async* {
- final rawEventStream = _wallets[walletId]!.eventsStream();
+ Stream<Event> eventsStream(OpaqueXelisWallet wallet) async* {
+ final rawEventStream = wallet.actual.eventsStream();
await for (final rawData in rawEventStream) {
final json = jsonDecode(rawData);
@@ -166,12 +164,14 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
}
@override
- Future<void> onlineMode(String walletId, {required String daemonAddress}) =>
- _wallets[walletId]!.onlineMode(daemonAddress: daemonAddress);
+ Future<void> onlineMode(
+ OpaqueXelisWallet wallet, {
+ required String daemonAddress,
+ }) => wallet.actual.onlineMode(daemonAddress: daemonAddress);
@override
- Future<void> offlineMode(String walletId) =>
- _wallets[walletId]?.offlineMode() ?? Future.value();
+ Future<void> offlineMode(OpaqueXelisWallet wallet) =>
+ wallet.actual.offlineMode();
@override
Future<void> updateTables({
@@ -183,10 +183,10 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
);
@override
- Future<String> getSeed(String walletId) => _wallets[walletId]!.getSeed();
+ Future<String> getSeed(OpaqueXelisWallet wallet) => wallet.actual.getSeed();
@override
- Future<void> createXelisWallet(
+ Future<OpaqueXelisWallet> createXelisWallet(
String walletId, {
required String name,
required String directory,
@@ -197,13 +197,7 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
String? precomputedTablesPath,
bool? l1Low,
}) async {
- if (walletInstanceExists(walletId)) {
- throw Exception(
- "Attempted overwrite of existing wallet in cache on create",
- );
- }
-
- _wallets[walletId] = await x_wallet.createXelisWallet(
+ final wallet = await x_wallet.createXelisWallet(
name: name,
directory: directory,
password: password,
@@ -213,10 +207,12 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
precomputedTablesPath: precomputedTablesPath,
l1Low: l1Low,
);
+
+ return OpaqueXelisWallet(wallet);
}
@override
- Future<void> openXelisWallet(
+ Future<OpaqueXelisWallet> openXelisWallet(
String walletId, {
required String name,
required String directory,
@@ -225,13 +221,7 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
String? precomputedTablesPath,
bool? l1Low,
}) async {
- if (walletInstanceExists(walletId)) {
- throw Exception(
- "Attempted overwrite of existing wallet in cache on open",
- );
- }
-
- _wallets[walletId] = await x_wallet.openXelisWallet(
+ final wallet = await x_wallet.openXelisWallet(
name: name,
directory: directory,
password: password,
@@ -239,46 +229,49 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
precomputedTablesPath: precomputedTablesPath,
l1Low: l1Low,
);
+
+ return OpaqueXelisWallet(wallet);
}
@override
- String getAddress(String walletId) => _wallets[walletId]!.getAddressStr();
+ String getAddress(OpaqueXelisWallet wallet) => wallet.actual.getAddressStr();
@override
- Future<String> getDaemonInfo(String walletId) =>
- _wallets[walletId]!.getDaemonInfo();
+ Future<String> getDaemonInfo(OpaqueXelisWallet wallet) =>
+ wallet.actual.getDaemonInfo();
@override
- Future<bool> isOnline(String walletId) => _wallets[walletId]!.isOnline();
+ Future<bool> isOnline(OpaqueXelisWallet wallet) => wallet.actual.isOnline();
@override
- Future<void> rescan(String walletId, {required BigInt topoheight}) =>
- _wallets[walletId]!.rescan(topoheight: topoheight);
+ Future<void> rescan(OpaqueXelisWallet wallet, {required BigInt topoheight}) =>
+ wallet.actual.rescan(topoheight: topoheight);
@override
- Future<List<TransactionEntryWrapper>> allHistory(String walletId) async =>
- (await _wallets[walletId]!.allHistory()).map((e) {
- final tx = _checkDecodeJsonStringTxEntry(e);
- return TransactionEntryWrapper(
- tx,
- entryType: _entryTypeConversion(tx.txEntryType),
- hash: tx.hash,
- timestamp: tx.timestamp,
- topoheight: tx.topoheight,
- );
- }).toList();
+ Future<List<TransactionEntryWrapper>> allHistory(
+ OpaqueXelisWallet wallet,
+ ) async => (await wallet.actual.allHistory()).map((e) {
+ final tx = _checkDecodeJsonStringTxEntry(e);
+ return TransactionEntryWrapper(
+ tx,
+ entryType: _entryTypeConversion(tx.txEntryType),
+ hash: tx.hash,
+ timestamp: tx.timestamp,
+ topoheight: tx.topoheight,
+ );
+ }).toList();
@override
Future<void> broadcastTransaction(
- String walletId, {
+ OpaqueXelisWallet wallet, {
required String txHash,
- }) => _wallets[walletId]!.broadcastTransaction(txHash: txHash);
+ }) => wallet.actual.broadcastTransaction(txHash: txHash);
@override
Future<String> createTransfersTransaction(
- String walletId, {
+ OpaqueXelisWallet wallet, {
required List<WrappedTransfer> transfers,
- }) => _wallets[walletId]!.createTransfersTransaction(
+ }) => wallet.actual.createTransfersTransaction(
transfers: transfers
.map(
(e) => x_wallet.Transfer(
@@ -293,9 +286,9 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
@override
Future<String> estimateFees(
- String walletId, {
+ OpaqueXelisWallet wallet, {
required List<WrappedTransfer> transfers,
- }) => _wallets[walletId]!.estimateFees(
+ }) => wallet.actual.estimateFees(
transfers: transfers
.map(
(e) => x_wallet.Transfer(
@@ -310,42 +303,52 @@ final class _LibXelisInterfaceImpl extends LibXelisInterface {
@override
Future<String> formatCoin(
- String walletId, {
+ OpaqueXelisWallet wallet, {
required BigInt atomicAmount,
String? assetHash,
- }) => _wallets[walletId]!.formatCoin(
+ }) => wallet.actual.formatCoin(
atomicAmount: atomicAmount,
assetHash: assetHash,
);
@override
- Future<int> getAssetDecimals(String walletId, {required String asset}) =>
- _wallets[walletId]!.getAssetDecimals(asset: asset);
+ Future<int> getAssetDecimals(
+ OpaqueXelisWallet wallet, {
+ required String asset,
+ }) => wallet.actual.getAssetDecimals(asset: asset);
@override
- Future<BigInt> getXelisBalanceRaw(String walletId) =>
- _wallets[walletId]!.getXelisBalanceRaw();
+ Future<BigInt> getXelisBalanceRaw(OpaqueXelisWallet wallet) =>
+ wallet.actual.getXelisBalanceRaw();
@override
- Future<bool> hasXelisBalance(String walletId) =>
- _wallets[walletId]!.hasXelisBalance();
+ Future<bool> hasXelisBalance(OpaqueXelisWallet wallet) =>
+ wallet.actual.hasXelisBalance();
@override
Future<bool> testDaemonConnection(String endPoint, bool useSSL) async {
- final daemon = xelis_sdk.DaemonClient(
- endPoint: endPoint,
- secureWebSocket: useSSL,
- timeout: 5000,
- );
- daemon.connect();
- final xelis_sdk.GetInfoResult networkInfo = await daemon.getInfo();
- daemon.disconnect();
-
- Logging.instance.i(
- "Xelis testNodeConnection result: \"${networkInfo.toString()}\"",
- );
+ try {
+ final daemon = xelis_sdk.DaemonClient(
+ endPoint: endPoint,
+ secureWebSocket: useSSL,
+ timeout: 5000,
+ );
+ daemon.connect();
+ final xelis_sdk.GetInfoResult networkInfo = await daemon.getInfo();
+ daemon.disconnect();
- return networkInfo.height != null;
+ Logging.instance.i(
+ "Xelis testNodeConnection result: \"${networkInfo.toString()}\"",
+ );
+ return true;
+ } catch (e, s) {
+ Logging.instance.w(
+ "xelis daemon connection test failed, returning false.",
+ error: e,
+ stackTrace: s,
+ );
+ return false;
+ }
}
}
Why this scored 32/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.