What changed, and why it matters
This commit refactors how the Monero and Wownero wallet code passes wallet objects around. Previously, many functions looked up a live wallet instance using only a wallet ID string, which could lead to the wrong wallet being used or a missing wallet being treated as present. The change makes wallet code explicitly carry and check a typed wallet object before calling sensitive operations such as viewing balances, creating transactions, and sending funds. It is a defensive fix that reduces the risk of accidental cross-wallet operations or crashes, but the commit message does not frame it as a security patch.
Treat this as a hardening/refactoring change rather than an active vulnerability fix. Review the new null-handling paths to ensure no operation silently skips safety steps when `wallet` is null, and verify that `WrappedWallet` cannot be confused between different wallet IDs. Continue normal testing of Monero/Wownero create, restore, send, and churn flows.
Security signals we found
Removes global wallet lookup by string ID, reducing risk of operating on the wrong wallet instance
Adds explicit null checks before balance, transaction, and send operations
Changes sensitive methods (createTx, commitTx, getKeys, getSeed) to require a concrete wallet object
Removes callback-based seed extraction in favor of direct typed access
No explicit security framing or CVE references in commit message
Evidence from the diff
The patch replaces the walletInstanceExists(walletId) / _wallets[walletId] pattern in the cs_monero interface with an explicit WrappedWallet? wallet field held by LibMoneroWallet. All cs_monero API calls now receive a WrappedWallet object instead of a String walletId. Callers must check wallet != null before invoking balance, transaction, sync, listener, and send operations. The template implementation removes the shared _wallets map and returns WrappedWallet from loadWallet, getCreatedWallet, getRestoredWallet, and getRestoredFromViewKeyWallet. Several call sites add null guards, and getCreatedWallet no longer uses a callback to return the seed/height; instead callers read them via getSeed(wallet) and getRefreshFromBlockHeight(wallet).
Changed components
lib/wallets/wallet/intermediate/lib_monero_wallet.dartlib/wallets/wallet/impl/monero_wallet.dartlib/wallets/wallet/impl/wownero_wallet.dartlib/wl_gen/interfaces/cs_monero_interface.darttool/wl_templates/XMR_cs_monero_interface_impl.template.dartlib/services/churning_service.dartlib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dartInspect captured patch +309 / −272
diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart
index 47ce7d2..f6f6b15 100644
--- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart
+++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart
@@ -5,11 +5,13 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../notifications/show_flush_bar.dart';
import '../../../../providers/db/main_db_provider.dart';
+import '../../../../providers/global/wallets_provider.dart';
import '../../../../themes/stack_colors.dart';
import '../../../../utilities/constants.dart';
import '../../../../utilities/text_styles.dart';
import '../../../../utilities/util.dart';
import '../../../../wallets/isar/providers/wallet_info_provider.dart';
+import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../../widgets/background.dart';
import '../../../../widgets/conditional_parent.dart';
import '../../../../widgets/custom_buttons/app_bar_icon_button.dart';
@@ -53,7 +55,11 @@ class _EditRefreshHeightViewState extends ConsumerState<EditRefreshHeightView> {
newRestoreHeight: newHeight,
isar: ref.read(mainDBProvider).isar,
);
- csMonero.setRefreshFromBlockHeight(widget.walletId, newHeight);
+ final wallet =
+ ref.read(pWallets).getWallet(widget.walletId) as LibMoneroWallet?;
+ if (wallet?.wallet != null) {
+ csMonero.setRefreshFromBlockHeight(wallet!.wallet!, newHeight);
+ }
} else {
errMessage = "Invalid height: ${_controller.text}";
}
@@ -89,8 +95,19 @@ class _EditRefreshHeightViewState extends ConsumerState<EditRefreshHeightView> {
@override
void initState() {
super.initState();
- _controller = TextEditingController()
- ..text = csMonero.getRefreshFromBlockHeight(widget.walletId).toString();
+ _controller = TextEditingController();
+ final wallet =
+ ref.read(pWallets).getWallet(widget.walletId) as LibMoneroWallet?;
+ if (wallet?.wallet != null) {
+ _controller.text = csMonero
+ .getRefreshFromBlockHeight(wallet!.wallet!)
+ .toString();
+ } else {
+ _controller.text = ref
+ .read(pWalletInfo(widget.walletId))
+ .restoreHeight
+ .toString();
+ }
}
@override
diff --git a/lib/services/churning_service.dart b/lib/services/churning_service.dart
index 1e18850..b1449fd 100644
--- a/lib/services/churning_service.dart
+++ b/lib/services/churning_service.dart
@@ -32,8 +32,8 @@ class ChurningService extends ChangeNotifier {
Object? lastSeenError;
bool _canChurn() {
- if (csMonero.walletInstanceExists(walletId) &&
- csMonero.getUnlockedBalance(walletId, accountIndex: kAccount)! >
+ if (wallet.wallet != null &&
+ csMonero.getUnlockedBalance(wallet.wallet!, accountIndex: kAccount)! >
BigInt.zero) {
return true;
} else {
@@ -48,7 +48,9 @@ class ChurningService extends ChangeNotifier {
return;
}
- final outputs = await csMonero.getOutputs(walletId, refresh: true);
+ final outputs = wallet.wallet == null
+ ? <CsOutput>[]
+ : await csMonero.getOutputs(wallet.wallet!, refresh: true);
final required = wallet.cryptoCurrency.minConfirms;
int lowestNumberOfConfirms = required;
@@ -184,7 +186,7 @@ class ChurningService extends ChangeNotifier {
Future<void> _churnTxSimple() async {
final address = csMonero.getAddress(
- walletId,
+ wallet.wallet!,
accountIndex: kAccount,
addressIndex: 0,
);
@@ -192,7 +194,7 @@ class ChurningService extends ChangeNotifier {
final height = await wallet.chainHeight;
final pending = await csMonero.createTx(
- walletId,
+ wallet.wallet!,
output: CsRecipient(
address,
BigInt.zero, // Doesn't matter if `sweep` is true
@@ -204,6 +206,6 @@ class ChurningService extends ChangeNotifier {
currentHeight: height,
);
- await csMonero.commitTx(walletId, pending);
+ await csMonero.commitTx(wallet.wallet!, pending);
}
}
diff --git a/lib/wallets/wallet/impl/monero_wallet.dart b/lib/wallets/wallet/impl/monero_wallet.dart
index e250192..876bec9 100644
--- a/lib/wallets/wallet/impl/monero_wallet.dart
+++ b/lib/wallets/wallet/impl/monero_wallet.dart
@@ -4,6 +4,8 @@ import 'package:compat/compat.dart' as lib_monero_compat;
import '../../../utilities/amount/amount.dart';
import '../../../wl_gen/interfaces/cs_monero_interface.dart';
+import '../../../wl_gen/interfaces/cs_salvium_interface.dart'
+ show WrappedWallet;
import '../../crypto_currency/crypto_currency.dart';
import '../intermediate/lib_monero_wallet.dart';
@@ -13,8 +15,7 @@ class MoneroWallet extends LibMoneroWallet {
@override
Future<Amount> estimateFeeFor(Amount amount, BigInt feeRate) async {
- if (!csMonero.walletInstanceExists(walletId) ||
- syncStatus is! lib_monero_compat.SyncedSyncStatus) {
+ if (wallet == null || syncStatus is! lib_monero_compat.SyncedSyncStatus) {
return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits);
}
@@ -23,7 +24,7 @@ class MoneroWallet extends LibMoneroWallet {
approximateFee = await csMonero.estimateFee(
feeRate.toInt(),
amount.raw,
- walletId: walletId,
+ wallet: wallet!,
);
});
@@ -38,33 +39,32 @@ class MoneroWallet extends LibMoneroWallet {
csMonero.walletExists(path, csCoin: CsCoin.monero);
@override
- Future<void> loadWallet({required String path, required String password}) =>
- csMonero.loadWallet(
- walletId,
- path: path,
- password: password,
- csCoin: CsCoin.monero,
- );
+ Future<WrappedWallet> loadWallet({
+ required String path,
+ required String password,
+ }) => csMonero.loadWallet(
+ walletId,
+ path: path,
+ password: password,
+ csCoin: CsCoin.monero,
+ );
@override
- Future<void> getCreatedWallet({
+ Future<WrappedWallet> getCreatedWallet({
required String path,
required String password,
required int wordCount,
required String seedOffset,
- required final void Function(int refreshFromBlockHeight, String seed)
- onCreated,
}) => csMonero.getCreatedWallet(
csCoin: CsCoin.monero,
path: path,
password: password,
wordCount: wordCount,
seedOffset: seedOffset,
- onCreated: onCreated,
);
@override
- Future<void> getRestoredWallet({
+ Future<WrappedWallet> getRestoredWallet({
required String path,
required String password,
required String mnemonic,
@@ -81,7 +81,7 @@ class MoneroWallet extends LibMoneroWallet {
);
@override
- Future<void> getRestoredFromViewKeyWallet({
+ Future<WrappedWallet> getRestoredFromViewKeyWallet({
required String path,
required String password,
required String address,
diff --git a/lib/wallets/wallet/impl/wownero_wallet.dart b/lib/wallets/wallet/impl/wownero_wallet.dart
index 5605971..691f601 100644
--- a/lib/wallets/wallet/impl/wownero_wallet.dart
+++ b/lib/wallets/wallet/impl/wownero_wallet.dart
@@ -6,6 +6,8 @@ import '../../../models/isar/models/blockchain_data/address.dart';
import '../../../utilities/amount/amount.dart';
import '../../../utilities/enums/fee_rate_type_enum.dart';
import '../../../wl_gen/interfaces/cs_monero_interface.dart';
+import '../../../wl_gen/interfaces/cs_salvium_interface.dart'
+ show WrappedWallet;
import '../../crypto_currency/crypto_currency.dart';
import '../../models/tx_data.dart';
import '../intermediate/lib_monero_wallet.dart';
@@ -16,8 +18,7 @@ class WowneroWallet extends LibMoneroWallet {
@override
Future<Amount> estimateFeeFor(Amount amount, BigInt feeRate) async {
- if (!csMonero.walletInstanceExists(walletId) ||
- syncStatus is! lib_monero_compat.SyncedSyncStatus) {
+ if (wallet == null || syncStatus is! lib_monero_compat.SyncedSyncStatus) {
return Amount.zeroWith(fractionDigits: cryptoCurrency.fractionDigits);
}
@@ -68,7 +69,7 @@ class WowneroWallet extends LibMoneroWallet {
approximateFee = await csMonero.estimateFee(
feeRate.toInt(),
amount.raw,
- walletId: walletId,
+ wallet: wallet!,
);
}
}
@@ -89,33 +90,32 @@ class WowneroWallet extends LibMoneroWallet {
csMonero.walletExists(path, csCoin: CsCoin.wownero);
@override
- Future<void> loadWallet({required String path, required String password}) =>
- csMonero.loadWallet(
- walletId,
- path: path,
- password: password,
- csCoin: CsCoin.wownero,
- );
+ Future<WrappedWallet> loadWallet({
+ required String path,
+ required String password,
+ }) => csMonero.loadWallet(
+ walletId,
+ path: path,
+ password: password,
+ csCoin: CsCoin.wownero,
+ );
@override
- Future<void> getCreatedWallet({
+ Future<WrappedWallet> getCreatedWallet({
required String path,
required String password,
required int wordCount,
required String seedOffset,
- required final void Function(int refreshFromBlockHeight, String seed)
- onCreated,
}) => csMonero.getCreatedWallet(
csCoin: CsCoin.wownero,
path: path,
password: password,
wordCount: wordCount,
seedOffset: seedOffset,
- onCreated: onCreated,
);
@override
- Future<void> getRestoredWallet({
+ Future<WrappedWallet> getRestoredWallet({
required String path,
required String password,
required String mnemonic,
@@ -132,7 +132,7 @@ class WowneroWallet extends LibMoneroWallet {
);
@override
- Future<void> getRestoredFromViewKeyWallet({
+ Future<WrappedWallet> getRestoredFromViewKeyWallet({
required String path,
required String password,
required String address,
diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart
index e0f1763..9f88a62 100644
--- a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart
+++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart
@@ -35,6 +35,7 @@ import '../../../utilities/enums/fee_rate_type_enum.dart';
import '../../../utilities/logger.dart';
import '../../../utilities/stack_file_system.dart';
import '../../../wl_gen/interfaces/cs_monero_interface.dart';
+import '../../../wl_gen/interfaces/cs_salvium_interface.dart';
import '../../crypto_currency/intermediate/cryptonote_currency.dart';
import '../../isar/models/wallet_info.dart';
import '../../models/tx_data.dart';
@@ -50,6 +51,8 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
@override
int get isarTransactionVersion => 2;
+ WrappedWallet? wallet;
+
LibMoneroWallet(super.currency, this.compatType) {
final bus = GlobalEventBus.instance;
@@ -135,18 +138,19 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
int currentKnownChainHeight = 0;
double highestPercentCached = 0;
- Future<void> loadWallet({required String path, required String password});
+ Future<WrappedWallet> loadWallet({
+ required String path,
+ required String password,
+ });
- Future<void> getCreatedWallet({
+ Future<WrappedWallet> getCreatedWallet({
required String path,
required String password,
required int wordCount,
required String seedOffset,
- required final void Function(int refreshFromBlockHeight, String seed)
- onCreated,
});
- Future<void> getRestoredWallet({
+ Future<WrappedWallet> getRestoredWallet({
required String path,
required String password,
required String mnemonic,
@@ -154,7 +158,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
int height = 0,
});
- Future<void> getRestoredFromViewKeyWallet({
+ Future<WrappedWallet> getRestoredFromViewKeyWallet({
required String path,
required String password,
required String address,
@@ -167,17 +171,16 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
bool walletExists(String path);
String getTxKeyFor({required String txid}) {
- if (!csMonero.walletInstanceExists(walletId)) {
+ if (wallet == null) {
throw Exception("Cannot get tx key in uninitialized libMoneroWallet");
}
- return csMonero.getTxKey(walletId, txid);
+ return csMonero.getTxKey(wallet!, txid);
}
void _setListener() {
- if (csMonero.walletInstanceExists(walletId) &&
- !csMonero.hasListeners(walletId)) {
+ if (wallet != null && !csMonero.hasListeners(wallet!)) {
csMonero.addListener(
- walletId,
+ wallet!,
CsWalletListener(
onSyncingUpdate: onSyncingUpdate,
onNewBlock: onNewBlock,
@@ -194,7 +197,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
Future<void> open() async {
bool wasNull = false;
- if (!csMonero.walletInstanceExists(walletId)) {
+ if (wallet == null) {
wasNull = true;
// libMoneroWalletT?.close();
final path = await pathForWallet(name: walletId, type: compatType);
@@ -208,7 +211,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
throw Exception("Password not found $e, $s");
}
- await loadWallet(path: path, password: password);
+ wallet = await loadWallet(path: path, password: password);
_setListener();
@@ -230,15 +233,15 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
if (wasNull) {
try {
_setSyncStatus(lib_monero_compat.ConnectingSyncStatus());
- csMonero.startSyncing(walletId);
+ csMonero.startSyncing(wallet!);
} catch (_) {
_setSyncStatus(lib_monero_compat.FailedSyncStatus());
// TODO log
}
}
_setListener();
- csMonero.startListeners(walletId);
- csMonero.startAutoSaving(walletId);
+ csMonero.startListeners(wallet!);
+ csMonero.startAutoSaving(wallet!);
unawaited(refresh());
}
@@ -263,12 +266,12 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
appRoot: appRoot,
);
}
- await csMonero.save(walletId);
+ await csMonero.save(wallet!);
}
Address addressFor({required int index, int account = 0}) {
final address = csMonero.getAddress(
- walletId,
+ wallet!,
accountIndex: account,
addressIndex: index,
);
@@ -292,17 +295,16 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
Future<CWKeyData?> getKeys() async {
final oldInfo = getLibMoneroWalletInfo(walletId);
- if (!csMonero.walletInstanceExists(walletId) ||
- (oldInfo != null && oldInfo.name != walletId)) {
+ if (wallet == null || (oldInfo != null && oldInfo.name != walletId)) {
return null;
}
try {
return CWKeyData(
walletId: walletId,
- publicViewKey: csMonero.getPublicViewKey(walletId),
- privateViewKey: csMonero.getPrivateViewKey(walletId),
- publicSpendKey: csMonero.getPublicSpendKey(walletId),
- privateSpendKey: csMonero.getPrivateSpendKey(walletId),
+ publicViewKey: csMonero.getPublicViewKey(wallet!),
+ privateViewKey: csMonero.getPrivateViewKey(wallet!),
+ publicSpendKey: csMonero.getPublicSpendKey(wallet!),
+ privateSpendKey: csMonero.getPrivateSpendKey(wallet!),
);
} catch (e, s) {
Logging.instance.f("getKeys failed: ", error: e, stackTrace: s);
@@ -327,11 +329,8 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
} catch (e, s) {
throw Exception("Password not found $e, $s");
}
- await loadWallet(path: path, password: password);
- return (
- csMonero.getAddress(walletId),
- csMonero.getPrivateViewKey(walletId),
- );
+ wallet = await loadWallet(path: path, password: password);
+ return (csMonero.getAddress(wallet!), csMonero.getPrivateViewKey(wallet!));
}
@override
@@ -348,22 +347,15 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
value: password,
);
- late final int refreshFromBlockHeight;
- late final String seedPhrase;
-
- await getCreatedWallet(
+ final wallet = await getCreatedWallet(
path: path,
password: password,
wordCount: wordCount,
seedOffset: "", // default for non restored wallets for now
- onCreated: (height, seed) {
- refreshFromBlockHeight = height;
- seedPhrase = seed;
- },
);
await info.updateRestoreHeight(
- newRestoreHeight: refreshFromBlockHeight,
+ newRestoreHeight: csMonero.getRefreshFromBlockHeight(wallet),
isar: mainDB.isar,
);
@@ -371,7 +363,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
// before wallet.init() is called
await secureStorageInterface.write(
key: Wallet.mnemonicKey(walletId: walletId),
- value: seedPhrase,
+ value: csMonero.getSeed(wallet),
);
await secureStorageInterface.write(
key: Wallet.mnemonicPassphraseKey(walletId: walletId),
@@ -394,8 +386,8 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
await mainDB.deleteWalletBlockchainData(walletId);
highestPercentCached = 0;
- unawaited(csMonero.rescanBlockchain(walletId));
- csMonero.startSyncing(walletId);
+ unawaited(csMonero.rescanBlockchain(wallet!));
+ csMonero.startSyncing(wallet!);
// unawaited(save());
});
unawaited(refresh());
@@ -433,11 +425,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
value: password,
);
- if (!csMonero.walletInstanceExists(walletId)) {
- await exit();
- }
-
- await getRestoredWallet(
+ final wallet = await getRestoredWallet(
path: path,
password: password,
mnemonic: mnemonic,
@@ -445,6 +433,12 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
seedOffset: seedOffset,
);
+ if (this.wallet != null) {
+ await exit();
+ }
+
+ this.wallet = wallet;
+
_setListener();
final newReceivingAddress =
@@ -453,7 +447,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
walletId: walletId,
derivationIndex: 0,
derivationPath: null,
- value: csMonero.getAddress(walletId),
+ value: csMonero.getAddress(this.wallet!),
publicKey: [],
type: AddressType.cryptonote,
subType: AddressSubType.receiving,
@@ -472,12 +466,12 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
_setListener();
// libMoneroWallet?.setRecoveringFromSeed(isRecovery: true);
- unawaited(csMonero.rescanBlockchain(walletId));
- csMonero.startSyncing(walletId);
+ unawaited(csMonero.rescanBlockchain(wallet!));
+ csMonero.startSyncing(wallet!);
// await save();
- csMonero.startListeners(walletId);
- csMonero.startAutoSaving(walletId);
+ csMonero.startListeners(wallet!);
+ csMonero.startAutoSaving(wallet!);
} catch (e, s) {
Logging.instance.e(
"Exception rethrown from recoverFromMnemonic(): ",
@@ -495,7 +489,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
@override
Future<bool> pingCheck() {
if (_canPing) {
- return csMonero.isConnectedToDaemon(walletId);
+ return csMonero.isConnectedToDaemon(wallet!);
} else {
return Future.value(false);
}
@@ -522,7 +516,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
if (_requireMutex) {
await _torConnectingLock.protect(() async {
await csMonero.connect(
- walletId,
+ wallet!,
daemonAddress: "$host:${node.port}",
daemonUsername: node.loginName,
daemonPassword: await node.getPassword(secureStorageInterface),
@@ -537,7 +531,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
});
} else {
await csMonero.connect(
- walletId,
+ wallet!,
daemonAddress: "$host:${node.port}",
daemonUsername: node.loginName,
daemonPassword: await node.getPassword(secureStorageInterface),
@@ -550,9 +544,9 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
: "${proxy.host.address}:${proxy.port}",
);
}
- csMonero.startSyncing(walletId);
- csMonero.startListeners(walletId);
- csMonero.startAutoSaving(walletId);
+ csMonero.startSyncing(wallet!);
+ csMonero.startListeners(wallet!);
+ csMonero.startAutoSaving(wallet!);
_setSyncStatus(lib_monero_compat.ConnectedSyncStatus());
} catch (e, s) {
@@ -569,7 +563,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
@override
Future<void> updateTransactions() async {
- if (!csMonero.walletInstanceExists(walletId)) {
+ if (wallet == null) {
return;
}
@@ -581,7 +575,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
.txidProperty()
.findAll();
- final allTxids = await csMonero.getAllTxids(walletId, refresh: true);
+ final allTxids = await csMonero.getAllTxids(wallet!, refresh: true);
final txidsToFetch = allTxids.toSet().difference(localTxids.toSet());
@@ -590,13 +584,13 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
}
final transactions = await csMonero.getTxs(
- walletId,
+ wallet!,
txids: txidsToFetch,
refresh: false,
);
final allOutputs = await csMonero.getOutputs(
- walletId,
+ wallet!,
includeSpent: true,
refresh: true,
);
@@ -707,7 +701,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
Future<Amount> get availableBalance async {
try {
return Amount(
- rawValue: csMonero.getUnlockedBalance(walletId)!,
+ rawValue: csMonero.getUnlockedBalance(wallet!)!,
fractionDigits: cryptoCurrency.fractionDigits,
);
} catch (_) {
@@ -717,14 +711,14 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
Future<Amount> get totalBalance async {
try {
- final full = csMonero.getBalance(walletId);
+ final full = csMonero.getBalance(wallet!);
if (full != null) {
return Amount(
rawValue: full,
fractionDigits: cryptoCurrency.fractionDigits,
);
} else {
- final transactions = await csMonero.getAllTxs(walletId, refresh: true);
+ final transactions = await csMonero.getAllTxs(wallet!, refresh: true);
BigInt transactionBalance = BigInt.zero;
for (final tx in transactions) {
if (!tx.isSpend) {
@@ -746,11 +740,13 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
@override
Future<void> exit() async {
- Logging.instance.i("exit called on $walletId");
- csMonero.stopAutoSaving(walletId);
- csMonero.stopListeners(walletId);
- csMonero.stopSyncing(walletId);
- await csMonero.save(walletId);
+ Logging.instance.i("exit called on $wallet!");
+ if (wallet != null) {
+ csMonero.stopAutoSaving(wallet!);
+ csMonero.stopListeners(wallet!);
+ csMonero.stopSyncing(wallet!);
+ await csMonero.save(wallet!);
+ }
}
Future<String> pathForWalletDir({
@@ -832,7 +828,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
final _utxosUpdateLock = Mutex();
Future<void> onUTXOsChanged(List<UTXO> utxos) async {
await _utxosUpdateLock.protect(() async {
- final cwUtxos = await csMonero.getOutputs(walletId, refresh: true);
+ final cwUtxos = await csMonero.getOutputs(wallet!, refresh: true);
// bool changed = false;
@@ -849,12 +845,12 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
if (u.isBlocked) {
if (!cw.isFrozen) {
- await csMonero.freezeOutput(walletId, cw.keyImage);
+ await csMonero.freezeOutput(wallet!, cw.keyImage);
// changed = true;
}
} else {
if (cw.isFrozen) {
- await csMonero.thawOutput(walletId, cw.keyImage);
+ await csMonero.thawOutput(wallet!, cw.keyImage);
// changed = true;
}
}
@@ -1011,9 +1007,11 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
if (mismatch) {
_canPing = false;
- csMonero.stopAutoSaving(walletId);
- csMonero.stopListeners(walletId);
- csMonero.stopSyncing(walletId);
+ if (wallet != null) {
+ csMonero.stopAutoSaving(wallet!);
+ csMonero.stopListeners(wallet!);
+ csMonero.stopSyncing(wallet!);
+ }
_setSyncStatus(lib_monero_compat.FailedSyncStatus());
}
@@ -1031,7 +1029,9 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
@override
Future<bool> updateUTXOs() async {
final List<UTXO> outputArray = [];
- final utxos = await csMonero.getOutputs(walletId, refresh: true);
+ final utxos = wallet == null
+ ? <CsOutput>[]
+ : await csMonero.getOutputs(wallet!, refresh: true);
for (final rawUTXO in utxos) {
if (!rawUTXO.spent) {
final current = await mainDB.isar.utxos
@@ -1120,7 +1120,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
// Slight possibility of race but should be irrelevant
await refreshMutex.acquire();
- csMonero.startSyncing(walletId);
+ csMonero.startSyncing(wallet!);
_setSyncStatus(lib_monero_compat.StartingSyncStatus());
await updateTransactions();
@@ -1134,7 +1134,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
refreshMutex.release();
}
- final synced = await csMonero.isSynced(walletId);
+ final synced = wallet != null && await csMonero.isSynced(wallet!);
if (synced) {
_setSyncStatus(lib_monero_compat.SyncedSyncStatus());
@@ -1183,7 +1183,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
try {
int highestIndex = -1;
- final entries = await csMonero.getAllTxs(walletId, refresh: true);
+ final entries = await csMonero.getAllTxs(wallet!, refresh: true);
for (final element in entries) {
if (!element.isSpend) {
final int curAddressIndex = element.addressIndexes.isEmpty
@@ -1326,7 +1326,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
final CsPendingTransaction pendingTransaction;
if (outputs.length == 1) {
pendingTransaction = await csMonero.createTx(
- walletId,
+ wallet!,
minConfirms: cryptoCurrency.minConfirms,
currentHeight: height,
output: outputs.first,
@@ -1337,7 +1337,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
);
} else {
pendingTransaction = await csMonero.createTxMultiDest(
- walletId,
+ wallet!,
minConfirms: cryptoCurrency.minConfirms,
currentHeight: height,
outputs: outputs,
@@ -1383,7 +1383,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
Future<TxData> confirmSend({required TxData txData}) async {
try {
try {
- await csMonero.commitTx(walletId, txData.pendingTransaction!);
+ await csMonero.commitTx(wallet!, txData.pendingTransaction!);
Logging.instance.d(
"transaction ${txData.pendingTransaction!.txid} has been sent",
@@ -1433,10 +1433,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
value: password,
);
- if (csMonero.walletInstanceExists(walletId)) {
- await exit();
- }
- await getRestoredFromViewKeyWallet(
+ final wallet = await getRestoredFromViewKeyWallet(
path: path,
password: password,
address: data.address,
@@ -1444,6 +1441,11 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
height: height,
);
+ if (this.wallet == null) {
+ await exit();
+ }
+ this.wallet = wallet;
+
_setListener();
final newReceivingAddress =
@@ -1452,7 +1454,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
walletId: walletId,
derivationIndex: 0,
derivationPath: null,
- value: csMonero.getAddress(walletId),
+ value: csMonero.getAddress(this.wallet!),
publicKey: [],
type: AddressType.cryptonote,
subType: AddressSubType.receiving,
@@ -1467,12 +1469,12 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
await updateNode();
_setListener();
- unawaited(csMonero.rescanBlockchain(walletId));
- csMonero.startSyncing(walletId);
+ unawaited(csMonero.rescanBlockchain(this.wallet!));
+ csMonero.startSyncing(this.wallet!);
// await save();
- csMonero.startListeners(walletId);
- csMonero.startAutoSaving(walletId);
+ csMonero.startListeners(this.wallet!);
+ csMonero.startAutoSaving(this.wallet!);
} catch (e, s) {
Logging.instance.e(
"Exception rethrown from recoverViewOnly(): ",
diff --git a/lib/wl_gen/interfaces/cs_monero_interface.dart b/lib/wl_gen/interfaces/cs_monero_interface.dart
index 4589a71..8987508 100644
--- a/lib/wl_gen/interfaces/cs_monero_interface.dart
+++ b/lib/wl_gen/interfaces/cs_monero_interface.dart
@@ -1,8 +1,11 @@
import '../../models/input.dart';
+import 'cs_salvium_interface.dart' show WrappedWallet;
export '../generated/cs_monero_interface_impl.dart';
abstract class CsMoneroInterface {
+ const CsMoneroInterface();
+
void setUseCsMoneroLoggerInternal(bool enable);
// tx prio forwarding
@@ -10,13 +13,15 @@ abstract class CsMoneroInterface {
int getTxPriorityMedium();
int getTxPriorityNormal();
- bool walletInstanceExists(String walletId);
-
bool walletExists(String path, {required CsCoin csCoin});
- Future<int> estimateFee(int rate, BigInt amount, {required String walletId});
+ Future<int> estimateFee(
+ int rate,
+ BigInt amount, {
+ required WrappedWallet wallet,
+ });
- Future<void> loadWallet(
+ Future<WrappedWallet> loadWallet(
String walletId, {
required CsCoin csCoin,
required String path,
@@ -24,22 +29,20 @@ abstract class CsMoneroInterface {
});
String getAddress(
- String walletId, {
+ WrappedWallet wallet, {
int accountIndex = 0,
int addressIndex = 0,
});
- Future<void> getCreatedWallet({
+ Future<WrappedWallet> getCreatedWallet({
required CsCoin csCoin,
required String path,
required String password,
required int wordCount,
required String seedOffset,
- required final void Function(int refreshFromBlockHeight, String seed)
- onCreated,
});
- Future<void> getRestoredWallet({
+ Future<WrappedWallet> getRestoredWallet({
required String walletId,
required CsCoin csCoin,
required String path,
@@ -49,7 +52,7 @@ abstract class CsMoneroInterface {
int height = 0,
});
- Future<void> getRestoredFromViewKeyWallet({
+ Future<WrappedWallet> getRestoredFromViewKeyWallet({
required String walletId,
required CsCoin csCoin,
required String path,
@@ -59,35 +62,35 @@ abstract class CsMoneroInterface {
int height = 0,
});
- String getTxKey(String walletId, String txid);
+ String getTxKey(WrappedWallet wallet, String txid);
- Future<void> save(String walletId);
+ Future<void> save(WrappedWallet wallet);
- String getPublicViewKey(String walletId);
- String getPrivateViewKey(String walletId);
- String getPublicSpendKey(String walletId);
- String getPrivateSpendKey(String walletId);
+ String getPublicViewKey(WrappedWallet wallet);
+ String getPrivateViewKey(WrappedWallet wallet);
+ String getPublicSpendKey(WrappedWallet wallet);
+ String getPrivateSpendKey(WrappedWallet wallet);
- Future<bool> isSynced(String walletId);
- void startSyncing(String walletId);
- void stopSyncing(String walletId);
+ Future<bool> isSynced(WrappedWallet wallet);
+ void startSyncing(WrappedWallet wallet);
+ void stopSyncing(WrappedWallet wallet);
- void startAutoSaving(String walletId);
- void stopAutoSaving(String walletId);
+ void startAutoSaving(WrappedWallet wallet);
+ void stopAutoSaving(WrappedWallet wallet);
- bool hasListeners(String walletId);
- void addListener(String walletId, CsWalletListener listener);
- void startListeners(String walletId);
- void stopListeners(String walletId);
+ bool hasListeners(WrappedWallet wallet);
+ void addListener(WrappedWallet wallet, CsWalletListener listener);
+ void startListeners(WrappedWallet wallet);
+ void stopListeners(WrappedWallet wallet);
- Future<bool> rescanBlockchain(String walletId);
- Future<bool> isConnectedToDaemon(String walletId);
+ Future<bool> rescanBlockchain(WrappedWallet wallet);
+ Future<bool> isConnectedToDaemon(WrappedWallet wallet);
- int getRefreshFromBlockHeight(String walletId);
- void setRefreshFromBlockHeight(String walletId, int height);
+ int getRefreshFromBlockHeight(WrappedWallet wallet);
+ void setRefreshFromBlockHeight(WrappedWallet wallet, int height);
Future<void> connect(
- String walletId, {
+ WrappedWallet wallet, {
required String daemonAddress,
required bool trusted,
String? daemonUsername,
@@ -97,24 +100,27 @@ abstract class CsMoneroInterface {
String? socksProxyAddress,
});
- Future<List<String>> getAllTxids(String walletId, {bool refresh = false});
+ Future<List<String>> getAllTxids(
+ WrappedWallet wallet, {
+ bool refresh = false,
+ });
- BigInt? getBalance(String walletId, {int accountIndex = 0});
- BigInt? getUnlockedBalance(String walletId, {int accountIndex = 0});
+ BigInt? getBalance(WrappedWallet wallet, {int accountIndex = 0});
+ BigInt? getUnlockedBalance(WrappedWallet wallet, {int accountIndex = 0});
Future<List<CsTransaction>> getAllTxs(
- String walletId, {
+ WrappedWallet wallet, {
bool refresh = false,
});
Future<List<CsTransaction>> getTxs(
- String walletId, {
+ WrappedWallet wallet, {
required Set<String> txids,
bool refresh = false,
});
Future<CsPendingTransaction> createTx(
- String walletId, {
+ WrappedWallet wallet, {
required CsRecipient output,
required int priority,
required bool sweep,
@@ -125,7 +131,7 @@ abstract class CsMoneroInterface {
});
Future<CsPendingTransaction> createTxMultiDest(
- String walletId, {
+ WrappedWallet wallet, {
required List<CsRecipient> outputs,
required int priority,
required bool sweep,
@@ -135,16 +141,16 @@ abstract class CsMoneroInterface {
required int currentHeight,
});
- Future<void> commitTx(String walletId, CsPendingTransaction tx);
+ Future<void> commitTx(WrappedWallet wallet, CsPendingTransaction tx);
Future<List<CsOutput>> getOutputs(
- String walletId, {
+ WrappedWallet wallet, {
bool refresh = false,
bool includeSpent = false,
});
- Future<void> freezeOutput(String walletId, String keyImage);
- Future<void> thawOutput(String walletId, String keyImage);
+ Future<void> freezeOutput(WrappedWallet wallet, String keyImage);
+ Future<void> thawOutput(WrappedWallet wallet, String keyImage);
List<String> getMoneroWordList(String language);
List<String> getWowneroWordList(String language, int seedLength);
@@ -152,6 +158,8 @@ abstract class CsMoneroInterface {
int getHeightByDate(DateTime date, {required CsCoin csCoin});
bool validateAddress(String address, int network, {required CsCoin csCoin});
+
+ String getSeed(WrappedWallet wallet);
}
enum CsCoin { monero, wownero }
@@ -221,7 +229,7 @@ final class CsPendingTransaction {
// forwarding class
final class CsTransaction {
- CsTransaction( {
+ CsTransaction({
required this.displayLabel,
required this.description,
required this.fee,
@@ -293,7 +301,6 @@ final class CsTransaction {
bool get isPending => confirmations < minConfirms;
final ({int type, String asset})? salviumData;
-
}
// forwarding class
diff --git a/tool/wl_templates/XMR_cs_monero_interface_impl.template.dart b/tool/wl_templates/XMR_cs_monero_interface_impl.template.dart
index 3ca3909..adcd951 100644
--- a/tool/wl_templates/XMR_cs_monero_interface_impl.template.dart
+++ b/tool/wl_templates/XMR_cs_monero_interface_impl.template.dart
@@ -18,18 +18,15 @@ CsMoneroInterface _getInterface() => throw Exception("XMR/WOW not enabled!");
//END_OFF
//ON
-CsMoneroInterface _getInterface() => _CsMoneroInterfaceImpl();
+CsMoneroInterface _getInterface() => const _CsMoneroInterfaceImpl();
class _CsMoneroInterfaceImpl extends CsMoneroInterface {
- final Map<String, lib_monero.Wallet> _wallets = {};
+ const _CsMoneroInterfaceImpl();
@override
void setUseCsMoneroLoggerInternal(bool enable) =>
lib_monero.Logging.useLogger = enable;
- @override
- bool walletInstanceExists(String walletId) => _wallets[walletId] != null;
-
@override
bool walletExists(String path, {required CsCoin csCoin}) => switch (csCoin) {
CsCoin.monero => lib_monero.MoneroWallet.isWalletExist(path),
@@ -37,7 +34,11 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
};
@override
- Future<int> estimateFee(int rate, BigInt amount, {required String walletId}) {
+ Future<int> estimateFee(
+ int rate,
+ BigInt amount, {
+ required WrappedWallet wallet,
+ }) {
lib_monero.TransactionPriority priority;
switch (rate) {
case 1:
@@ -58,31 +59,30 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
break;
}
- return _wallets[walletId]!.estimateFee(priority, amount.toInt());
+ return wallet.get<lib_monero.Wallet>().estimateFee(
+ priority,
+ amount.toInt(),
+ );
}
@override
- Future<void> loadWallet(
+ Future<WrappedWallet> loadWallet(
String walletId, {
required CsCoin csCoin,
required String path,
required String password,
}) async {
- switch (csCoin) {
- case CsCoin.monero:
- _wallets[walletId] = await lib_monero.MoneroWallet.loadWallet(
- path: path,
- password: password,
- );
- break;
+ return WrappedWallet(switch (csCoin) {
+ CsCoin.monero => await lib_monero.MoneroWallet.loadWallet(
+ path: path,
+ password: password,
+ ),
- case CsCoin.wownero:
- _wallets[walletId] = await lib_monero.WowneroWallet.loadWallet(
- path: path,
- password: password,
- );
- break;
- }
+ CsCoin.wownero => await lib_monero.WowneroWallet.loadWallet(
+ path: path,
+ password: password,
+ ),
+ });
}
@override
@@ -96,22 +96,21 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
@override
String getAddress(
- String walletId, {
+ WrappedWallet wallet, {
int accountIndex = 0,
int addressIndex = 0,
- }) => _wallets[walletId]!
+ }) => wallet
+ .get<lib_monero.Wallet>()
.getAddress(accountIndex: accountIndex, addressIndex: addressIndex)
.value;
@override
- Future<void> getCreatedWallet({
+ Future<WrappedWallet> getCreatedWallet({
required CsCoin csCoin,
required String path,
required String password,
required int wordCount,
required String seedOffset,
- required final void Function(int refreshFromBlockHeight, String seed)
- onCreated,
}) async {
final lib_monero.Wallet wallet;
@@ -147,14 +146,11 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
break;
}
- onCreated(
- wallet.getRefreshFromBlockHeight(),
- wallet.getSeed(seedOffset: seedOffset).trim(),
- );
+ return WrappedWallet(wallet);
}
@override
- Future<void> getRestoredWallet({
+ Future<WrappedWallet> getRestoredWallet({
required String walletId,
required CsCoin csCoin,
required String path,
@@ -163,7 +159,7 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
required String seedOffset,
int height = 0,
}) async {
- _wallets[walletId] = switch (csCoin) {
+ return WrappedWallet(switch (csCoin) {
CsCoin.monero => await lib_monero.MoneroWallet.restoreWalletFromSeed(
path: path,
password: password,
@@ -179,11 +175,11 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
restoreHeight: height,
seedOffset: seedOffset,
),
- };
+ });
}
@override
- Future<void> getRestoredFromViewKeyWallet({
+ Future<WrappedWallet> getRestoredFromViewKeyWallet({
required String walletId,
required CsCoin csCoin,
required String path,
@@ -192,7 +188,7 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
required String privateViewKey,
int height = 0,
}) async {
- _wallets[walletId] = switch (csCoin) {
+ return WrappedWallet(switch (csCoin) {
CsCoin.monero => await lib_monero.MoneroWallet.createViewOnlyWallet(
path: path,
password: password,
@@ -208,56 +204,60 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
viewKey: privateViewKey,
restoreHeight: height,
),
- };
+ });
}
@override
- String getTxKey(String walletId, String txid) =>
- _wallets[walletId]!.getTxKey(txid);
+ String getTxKey(WrappedWallet wallet, String txid) =>
+ wallet.get<lib_monero.Wallet>().getTxKey(txid);
@override
- Future<void> save(String walletId) => _wallets[walletId]!.save();
+ Future<void> save(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().save();
@override
- String getPublicViewKey(String walletId) =>
- _wallets[walletId]!.getPublicViewKey();
+ String getPublicViewKey(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().getPublicViewKey();
@override
- String getPrivateViewKey(String walletId) =>
- _wallets[walletId]!.getPrivateViewKey();
+ String getPrivateViewKey(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().getPrivateViewKey();
@override
- String getPublicSpendKey(String walletId) =>
- _wallets[walletId]!.getPublicSpendKey();
+ String getPublicSpendKey(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().getPublicSpendKey();
@override
- String getPrivateSpendKey(String walletId) =>
- _wallets[walletId]!.getPrivateSpendKey();
+ String getPrivateSpendKey(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().getPrivateSpendKey();
@override
- Future<bool> isSynced(String walletId) =>
- _wallets[walletId]?.isSynced() ?? Future.value(false);
+ Future<bool> isSynced(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().isSynced();
@override
- void startSyncing(String walletId) => _wallets[walletId]?.startSyncing();
+ void startSyncing(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().startSyncing();
@override
- void stopSyncing(String walletId) => _wallets[walletId]?.stopSyncing();
+ void stopSyncing(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().stopSyncing();
@override
- void startAutoSaving(String walletId) =>
- _wallets[walletId]?.startAutoSaving();
+ void startAutoSaving(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().startAutoSaving();
@override
- void stopAutoSaving(String walletId) => _wallets[walletId]?.stopAutoSaving();
+ void stopAutoSaving(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().stopAutoSaving();
@override
- bool hasListeners(String walletId) =>
- _wallets[walletId]!.getListeners().isNotEmpty;
+ bool hasListeners(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().getListeners().isNotEmpty;
@override
- void addListener(String walletId, CsWalletListener listener) =>
- _wallets[walletId]?.addListener(
+ void addListener(WrappedWallet wallet, CsWalletListener listener) =>
+ wallet.get<lib_monero.Wallet>().addListener(
lib_monero.WalletListener(
onSyncingUpdate: listener.onSyncingUpdate,
onNewBlock: listener.onNewBlock,
@@ -267,30 +267,32 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
);
@override
- void startListeners(String walletId) => _wallets[walletId]?.startListeners();
+ void startListeners(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().startListeners();
@override
- void stopListeners(String walletId) => _wallets[walletId]?.stopListeners();
+ void stopListeners(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().stopListeners();
@override
- int getRefreshFromBlockHeight(String walletId) =>
- _wallets[walletId]!.getRefreshFromBlockHeight();
+ int getRefreshFromBlockHeight(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().getRefreshFromBlockHeight();
@override
- void setRefreshFromBlockHeight(String walletId, int height) =>
- _wallets[walletId]!.setRefreshFromBlockHeight(height);
+ void setRefreshFromBlockHeight(WrappedWallet wallet, int height) =>
+ wallet.get<lib_monero.Wallet>().setRefreshFromBlockHeight(height);
@override
- Future<bool> rescanBlockchain(String walletId) =>
- _wallets[walletId]?.rescanBlockchain() ?? Future.value(false);
+ Future<bool> rescanBlockchain(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().rescanBlockchain();
@override
- Future<bool> isConnectedToDaemon(String walletId) =>
- _wallets[walletId]?.isConnectedToDaemon() ?? Future.value(false);
+ Future<bool> isConnectedToDaemon(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().isConnectedToDaemon();
@override
Future<void> connect(
- String walletId, {
+ WrappedWallet wallet, {
required String daemonAddress,
required bool trusted,
String? daemonUsername,
@@ -299,7 +301,7 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
bool isLightWallet = false,
String? socksProxyAddress,
}) async {
- await _wallets[walletId]?.connect(
+ await wallet.get<lib_monero.Wallet>().connect(
daemonAddress: daemonAddress,
trusted: trusted,
daemonUsername: daemonUsername,
@@ -311,24 +313,29 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
}
@override
- Future<List<String>> getAllTxids(String walletId, {bool refresh = false}) =>
- _wallets[walletId]!.getAllTxids(refresh: refresh);
+ Future<List<String>> getAllTxids(
+ WrappedWallet wallet, {
+ bool refresh = false,
+ }) => wallet.get<lib_monero.Wallet>().getAllTxids(refresh: refresh);
@override
- BigInt? getBalance(String walletId, {int accountIndex = 0}) =>
- _wallets[walletId]?.getBalance(accountIndex: accountIndex);
+ BigInt? getBalance(WrappedWallet wallet, {int accountIndex = 0}) =>
+ wallet.get<lib_monero.Wallet>().getBalance(accountIndex: accountIndex);
@override
- BigInt? getUnlockedBalance(String walletId, {int accountIndex = 0}) =>
- _wallets[walletId]?.getUnlockedBalance(accountIndex: accountIndex);
+ BigInt? getUnlockedBalance(WrappedWallet wallet, {int accountIndex = 0}) =>
+ wallet.get<lib_monero.Wallet>().getUnlockedBalance(
+ accountIndex: accountIndex,
+ );
@override
Future<List<CsTransaction>> getAllTxs(
- String walletId, {
+ WrappedWallet wallet, {
bool refresh = false,
}) async {
- final transactions = await _wallets[walletId]?.getAllTxs(refresh: refresh);
- if (transactions == null) return [];
+ final transactions = await wallet.get<lib_monero.Wallet>().getAllTxs(
+ refresh: refresh,
+ );
return transactions
.map(
(e) => CsTransaction(
@@ -353,15 +360,14 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
@override
Future<List<CsTransaction>> getTxs(
- String walletId, {
+ WrappedWallet wallet, {
required Set<String> txids,
bool refresh = false,
}) async {
- final transactions = await _wallets[walletId]?.getTxs(
+ final transactions = await wallet.get<lib_monero.Wallet>().getTxs(
txids: txids,
refresh: refresh,
);
- if (transactions == null) return [];
return transactions
.map(
(e) => CsTransaction(
@@ -386,7 +392,7 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
@override
Future<CsPendingTransaction> createTx(
- String walletId, {
+ WrappedWallet wallet, {
required CsRecipient output,
required int priority,
required bool sweep,
@@ -395,7 +401,7 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
required int minConfirms,
required int currentHeight,
}) async {
- final pending = await _wallets[walletId]!.createTx(
+ final pending = await wallet.get<lib_monero.Wallet>().createTx(
output: lib_monero.Recipient(
address: output.address,
amount: output.amount,
@@ -437,7 +443,7 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
@override
Future<CsPendingTransaction> createTxMultiDest(
- String walletId, {
+ WrappedWallet wallet, {
required List<CsRecipient> outputs,
required int priority,
required bool sweep,
@@ -446,7 +452,7 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
required int minConfirms,
required int currentHeight,
}) async {
- final pending = await _wallets[walletId]!.createTxMultiDest(
+ final pending = await wallet.get<lib_monero.Wallet>().createTxMultiDest(
outputs: outputs
.map(
(e) => lib_monero.Recipient(address: e.address, amount: e.amount),
@@ -488,22 +494,21 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
}
@override
- Future<void> commitTx(String walletId, CsPendingTransaction tx) =>
- _wallets[walletId]!.commitTx(tx.value as lib_monero.PendingTransaction);
+ Future<void> commitTx(WrappedWallet wallet, CsPendingTransaction tx) => wallet
+ .get<lib_monero.Wallet>()
+ .commitTx(tx.value as lib_monero.PendingTransaction);
@override
Future<List<CsOutput>> getOutputs(
- String walletId, {
+ WrappedWallet wallet, {
bool refresh = false,
bool includeSpent = false,
}) async {
- final outputs = await _wallets[walletId]?.getOutputs(
+ final outputs = await wallet.get<lib_monero.Wallet>().getOutputs(
includeSpent: includeSpent,
refresh: refresh,
);
- if (outputs == null) return [];
-
return outputs
.map(
(e) => CsOutput(
@@ -524,12 +529,12 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
}
@override
- Future<void> freezeOutput(String walletId, String keyImage) =>
- _wallets[walletId]!.freezeOutput(keyImage);
+ Future<void> freezeOutput(WrappedWallet wallet, String keyImage) =>
+ wallet.get<lib_monero.Wallet>().freezeOutput(keyImage);
@override
- Future<void> thawOutput(String walletId, String keyImage) =>
- _wallets[walletId]!.thawOutput(keyImage);
+ Future<void> thawOutput(WrappedWallet wallet, String keyImage) =>
+ wallet.get<lib_monero.Wallet>().thawOutput(keyImage);
@override
List<String> getMoneroWordList(String language) =>
@@ -554,6 +559,10 @@ class _CsMoneroInterfaceImpl extends CsMoneroInterface {
CsCoin.monero => xmr_wallet_ffi.validateAddress(address, network),
CsCoin.wownero => wow_wallet_ffi.validateAddress(address, network),
};
+
+ @override
+ String getSeed(WrappedWallet wallet) =>
+ wallet.get<lib_monero.Wallet>().getSeed();
}
//END_ON
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.