diff --git a/.gitignore b/.gitignore
index efa6e25e7..597ed4be4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -101,21 +101,7 @@ pubspec.yaml
# FVM Version Cache
.fvm/
-android/app/src/main/jniLibs/arm64-v8a/libwownero_wallet2_api_c.so
-android/app/src/main/jniLibs/arm64-v8a/libmonero_wallet2_api_c.so
-android/app/src/main/jniLibs/armeabi-v7a/libmonero_wallet2_api_c.so
-android/app/src/main/jniLibs/armeabi-v7a/libwownero_wallet2_api_c.so
-android/app/src/main/jniLibs/x86_64/libmonero_wallet2_api_c.so
-android/app/src/main/jniLibs/x86_64/libwownero_wallet2_api_c.so
-macos/monero_wallet2_api_c.dylib
-macos/wownero_wallet2_api_c.dylib
-/macos/monero_libwallet2_api_c.dylib
-/macos/wownero_libwallet2_api_c.dylib
-/ios/monero_libwallet2_api_c.dylib
-/ios/wownero_libwallet2_api_c.dylib
-/android/app/src/main/jniLibs/arm64-v8a/libmonero_libwallet2_api_c.so
-/android/app/src/main/jniLibs/armeabi-v7a/libmonero_libwallet2_api_c.so
-/android/app/src/main/jniLibs/x86_64/libmonero_libwallet2_api_c.so
-/android/app/src/main/jniLibs/arm64-v8a/libwownero_libwallet2_api_c.so
-/android/app/src/main/jniLibs/armeabi-v7a/libwownero_libwallet2_api_c.so
-/android/app/src/main/jniLibs/x86_64/libwownero_libwallet2_api_c.so
+scripts/linux/build/libsecret/subprojects/gi-docgen/.meson-subproject-wrap-hash.txt
+
+crypto_plugins/cs_monero/built_outputs
+crypto_plugins/cs_monero/build
diff --git a/.gitmodules b/.gitmodules
index 925be21c0..6051a5f9b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,12 +1,12 @@
[submodule "crypto_plugins/flutter_libepiccash"]
path = crypto_plugins/flutter_libepiccash
url = https://github.com/cypherstack/flutter_libepiccash.git
-[submodule "crypto_plugins/flutter_libmonero"]
- path = crypto_plugins/flutter_libmonero
- url = https://github.com/cypherstack/flutter_libmonero.git
[submodule "crypto_plugins/flutter_liblelantus"]
path = crypto_plugins/flutter_liblelantus
url = https://github.com/cypherstack/flutter_liblelantus.git
[submodule "crypto_plugins/frostdart"]
path = crypto_plugins/frostdart
url = https://github.com/cypherstack/frostdart
+[submodule "crypto_plugins/cs_monero"]
+ path = crypto_plugins/cs_monero
+ url = https://github.com/cypherstack/cs_monero
diff --git a/android/app/src/main/jniLibs/arm64-v8a/.gitkeep b/android/app/src/main/jniLibs/arm64-v8a/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/android/app/src/main/jniLibs/armeabi-v7a/.gitkeep b/android/app/src/main/jniLibs/armeabi-v7a/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/android/app/src/main/jniLibs/x86_64/.gitkeep b/android/app/src/main/jniLibs/x86_64/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/crypto_plugins/cs_monero b/crypto_plugins/cs_monero
new file mode 160000
index 000000000..fee51e29e
--- /dev/null
+++ b/crypto_plugins/cs_monero
@@ -0,0 +1 @@
+Subproject commit fee51e29e97ee8c1f57082b126173eeaf39a79f1
diff --git a/crypto_plugins/flutter_libmonero b/crypto_plugins/flutter_libmonero
deleted file mode 160000
index 66369ef5b..000000000
--- a/crypto_plugins/flutter_libmonero
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 66369ef5b432e4d58e76b6cc4f91a5e24eb6b1ea
diff --git a/ios/MoneroWallet.framework/.gitignore b/ios/MoneroWallet.framework/.gitignore
deleted file mode 100644
index 38de9b351..000000000
--- a/ios/MoneroWallet.framework/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-MoneroWallet
\ No newline at end of file
diff --git a/ios/MoneroWallet.framework/Info.plist b/ios/MoneroWallet.framework/Info.plist
deleted file mode 100644
index de2be3211..000000000
--- a/ios/MoneroWallet.framework/Info.plist
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
- BuildMachineOSBuild
- 23E224
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- MoneroWallet
- CFBundleIdentifier
- com.cypherstack.MoneroWallet
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- MoneroWallet
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ???
- CFBundleSupportedPlatforms
-
- iPhoneOS
-
- CFBundleVersion
- 1
- DTCompiler
- com.apple.compilers.llvm.clang.1_0
- DTPlatformBuild
- 21E210
- DTPlatformName
- iphoneos
- DTPlatformVersion
- 17.4
- DTSDKBuild
- 21E210
- DTSDKName
- iphoneos17.4
- DTXcode
- 1530
- DTXcodeBuild
- 15E204a
- MinimumOSVersion
- 16.0
- UIDeviceFamily
-
- 1
- 2
-
- UIRequiredDeviceCapabilities
-
- arm64
-
-
-
diff --git a/ios/WowneroWallet.framework/.gitignore b/ios/WowneroWallet.framework/.gitignore
deleted file mode 100644
index 98afbebec..000000000
--- a/ios/WowneroWallet.framework/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-WowneroWallet
\ No newline at end of file
diff --git a/ios/WowneroWallet.framework/Info.plist b/ios/WowneroWallet.framework/Info.plist
deleted file mode 100644
index d1d435920..000000000
--- a/ios/WowneroWallet.framework/Info.plist
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
- BuildMachineOSBuild
- 23E224
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- WowneroWallet
- CFBundleIdentifier
- com.cypherstack.WowneroWallet
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- WowneroWallet
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ???
- CFBundleSupportedPlatforms
-
- iPhoneOS
-
- CFBundleVersion
- 1
- DTCompiler
- com.apple.compilers.llvm.clang.1_0
- DTPlatformBuild
- 21E210
- DTPlatformName
- iphoneos
- DTPlatformVersion
- 17.4
- DTSDKBuild
- 21E210
- DTSDKName
- iphoneos17.4
- DTXcode
- 1530
- DTXcodeBuild
- 15E204a
- MinimumOSVersion
- 16.0
- UIDeviceFamily
-
- 1
- 2
-
- UIRequiredDeviceCapabilities
-
- arm64
-
-
-
diff --git a/lib/db/hive/db.dart b/lib/db/hive/db.dart
index 1e4c670e1..c71826fbc 100644
--- a/lib/db/hive/db.dart
+++ b/lib/db/hive/db.dart
@@ -10,7 +10,7 @@
import 'dart:isolate';
-import 'package:cw_core/wallet_info.dart' as xmr;
+import 'package:compat/compat.dart' as lib_monero_compat;
import 'package:hive/hive.dart' show Box;
import 'package:hive/src/hive_impl.dart';
import 'package:mutex/mutex.dart';
@@ -71,7 +71,7 @@ class DB {
Box? _boxTradesV2;
Box? _boxTradeNotes;
Box? _boxFavoriteWallets;
- Box? _walletInfoSource;
+ Box? _walletInfoSource;
Box? _boxPrefs;
Box? _boxTradeLookup;
Box? _boxDBInfo;
@@ -85,7 +85,8 @@ class DB {
final Map> _getSparkUsedCoinsTagsCacheBoxes = {};
// exposed for monero
- Box get moneroWalletInfoBox => _walletInfoSource!;
+ Box get moneroWalletInfoBox =>
+ _walletInfoSource!;
// mutex for stack backup
final mutex = Mutex();
@@ -147,8 +148,8 @@ class DB {
_boxTradesV2 = await hive.openBox(boxNameTradesV2);
_boxTradeNotes = await hive.openBox(boxNameTradeNotes);
_boxTradeLookup = await hive.openBox(boxNameTradeLookup);
- _walletInfoSource =
- await hive.openBox(xmr.WalletInfo.boxName);
+ _walletInfoSource = await hive.openBox(
+ lib_monero_compat.WalletInfo.boxName);
_boxFavoriteWallets = await hive.openBox(boxNameFavoriteWallets);
await Future.wait([
diff --git a/lib/main.dart b/lib/main.dart
index 3dc8f53bc..30edb2bbb 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -13,11 +13,8 @@ import 'dart:io';
import 'dart:math';
import 'package:coinlib_flutter/coinlib_flutter.dart';
-import 'package:cw_core/node.dart';
-import 'package:cw_core/pathForWallet.dart';
-import 'package:cw_core/unspent_coins_info.dart';
-import 'package:cw_core/wallet_info.dart';
-import 'package:cw_core/wallet_type.dart';
+import 'package:compat/compat.dart' as lib_monero_compat;
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -92,10 +89,11 @@ void main(List args) async {
StackFileSystem.setDesktopOverrideDir(args.last);
}
- // Tell flutter_libmonero how to get access to the application dir
- FS.setApplicationRootDirectoryFunction(
- StackFileSystem.applicationRootDirectory,
- );
+ // no longer requried
+ // // Tell flutter_libmonero how to get access to the application dir
+ // FS.setApplicationRootDirectoryFunction(
+ // StackFileSystem.applicationRootDirectory,
+ // );
// TODO set any other external libs file paths (bad external lib design workaround)
final loadCoinlibFuture = loadCoinlib();
@@ -170,15 +168,18 @@ void main(List args) async {
// node model adapter
DB.instance.hive.registerAdapter(NodeModelAdapter());
- DB.instance.hive.registerAdapter(NodeAdapter());
+ // DB.instance.hive.registerAdapter(NodeAdapter());
- if (!DB.instance.hive.isAdapterRegistered(WalletInfoAdapter().typeId)) {
- DB.instance.hive.registerAdapter(WalletInfoAdapter());
+ if (!DB.instance.hive
+ .isAdapterRegistered(lib_monero_compat.WalletInfoAdapter().typeId)) {
+ DB.instance.hive.registerAdapter(lib_monero_compat.WalletInfoAdapter());
}
- DB.instance.hive.registerAdapter(WalletTypeAdapter());
+ DB.instance.hive.registerAdapter(lib_monero_compat.WalletTypeAdapter());
- DB.instance.hive.registerAdapter(UnspentCoinsInfoAdapter());
+ // DB.instance.hive.registerAdapter(UnspentCoinsInfoAdapter());
+
+ lib_monero.Logging.useLogger = true;
DB.instance.hive.init(
(await StackFileSystem.applicationHiveDirectory()).path,
diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart
index 0b7fcc37b..cd0115128 100644
--- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart
+++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart
@@ -67,7 +67,7 @@ class _RestoreOptionsViewState extends ConsumerState {
late final TextEditingController passwordController;
final bool _nextEnabled = true;
- DateTime _restoreFromDate = DateTime.fromMillisecondsSinceEpoch(0);
+ DateTime? _restoreFromDate;
bool hidePassword = true;
bool _expandedAdavnced = false;
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 1e0b259fd..984f774ab 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
@@ -16,10 +16,10 @@ import 'dart:math';
import 'package:bip39/bip39.dart' as bip39;
import 'package:bip39/src/wordlists/english.dart' as bip39wordlist;
+import 'package:compat/compat.dart' as lib_monero_compat;
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
-import 'package:flutter_libmonero/monero/monero.dart' as libxmr;
-import 'package:flutter_libmonero/wownero/wownero.dart' as libwow;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
@@ -86,7 +86,7 @@ class RestoreWalletView extends ConsumerStatefulWidget {
final CryptoCurrency coin;
final String mnemonicPassphrase;
final int seedWordsLength;
- final DateTime restoreFromDate;
+ final DateTime? restoreFromDate;
final bool enableLelantusScanning;
final BarcodeScannerInterface barcodeScanner;
@@ -181,7 +181,7 @@ class _RestoreWalletViewState extends ConsumerState {
if (widget.coin is Monero) {
switch (widget.seedWordsLength) {
case 25:
- return libxmr.monero.getMoneroWordList("English").contains(word);
+ return lib_monero.getMoneroWordList("English").contains(word);
case 16:
return Monero.sixteenWordsWordList.contains(word);
default:
@@ -189,7 +189,7 @@ class _RestoreWalletViewState extends ConsumerState {
}
}
if (widget.coin is Wownero) {
- final wowneroWordList = libwow.wownero.getWowneroWordList(
+ final wowneroWordList = lib_monero.getWowneroWordList(
"English",
seedWordsLength: widget.seedWordsLength,
);
@@ -219,29 +219,35 @@ class _RestoreWalletViewState extends ConsumerState {
int height = 0;
String? otherDataJsonString;
- if (widget.coin is Monero) {
- height = libxmr.monero.getHeigthByDate(date: widget.restoreFromDate);
- } else if (widget.coin is Wownero) {
- height = libwow.wownero.getHeightByDate(date: widget.restoreFromDate);
+ if (widget.restoreFromDate != null) {
+ if (widget.coin is Monero) {
+ height = lib_monero_compat.getMoneroHeigthByDate(
+ date: widget.restoreFromDate!,
+ );
+ }
+ if (widget.coin is Wownero) {
+ height = lib_monero_compat.getWowneroHeightByDate(
+ date: widget.restoreFromDate!,
+ );
+ }
+ if (height < 0) {
+ height = 0;
+ }
}
- // todo: wait until this implemented
- // else if (widget.coin is Wownero) {
- // height = wownero.getHeightByDate(date: widget.restoreFromDate);
- // }
// TODO: make more robust estimate of date maybe using https://explorer.epic.tech/api-index
if (widget.coin is Epiccash) {
- final int secondsSinceEpoch =
- widget.restoreFromDate.millisecondsSinceEpoch ~/ 1000;
- const int epicCashFirstBlock = 1565370278;
- const double overestimateSecondsPerBlock = 61;
- final int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock;
- final int approximateHeight =
- chosenSeconds ~/ overestimateSecondsPerBlock;
- //todo: check if print needed
- // debugPrint(
- // "approximate height: $approximateHeight chosen_seconds: $chosenSeconds");
- height = approximateHeight;
+ if (widget.restoreFromDate != null) {
+ final int secondsSinceEpoch =
+ widget.restoreFromDate!.millisecondsSinceEpoch ~/ 1000;
+ const int epicCashFirstBlock = 1565370278;
+ const double overestimateSecondsPerBlock = 61;
+ final int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock;
+ final int approximateHeight =
+ chosenSeconds ~/ overestimateSecondsPerBlock;
+
+ height = approximateHeight;
+ }
if (height < 0) {
height = 0;
}
diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart
index 643768f19..f499775b1 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/wallet_mixin_interfaces/cw_based_interface.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';
@@ -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 CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
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 3c52c8efc..711a25a45 100644
--- a/lib/pages/pinpad_views/lock_screen_view.dart
+++ b/lib/pages/pinpad_views/lock_screen_view.dart
@@ -26,7 +26,7 @@ import '../../utilities/biometrics.dart';
import '../../utilities/flutter_secure_storage_interface.dart';
import '../../utilities/show_loading.dart';
import '../../utilities/text_styles.dart';
-import '../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
+import '../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../widgets/background.dart';
import '../../widgets/custom_buttons/app_bar_icon_button.dart';
import '../../widgets/custom_buttons/blue_text_button.dart';
@@ -102,7 +102,7 @@ class _LockscreenViewState extends ConsumerState {
final wallet = ref.read(pWallets).getWallet(walletId);
final Future loadFuture;
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
loadFuture =
wallet.init().then((value) async => await (wallet).open());
} else {
diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart
index cd7d5f01a..584d868d2 100644
--- a/lib/pages/send_view/send_view.dart
+++ b/lib/pages/send_view/send_view.dart
@@ -11,10 +11,10 @@
import 'dart:async';
import 'dart:io';
-import 'package:cw_core/monero_transaction_priority.dart';
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:tuple/tuple.dart';
@@ -470,22 +470,22 @@ class _SendViewState extends ConsumerState {
Amount fee;
if (coin is Monero) {
- MoneroTransactionPriority specialMoneroId;
+ lib_monero.TransactionPriority specialMoneroId;
switch (ref.read(feeRateTypeStateProvider.state).state) {
case FeeRateType.fast:
- specialMoneroId = MoneroTransactionPriority.fast;
+ specialMoneroId = lib_monero.TransactionPriority.high;
break;
case FeeRateType.average:
- specialMoneroId = MoneroTransactionPriority.regular;
+ specialMoneroId = lib_monero.TransactionPriority.medium;
break;
case FeeRateType.slow:
- specialMoneroId = MoneroTransactionPriority.slow;
+ specialMoneroId = lib_monero.TransactionPriority.normal;
break;
default:
throw ArgumentError("custom fee not available for monero");
}
- fee = await wallet.estimateFeeFor(amount, specialMoneroId.raw!);
+ fee = await wallet.estimateFeeFor(amount, specialMoneroId.value);
cachedFees[amount] = ref.read(pAmountFormatter(coin)).format(
fee,
withUnitName: true,
diff --git a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart
index a70098c03..0ca0dba47 100644
--- a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart
+++ b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart
@@ -8,9 +8,10 @@
*
*/
-import 'package:cw_core/monero_transaction_priority.dart';
import 'package:flutter/material.dart';
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter_riverpod/flutter_riverpod.dart';
+
import '../../../models/paymint/fee_object_model.dart';
import '../../../providers/providers.dart';
import '../../../providers/ui/fee_rate_type_state_provider.dart';
@@ -90,7 +91,7 @@ class _TransactionFeeSelectionSheetState
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.fast.raw!,
+ lib_monero.TransactionPriority.high.value,
);
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
} else if (coin is Firo) {
@@ -127,7 +128,7 @@ class _TransactionFeeSelectionSheetState
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.regular.raw!,
+ lib_monero.TransactionPriority.medium.value,
);
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
} else if (coin is Firo) {
@@ -163,7 +164,7 @@ class _TransactionFeeSelectionSheetState
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.slow.raw!,
+ lib_monero.TransactionPriority.normal.value,
);
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
} else if (coin is Firo) {
diff --git a/lib/pages/settings_views/global_settings_view/about_view.dart b/lib/pages/settings_views/global_settings_view/about_view.dart
index f4c3eb7ec..b72c3222c 100644
--- a/lib/pages/settings_views/global_settings_view/about_view.dart
+++ b/lib/pages/settings_views/global_settings_view/about_view.dart
@@ -272,48 +272,48 @@ class AboutView extends ConsumerWidget {
const SizedBox(
height: 12,
),
- if (AppConfig.coins.whereType().isNotEmpty)
- FutureBuilder(
- future: GitStatus.getMoneroCommitStatus(),
- builder: (
- context,
- AsyncSnapshot snapshot,
- ) {
- CommitStatus stateOfCommit =
- CommitStatus.notLoaded;
-
- if (snapshot.connectionState ==
- ConnectionState.done &&
- snapshot.hasData) {
- stateOfCommit = snapshot.data!;
- }
- return RoundedWhiteContainer(
- child: Column(
- crossAxisAlignment:
- CrossAxisAlignment.stretch,
- children: [
- Text(
- "Monero Build Commit",
- style: STextStyles.titleBold12(context),
- ),
- const SizedBox(
- height: 4,
- ),
- SelectableText(
- GitStatus.moneroCommit,
- style: GitStatus.styleForStatus(
- stateOfCommit,
- context,
- ),
- ),
- ],
- ),
- );
- },
- ),
- const SizedBox(
- height: 12,
- ),
+ // if (AppConfig.coins.whereType().isNotEmpty)
+ // FutureBuilder(
+ // future: GitStatus.getMoneroCommitStatus(),
+ // builder: (
+ // context,
+ // AsyncSnapshot snapshot,
+ // ) {
+ // CommitStatus stateOfCommit =
+ // CommitStatus.notLoaded;
+ //
+ // if (snapshot.connectionState ==
+ // ConnectionState.done &&
+ // snapshot.hasData) {
+ // stateOfCommit = snapshot.data!;
+ // }
+ // return RoundedWhiteContainer(
+ // child: Column(
+ // crossAxisAlignment:
+ // CrossAxisAlignment.stretch,
+ // children: [
+ // Text(
+ // "Monero Build Commit",
+ // style: STextStyles.titleBold12(context),
+ // ),
+ // const SizedBox(
+ // height: 4,
+ // ),
+ // SelectableText(
+ // GitStatus.moneroCommit,
+ // style: GitStatus.styleForStatus(
+ // stateOfCommit,
+ // context,
+ // ),
+ // ),
+ // ],
+ // ),
+ // );
+ // },
+ // ),
+ // const SizedBox(
+ // height: 12,
+ // ),
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart
index 81297430e..92e5cc256 100644
--- a/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart
+++ b/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart
@@ -18,7 +18,7 @@ import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_libepiccash/git_versions.dart' as EPIC_VERSIONS;
-import 'package:flutter_libmonero/git_versions.dart' as MONERO_VERSIONS;
+// import 'package:flutter_libmonero/git_versions.dart' as MONERO_VERSIONS;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:lelantus/git_versions.dart' as FIRO_VERSIONS;
@@ -313,8 +313,8 @@ class _DebugViewState extends ConsumerState {
FIRO_VERSIONS.getPluginVersion();
final String epicCashCommit =
EPIC_VERSIONS.getPluginVersion();
- final String moneroCommit =
- MONERO_VERSIONS.getPluginVersion();
+ // final String moneroCommit =
+ // MONERO_VERSIONS.getPluginVersion();
final DeviceInfoPlugin deviceInfoPlugin =
DeviceInfoPlugin();
final deviceInfo =
@@ -347,7 +347,7 @@ class _DebugViewState extends ConsumerState {
"appName": appName,
"firoCommit": firoCommit,
"epicCashCommit": epicCashCommit,
- "moneroCommit": moneroCommit,
+ // "moneroCommit": moneroCommit,
"deviceInfoMap": deviceInfoMap,
"errorLogs": errorLogs,
};
diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
index 478440c99..7888635b7 100644
--- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
+++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
@@ -29,7 +29,7 @@ import '../../../../utilities/text_styles.dart';
import '../../../../utilities/util.dart';
import '../../../../wallets/crypto_currency/crypto_currency.dart';
import '../../../../wallets/crypto_currency/intermediate/cryptonote_currency.dart';
-import '../../../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.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';
@@ -222,7 +222,7 @@ class _AddEditNodeViewState extends ConsumerState {
// strip unused path
String address = formData.host!;
- if (coin is CwBasedInterface) {
+ if (coin is LibMoneroWallet) {
if (address.startsWith("http")) {
final uri = Uri.parse(address);
address = "${uri.scheme}://${uri.host}";
@@ -837,7 +837,7 @@ class _NodeFormState extends ConsumerState {
} else {
enableSSLCheckbox = true;
}
- } else if (widget.coin is CwBasedInterface) {
+ } else if (widget.coin is LibMoneroWallet) {
if (newValue.startsWith("https://")) {
_useSSL = true;
} else if (newValue.startsWith("http://")) {
@@ -1052,7 +1052,7 @@ class _NodeFormState extends ConsumerState {
),
],
),
- if (widget.coin is CwBasedInterface)
+ if (widget.coin is LibMoneroWallet)
Row(
children: [
GestureDetector(
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
index a4d7d69fe..32430d228 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
@@ -54,8 +54,8 @@ import '../../../../../wallets/wallet/impl/bitcoin_frost_wallet.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/wallet.dart';
-import '../../../../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/private_key_interface.dart';
@@ -503,7 +503,7 @@ abstract class SWB {
Future? restoringFuture;
- if (!(wallet is CwBasedInterface || wallet is EpiccashWallet)) {
+ if (!(wallet is LibMoneroWallet || wallet is EpiccashWallet)) {
if (wallet is BitcoinFrostWallet) {
restoringFuture = wallet.recover(
isRescan: false,
diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart
index 6985bb00c..22d3a4073 100644
--- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart
+++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart
@@ -36,7 +36,7 @@ import '../../../wallets/crypto_currency/intermediate/frost_currency.dart';
import '../../../wallets/crypto_currency/intermediate/nano_currency.dart';
import '../../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
import '../../../wallets/wallet/impl/epiccash_wallet.dart';
-import '../../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
+import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart';
import '../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import '../../../widgets/background.dart';
@@ -307,7 +307,7 @@ class _WalletSettingsViewState extends ConsumerState {
KeyDataInterface? keyData;
if (wallet is ExtendedKeysInterface) {
keyData = await wallet.getXPrivs();
- } else if (wallet is CwBasedInterface) {
+ } else if (wallet is LibMoneroWallet) {
keyData = await wallet.getKeys();
}
diff --git a/lib/pages/special/firo_rescan_recovery_error_dialog.dart b/lib/pages/special/firo_rescan_recovery_error_dialog.dart
index 92d226d4b..fa59d841a 100644
--- a/lib/pages/special/firo_rescan_recovery_error_dialog.dart
+++ b/lib/pages/special/firo_rescan_recovery_error_dialog.dart
@@ -12,7 +12,7 @@ import '../../utilities/assets.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
import '../../wallets/isar/providers/wallet_info_provider.dart';
-import '../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
+import '../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart';
import '../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import '../../widgets/background.dart';
@@ -270,7 +270,7 @@ class _FiroRescanRecoveryErrorViewState
KeyDataInterface? keyData;
if (wallet is ExtendedKeysInterface) {
keyData = await wallet.getXPrivs();
- } else if (wallet is CwBasedInterface) {
+ } else if (wallet is LibMoneroWallet) {
keyData = await wallet.getKeys();
}
diff --git a/lib/pages/wallets_view/sub_widgets/favorite_card.dart b/lib/pages/wallets_view/sub_widgets/favorite_card.dart
index ab91cc759..48d0d1257 100644
--- a/lib/pages/wallets_view/sub_widgets/favorite_card.dart
+++ b/lib/pages/wallets_view/sub_widgets/favorite_card.dart
@@ -13,7 +13,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
-import '../../wallet_view/wallet_view.dart';
+
import '../../../pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart';
import '../../../providers/providers.dart';
import '../../../themes/coin_icon_provider.dart';
@@ -26,9 +26,10 @@ 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/wallet_mixin_interfaces/cw_based_interface.dart';
+import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../widgets/coin_card.dart';
import '../../../widgets/conditional_parent.dart';
+import '../../wallet_view/wallet_view.dart';
class FavoriteCard extends ConsumerStatefulWidget {
const FavoriteCard({
@@ -117,7 +118,7 @@ class _FavoriteCardState extends ConsumerState {
final wallet = ref.read(pWallets).getWallet(walletId);
final Future loadFuture;
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
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 5602d2419..3ac87eb2e 100644
--- a/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart
+++ b/lib/pages/wallets_view/sub_widgets/wallet_list_item.dart
@@ -24,7 +24,7 @@ import '../../../utilities/show_loading.dart';
import '../../../utilities/text_styles.dart';
import '../../../utilities/util.dart';
import '../../../wallets/crypto_currency/crypto_currency.dart';
-import '../../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
+import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../widgets/dialogs/tor_warning_dialog.dart';
import '../../../widgets/rounded_white_container.dart';
import '../../wallet_view/wallet_view.dart';
@@ -84,7 +84,7 @@ class WalletListItem extends ConsumerWidget {
.wallets
.firstWhere((e) => e.info.coin == coin);
final Future loadFuture;
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
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 e440af8fe..7771c33f5 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
@@ -10,7 +10,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'wallet_view/desktop_wallet_view.dart';
+
import '../../providers/global/active_wallet_provider.dart';
import '../../providers/global/wallets_provider.dart';
import '../../themes/stack_colors.dart';
@@ -18,9 +18,10 @@ import '../../utilities/constants.dart';
import '../../utilities/show_loading.dart';
import '../../utilities/util.dart';
import '../../wallets/crypto_currency/crypto_currency.dart';
-import '../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
+import '../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../widgets/rounded_container.dart';
import '../../widgets/wallet_info_row/wallet_info_row.dart';
+import 'wallet_view/desktop_wallet_view.dart';
class CoinWalletsTable extends ConsumerWidget {
const CoinWalletsTable({
@@ -81,7 +82,7 @@ class CoinWalletsTable extends ConsumerWidget {
final wallet =
ref.read(pWallets).getWallet(walletIds[i]);
final Future loadFuture;
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
loadFuture = wallet
.init()
.then((value) async => await (wallet).open());
diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart
index 3b25f0dad..6326a6474 100644
--- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart
+++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart
@@ -8,9 +8,9 @@
*
*/
-import 'package:cw_core/monero_transaction_priority.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@@ -86,7 +86,7 @@ class _DesktopFeeDropDownState extends ConsumerState {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.fast.raw!,
+ lib_monero.TransactionPriority.high.value,
);
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
} else if (coin is Firo) {
@@ -136,7 +136,7 @@ class _DesktopFeeDropDownState extends ConsumerState {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.regular.raw!,
+ lib_monero.TransactionPriority.medium.value,
);
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
} else if (coin is Firo) {
@@ -186,7 +186,7 @@ class _DesktopFeeDropDownState extends ConsumerState {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.slow.raw!,
+ lib_monero.TransactionPriority.normal.value,
);
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
} else if (coin is Firo) {
diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
index ce3ab2b1f..80dea6795 100644
--- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
+++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
@@ -10,11 +10,11 @@
import 'dart:async';
-import 'package:cw_core/monero_transaction_priority.dart';
import 'package:decimal/decimal.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
@@ -1860,7 +1860,7 @@ class _DesktopSendState extends ConsumerState {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.regular.raw!,
+ lib_monero.TransactionPriority.medium.value,
);
ref
.read(feeSheetSessionCacheProvider)
diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart
index e332c4543..3ae249dfb 100644
--- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart
+++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart
@@ -23,7 +23,7 @@ import '../../../../utilities/assets.dart';
import '../../../../utilities/constants.dart';
import '../../../../utilities/text_styles.dart';
import '../../../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
-import '../../../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
+import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart';
import '../../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import '../../../../widgets/desktop/desktop_dialog.dart';
@@ -106,7 +106,7 @@ class _UnlockWalletKeysDesktopState
KeyDataInterface? keyData;
if (wallet is ExtendedKeysInterface) {
keyData = await wallet.getXPrivs();
- } else if (wallet is CwBasedInterface) {
+ } else if (wallet is LibMoneroWallet) {
keyData = await wallet.getKeys();
}
@@ -353,7 +353,7 @@ class _UnlockWalletKeysDesktopState
KeyDataInterface? keyData;
if (wallet is ExtendedKeysInterface) {
keyData = await wallet.getXPrivs();
- } else if (wallet is CwBasedInterface) {
+ } else if (wallet is LibMoneroWallet) {
keyData = await wallet.getKeys();
}
diff --git a/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart b/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart
index 34c8a8dba..98a7dec34 100644
--- a/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart
+++ b/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart
@@ -434,63 +434,63 @@ class DesktopAboutView extends ConsumerWidget {
);
},
),
- if (AppConfig.coins
- .whereType()
- .isNotEmpty)
- FutureBuilder(
- future: GitStatus
- .getMoneroCommitStatus(),
- builder: (
- context,
- AsyncSnapshot
- snapshot,
- ) {
- CommitStatus stateOfCommit =
- CommitStatus.notLoaded;
-
- if (snapshot.connectionState ==
- ConnectionState
- .done &&
- snapshot.hasData) {
- stateOfCommit =
- snapshot.data!;
- }
- return Column(
- mainAxisSize:
- MainAxisSize.min,
- crossAxisAlignment:
- CrossAxisAlignment
- .start,
- children: [
- Text(
- "Monero Build Commit",
- style: STextStyles
- .desktopTextExtraExtraSmall(
- context,
- ).copyWith(
- color: Theme.of(
- context,
- )
- .extension<
- StackColors>()!
- .textDark,
- ),
- ),
- const SizedBox(
- height: 2,
- ),
- SelectableText(
- GitStatus.moneroCommit,
- style: GitStatus
- .styleForStatus(
- stateOfCommit,
- context,
- ),
- ),
- ],
- );
- },
- ),
+ // if (AppConfig.coins
+ // .whereType()
+ // .isNotEmpty)
+ // FutureBuilder(
+ // future: GitStatus
+ // .getMoneroCommitStatus(),
+ // builder: (
+ // context,
+ // AsyncSnapshot
+ // snapshot,
+ // ) {
+ // CommitStatus stateOfCommit =
+ // CommitStatus.notLoaded;
+ //
+ // if (snapshot.connectionState ==
+ // ConnectionState
+ // .done &&
+ // snapshot.hasData) {
+ // stateOfCommit =
+ // snapshot.data!;
+ // }
+ // return Column(
+ // mainAxisSize:
+ // MainAxisSize.min,
+ // crossAxisAlignment:
+ // CrossAxisAlignment
+ // .start,
+ // children: [
+ // Text(
+ // "Monero Build Commit",
+ // style: STextStyles
+ // .desktopTextExtraExtraSmall(
+ // context,
+ // ).copyWith(
+ // color: Theme.of(
+ // context,
+ // )
+ // .extension<
+ // StackColors>()!
+ // .textDark,
+ // ),
+ // ),
+ // const SizedBox(
+ // height: 2,
+ // ),
+ // SelectableText(
+ // GitStatus.moneroCommit,
+ // style: GitStatus
+ // .styleForStatus(
+ // stateOfCommit,
+ // context,
+ // ),
+ // ),
+ // ],
+ // );
+ // },
+ // ),
],
),
const SizedBox(height: 35),
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index b449525b6..6c58b600e 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -1456,7 +1456,7 @@ class RouteGenerator {
case RestoreWalletView.routeName:
if (args
- is Tuple6) {
+ is Tuple6) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => RestoreWalletView(
diff --git a/lib/services/wallets.dart b/lib/services/wallets.dart
index c4e75bde8..d7b93cf33 100644
--- a/lib/services/wallets.dart
+++ b/lib/services/wallets.dart
@@ -10,8 +10,7 @@
import 'dart:async';
-import 'package:flutter_libmonero/monero/monero.dart' as monero;
-import 'package:flutter_libmonero/wownero/wownero.dart' as wownero;
+import 'package:compat/compat.dart' as lib_monero_compat;
import 'package:isar/isar.dart';
import '../app_config.dart';
@@ -21,11 +20,12 @@ import '../utilities/enums/sync_type_enum.dart';
import '../utilities/flutter_secure_storage_interface.dart';
import '../utilities/logger.dart';
import '../utilities/prefs.dart';
+import '../utilities/stack_file_system.dart';
import '../wallets/crypto_currency/crypto_currency.dart';
import '../wallets/isar/models/wallet_info.dart';
import '../wallets/wallet/impl/epiccash_wallet.dart';
+import '../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../wallets/wallet/wallet.dart';
-import '../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
import 'event_bus/events/wallet_added_event.dart';
import 'event_bus/global_event_bus.dart';
import 'node_service.dart';
@@ -86,15 +86,19 @@ class Wallets {
await secureStorage.delete(key: Wallet.privateKeyKey(walletId: walletId));
if (info.coin is Wownero) {
- final wowService = wownero.wownero
- .createWowneroWalletService(DB.instance.moneroWalletInfoBox);
- await wowService.remove(walletId);
+ await lib_monero_compat.deleteWalletFiles(
+ name: walletId,
+ type: lib_monero_compat.WalletType.wownero,
+ appRoot: await StackFileSystem.applicationRootDirectory(),
+ );
Logging.instance
.log("monero wallet: $walletId deleted", level: LogLevel.Info);
} else if (info.coin is Monero) {
- final xmrService = monero.monero
- .createMoneroWalletService(DB.instance.moneroWalletInfoBox);
- await xmrService.remove(walletId);
+ await lib_monero_compat.deleteWalletFiles(
+ name: walletId,
+ type: lib_monero_compat.WalletType.monero,
+ appRoot: await StackFileSystem.applicationRootDirectory(),
+ );
Logging.instance
.log("monero wallet: $walletId deleted", level: LogLevel.Info);
} else if (info.coin is Epiccash) {
@@ -220,7 +224,7 @@ class Wallets {
final shouldSetAutoSync = shouldAutoSyncAll ||
walletIdsToEnableAutoSync.contains(walletInfo.walletId);
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
// walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
} else {
walletInitFutures.add(
@@ -327,7 +331,7 @@ class Wallets {
nodeService: nodeService,
prefs: prefs,
).then((wallet) {
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
// walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
walletIdCompleter.complete("dummy_ignore");
@@ -457,7 +461,7 @@ class Wallets {
nodeService: nodeService,
prefs: prefs,
).then((wallet) {
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
// walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
walletIdCompleter.complete("dummy_ignore");
@@ -577,7 +581,7 @@ class Wallets {
walletIdsToEnableAutoSync.contains(wallet.walletId);
if (isDesktop) {
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
// walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
} else {
walletInitFutures.add(
diff --git a/lib/utilities/git_status.dart b/lib/utilities/git_status.dart
index 818660427..093bc39af 100644
--- a/lib/utilities/git_status.dart
+++ b/lib/utilities/git_status.dart
@@ -2,7 +2,7 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_libepiccash/git_versions.dart' as epic_versions;
-import 'package:flutter_libmonero/git_versions.dart' as monero_versions;
+// import 'package:flutter_libmonero/git_versions.dart' as monero_versions;
import 'package:http/http.dart';
import 'package:lelantus/git_versions.dart' as firo_versions;
@@ -20,7 +20,7 @@ enum CommitStatus { isHead, isOldCommit, notACommit, notLoaded }
abstract class GitStatus {
static String get firoCommit => firo_versions.getPluginVersion();
static String get epicCashCommit => epic_versions.getPluginVersion();
- static String get moneroCommit => monero_versions.getPluginVersion();
+ // static String get moneroCommit => monero_versions.getPluginVersion();
static String get appCommitHash => AppConfig.commitHash;
@@ -78,31 +78,31 @@ abstract class GitStatus {
return _cachedEpicStatus!;
}
-
- static CommitStatus? _cachedMoneroStatus;
- static Future getMoneroCommitStatus() async {
- if (_cachedMoneroStatus != null) {
- return _cachedMoneroStatus!;
- }
-
- final List results = await Future.wait([
- _doesCommitExist("cypherstack", "flutter_libmonero", moneroCommit),
- _isHeadCommit("cypherstack", "flutter_libmonero", "main", moneroCommit),
- ]);
-
- final commitExists = results[0];
- final commitIsHead = results[1];
-
- if (commitExists && commitIsHead) {
- _cachedMoneroStatus = CommitStatus.isHead;
- } else if (commitExists) {
- _cachedMoneroStatus = CommitStatus.isOldCommit;
- } else {
- _cachedMoneroStatus = CommitStatus.notACommit;
- }
-
- return _cachedMoneroStatus!;
- }
+ //
+ // static CommitStatus? _cachedMoneroStatus;
+ // static Future getMoneroCommitStatus() async {
+ // if (_cachedMoneroStatus != null) {
+ // return _cachedMoneroStatus!;
+ // }
+ //
+ // final List results = await Future.wait([
+ // _doesCommitExist("cypherstack", "flutter_libmonero", moneroCommit),
+ // _isHeadCommit("cypherstack", "flutter_libmonero", "main", moneroCommit),
+ // ]);
+ //
+ // final commitExists = results[0];
+ // final commitIsHead = results[1];
+ //
+ // if (commitExists && commitIsHead) {
+ // _cachedMoneroStatus = CommitStatus.isHead;
+ // } else if (commitExists) {
+ // _cachedMoneroStatus = CommitStatus.isOldCommit;
+ // } else {
+ // _cachedMoneroStatus = CommitStatus.notACommit;
+ // }
+ //
+ // return _cachedMoneroStatus!;
+ // }
static TextStyle styleForStatus(CommitStatus status, BuildContext context) {
final Color color;
diff --git a/lib/wallets/models/tx_data.dart b/lib/wallets/models/tx_data.dart
index 99a28a138..231cb99d7 100644
--- a/lib/wallets/models/tx_data.dart
+++ b/lib/wallets/models/tx_data.dart
@@ -1,5 +1,4 @@
-import 'package:cw_monero/pending_monero_transaction.dart';
-import 'package:cw_wownero/pending_wownero_transaction.dart';
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:tezart/tezart.dart' as tezart;
import 'package:web3dart/web3dart.dart' as web3dart;
@@ -49,11 +48,8 @@ class TxData {
final BigInt? chainId;
final BigInt? feeInWei;
- // wownero specific
- final PendingWowneroTransaction? pendingWowneroTransaction;
-
- // monero specific
- final PendingMoneroTransaction? pendingMoneroTransaction;
+ // wownero and monero specific
+ final lib_monero.PendingTransaction? pendingTransaction;
// firo lelantus specific
final int? jMintValue;
@@ -104,8 +100,7 @@ class TxData {
this.nonce,
this.chainId,
this.feeInWei,
- this.pendingWowneroTransaction,
- this.pendingMoneroTransaction,
+ this.pendingTransaction,
this.jMintValue,
this.spendCoinIndexes,
this.height,
@@ -196,8 +191,7 @@ class TxData {
int? nonce,
BigInt? chainId,
BigInt? feeInWei,
- PendingWowneroTransaction? pendingWowneroTransaction,
- PendingMoneroTransaction? pendingMoneroTransaction,
+ lib_monero.PendingTransaction? pendingTransaction,
int? jMintValue,
List? spendCoinIndexes,
int? height,
@@ -241,10 +235,7 @@ class TxData {
nonce: nonce ?? this.nonce,
chainId: chainId ?? this.chainId,
feeInWei: feeInWei ?? this.feeInWei,
- pendingWowneroTransaction:
- pendingWowneroTransaction ?? this.pendingWowneroTransaction,
- pendingMoneroTransaction:
- pendingMoneroTransaction ?? this.pendingMoneroTransaction,
+ pendingTransaction: pendingTransaction ?? this.pendingTransaction,
jMintValue: jMintValue ?? this.jMintValue,
spendCoinIndexes: spendCoinIndexes ?? this.spendCoinIndexes,
height: height ?? this.height,
@@ -284,8 +275,7 @@ class TxData {
'nonce: $nonce, '
'chainId: $chainId, '
'feeInWei: $feeInWei, '
- 'pendingWowneroTransaction: $pendingWowneroTransaction, '
- 'pendingMoneroTransaction: $pendingMoneroTransaction, '
+ 'pendingTransaction: $pendingTransaction, '
'jMintValue: $jMintValue, '
'spendCoinIndexes: $spendCoinIndexes, '
'height: $height, '
diff --git a/lib/wallets/wallet/impl/monero_wallet.dart b/lib/wallets/wallet/impl/monero_wallet.dart
index c3c3ea02a..0bc11c3e3 100644
--- a/lib/wallets/wallet/impl/monero_wallet.dart
+++ b/lib/wallets/wallet/impl/monero_wallet.dart
@@ -1,206 +1,51 @@
import 'dart:async';
-import 'dart:io';
-import 'dart:math';
-import 'package:cw_core/monero_transaction_priority.dart';
-import 'package:cw_core/node.dart';
-import 'package:cw_core/pending_transaction.dart';
-import 'package:cw_core/sync_status.dart';
-import 'package:cw_core/transaction_direction.dart';
-import 'package:cw_core/utxo.dart' as cw;
-import 'package:cw_core/wallet_base.dart';
-import 'package:cw_core/wallet_credentials.dart';
-import 'package:cw_core/wallet_info.dart';
-import 'package:cw_core/wallet_type.dart';
-import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart';
-import 'package:cw_monero/monero_wallet.dart';
-import 'package:cw_monero/monero_wallet_service.dart';
-import 'package:cw_monero/pending_monero_transaction.dart';
-import 'package:decimal/decimal.dart';
-import 'package:flutter_libmonero/core/wallet_creation_service.dart';
-import 'package:flutter_libmonero/monero/monero.dart' as xmr_dart;
-import 'package:flutter_libmonero/view_model/send/output.dart' as monero_output;
-import 'package:isar/isar.dart';
-import 'package:mutex/mutex.dart';
-import 'package:tuple/tuple.dart';
+import 'package:compat/compat.dart' as lib_monero_compat;
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
-import '../../../db/hive/db.dart';
-import '../../../models/isar/models/blockchain_data/address.dart';
-import '../../../models/isar/models/blockchain_data/transaction.dart';
-import '../../../models/isar/models/blockchain_data/utxo.dart';
-import '../../../models/keys/cw_key_data.dart';
-import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart';
-import '../../../services/event_bus/events/global/tor_status_changed_event.dart';
-import '../../../services/event_bus/global_event_bus.dart';
-import '../../../services/tor_service.dart';
import '../../../utilities/amount/amount.dart';
-import '../../../utilities/enums/fee_rate_type_enum.dart';
-import '../../../utilities/logger.dart';
import '../../crypto_currency/crypto_currency.dart';
-import '../../models/tx_data.dart';
-import '../intermediate/cryptonote_wallet.dart';
-import '../wallet.dart';
-import '../wallet_mixin_interfaces/cw_based_interface.dart';
+import '../intermediate/lib_monero_wallet.dart';
-class MoneroWallet extends CryptonoteWallet with CwBasedInterface {
- MoneroWallet(CryptoCurrencyNetwork network) : super(Monero(network)) {
- final bus = GlobalEventBus.instance;
-
- // Listen for tor status changes.
- _torStatusListener = bus.on().listen(
- (event) async {
- switch (event.newStatus) {
- case TorConnectionStatus.connecting:
- if (!_torConnectingLock.isLocked) {
- await _torConnectingLock.acquire();
- }
- _requireMutex = true;
- break;
-
- case TorConnectionStatus.connected:
- case TorConnectionStatus.disconnected:
- if (_torConnectingLock.isLocked) {
- _torConnectingLock.release();
- }
- _requireMutex = false;
- break;
- }
- },
- );
-
- // Listen for tor preference changes.
- _torPreferenceListener = bus.on().listen(
- (event) async {
- await updateNode();
- },
- );
-
- // Potentially dangerous hack. See comments in _startInit()
- _startInit();
- }
-
- // cw based wallet listener to handle synchronization of utxo frozen states
- late final StreamSubscription> _streamSub;
- Future _startInit() async {
- // Delay required as `mainDB` is not initialized in constructor.
- // This is a hack and could lead to a race condition.
- Future.delayed(const Duration(seconds: 2), () {
- _streamSub = mainDB.isar.utxos
- .where()
- .walletIdEqualTo(walletId)
- .watch(fireImmediately: true)
- .listen((utxos) async {
- await onUTXOsCHanged(utxos);
- await updateBalance(shouldUpdateUtxos: false);
- });
- });
- }
-
- @override
- MoneroWalletBase? cwWalletBase;
-
- @override
- MoneroWalletService? cwWalletService;
-
- @override
- Address addressFor({required int index, int account = 0}) {
- final String address = (cwWalletBase as MoneroWalletBase)
- .getTransactionAddress(account, index);
-
- final newReceivingAddress = Address(
- walletId: walletId,
- derivationIndex: index,
- derivationPath: null,
- value: address,
- publicKey: [],
- type: AddressType.cryptonote,
- subType: AddressSubType.receiving,
- );
-
- return newReceivingAddress;
- }
-
- @override
- Future open() async {
- String? password;
- try {
- password = await cwKeysStorage.getWalletPassword(walletName: walletId);
- } catch (e, s) {
- throw Exception("Password not found $e, $s");
- }
-
- bool wasNull = false;
-
- if (cwWalletBase == null) {
- wasNull = true;
- // cwWalletBaseT?.close();
- cwWalletBase ??= (await cwWalletService!.openWallet(walletId, password))
- as MoneroWalletBase;
-
- cwWalletBase?.onNewBlock ??= onNewBlock;
- cwWalletBase?.onNewTransaction ??= onNewTransaction;
- cwWalletBase?.syncStatusChanged ??= syncStatusChanged;
-
- await updateNode();
- }
-
- Address? currentAddress = await getCurrentReceivingAddress();
- if (currentAddress == null) {
- currentAddress = addressFor(index: 0);
- await mainDB.updateOrPutAddresses([currentAddress]);
- }
- if (info.cachedReceivingAddress != currentAddress.value) {
- await info.updateReceivingAddress(
- newAddress: currentAddress.value,
- isar: mainDB.isar,
- );
- }
-
- if (wasNull) {
- await cwWalletBase?.startSync();
- } else {
- cwWalletBase?.wallet.startListeners();
- }
- unawaited(refresh());
-
- autoSaveTimer?.cancel();
- autoSaveTimer = Timer.periodic(
- const Duration(seconds: 193),
- (_) async => await cwWalletBase?.save(),
- );
- }
+class MoneroWallet extends LibMoneroWallet {
+ MoneroWallet(CryptoCurrencyNetwork network)
+ : super(
+ Monero(network),
+ lib_monero_compat.WalletType.monero,
+ );
@override
Future estimateFeeFor(Amount amount, int feeRate) async {
- if (cwWalletBase == null || cwWalletBase?.syncStatus is! SyncedSyncStatus) {
+ if (libMoneroWallet == null ||
+ syncStatus is! lib_monero_compat.SyncedSyncStatus) {
return Amount.zeroWith(
fractionDigits: cryptoCurrency.fractionDigits,
);
}
- MoneroTransactionPriority priority;
+ lib_monero.TransactionPriority priority;
switch (feeRate) {
case 1:
- priority = MoneroTransactionPriority.regular;
+ priority = lib_monero.TransactionPriority.low;
break;
case 2:
- priority = MoneroTransactionPriority.medium;
+ priority = lib_monero.TransactionPriority.medium;
break;
case 3:
- priority = MoneroTransactionPriority.fast;
+ priority = lib_monero.TransactionPriority.high;
break;
case 4:
- priority = MoneroTransactionPriority.fastest;
+ priority = lib_monero.TransactionPriority.last;
break;
case 0:
default:
- priority = MoneroTransactionPriority.slow;
+ priority = lib_monero.TransactionPriority.normal;
break;
}
int approximateFee = 0;
await estimateFeeMutex.protect(() async {
- approximateFee = cwWalletBase!.calculateEstimatedFee(
+ approximateFee = await libMoneroWallet!.estimateFee(
priority,
amount.raw.toInt(),
);
@@ -213,573 +58,49 @@ class MoneroWallet extends CryptonoteWallet with CwBasedInterface {
}
@override
- Future pingCheck() async {
- return await cwWalletBase?.isConnected() ?? false;
- }
+ bool walletExists(String path) => lib_monero.MoneroWallet.isWalletExist(path);
@override
- Future updateNode() async {
- final node = getCurrentNode();
-
- String host = Uri.parse(node.host).host;
- if (host.isEmpty) {
- host = node.host;
- }
- ({InternetAddress host, int port})? proxy;
- if (prefs.useTor) {
- proxy = TorService.sharedInstance.getProxyInfo();
- }
- if (_requireMutex) {
- await _torConnectingLock.protect(() async {
- await cwWalletBase?.connectToNode(
- node: Node(
- uri: "$host:${node.port}",
- type: WalletType.monero,
- trusted: node.trusted ?? false,
- useSSL: node.useSSL,
- ),
- socksProxyAddress:
- proxy == null ? null : "${proxy.host.address}:${proxy.port}",
- );
- });
- } else {
- await cwWalletBase?.connectToNode(
- node: Node(
- uri: "$host:${node.port}",
- type: WalletType.monero,
- trusted: node.trusted ?? false,
- useSSL: node.useSSL,
- ),
- socksProxyAddress:
- proxy == null ? null : "${proxy.host.address}:${proxy.port}",
- );
- }
-
- return;
- }
-
- @override
- Future getKeys() async {
- final base = cwWalletBase;
-
- if (base == null || base.walletInfo.name != walletId) {
- return null;
- }
-
- return CWKeyData(
- walletId: walletId,
- publicViewKey: base.keys.publicViewKey,
- privateViewKey: base.keys.privateViewKey,
- publicSpendKey: base.keys.publicSpendKey,
- privateSpendKey: base.keys.privateSpendKey,
+ void loadWallet({
+ required String path,
+ required String password,
+ }) {
+ libMoneroWallet = lib_monero.MoneroWallet.loadWallet(
+ path: path,
+ password: password,
);
}
@override
- Future updateTransactions() async {
- final base = cwWalletBase;
-
- if (base == null || base.walletInfo.name != walletId) {
- return;
- }
- await base.updateTransactions();
- final transactions = base.transactionHistory?.transactions;
-
- // final cachedTransactions =
- // DB.instance.get(boxName: walletId, key: 'latest_tx_model')
- // as TransactionData?;
- // int latestTxnBlockHeight =
- // DB.instance.get(boxName: walletId, key: "storedTxnDataHeight")
- // as int? ??
- // 0;
- //
- // final txidsList = DB.instance
- // .get(boxName: walletId, key: "cachedTxids") as List? ??
- // [];
- //
- // final Set cachedTxids = Set.from(txidsList);
-
- // TODO: filter to skip cached + confirmed txn processing in next step
- // final unconfirmedCachedTransactions =
- // cachedTransactions?.getAllTransactions() ?? {};
- // unconfirmedCachedTransactions
- // .removeWhere((key, value) => value.confirmedStatus);
- //
- // if (cachedTransactions != null) {
- // for (final tx in allTxHashes.toList(growable: false)) {
- // final txHeight = tx["height"] as int;
- // if (txHeight > 0 &&
- // txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS) {
- // if (unconfirmedCachedTransactions[tx["tx_hash"] as String] == null) {
- // allTxHashes.remove(tx);
- // }
- // }
- // }
- // }
-
- final List> txnsData = [];
-
- if (transactions != null) {
- for (final tx in transactions.entries) {
- Address? address;
- TransactionType type;
- if (tx.value.direction == TransactionDirection.incoming) {
- final addressInfo = tx.value.additionalInfo;
-
- final addressString = cwWalletBase?.getTransactionAddress(
- addressInfo!['accountIndex'] as int,
- addressInfo['addressIndex'] as int,
- );
-
- if (addressString != null) {
- address = await mainDB
- .getAddresses(walletId)
- .filter()
- .valueEqualTo(addressString)
- .findFirst();
- }
-
- type = TransactionType.incoming;
- } else {
- // txn.address = "";
- type = TransactionType.outgoing;
- }
-
- final txn = Transaction(
- walletId: walletId,
- txid: tx.value.id,
- timestamp: (tx.value.date.millisecondsSinceEpoch ~/ 1000),
- type: type,
- subType: TransactionSubType.none,
- amount: tx.value.amount ?? 0,
- amountString: Amount(
- rawValue: BigInt.from(tx.value.amount ?? 0),
- fractionDigits: cryptoCurrency.fractionDigits,
- ).toJsonString(),
- fee: tx.value.fee ?? 0,
- height: tx.value.height,
- isCancelled: false,
- isLelantus: false,
- slateId: null,
- otherData: null,
- nonce: null,
- inputs: [],
- outputs: [],
- numberOfMessages: null,
- );
-
- txnsData.add(Tuple2(txn, address));
- }
- }
-
- await mainDB.isar.writeTxn(() async {
- await mainDB.isar.transactions
- .where()
- .walletIdEqualTo(walletId)
- .deleteAll();
- for (final data in txnsData) {
- final tx = data.item1;
-
- // save transaction
- await mainDB.isar.transactions.put(tx);
-
- if (data.item2 != null) {
- final address = await mainDB.getAddress(walletId, data.item2!.value);
-
- // check if address exists in db and add if it does not
- if (address == null) {
- await mainDB.isar.addresses.put(data.item2!);
- }
-
- // link and save address
- tx.address.value = address ?? data.item2!;
- await tx.address.save();
- }
- }
- });
- }
-
- @override
- Future init({bool? isRestore}) async {
- cwWalletService ??= xmr_dart.monero
- .createMoneroWalletService(DB.instance.moneroWalletInfoBox)
- as MoneroWalletService;
-
- if (!(await cwWalletService!.isWalletExist(walletId)) &&
- isRestore != true) {
- WalletInfo walletInfo;
- WalletCredentials credentials;
- try {
- final dirPath =
- await pathForWalletDir(name: walletId, type: WalletType.monero);
- final path =
- await pathForWallet(name: walletId, type: WalletType.monero);
- credentials = xmr_dart.monero.createMoneroNewWalletCredentials(
- name: walletId,
- language: "English",
- );
-
- walletInfo = WalletInfo.external(
- id: WalletBase.idFor(walletId, WalletType.monero),
- name: walletId,
- type: WalletType.monero,
- isRecovery: false,
- restoreHeight: credentials.height ?? 0,
- date: DateTime.now(),
- path: path,
- dirPath: dirPath,
- address: '',
- );
- credentials.walletInfo = walletInfo;
-
- final _walletCreationService = WalletCreationService(
- secureStorage: secureStorageInterface,
- walletService: cwWalletService!,
- keyService: cwKeysStorage,
- type: WalletType.monero,
- );
- // To restore from a seed
- final wallet = await _walletCreationService.create(credentials);
-
- // subtract a couple days to ensure we have a buffer for SWB
- final bufferedCreateHeight = xmr_dart.monero.getHeigthByDate(
- date: DateTime.now().subtract(const Duration(days: 2)),
- );
-
- await info.updateRestoreHeight(
- newRestoreHeight: bufferedCreateHeight,
- isar: mainDB.isar,
- );
-
- // special case for xmr/wow. Normally mnemonic + passphrase is saved
- // before wallet.init() is called
- await secureStorageInterface.write(
- key: Wallet.mnemonicKey(walletId: walletId),
- value: wallet.seed.trim(),
- );
- await secureStorageInterface.write(
- key: Wallet.mnemonicPassphraseKey(walletId: walletId),
- value: "",
- );
-
- walletInfo.restoreHeight = bufferedCreateHeight;
-
- walletInfo.address = wallet.walletAddresses.address;
- await DB.instance
- .add(boxName: WalletInfo.boxName, value: walletInfo);
-
- wallet.close();
- } catch (e, s) {
- Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
- cwWalletBase?.close();
- }
- await updateNode();
- }
-
- return super.init();
- }
-
- @override
- Future recover({required bool isRescan}) async {
- if (isRescan) {
- await refreshMutex.protect(() async {
- // clear blockchain info
- await mainDB.deleteWalletBlockchainData(walletId);
-
- final restoreHeight = cwWalletBase?.walletInfo.restoreHeight;
- highestPercentCached = 0;
- await cwWalletBase?.rescan(height: restoreHeight ?? 0);
- });
- unawaited(refresh());
- return;
- }
-
- await refreshMutex.protect(() async {
- final mnemonic = await getMnemonic();
- final seedLength = mnemonic.trim().split(" ").length;
-
- if (seedLength != 25 && seedLength != 16) {
- throw Exception("Invalid monero mnemonic length found: $seedLength");
- }
-
- try {
- final height = max(info.restoreHeight, 0);
-
- await info.updateRestoreHeight(
- newRestoreHeight: height,
- isar: mainDB.isar,
- );
-
- cwWalletService = xmr_dart.monero
- .createMoneroWalletService(DB.instance.moneroWalletInfoBox)
- as MoneroWalletService;
- WalletInfo walletInfo;
- WalletCredentials credentials;
- final String name = walletId;
- final dirPath =
- await pathForWalletDir(name: name, type: WalletType.monero);
- final path = await pathForWallet(name: name, type: WalletType.monero);
- credentials =
- xmr_dart.monero.createMoneroRestoreWalletFromSeedCredentials(
- name: name,
- height: height,
- mnemonic: mnemonic.trim(),
- );
- try {
- walletInfo = WalletInfo.external(
- id: WalletBase.idFor(name, WalletType.monero),
- name: name,
- type: WalletType.monero,
- isRecovery: false,
- restoreHeight: credentials.height ?? 0,
- date: DateTime.now(),
- path: path,
- dirPath: dirPath,
- address: '',
- );
- credentials.walletInfo = walletInfo;
-
- final cwWalletCreationService = WalletCreationService(
- secureStorage: secureStorageInterface,
- walletService: cwWalletService!,
- keyService: cwKeysStorage,
- type: WalletType.monero,
- );
- // To restore from a seed
- final wallet =
- await cwWalletCreationService.restoreFromSeed(credentials);
- walletInfo.address = wallet.walletAddresses.address;
- await DB.instance
- .add(boxName: WalletInfo.boxName, value: walletInfo);
- cwWalletBase?.close();
- cwWalletBase = wallet as MoneroWalletBase;
- cwWalletBase?.onNewBlock = onNewBlock;
- cwWalletBase?.onNewTransaction = onNewTransaction;
- cwWalletBase?.syncStatusChanged = syncStatusChanged;
- if (walletInfo.address != null) {
- final newReceivingAddress = await getCurrentReceivingAddress() ??
- Address(
- walletId: walletId,
- derivationIndex: 0,
- derivationPath: null,
- value: walletInfo.address!,
- publicKey: [],
- type: AddressType.cryptonote,
- subType: AddressSubType.receiving,
- );
-
- await mainDB.updateOrPutAddresses([newReceivingAddress]);
- await info.updateReceivingAddress(
- newAddress: newReceivingAddress.value,
- isar: mainDB.isar,
- );
- }
- } catch (e, s) {
- Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
- }
- await updateNode();
-
- await cwWalletBase?.rescan(height: credentials.height);
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from recoverFromMnemonic(): $e\n$s",
- level: LogLevel.Error,
- );
- rethrow;
- }
- });
- }
-
- @override
- Future prepareSend({required TxData txData}) async {
- try {
- final feeRate = txData.feeRateType;
- if (feeRate is FeeRateType) {
- MoneroTransactionPriority feePriority;
- switch (feeRate) {
- case FeeRateType.fast:
- feePriority = MoneroTransactionPriority.fast;
- break;
- case FeeRateType.average:
- feePriority = MoneroTransactionPriority.regular;
- break;
- case FeeRateType.slow:
- feePriority = MoneroTransactionPriority.slow;
- break;
- default:
- throw ArgumentError("Invalid use of custom fee");
- }
-
- Future? awaitPendingTransaction;
- try {
- // check for send all
- bool isSendAll = false;
- final balance = await availableBalance;
- if (txData.amount! == balance &&
- txData.recipients!.first.amount == balance) {
- isSendAll = true;
- }
-
- final List outputs = [];
- for (final recipient in txData.recipients!) {
- final output = monero_output.Output(cwWalletBase!);
- output.address = recipient.address;
- output.sendAll = isSendAll;
- final String amountToSend = recipient.amount.decimal.toString();
- output.setCryptoAmount(amountToSend);
- outputs.add(output);
- }
-
- final tmp =
- xmr_dart.monero.createMoneroTransactionCreationCredentials(
- outputs: outputs,
- priority: feePriority,
- );
-
- final height = await chainHeight;
- final inputs = txData.utxos
- ?.map(
- (e) => cw.UTXO(
- address: e.address!,
- hash: e.txid,
- keyImage: e.keyImage!,
- value: e.value,
- isFrozen: e.isBlocked,
- isUnlocked: e.blockHeight != null &&
- (height - (e.blockHeight ?? 0)) >=
- cryptoCurrency.minConfirms,
- height: e.blockHeight ?? 0,
- vout: e.vout,
- spent: e.used ?? false,
- coinbase: e.isCoinbase,
- ),
- )
- .toList();
-
- await prepareSendMutex.protect(() async {
- awaitPendingTransaction = cwWalletBase!.createTransaction(
- tmp,
- inputs: inputs,
- );
- });
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from prepareSend(): $e\n$s",
- level: LogLevel.Warning,
- );
- }
-
- final PendingMoneroTransaction pendingMoneroTransaction =
- await (awaitPendingTransaction!) as PendingMoneroTransaction;
- final realFee = Amount.fromDecimal(
- Decimal.parse(pendingMoneroTransaction.feeFormatted),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
-
- return txData.copyWith(
- fee: realFee,
- pendingMoneroTransaction: pendingMoneroTransaction,
- );
- } else {
- throw ArgumentError("Invalid fee rate argument provided!");
- }
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from prepare send(): $e\n$s",
- level: LogLevel.Info,
+ Future getCreatedWallet({
+ required String path,
+ required String password,
+ }) async =>
+ await lib_monero.MoneroWallet.create(
+ path: path,
+ password: password,
+ seedType: lib_monero.MoneroSeedType
+ .sixteen, // TODO: check we want to actually use 16 here
);
- if (e.toString().contains("Incorrect unlocked balance")) {
- throw Exception("Insufficient balance!");
- } else if (e is CreationTransactionException) {
- throw Exception("Insufficient funds to pay for transaction fee!");
- } else {
- throw Exception("Transaction failed with error code $e");
- }
- }
- }
-
@override
- Future confirmSend({required TxData txData}) async {
- try {
- try {
- await txData.pendingMoneroTransaction!.commit();
- Logging.instance.log(
- "transaction ${txData.pendingMoneroTransaction!.id} has been sent",
- level: LogLevel.Info,
- );
- return txData.copyWith(txid: txData.pendingMoneroTransaction!.id);
- } catch (e, s) {
- Logging.instance.log(
- "${info.name} monero confirmSend: $e\n$s",
- level: LogLevel.Error,
- );
- rethrow;
- }
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from confirmSend(): $e\n$s",
- level: LogLevel.Info,
+ Future getRestoredWallet({
+ required String path,
+ required String password,
+ required String mnemonic,
+ int height = 0,
+ }) async =>
+ await lib_monero.MoneroWallet.restoreWalletFromSeed(
+ path: path,
+ password: password,
+ seed: mnemonic,
+ restoreHeight: height,
);
- rethrow;
- }
- }
@override
- Future get availableBalance async {
- try {
- int runningBalance = 0;
- for (final entry in cwWalletBase!.balance!.entries) {
- runningBalance += entry.value.unlockedBalance;
- }
- return Amount(
- rawValue: BigInt.from(runningBalance),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
- } catch (_) {
- return info.cachedBalance.spendable;
+ void invalidSeedLengthCheck(int length) {
+ if (length != 25 && length != 16) {
+ throw Exception("Invalid monero mnemonic length found: $length");
}
}
-
- @override
- Future get totalBalance async {
- try {
- final balanceEntries = cwWalletBase?.balance?.entries;
- if (balanceEntries != null) {
- int bal = 0;
- for (final element in balanceEntries) {
- bal = bal + element.value.fullBalance;
- }
- return Amount(
- rawValue: BigInt.from(bal),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
- } else {
- final transactions = cwWalletBase!.transactionHistory!.transactions;
- int transactionBalance = 0;
- for (final tx in transactions!.entries) {
- if (tx.value.direction == TransactionDirection.incoming) {
- transactionBalance += tx.value.amount!;
- } else {
- transactionBalance += -tx.value.amount! - tx.value.fee!;
- }
- }
-
- return Amount(
- rawValue: BigInt.from(transactionBalance),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
- }
- } catch (_) {
- return info.cachedBalance.total;
- }
- }
-
- // ============== Private ====================================================
-
- StreamSubscription? _torStatusListener;
- StreamSubscription? _torPreferenceListener;
-
- final Mutex _torConnectingLock = Mutex();
- bool _requireMutex = false;
}
diff --git a/lib/wallets/wallet/impl/wownero_wallet.dart b/lib/wallets/wallet/impl/wownero_wallet.dart
index 40c8cd644..afcfee319 100644
--- a/lib/wallets/wallet/impl/wownero_wallet.dart
+++ b/lib/wallets/wallet/impl/wownero_wallet.dart
@@ -1,157 +1,52 @@
import 'dart:async';
-import 'dart:io';
-import 'dart:math';
-import 'package:cw_core/monero_transaction_priority.dart';
-import 'package:cw_core/node.dart';
-import 'package:cw_core/pending_transaction.dart';
-import 'package:cw_core/sync_status.dart';
-import 'package:cw_core/transaction_direction.dart';
-import 'package:cw_core/utxo.dart' as cw;
-import 'package:cw_core/wallet_base.dart';
-import 'package:cw_core/wallet_credentials.dart';
-import 'package:cw_core/wallet_info.dart';
-import 'package:cw_core/wallet_type.dart';
-import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart';
-import 'package:cw_wownero/pending_wownero_transaction.dart';
-import 'package:cw_wownero/wownero_wallet.dart';
-import 'package:cw_wownero/wownero_wallet_service.dart';
-import 'package:decimal/decimal.dart';
-import 'package:flutter_libmonero/core/wallet_creation_service.dart';
-import 'package:flutter_libmonero/view_model/send/output.dart'
- as wownero_output;
-import 'package:flutter_libmonero/wownero/wownero.dart' as wow_dart;
-import 'package:isar/isar.dart';
-import 'package:monero/wownero.dart' as wownerodart;
-import 'package:mutex/mutex.dart';
-import 'package:tuple/tuple.dart';
+import 'package:compat/compat.dart' as lib_monero_compat;
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
-import '../../../db/hive/db.dart';
-import '../../../models/isar/models/blockchain_data/address.dart';
-import '../../../models/isar/models/blockchain_data/transaction.dart';
-import '../../../models/isar/models/blockchain_data/utxo.dart';
-import '../../../models/keys/cw_key_data.dart';
-import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart';
-import '../../../services/event_bus/events/global/tor_status_changed_event.dart';
-import '../../../services/event_bus/global_event_bus.dart';
-import '../../../services/tor_service.dart';
import '../../../utilities/amount/amount.dart';
import '../../../utilities/enums/fee_rate_type_enum.dart';
-import '../../../utilities/logger.dart';
import '../../crypto_currency/crypto_currency.dart';
import '../../models/tx_data.dart';
-import '../intermediate/cryptonote_wallet.dart';
-import '../wallet.dart';
-import '../wallet_mixin_interfaces/cw_based_interface.dart';
+import '../intermediate/lib_monero_wallet.dart';
-class WowneroWallet extends CryptonoteWallet with CwBasedInterface {
- WowneroWallet(CryptoCurrencyNetwork network) : super(Wownero(network)) {
- final bus = GlobalEventBus.instance;
-
- // Listen for tor status changes.
- _torStatusListener = bus.on().listen(
- (event) async {
- switch (event.newStatus) {
- case TorConnectionStatus.connecting:
- if (!_torConnectingLock.isLocked) {
- await _torConnectingLock.acquire();
- }
- _requireMutex = true;
- break;
-
- case TorConnectionStatus.connected:
- case TorConnectionStatus.disconnected:
- if (_torConnectingLock.isLocked) {
- _torConnectingLock.release();
- }
- _requireMutex = false;
- break;
- }
- },
- );
-
- // Listen for tor preference changes.
- _torPreferenceListener = bus.on().listen(
- (event) async {
- await updateNode();
- },
- );
-
- // Potentially dangerous hack. See comments in _startInit()
- _startInit();
- }
-
- // cw based wallet listener to handle synchronization of utxo frozen states
- late final StreamSubscription> _streamSub;
- Future _startInit() async {
- // Delay required as `mainDB` is not initialized in constructor.
- // This is a hack and could lead to a race condition.
- Future.delayed(const Duration(seconds: 2), () {
- _streamSub = mainDB.isar.utxos
- .where()
- .walletIdEqualTo(walletId)
- .watch(fireImmediately: true)
- .listen((utxos) async {
- await onUTXOsCHanged(utxos);
- await updateBalance(shouldUpdateUtxos: false);
- });
- });
- }
-
- @override
- WowneroWalletBase? cwWalletBase;
-
- @override
- WowneroWalletService? cwWalletService;
-
- @override
- Address addressFor({required int index, int account = 0}) {
- final String address = (cwWalletBase as WowneroWalletBase)
- .getTransactionAddress(account, index);
-
- final newReceivingAddress = Address(
- walletId: walletId,
- derivationIndex: index,
- derivationPath: null,
- value: address,
- publicKey: [],
- type: AddressType.cryptonote,
- subType: AddressSubType.receiving,
- );
-
- return newReceivingAddress;
- }
+class WowneroWallet extends LibMoneroWallet {
+ WowneroWallet(CryptoCurrencyNetwork network)
+ : super(
+ Wownero(network),
+ lib_monero_compat.WalletType.wownero,
+ );
@override
Future estimateFeeFor(Amount amount, int feeRate) async {
- if (cwWalletBase == null || cwWalletBase?.syncStatus is! SyncedSyncStatus) {
+ if (libMoneroWallet == null ||
+ syncStatus is! lib_monero_compat.SyncedSyncStatus) {
return Amount.zeroWith(
fractionDigits: cryptoCurrency.fractionDigits,
);
}
- MoneroTransactionPriority priority;
+ lib_monero.TransactionPriority priority;
FeeRateType feeRateType = FeeRateType.slow;
switch (feeRate) {
case 1:
- priority = MoneroTransactionPriority.regular;
+ priority = lib_monero.TransactionPriority.low;
feeRateType = FeeRateType.average;
break;
case 2:
- priority = MoneroTransactionPriority.medium;
+ priority = lib_monero.TransactionPriority.medium;
feeRateType = FeeRateType.average;
break;
case 3:
- priority = MoneroTransactionPriority.fast;
+ priority = lib_monero.TransactionPriority.high;
feeRateType = FeeRateType.fast;
break;
case 4:
- priority = MoneroTransactionPriority.fastest;
+ priority = lib_monero.TransactionPriority.last;
feeRateType = FeeRateType.fast;
break;
case 0:
default:
- priority = MoneroTransactionPriority.slow;
+ priority = lib_monero.TransactionPriority.normal;
feeRateType = FeeRateType.slow;
break;
}
@@ -179,7 +74,7 @@ class WowneroWallet extends CryptonoteWallet with CwBasedInterface {
// unsure why this delay?
await Future.delayed(const Duration(milliseconds: 500));
} catch (e) {
- approximateFee = cwWalletBase!.calculateEstimatedFee(
+ approximateFee = libMoneroWallet!.estimateFee(
priority,
amount.raw.toInt(),
);
@@ -198,634 +93,51 @@ class WowneroWallet extends CryptonoteWallet with CwBasedInterface {
}
@override
- Future pingCheck() async {
- return await cwWalletBase?.isConnected() ?? false;
- }
+ bool walletExists(String path) =>
+ lib_monero.WowneroWallet.isWalletExist(path);
@override
- Future updateNode() async {
- final node = getCurrentNode();
-
- final host = Uri.parse(node.host).host;
- ({InternetAddress host, int port})? proxy;
- if (prefs.useTor) {
- proxy = TorService.sharedInstance.getProxyInfo();
- }
- if (_requireMutex) {
- await _torConnectingLock.protect(() async {
- await cwWalletBase?.connectToNode(
- node: Node(
- uri: "$host:${node.port}",
- type: WalletType.wownero,
- trusted: node.trusted ?? false,
- useSSL: node.useSSL,
- ),
- socksProxyAddress:
- proxy == null ? null : "${proxy.host.address}:${proxy.port}",
- );
- });
- } else {
- await cwWalletBase?.connectToNode(
- node: Node(
- uri: "$host:${node.port}",
- type: WalletType.wownero,
- trusted: node.trusted ?? false,
- useSSL: node.useSSL,
- ),
- socksProxyAddress:
- proxy == null ? null : "${proxy.host.address}:${proxy.port}",
- );
- }
-
- return;
- }
-
- @override
- Future getKeys() async {
- final base = cwWalletBase;
-
- if (base == null || base.walletInfo.name != walletId) {
- return null;
- }
-
- return CWKeyData(
- walletId: walletId,
- publicViewKey: base.keys.publicViewKey,
- privateViewKey: base.keys.privateViewKey,
- publicSpendKey: base.keys.publicSpendKey,
- privateSpendKey: base.keys.privateSpendKey,
+ void loadWallet({
+ required String path,
+ required String password,
+ }) {
+ libMoneroWallet = lib_monero.WowneroWallet.loadWallet(
+ path: path,
+ password: password,
);
}
@override
- Future updateTransactions() async {
- final base = cwWalletBase;
-
- if (base == null || base.walletInfo.name != walletId) {
- return;
- }
- await base.updateTransactions();
- final transactions = base.transactionHistory?.transactions;
-
- // final cachedTransactions =
- // DB.instance.get(boxName: walletId, key: 'latest_tx_model')
- // as TransactionData?;
- // int latestTxnBlockHeight =
- // DB.instance.get(boxName: walletId, key: "storedTxnDataHeight")
- // as int? ??
- // 0;
- //
- // final txidsList = DB.instance
- // .get(boxName: walletId, key: "cachedTxids") as List? ??
- // [];
- //
- // final Set cachedTxids = Set.from(txidsList);
-
- // TODO: filter to skip cached + confirmed txn processing in next step
- // final unconfirmedCachedTransactions =
- // cachedTransactions?.getAllTransactions() ?? {};
- // unconfirmedCachedTransactions
- // .removeWhere((key, value) => value.confirmedStatus);
- //
- // if (cachedTransactions != null) {
- // for (final tx in allTxHashes.toList(growable: false)) {
- // final txHeight = tx["height"] as int;
- // if (txHeight > 0 &&
- // txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS) {
- // if (unconfirmedCachedTransactions[tx["tx_hash"] as String] == null) {
- // allTxHashes.remove(tx);
- // }
- // }
- // }
- // }
-
- final List> txnsData = [];
-
- if (transactions != null) {
- for (final tx in transactions.entries) {
- Address? address;
- TransactionType type;
- if (tx.value.direction == TransactionDirection.incoming) {
- final addressInfo = tx.value.additionalInfo;
-
- final addressString = cwWalletBase?.getTransactionAddress(
- addressInfo!['accountIndex'] as int,
- addressInfo['addressIndex'] as int,
- );
-
- if (addressString != null) {
- address = await mainDB
- .getAddresses(walletId)
- .filter()
- .valueEqualTo(addressString)
- .findFirst();
- }
-
- type = TransactionType.incoming;
- } else {
- // txn.address = "";
- type = TransactionType.outgoing;
- }
-
- final txn = Transaction(
- walletId: walletId,
- txid: tx.value.id,
- timestamp: (tx.value.date.millisecondsSinceEpoch ~/ 1000),
- type: type,
- subType: TransactionSubType.none,
- amount: tx.value.amount ?? 0,
- amountString: Amount(
- rawValue: BigInt.from(tx.value.amount ?? 0),
- fractionDigits: cryptoCurrency.fractionDigits,
- ).toJsonString(),
- fee: tx.value.fee ?? 0,
- height: tx.value.height,
- isCancelled: false,
- isLelantus: false,
- slateId: null,
- otherData: null,
- nonce: null,
- inputs: [],
- outputs: [],
- numberOfMessages: null,
- );
-
- txnsData.add(Tuple2(txn, address));
- }
- }
-
- await mainDB.isar.writeTxn(() async {
- await mainDB.isar.transactions
- .where()
- .walletIdEqualTo(walletId)
- .deleteAll();
- for (final data in txnsData) {
- final tx = data.item1;
-
- // save transaction
- await mainDB.isar.transactions.put(tx);
-
- if (data.item2 != null) {
- final address = await mainDB.getAddress(walletId, data.item2!.value);
-
- // check if address exists in db and add if it does not
- if (address == null) {
- await mainDB.isar.addresses.put(data.item2!);
- }
-
- // link and save address
- tx.address.value = address ?? data.item2!;
- await tx.address.save();
- }
- }
- });
- }
-
- @override
- Future init({bool? isRestore}) async {
- cwWalletService = wow_dart.wownero
- .createWowneroWalletService(DB.instance.moneroWalletInfoBox)
- as WowneroWalletService;
-
- if (!(await cwWalletService!.isWalletExist(walletId)) &&
- isRestore != true) {
- WalletInfo walletInfo;
- WalletCredentials credentials;
- try {
- final dirPath =
- await pathForWalletDir(name: walletId, type: WalletType.wownero);
- final path =
- await pathForWallet(name: walletId, type: WalletType.wownero);
- credentials = wow_dart.wownero.createWowneroNewWalletCredentials(
- name: walletId,
- language: "English",
- seedWordsLength: 14,
- );
-
- walletInfo = WalletInfo.external(
- id: WalletBase.idFor(walletId, WalletType.wownero),
- name: walletId,
- type: WalletType.wownero,
- isRecovery: false,
- restoreHeight: credentials.height ?? 0,
- date: DateTime.now(),
- path: path,
- dirPath: dirPath,
- address: '',
- );
- credentials.walletInfo = walletInfo;
-
- final _walletCreationService = WalletCreationService(
- secureStorage: secureStorageInterface,
- walletService: cwWalletService!,
- keyService: cwKeysStorage,
- type: WalletType.wownero,
- );
- // To restore from a seed
- final wallet = await _walletCreationService.create(credentials)
- as WowneroWalletBase;
-
- final height =
- wownerodart.Wallet_getRefreshFromBlockHeight(wallet.wallet.wptr);
-
- await info.updateRestoreHeight(
- newRestoreHeight: height,
- isar: mainDB.isar,
- );
-
- // special case for xmr/wow. Normally mnemonic + passphrase is saved
- // before wallet.init() is called
- await secureStorageInterface.write(
- key: Wallet.mnemonicKey(walletId: walletId),
- value: wallet.seed.trim(),
- );
- await secureStorageInterface.write(
- key: Wallet.mnemonicPassphraseKey(walletId: walletId),
- value: "",
- );
-
- walletInfo.restoreHeight = height;
-
- walletInfo.address = wallet.walletAddresses.address;
- await DB.instance
- .add(boxName: WalletInfo.boxName, value: walletInfo);
-
- wallet.close();
- } catch (e, s) {
- Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
- cwWalletBase?.close();
- }
- await updateNode();
- }
-
- return super.init();
- }
-
- @override
- Future open() async {
- String? password;
- try {
- password = await cwKeysStorage.getWalletPassword(walletName: walletId);
- } catch (e, s) {
- throw Exception("Password not found $e, $s");
- }
-
- bool wasNull = false;
-
- if (cwWalletBase == null) {
- wasNull = true;
- // cwWalletBaseT?.close();
- cwWalletBase = (await cwWalletService!.openWallet(walletId, password))
- as WowneroWalletBase;
-
- cwWalletBase?.onNewBlock = onNewBlock;
- cwWalletBase?.onNewTransaction = onNewTransaction;
- cwWalletBase?.syncStatusChanged = syncStatusChanged;
-
- await updateNode();
- }
-
- Address? currentAddress = await getCurrentReceivingAddress();
- if (currentAddress == null) {
- currentAddress = addressFor(index: 0);
- await mainDB.updateOrPutAddresses([currentAddress]);
- }
- if (info.cachedReceivingAddress != currentAddress.value) {
- await info.updateReceivingAddress(
- newAddress: currentAddress.value,
- isar: mainDB.isar,
- );
- }
-
- if (wasNull) {
- await cwWalletBase?.startSync();
- } else {
- cwWalletBase?.wallet.startListeners();
- }
- unawaited(refresh());
-
- autoSaveTimer = Timer.periodic(
- const Duration(seconds: 193),
- (_) async => await cwWalletBase?.save(),
- );
- }
-
- @override
- Future recover({required bool isRescan}) async {
- if (isRescan) {
- await refreshMutex.protect(() async {
- // clear blockchain info
- await mainDB.deleteWalletBlockchainData(walletId);
-
- final restoreHeight = cwWalletBase?.walletInfo.restoreHeight;
- highestPercentCached = 0;
- await cwWalletBase?.rescan(height: restoreHeight ?? 0);
- });
- unawaited(refresh());
- return;
- }
-
- await refreshMutex.protect(() async {
- final mnemonic = await getMnemonic();
- final seedLength = mnemonic.trim().split(" ").length;
-
- if (!(seedLength == 14 || seedLength == 25)) {
- throw Exception("Invalid wownero mnemonic length found: $seedLength");
- }
-
- try {
- int height = info.restoreHeight;
-
- // extract seed height from 14 word seed
- if (seedLength == 14) {
- height = 0;
- } else {
- height = max(height, 0);
- }
-
- await info.updateRestoreHeight(
- newRestoreHeight: height,
- isar: mainDB.isar,
- );
-
- cwWalletService = wow_dart.wownero
- .createWowneroWalletService(DB.instance.moneroWalletInfoBox)
- as WowneroWalletService;
- WalletInfo walletInfo;
- WalletCredentials credentials;
- final String name = walletId;
- final dirPath =
- await pathForWalletDir(name: name, type: WalletType.wownero);
- final path = await pathForWallet(name: name, type: WalletType.wownero);
- credentials =
- wow_dart.wownero.createWowneroRestoreWalletFromSeedCredentials(
- name: name,
- height: height,
- mnemonic: mnemonic.trim(),
- );
- try {
- walletInfo = WalletInfo.external(
- id: WalletBase.idFor(name, WalletType.wownero),
- name: name,
- type: WalletType.wownero,
- isRecovery: false,
- restoreHeight: credentials.height ?? 0,
- date: DateTime.now(),
- path: path,
- dirPath: dirPath,
- // TODO: find out what to put for address
- address: '',
- );
- credentials.walletInfo = walletInfo;
-
- final cwWalletCreationService = WalletCreationService(
- secureStorage: secureStorageInterface,
- walletService: cwWalletService!,
- keyService: cwKeysStorage,
- type: WalletType.wownero,
- );
- // To restore from a seed
- final wallet = await cwWalletCreationService
- .restoreFromSeed(credentials) as WowneroWalletBase;
- height =
- wownerodart.Wallet_getRefreshFromBlockHeight(wallet.wallet.wptr);
- walletInfo.address = wallet.walletAddresses.address;
- walletInfo.restoreHeight = height;
- await info.updateRestoreHeight(
- newRestoreHeight: height,
- isar: mainDB.isar,
- );
- await DB.instance
- .add(boxName: WalletInfo.boxName, value: walletInfo);
- cwWalletBase?.close();
- cwWalletBase = wallet;
- cwWalletBase?.onNewBlock = onNewBlock;
- cwWalletBase?.onNewTransaction = onNewTransaction;
- cwWalletBase?.syncStatusChanged = syncStatusChanged;
- if (walletInfo.address != null) {
- final newReceivingAddress = await getCurrentReceivingAddress() ??
- Address(
- walletId: walletId,
- derivationIndex: 0,
- derivationPath: null,
- value: walletInfo.address!,
- publicKey: [],
- type: AddressType.cryptonote,
- subType: AddressSubType.receiving,
- );
-
- await mainDB.updateOrPutAddresses([newReceivingAddress]);
- await info.updateReceivingAddress(
- newAddress: newReceivingAddress.value,
- isar: mainDB.isar,
- );
- }
- } catch (e, s) {
- Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
- }
- await updateNode();
-
- await cwWalletBase?.rescan(height: credentials.height);
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from recoverFromMnemonic(): $e\n$s",
- level: LogLevel.Error,
- );
- rethrow;
- }
- });
- }
-
- @override
- Future prepareSend({required TxData txData}) async {
- try {
- final feeRate = txData.feeRateType;
- if (feeRate is FeeRateType) {
- MoneroTransactionPriority feePriority;
- switch (feeRate) {
- case FeeRateType.fast:
- feePriority = MoneroTransactionPriority.fast;
- break;
- case FeeRateType.average:
- feePriority = MoneroTransactionPriority.regular;
- break;
- case FeeRateType.slow:
- feePriority = MoneroTransactionPriority.slow;
- break;
- default:
- throw ArgumentError("Invalid use of custom fee");
- }
-
- Future? awaitPendingTransaction;
- try {
- // check for send all
- bool isSendAll = false;
- final balance = await availableBalance;
- if (txData.amount! == balance &&
- txData.recipients!.first.amount == balance) {
- isSendAll = true;
- }
-
- final List outputs = [];
- for (final recipient in txData.recipients!) {
- final output = wownero_output.Output(cwWalletBase!);
- output.address = recipient.address;
- output.sendAll = isSendAll;
- final String amountToSend = recipient.amount.decimal.toString();
- output.setCryptoAmount(amountToSend);
- outputs.add(output);
- }
-
- final tmp =
- wow_dart.wownero.createWowneroTransactionCreationCredentials(
- outputs: outputs,
- priority: feePriority,
- );
-
- final height = await chainHeight;
- final inputs = txData.utxos
- ?.map(
- (e) => cw.UTXO(
- address: e.address!,
- hash: e.txid,
- keyImage: e.keyImage!,
- value: e.value,
- isFrozen: e.isBlocked,
- isUnlocked: e.blockHeight != null &&
- (height - (e.blockHeight ?? 0)) >=
- cryptoCurrency.minConfirms,
- height: e.blockHeight ?? 0,
- vout: e.vout,
- spent: e.used ?? false,
- coinbase: e.isCoinbase,
- ),
- )
- .toList();
-
- await prepareSendMutex.protect(() async {
- awaitPendingTransaction = cwWalletBase!.createTransaction(
- tmp,
- inputs: inputs,
- );
- });
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from prepareSend(): $e\n$s",
- level: LogLevel.Warning,
- );
- }
-
- final PendingWowneroTransaction pendingWowneroTransaction =
- await (awaitPendingTransaction!) as PendingWowneroTransaction;
- final realFee = Amount.fromDecimal(
- Decimal.parse(pendingWowneroTransaction.feeFormatted),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
-
- return txData.copyWith(
- fee: realFee,
- pendingWowneroTransaction: pendingWowneroTransaction,
- );
- } else {
- throw ArgumentError("Invalid fee rate argument provided!");
- }
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from prepare send(): $e\n$s",
- level: LogLevel.Info,
+ Future getCreatedWallet({
+ required String path,
+ required String password,
+ }) async =>
+ await lib_monero.WowneroWallet.create(
+ path: path,
+ password: password,
+ seedType: lib_monero.WowneroSeedType
+ .fourteen, // TODO: check we want to actually use 14 here
+ overrideDeprecated14WordSeedException: true,
);
- if (e.toString().contains("Incorrect unlocked balance")) {
- throw Exception("Insufficient balance!");
- } else if (e is CreationTransactionException) {
- throw Exception("Insufficient funds to pay for transaction fee!");
- } else {
- throw Exception("Transaction failed with error code $e");
- }
- }
- }
-
@override
- Future confirmSend({required TxData txData}) async {
- try {
- try {
- await txData.pendingWowneroTransaction!.commit();
- Logging.instance.log(
- "transaction ${txData.pendingWowneroTransaction!.id} has been sent",
- level: LogLevel.Info,
- );
- return txData.copyWith(txid: txData.pendingWowneroTransaction!.id);
- } catch (e, s) {
- Logging.instance.log(
- "${info.name} wownero confirmSend: $e\n$s",
- level: LogLevel.Error,
- );
- rethrow;
- }
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from confirmSend(): $e\n$s",
- level: LogLevel.Info,
+ Future getRestoredWallet({
+ required String path,
+ required String password,
+ required String mnemonic,
+ int height = 0,
+ }) async =>
+ await lib_monero.WowneroWallet.restoreWalletFromSeed(
+ path: path,
+ password: password,
+ seed: mnemonic,
+ restoreHeight: height,
);
- rethrow;
- }
- }
@override
- Future get availableBalance async {
- try {
- int runningBalance = 0;
- for (final entry in cwWalletBase!.balance!.entries) {
- runningBalance += entry.value.unlockedBalance;
- }
- return Amount(
- rawValue: BigInt.from(runningBalance),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
- } catch (_) {
- return info.cachedBalance.spendable;
+ void invalidSeedLengthCheck(int length) {
+ if (!(length == 14 || length == 25)) {
+ throw Exception("Invalid wownero mnemonic length found: $length");
}
}
-
- @override
- Future get totalBalance async {
- try {
- final balanceEntries = cwWalletBase?.balance?.entries;
- if (balanceEntries != null) {
- int bal = 0;
- for (final element in balanceEntries) {
- bal = bal + element.value.fullBalance;
- }
- return Amount(
- rawValue: BigInt.from(bal),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
- } else {
- final transactions = cwWalletBase!.transactionHistory!.transactions;
- int transactionBalance = 0;
- for (final tx in transactions!.entries) {
- if (tx.value.direction == TransactionDirection.incoming) {
- transactionBalance += tx.value.amount!;
- } else {
- transactionBalance += -tx.value.amount! - tx.value.fee!;
- }
- }
-
- return Amount(
- rawValue: BigInt.from(transactionBalance),
- fractionDigits: cryptoCurrency.fractionDigits,
- );
- }
- } catch (_) {
- return info.cachedBalance.total;
- }
- }
-
- // ============== Private ====================================================
-
- StreamSubscription? _torStatusListener;
- StreamSubscription? _torPreferenceListener;
-
- final Mutex _torConnectingLock = Mutex();
- bool _requireMutex = false;
}
diff --git a/lib/wallets/wallet/intermediate/lib_monero_wallet.dart b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart
new file mode 100644
index 000000000..5def92c41
--- /dev/null
+++ b/lib/wallets/wallet/intermediate/lib_monero_wallet.dart
@@ -0,0 +1,1293 @@
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:math';
+
+import 'package:compat/compat.dart' as lib_monero_compat;
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
+import 'package:isar/isar.dart';
+import 'package:mutex/mutex.dart';
+import 'package:stack_wallet_backup/generate_password.dart';
+import 'package:tuple/tuple.dart';
+
+import '../../../db/hive/db.dart';
+import '../../../models/balance.dart';
+import '../../../models/isar/models/blockchain_data/address.dart';
+import '../../../models/isar/models/blockchain_data/transaction.dart';
+import '../../../models/isar/models/blockchain_data/utxo.dart';
+import '../../../models/keys/cw_key_data.dart';
+import '../../../models/paymint/fee_object_model.dart';
+import '../../../services/event_bus/events/global/blocks_remaining_event.dart';
+import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart';
+import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart';
+import '../../../services/event_bus/events/global/tor_status_changed_event.dart';
+import '../../../services/event_bus/events/global/updated_in_background_event.dart';
+import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart';
+import '../../../services/event_bus/global_event_bus.dart';
+import '../../../services/tor_service.dart';
+import '../../../utilities/amount/amount.dart';
+import '../../../utilities/enums/fee_rate_type_enum.dart';
+import '../../../utilities/logger.dart';
+import '../../../utilities/stack_file_system.dart';
+import '../../crypto_currency/intermediate/cryptonote_currency.dart';
+import '../../isar/models/wallet_info.dart';
+import '../../models/tx_data.dart';
+import '../wallet.dart';
+import '../wallet_mixin_interfaces/multi_address_interface.dart';
+import 'cryptonote_wallet.dart';
+
+abstract class LibMoneroWallet
+ extends CryptonoteWallet implements MultiAddressInterface {
+ LibMoneroWallet(super.currency, this.compatType) {
+ final bus = GlobalEventBus.instance;
+
+ // Listen for tor status changes.
+ _torStatusListener = bus.on().listen(
+ (event) async {
+ switch (event.newStatus) {
+ case TorConnectionStatus.connecting:
+ if (!_torConnectingLock.isLocked) {
+ await _torConnectingLock.acquire();
+ }
+ _requireMutex = true;
+ break;
+
+ case TorConnectionStatus.connected:
+ case TorConnectionStatus.disconnected:
+ if (_torConnectingLock.isLocked) {
+ _torConnectingLock.release();
+ }
+ _requireMutex = false;
+ break;
+ }
+ },
+ );
+
+ // Listen for tor preference changes.
+ _torPreferenceListener = bus.on().listen(
+ (event) async {
+ await updateNode();
+ },
+ );
+
+ // Potentially dangerous hack. See comments in _startInit()
+ _startInit();
+ }
+ // cw based wallet listener to handle synchronization of utxo frozen states
+ late final StreamSubscription> _streamSub;
+ Future _startInit() async {
+ // Delay required as `mainDB` is not initialized in constructor.
+ // This is a hack and could lead to a race condition.
+ Future.delayed(const Duration(seconds: 2), () {
+ _streamSub = mainDB.isar.utxos
+ .where()
+ .walletIdEqualTo(walletId)
+ .watch(fireImmediately: true)
+ .listen((utxos) async {
+ await onUTXOsChanged(utxos);
+ await updateBalance(shouldUpdateUtxos: false);
+ });
+ });
+ }
+
+ final lib_monero_compat.WalletType compatType;
+ lib_monero.Wallet? libMoneroWallet;
+
+ lib_monero_compat.SyncStatus? get syncStatus => _syncStatus;
+ lib_monero_compat.SyncStatus? _syncStatus;
+ int _syncedCount = 0;
+ void _setSyncStatus(lib_monero_compat.SyncStatus status) {
+ if (status is lib_monero_compat.SyncedSyncStatus) {
+ if (_syncStatus is lib_monero_compat.SyncedSyncStatus) {
+ _syncedCount++;
+ }
+ } else {
+ _syncedCount = 0;
+ }
+
+ if (_syncedCount < 3) {
+ _syncStatus = status;
+ syncStatusChanged();
+ }
+ }
+
+ final prepareSendMutex = Mutex();
+ final estimateFeeMutex = Mutex();
+
+ bool _txRefreshLock = false;
+ int _lastCheckedHeight = -1;
+ int _txCount = 0;
+ int currentKnownChainHeight = 0;
+ double highestPercentCached = 0;
+
+ void loadWallet({required String path, required String password});
+
+ Future getCreatedWallet({
+ required String path,
+ required String password,
+ });
+
+ Future getRestoredWallet({
+ required String path,
+ required String password,
+ required String mnemonic,
+ int height = 0,
+ });
+
+ void invalidSeedLengthCheck(int length);
+
+ bool walletExists(String path);
+
+ void _setListener() {
+ libMoneroWallet?.addListener(
+ lib_monero.WalletListener(
+ onSyncingUpdate: onSyncingUpdate,
+ onNewBlock: onNewBlock,
+ onBalancesChanged: onBalancesChanged,
+ onError: (e, s) {
+ Logging.instance.log("$e\n$s", level: LogLevel.Warning);
+ },
+ ),
+ );
+ }
+
+ Future open() async {
+ bool wasNull = false;
+
+ if (libMoneroWallet == null) {
+ wasNull = true;
+ // libMoneroWalletT?.close();
+ final path = await pathForWallet(
+ name: walletId,
+ type: compatType,
+ );
+
+ final String password;
+ try {
+ password = (await secureStorageInterface.read(
+ key: lib_monero_compat.libMoneroWalletPasswordKey(walletId),
+ ))!;
+ } catch (e, s) {
+ throw Exception("Password not found $e, $s");
+ }
+
+ loadWallet(path: path, password: password);
+
+ _setListener();
+
+ // TODO watcher
+ // libMoneroWallet?.syncStatusChanged = syncStatusChanged;
+
+ await updateNode();
+ }
+
+ Address? currentAddress = await getCurrentReceivingAddress();
+ if (currentAddress == null) {
+ currentAddress = addressFor(index: 0);
+ await mainDB.updateOrPutAddresses([currentAddress]);
+ }
+ if (info.cachedReceivingAddress != currentAddress.value) {
+ await info.updateReceivingAddress(
+ newAddress: currentAddress.value,
+ isar: mainDB.isar,
+ );
+ }
+
+ if (wasNull) {
+ try {
+ _setSyncStatus(lib_monero_compat.ConnectingSyncStatus());
+ libMoneroWallet?.startSyncing();
+ } catch (_) {
+ _setSyncStatus(lib_monero_compat.FailedSyncStatus());
+ // TODO log
+ }
+ }
+
+ libMoneroWallet?.startListeners();
+ libMoneroWallet?.startAutoSaving();
+
+ unawaited(refresh());
+ }
+
+ @Deprecated("Only used in the case of older wallets")
+ lib_monero_compat.WalletInfo? getLibMoneroWalletInfo(
+ String walletId,
+ ) {
+ try {
+ return DB.instance.moneroWalletInfoBox.values.firstWhere(
+ (info) => info.id == lib_monero_compat.hiveIdFor(walletId, compatType),
+ );
+ } catch (_) {
+ return null;
+ }
+ }
+
+ Future save() async {
+ print("save is called");
+ if (!Platform.isWindows) {
+ final appRoot = await StackFileSystem.applicationRootDirectory();
+ await lib_monero_compat.backupWalletFiles(
+ name: walletId,
+ type: compatType,
+ appRoot: appRoot,
+ );
+ }
+ await libMoneroWallet!.save();
+ }
+
+ Address addressFor({required int index, int account = 0}) {
+ final address = libMoneroWallet!.getAddress(
+ accountIndex: account,
+ addressIndex: index,
+ );
+
+ final newReceivingAddress = Address(
+ walletId: walletId,
+ derivationIndex: index,
+ derivationPath: null,
+ value: address.value,
+ publicKey: [],
+ type: AddressType.cryptonote,
+ subType: AddressSubType.receiving,
+ );
+
+ return newReceivingAddress;
+ }
+
+ Future getKeys() async {
+ final base = libMoneroWallet;
+
+ final oldInfo = getLibMoneroWalletInfo(
+ walletId,
+ );
+ if (base == null || (oldInfo != null && oldInfo.name != walletId)) {
+ return null;
+ }
+
+ return CWKeyData(
+ walletId: walletId,
+ publicViewKey: base.getPublicViewKey(),
+ privateViewKey: base.getPrivateViewKey(),
+ publicSpendKey: base.getPublicSpendKey(),
+ privateSpendKey: base.getPrivateSpendKey(),
+ );
+ }
+
+ @override
+ Future init({bool? isRestore}) async {
+ final path = await pathForWallet(
+ name: walletId,
+ type: compatType,
+ );
+ if (!(walletExists(path)) && isRestore != true) {
+ try {
+ final password = generatePassword();
+ await secureStorageInterface.write(
+ key: lib_monero_compat.libMoneroWalletPasswordKey(walletId),
+ value: password,
+ );
+ final wallet = await getCreatedWallet(path: path, password: password);
+
+ final height = wallet.getSyncFromBlockHeight();
+
+ await info.updateRestoreHeight(
+ newRestoreHeight: height,
+ isar: mainDB.isar,
+ );
+
+ // special case for xmr/wow. Normally mnemonic + passphrase is saved
+ // before wallet.init() is called
+ await secureStorageInterface.write(
+ key: Wallet.mnemonicKey(walletId: walletId),
+ value: wallet.getSeed().trim(),
+ );
+ await secureStorageInterface.write(
+ key: Wallet.mnemonicPassphraseKey(walletId: walletId),
+ value: "",
+ );
+ } catch (e, s) {
+ Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
+ }
+ await updateNode();
+ }
+
+ return super.init();
+ }
+
+ @override
+ Future recover({required bool isRescan}) async {
+ if (isRescan) {
+ await refreshMutex.protect(() async {
+ // clear blockchain info
+ await mainDB.deleteWalletBlockchainData(walletId);
+
+ highestPercentCached = 0;
+ unawaited(libMoneroWallet?.rescanBlockchain());
+ libMoneroWallet?.startSyncing();
+ // unawaited(save());
+ });
+ unawaited(refresh());
+ return;
+ }
+
+ await refreshMutex.protect(() async {
+ final mnemonic = await getMnemonic();
+ final seedLength = mnemonic.trim().split(" ").length;
+
+ invalidSeedLengthCheck(seedLength);
+
+ try {
+ final height = max(info.restoreHeight, 0);
+
+ await info.updateRestoreHeight(
+ newRestoreHeight: height,
+ isar: mainDB.isar,
+ );
+
+ final String name = walletId;
+
+ final path = await pathForWallet(
+ name: name,
+ type: compatType,
+ );
+
+ try {
+ final password = generatePassword();
+ await secureStorageInterface.write(
+ key: lib_monero_compat.libMoneroWalletPasswordKey(walletId),
+ value: password,
+ );
+ final wallet = await getRestoredWallet(
+ path: path,
+ password: password,
+ mnemonic: mnemonic,
+ height: height,
+ );
+
+ if (libMoneroWallet != null) {
+ await exit();
+ }
+
+ libMoneroWallet = wallet;
+
+ _setListener();
+
+ final newReceivingAddress = await getCurrentReceivingAddress() ??
+ Address(
+ walletId: walletId,
+ derivationIndex: 0,
+ derivationPath: null,
+ value: wallet.getAddress().value,
+ publicKey: [],
+ type: AddressType.cryptonote,
+ subType: AddressSubType.receiving,
+ );
+
+ await mainDB.updateOrPutAddresses([newReceivingAddress]);
+ await info.updateReceivingAddress(
+ newAddress: newReceivingAddress.value,
+ isar: mainDB.isar,
+ );
+ } catch (e, s) {
+ Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
+ }
+ await updateNode();
+
+ // libMoneroWallet?.setRecoveringFromSeed(isRecovery: true);
+ unawaited(libMoneroWallet?.rescanBlockchain());
+ libMoneroWallet?.startSyncing();
+
+ // await save();
+ libMoneroWallet?.startListeners();
+ libMoneroWallet?.startAutoSaving();
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from recoverFromMnemonic(): $e\n$s",
+ level: LogLevel.Error,
+ );
+ rethrow;
+ }
+ });
+ }
+
+ @override
+ Future pingCheck() async {
+ return (await libMoneroWallet?.isConnectedToDaemon()) ?? false;
+ }
+
+ @override
+ Future updateNode() async {
+ final node = getCurrentNode();
+
+ final host = Uri.parse(node.host).host;
+ ({InternetAddress host, int port})? proxy;
+ if (prefs.useTor) {
+ proxy = TorService.sharedInstance.getProxyInfo();
+ }
+
+ _setSyncStatus(lib_monero_compat.ConnectingSyncStatus());
+ try {
+ if (_requireMutex) {
+ await _torConnectingLock.protect(() async {
+ await libMoneroWallet?.connect(
+ daemonAddress: "$host:${node.port}",
+ daemonUsername: node.loginName,
+ daemonPassword: await node.getPassword(secureStorageInterface),
+ trusted: node.trusted ?? false,
+ useSSL: node.useSSL,
+ socksProxyAddress:
+ proxy == null ? null : "${proxy.host.address}:${proxy.port}",
+ );
+ });
+ } else {
+ await libMoneroWallet?.connect(
+ daemonAddress: "$host:${node.port}",
+ daemonUsername: node.loginName,
+ daemonPassword: await node.getPassword(secureStorageInterface),
+ trusted: node.trusted ?? false,
+ useSSL: node.useSSL,
+ socksProxyAddress:
+ proxy == null ? null : "${proxy.host.address}:${proxy.port}",
+ );
+ }
+
+ _setSyncStatus(lib_monero_compat.ConnectedSyncStatus());
+ } catch (e, s) {
+ _setSyncStatus(lib_monero_compat.FailedSyncStatus());
+ Logging.instance.log(
+ "Exception caught in $runtimeType.updateNode(): $e\n$s",
+ level: LogLevel.Error,
+ );
+ }
+
+ return;
+ }
+
+ @override
+ Future updateTransactions() async {
+ final base = libMoneroWallet;
+
+ if (base == null) {
+ return;
+ }
+ await base.refreshTransactions();
+ final transactions = base.getTxs();
+
+ // final cachedTransactions =
+ // DB.instance.get(boxName: walletId, key: 'latest_tx_model')
+ // as TransactionData?;
+ // int latestTxnBlockHeight =
+ // DB.instance.get(boxName: walletId, key: "storedTxnDataHeight")
+ // as int? ??
+ // 0;
+ //
+ // final txidsList = DB.instance
+ // .get(boxName: walletId, key: "cachedTxids") as List? ??
+ // [];
+ //
+ // final Set cachedTxids = Set.from(txidsList);
+
+ // TODO: filter to skip cached + confirmed txn processing in next step
+ // final unconfirmedCachedTransactions =
+ // cachedTransactions?.getAllTransactions() ?? {};
+ // unconfirmedCachedTransactions
+ // .removeWhere((key, value) => value.confirmedStatus);
+ //
+ // if (cachedTransactions != null) {
+ // for (final tx in allTxHashes.toList(growable: false)) {
+ // final txHeight = tx["height"] as int;
+ // if (txHeight > 0 &&
+ // txHeight < latestTxnBlockHeight - MINIMUM_CONFIRMATIONS) {
+ // if (unconfirmedCachedTransactions[tx["tx_hash"] as String] == null) {
+ // allTxHashes.remove(tx);
+ // }
+ // }
+ // }
+ // }
+
+ final List> txnsData = [];
+
+ for (final tx in transactions) {
+ Address? address;
+ TransactionType type;
+ if (!tx.isSpend) {
+ final addressString = libMoneroWallet
+ ?.getAddress(
+ accountIndex: tx.accountIndex,
+ addressIndex: tx.addressIndex,
+ )
+ .value;
+
+ if (addressString != null) {
+ address = await mainDB
+ .getAddresses(walletId)
+ .filter()
+ .valueEqualTo(addressString)
+ .findFirst();
+ }
+
+ type = TransactionType.incoming;
+ } else {
+ // txn.address = "";
+ type = TransactionType.outgoing;
+ }
+
+ final txn = Transaction(
+ walletId: walletId,
+ txid: tx.hash,
+ timestamp: (tx.timeStamp.millisecondsSinceEpoch ~/ 1000),
+ type: type,
+ subType: TransactionSubType.none,
+ amount: tx.amount,
+ amountString: Amount(
+ rawValue: BigInt.from(tx.amount),
+ fractionDigits: cryptoCurrency.fractionDigits,
+ ).toJsonString(),
+ fee: tx.fee,
+ height: tx.blockheight,
+ isCancelled: false,
+ isLelantus: false,
+ slateId: null,
+ otherData: null,
+ nonce: null,
+ inputs: [],
+ outputs: [],
+ numberOfMessages: null,
+ );
+
+ txnsData.add(Tuple2(txn, address));
+ }
+ await mainDB.isar.writeTxn(() async {
+ await mainDB.isar.transactions
+ .where()
+ .walletIdEqualTo(walletId)
+ .deleteAll();
+ for (final data in txnsData) {
+ final tx = data.item1;
+
+ // save transaction
+ await mainDB.isar.transactions.put(tx);
+
+ if (data.item2 != null) {
+ final address = await mainDB.getAddress(walletId, data.item2!.value);
+
+ // check if address exists in db and add if it does not
+ if (address == null) {
+ await mainDB.isar.addresses.put(data.item2!);
+ }
+
+ // link and save address
+ tx.address.value = address ?? data.item2!;
+ await tx.address.save();
+ }
+ }
+ });
+ }
+
+ Future get availableBalance async {
+ try {
+ return Amount(
+ rawValue: BigInt.from(libMoneroWallet!.getUnlockedBalance()),
+ fractionDigits: cryptoCurrency.fractionDigits,
+ );
+ } catch (_) {
+ return info.cachedBalance.spendable;
+ }
+ }
+
+ Future get totalBalance async {
+ try {
+ final full = libMoneroWallet?.getBalance();
+ if (full != null) {
+ return Amount(
+ rawValue: BigInt.from(full),
+ fractionDigits: cryptoCurrency.fractionDigits,
+ );
+ } else {
+ final transactions = libMoneroWallet!.getTxs();
+ int transactionBalance = 0;
+ for (final tx in transactions) {
+ if (!tx.isSpend) {
+ transactionBalance += tx.amount;
+ } else {
+ transactionBalance += -tx.amount - tx.fee;
+ }
+ }
+
+ return Amount(
+ rawValue: BigInt.from(transactionBalance),
+ fractionDigits: cryptoCurrency.fractionDigits,
+ );
+ }
+ } catch (_) {
+ return info.cachedBalance.total;
+ }
+ }
+
+ @override
+ Future exit() async {
+ libMoneroWallet?.stopAutoSaving();
+ libMoneroWallet?.stopListeners();
+ libMoneroWallet?.stopSyncing();
+ await libMoneroWallet?.save();
+ }
+
+ Future pathForWalletDir({
+ required String name,
+ required lib_monero_compat.WalletType type,
+ }) async {
+ final Directory root = await StackFileSystem.applicationRootDirectory();
+ return lib_monero_compat.pathForWalletDir(
+ name: name,
+ type: type.name.toLowerCase(),
+ appRoot: root,
+ );
+ }
+
+ Future pathForWallet({
+ required String name,
+ required lib_monero_compat.WalletType type,
+ }) async =>
+ await pathForWalletDir(name: name, type: type)
+ .then((path) => '$path/$name');
+
+ void onSyncingUpdate({
+ required int syncHeight,
+ required int nodeHeight,
+ String? message,
+ }) {
+ if (nodeHeight > 0 && syncHeight >= 0) {
+ currentKnownChainHeight = nodeHeight;
+ updateChainHeight();
+ final blocksLeft = nodeHeight - syncHeight;
+ final lib_monero_compat.SyncStatus status;
+ if (blocksLeft < 100) {
+ status = lib_monero_compat.SyncedSyncStatus();
+
+ // if (!_hasSyncAfterStartup) {
+ // _hasSyncAfterStartup = true;
+ // await save();
+ // }
+ //
+ // if (walletInfo.isRecovery!) {
+ // await setAsRecovered();
+ // }
+ } else {
+ final percent = syncHeight / currentKnownChainHeight;
+
+ status = lib_monero_compat.SyncingSyncStatus(
+ blocksLeft,
+ percent,
+ currentKnownChainHeight,
+ );
+ }
+
+ _setSyncStatus(status);
+ _refreshTxDataHelper();
+ }
+ }
+
+ void onBalancesChanged({
+ required int newBalance,
+ required int newUnlockedBalance,
+ }) {
+ // do something?
+ }
+
+ void onNewBlock(int nodeHeight) {
+ // do something?
+ }
+
+ final _utxosUpdateLock = Mutex();
+ Future onUTXOsChanged(List utxos) async {
+ await _utxosUpdateLock.protect(() async {
+ final cwUtxos = await libMoneroWallet?.getOutputs() ?? [];
+
+ // bool changed = false;
+
+ for (final cw in cwUtxos) {
+ final match = utxos.where(
+ (e) =>
+ e.keyImage != null &&
+ e.keyImage!.isNotEmpty &&
+ e.keyImage == cw.keyImage,
+ );
+
+ if (match.isNotEmpty) {
+ final u = match.first;
+
+ if (u.isBlocked) {
+ if (!cw.isFrozen) {
+ await libMoneroWallet?.freezeOutput(cw.keyImage);
+ // changed = true;
+ }
+ } else {
+ if (cw.isFrozen) {
+ await libMoneroWallet?.thawOutput(cw.keyImage);
+ // changed = true;
+ }
+ }
+ }
+ }
+
+ // if (changed) {
+ // await libMoneroWallet?.updateUTXOs();
+ // }
+ });
+ }
+
+ void onNewTransaction() {
+ // TODO: [prio=low] get rid of UpdatedInBackgroundEvent and move to
+ // adding the v2 tx to the db which would update ui automagically since the
+ // db is watched by the ui
+ // call this here?
+ GlobalEventBus.instance.fire(
+ UpdatedInBackgroundEvent(
+ "New data found in $walletId ${info.name} in background!",
+ walletId,
+ ),
+ );
+ }
+
+ void syncStatusChanged() async {
+ final _syncStatus = syncStatus;
+
+ if (_syncStatus != null) {
+ if (_syncStatus.progress() == 1 && refreshMutex.isLocked) {
+ refreshMutex.release();
+ }
+
+ WalletSyncStatus? status;
+ xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(true);
+
+ if (_syncStatus is lib_monero_compat.SyncingSyncStatus) {
+ final int blocksLeft = _syncStatus.blocksLeft;
+
+ // ensure at least 1 to prevent math errors
+ final int height = max(1, _syncStatus.height);
+
+ final nodeHeight = height + blocksLeft;
+ currentKnownChainHeight = nodeHeight;
+
+ // final percent = height / nodeHeight;
+ final percent = _syncStatus.ptc;
+
+ final highest = max(highestPercentCached, percent);
+
+ final unchanged = highest == highestPercentCached;
+ if (unchanged) {
+ return;
+ }
+
+ // update cached
+ if (highestPercentCached < percent) {
+ highestPercentCached = percent;
+ }
+
+ GlobalEventBus.instance.fire(
+ RefreshPercentChangedEvent(
+ highest,
+ walletId,
+ ),
+ );
+ GlobalEventBus.instance.fire(
+ BlocksRemainingEvent(
+ blocksLeft,
+ walletId,
+ ),
+ );
+ } else if (_syncStatus is lib_monero_compat.SyncedSyncStatus) {
+ status = WalletSyncStatus.synced;
+ } else if (_syncStatus is lib_monero_compat.NotConnectedSyncStatus) {
+ status = WalletSyncStatus.unableToSync;
+ xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false);
+ } else if (_syncStatus is lib_monero_compat.StartingSyncStatus) {
+ status = WalletSyncStatus.syncing;
+ GlobalEventBus.instance.fire(
+ RefreshPercentChangedEvent(
+ highestPercentCached,
+ walletId,
+ ),
+ );
+ } else if (_syncStatus is lib_monero_compat.FailedSyncStatus) {
+ status = WalletSyncStatus.unableToSync;
+ xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false);
+ } else if (_syncStatus is lib_monero_compat.ConnectingSyncStatus) {
+ status = WalletSyncStatus.syncing;
+ GlobalEventBus.instance.fire(
+ RefreshPercentChangedEvent(
+ highestPercentCached,
+ walletId,
+ ),
+ );
+ } else if (_syncStatus is lib_monero_compat.ConnectedSyncStatus) {
+ status = WalletSyncStatus.syncing;
+ GlobalEventBus.instance.fire(
+ RefreshPercentChangedEvent(
+ highestPercentCached,
+ walletId,
+ ),
+ );
+ } else if (_syncStatus is lib_monero_compat.LostConnectionSyncStatus) {
+ status = WalletSyncStatus.unableToSync;
+ xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false);
+ }
+
+ if (status != null) {
+ GlobalEventBus.instance.fire(
+ WalletSyncStatusChangedEvent(
+ status,
+ walletId,
+ info.coin,
+ ),
+ );
+ }
+ }
+ }
+
+ @override
+ Future checkSaveInitialReceivingAddress() async {
+ // this doesn't work without opening the wallet first which takes a while
+ }
+
+ // ============ Private ======================================================
+ Future _refreshTxDataHelper() async {
+ if (_txRefreshLock) return;
+ _txRefreshLock = true;
+
+ final _syncStatus = syncStatus;
+
+ if (_syncStatus != null &&
+ _syncStatus is lib_monero_compat.SyncingSyncStatus) {
+ final int blocksLeft = _syncStatus.blocksLeft;
+ final tenKChange = blocksLeft ~/ 10000;
+
+ // only refresh transactions periodically during a sync
+ if (_lastCheckedHeight == -1 || tenKChange < _lastCheckedHeight) {
+ _lastCheckedHeight = tenKChange;
+ await _refreshTxData();
+ }
+ } else {
+ await _refreshTxData();
+ }
+
+ _txRefreshLock = false;
+ }
+
+ Future _refreshTxData() async {
+ await updateTransactions();
+ final count = await mainDB.getTransactions(walletId).count();
+
+ if (count > _txCount) {
+ _txCount = count;
+ await updateBalance();
+ GlobalEventBus.instance.fire(
+ UpdatedInBackgroundEvent(
+ "New transaction data found in $walletId ${info.name}!",
+ walletId,
+ ),
+ );
+ }
+ }
+
+ // ============ Overrides ====================================================
+
+ @override
+ FilterOperation? get changeAddressFilterOperation => null;
+
+ @override
+ FilterOperation? get receivingAddressFilterOperation => null;
+
+ @override
+ Future updateUTXOs() async {
+ final List outputArray = [];
+ final utxos = await libMoneroWallet?.getOutputs() ?? [];
+ for (final rawUTXO in utxos) {
+ if (!rawUTXO.spent) {
+ final current = await mainDB.isar.utxos
+ .where()
+ .walletIdEqualTo(walletId)
+ .filter()
+ .voutEqualTo(rawUTXO.vout)
+ .and()
+ .txidEqualTo(rawUTXO.hash)
+ .findFirst();
+ final tx = await mainDB.isar.transactions
+ .where()
+ .walletIdEqualTo(walletId)
+ .filter()
+ .txidEqualTo(rawUTXO.hash)
+ .findFirst();
+
+ final otherDataMap = {
+ "keyImage": rawUTXO.keyImage,
+ "spent": rawUTXO.spent,
+ };
+
+ final utxo = UTXO(
+ address: rawUTXO.address,
+ walletId: walletId,
+ txid: rawUTXO.hash,
+ vout: rawUTXO.vout,
+ value: rawUTXO.value,
+ name: current?.name ?? "",
+ isBlocked: current?.isBlocked ?? rawUTXO.isFrozen,
+ blockedReason: current?.blockedReason ?? "",
+ isCoinbase: rawUTXO.coinbase,
+ blockHash: "",
+ blockHeight:
+ tx?.height ?? (rawUTXO.height > 0 ? rawUTXO.height : null),
+ blockTime: tx?.timestamp,
+ otherData: jsonEncode(otherDataMap),
+ );
+
+ outputArray.add(utxo);
+ }
+ }
+
+ await mainDB.updateUTXOs(walletId, outputArray);
+
+ return true;
+ }
+
+ @override
+ Future updateBalance({bool shouldUpdateUtxos = true}) async {
+ if (shouldUpdateUtxos) {
+ await updateUTXOs();
+ }
+
+ final total = await totalBalance;
+ final available = await availableBalance;
+
+ final balance = Balance(
+ total: total,
+ spendable: available,
+ blockedTotal: Amount(
+ rawValue: BigInt.zero,
+ fractionDigits: cryptoCurrency.fractionDigits,
+ ),
+ pendingSpendable: total - available,
+ );
+
+ await info.updateBalance(newBalance: balance, isar: mainDB.isar);
+ }
+
+ @override
+ Future refresh() async {
+ // Awaiting this lock could be dangerous.
+ // Since refresh is periodic (generally)
+ if (refreshMutex.isLocked) {
+ return;
+ }
+
+ // this acquire should be almost instant due to above check.
+ // Slight possibility of race but should be irrelevant
+ await refreshMutex.acquire();
+
+ GlobalEventBus.instance.fire(
+ WalletSyncStatusChangedEvent(
+ WalletSyncStatus.syncing,
+ walletId,
+ info.coin,
+ ),
+ );
+
+ await updateTransactions();
+ await updateBalance();
+
+ if (info.otherData[WalletInfoKeys.reuseAddress] != true) {
+ await checkReceivingAddressForTransactions();
+ }
+
+ if (syncStatus is lib_monero_compat.SyncedSyncStatus) {
+ // refreshMutex.release();
+ GlobalEventBus.instance.fire(
+ WalletSyncStatusChangedEvent(
+ WalletSyncStatus.synced,
+ walletId,
+ info.coin,
+ ),
+ );
+ }
+ }
+
+ @override
+ Future generateNewReceivingAddress() async {
+ try {
+ final currentReceiving = await getCurrentReceivingAddress();
+
+ final newReceivingIndex =
+ currentReceiving == null ? 0 : currentReceiving.derivationIndex + 1;
+
+ final newReceivingAddress = addressFor(index: newReceivingIndex);
+
+ // Add that new receiving address
+ await mainDB.putAddress(newReceivingAddress);
+ await info.updateReceivingAddress(
+ newAddress: newReceivingAddress.value,
+ isar: mainDB.isar,
+ );
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception in generateNewAddress(): $e\n$s",
+ level: LogLevel.Error,
+ );
+ }
+ }
+
+ @override
+ Future checkReceivingAddressForTransactions() async {
+ if (info.otherData[WalletInfoKeys.reuseAddress] == true) {
+ try {
+ throw Exception();
+ } catch (_, s) {
+ Logging.instance.log(
+ "checkReceivingAddressForTransactions called but reuse address flag set: $s",
+ level: LogLevel.Error,
+ );
+ }
+ }
+
+ try {
+ int highestIndex = -1;
+ final entries = libMoneroWallet?.getTxs();
+ if (entries != null) {
+ for (final element in entries) {
+ if (!element.isSpend) {
+ final int curAddressIndex = element.addressIndex;
+ if (curAddressIndex > highestIndex) {
+ highestIndex = curAddressIndex;
+ }
+ }
+ }
+ }
+
+ // Check the new receiving index
+ final currentReceiving = await getCurrentReceivingAddress();
+ final curIndex = currentReceiving?.derivationIndex ?? -1;
+
+ if (highestIndex >= curIndex) {
+ // First increment the receiving index
+ final newReceivingIndex = curIndex + 1;
+
+ // Use new index to derive a new receiving address
+ final newReceivingAddress = addressFor(index: newReceivingIndex);
+
+ final existing = await mainDB
+ .getAddresses(walletId)
+ .filter()
+ .valueEqualTo(newReceivingAddress.value)
+ .findFirst();
+ if (existing == null) {
+ // Add that new change address
+ await mainDB.putAddress(newReceivingAddress);
+ } else {
+ // we need to update the address
+ await mainDB.updateAddress(existing, newReceivingAddress);
+ }
+ if (info.otherData[WalletInfoKeys.reuseAddress] != true) {
+ // keep checking until address with no tx history is set as current
+ await checkReceivingAddressForTransactions();
+ }
+ }
+ } on SocketException catch (se, s) {
+ Logging.instance.log(
+ "SocketException caught in _checkReceivingAddressForTransactions(): $se\n$s",
+ level: LogLevel.Error,
+ );
+ return;
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from _checkReceivingAddressForTransactions(): $e\n$s",
+ level: LogLevel.Error,
+ );
+ rethrow;
+ }
+ }
+
+ // TODO: this needs some work. Prio's may need to be changed as well as estimated blocks
+ @override
+ Future get fees async => FeeObject(
+ numberOfBlocksFast: 10,
+ numberOfBlocksAverage: 15,
+ numberOfBlocksSlow: 20,
+ fast: lib_monero.TransactionPriority.high.value,
+ medium: lib_monero.TransactionPriority.medium.value,
+ slow: lib_monero.TransactionPriority.normal.value,
+ );
+
+ @override
+ Future updateChainHeight() async {
+ await info.updateCachedChainHeight(
+ newHeight: currentKnownChainHeight,
+ isar: mainDB.isar,
+ );
+ }
+
+ @override
+ Future checkChangeAddressForTransactions() async {
+ // do nothing
+ }
+
+ @override
+ Future generateNewChangeAddress() async {
+ // do nothing
+ }
+
+ @override
+ Future prepareSend({required TxData txData}) async {
+ try {
+ final feeRate = txData.feeRateType;
+ if (feeRate is FeeRateType) {
+ lib_monero.TransactionPriority feePriority;
+ switch (feeRate) {
+ case FeeRateType.fast:
+ feePriority = lib_monero.TransactionPriority.high;
+ break;
+ case FeeRateType.average:
+ feePriority = lib_monero.TransactionPriority.medium;
+ break;
+ case FeeRateType.slow:
+ feePriority = lib_monero.TransactionPriority.normal;
+ break;
+ default:
+ throw ArgumentError("Invalid use of custom fee");
+ }
+
+ try {
+ // TODO: ???
+ // check for send all
+ bool isSendAll = false;
+
+ final balance = await availableBalance;
+ if (txData.amount! == balance &&
+ txData.recipients!.first.amount == balance) {
+ isSendAll = true;
+ }
+
+ if (isSendAll && txData.recipients!.length > 1) {
+ throw Exception("Send all not supported with multiple recipients");
+ }
+
+ final List outputs = [];
+ for (final recipient in txData.recipients!) {
+ final output = lib_monero.Recipient(
+ address: recipient.address,
+ amount: recipient.amount.decimal.toString(),
+ );
+
+ outputs.add(output);
+ }
+
+ if (outputs.isEmpty) {
+ throw Exception("No recipients provided");
+ }
+
+ final height = await chainHeight;
+ final inputs = txData.utxos
+ ?.map(
+ (e) => lib_monero.Output(
+ address: e.address!,
+ hash: e.txid,
+ keyImage: e.keyImage!,
+ value: e.value,
+ isFrozen: e.isBlocked,
+ isUnlocked: e.blockHeight != null &&
+ (height - (e.blockHeight ?? 0)) >=
+ cryptoCurrency.minConfirms,
+ height: e.blockHeight ?? 0,
+ vout: e.vout,
+ spent: e.used ?? false,
+ coinbase: e.isCoinbase,
+ ),
+ )
+ .toList();
+
+ return await prepareSendMutex.protect(() async {
+ final lib_monero.PendingTransaction pendingTransaction;
+ if (outputs.length == 1) {
+ pendingTransaction = await libMoneroWallet!.createTx(
+ address: outputs.first.address,
+ paymentId: "",
+ amount: isSendAll ? null : outputs.first.amount,
+ priority: feePriority,
+ preferredInputs: inputs?.map((e) => e.keyImage).toList() ?? [],
+ );
+ } else {
+ pendingTransaction = await libMoneroWallet!.createTxMultiDest(
+ outputs: outputs,
+ paymentId: "",
+ priority: feePriority,
+ preferredInputs: inputs?.map((e) => e.keyImage).toList() ?? [],
+ );
+ }
+
+ final realFee = Amount(
+ rawValue: BigInt.from(pendingTransaction.fee!),
+ fractionDigits: cryptoCurrency.fractionDigits,
+ );
+
+ return txData.copyWith(
+ fee: realFee,
+ pendingTransaction: pendingTransaction,
+ );
+ });
+ } catch (e) {
+ rethrow;
+ }
+ } else {
+ throw ArgumentError("Invalid fee rate argument provided!");
+ }
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from prepare send(): $e\n$s",
+ level: LogLevel.Info,
+ );
+
+ if (e.toString().contains("Incorrect unlocked balance")) {
+ throw Exception("Insufficient balance!");
+ } else if (e is lib_monero.CreationTransactionException) {
+ throw Exception("Insufficient funds to pay for transaction fee!");
+ } else {
+ throw Exception("Transaction failed with error: $e");
+ }
+ }
+ }
+
+ @override
+ Future confirmSend({required TxData txData}) async {
+ try {
+ try {
+ await libMoneroWallet!.commitTx(
+ txData.pendingTransaction!,
+ );
+
+ Logging.instance.log(
+ "transaction ${txData.pendingTransaction!.txid} has been sent",
+ level: LogLevel.Info,
+ );
+ return txData.copyWith(txid: txData.pendingTransaction!.txid);
+ } catch (e, s) {
+ Logging.instance.log(
+ "${info.name} ${compatType.name.toLowerCase()} confirmSend: $e\n$s",
+ level: LogLevel.Error,
+ );
+ rethrow;
+ }
+ } catch (e, s) {
+ Logging.instance.log(
+ "Exception rethrown from confirmSend(): $e\n$s",
+ level: LogLevel.Info,
+ );
+ rethrow;
+ }
+ }
+
+ // ============== Private ====================================================
+
+ StreamSubscription? _torStatusListener;
+ StreamSubscription? _torPreferenceListener;
+
+ final Mutex _torConnectingLock = Mutex();
+ bool _requireMutex = false;
+}
diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart
deleted file mode 100644
index ba054fa1f..000000000
--- a/lib/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart
+++ /dev/null
@@ -1,532 +0,0 @@
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-import 'dart:math';
-
-import 'package:cw_core/monero_transaction_priority.dart';
-import 'package:cw_core/sync_status.dart';
-import 'package:cw_core/transaction_direction.dart';
-import 'package:cw_core/utxo.dart' as cw;
-import 'package:cw_core/wallet_base.dart';
-import 'package:cw_core/wallet_service.dart';
-import 'package:cw_core/wallet_type.dart';
-import 'package:flutter_libmonero/core/key_service.dart';
-import 'package:isar/isar.dart';
-import 'package:mutex/mutex.dart';
-
-import '../../../models/balance.dart';
-import '../../../models/isar/models/blockchain_data/address.dart';
-import '../../../models/isar/models/blockchain_data/transaction.dart';
-import '../../../models/isar/models/blockchain_data/utxo.dart';
-import '../../../models/keys/cw_key_data.dart';
-import '../../../models/paymint/fee_object_model.dart';
-import '../../../services/event_bus/events/global/blocks_remaining_event.dart';
-import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart';
-import '../../../services/event_bus/events/global/updated_in_background_event.dart';
-import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart';
-import '../../../services/event_bus/global_event_bus.dart';
-import '../../../utilities/amount/amount.dart';
-import '../../../utilities/logger.dart';
-import '../../../utilities/stack_file_system.dart';
-import '../../crypto_currency/intermediate/cryptonote_currency.dart';
-import '../../isar/models/wallet_info.dart';
-import '../intermediate/cryptonote_wallet.dart';
-import 'multi_address_interface.dart';
-
-mixin CwBasedInterface on CryptonoteWallet
- implements MultiAddressInterface {
- final prepareSendMutex = Mutex();
- final estimateFeeMutex = Mutex();
-
- KeyService? _cwKeysStorageCached;
- KeyService get cwKeysStorage =>
- _cwKeysStorageCached ??= KeyService(secureStorageInterface);
-
- bool _txRefreshLock = false;
- int _lastCheckedHeight = -1;
- int _txCount = 0;
- int currentKnownChainHeight = 0;
- double highestPercentCached = 0;
-
- Timer? autoSaveTimer;
- Future pathForWalletDir({
- required String name,
- required WalletType type,
- }) async {
- final Directory root = await StackFileSystem.applicationRootDirectory();
-
- final prefix = walletTypeToString(type).toLowerCase();
- final walletsDir = Directory('${root.path}/wallets');
- final walletDire = Directory('${walletsDir.path}/$prefix/$name');
-
- if (!walletDire.existsSync()) {
- walletDire.createSync(recursive: true);
- }
-
- return walletDire.path;
- }
-
- Future pathForWallet({
- required String name,
- required WalletType type,
- }) async =>
- await pathForWalletDir(name: name, type: type)
- .then((path) => '$path/$name');
-
- void onNewBlock({required int height, required int blocksLeft}) {
- currentKnownChainHeight = height;
- updateChainHeight();
- _refreshTxDataHelper();
- }
-
- final _utxosUpdateLock = Mutex();
- Future onUTXOsCHanged(List utxos) async {
- await _utxosUpdateLock.protect(() async {
- final cwUtxos = cwWalletBase?.utxos ?? [];
-
- bool changed = false;
-
- for (final cw in cwUtxos) {
- final match = utxos.where(
- (e) =>
- e.keyImage != null &&
- e.keyImage!.isNotEmpty &&
- e.keyImage == cw.keyImage,
- );
-
- if (match.isNotEmpty) {
- final u = match.first;
-
- if (u.isBlocked) {
- if (!cw.isFrozen) {
- await cwWalletBase?.freeze(cw.keyImage);
- changed = true;
- }
- } else {
- if (cw.isFrozen) {
- await cwWalletBase?.thaw(cw.keyImage);
- changed = true;
- }
- }
- }
- }
-
- if (changed) {
- await cwWalletBase?.updateUTXOs();
- }
- });
- }
-
- void onNewTransaction() {
- // TODO: [prio=low] get rid of UpdatedInBackgroundEvent and move to
- // adding the v2 tx to the db which would update ui automagically since the
- // db is watched by the ui
- // call this here?
- GlobalEventBus.instance.fire(
- UpdatedInBackgroundEvent(
- "New data found in $walletId ${info.name} in background!",
- walletId,
- ),
- );
- }
-
- void syncStatusChanged() async {
- final syncStatus = cwWalletBase?.syncStatus;
-
- if (syncStatus != null) {
- if (syncStatus.progress() == 1 && refreshMutex.isLocked) {
- refreshMutex.release();
- }
-
- WalletSyncStatus? status;
- xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(true);
-
- if (syncStatus is SyncingSyncStatus) {
- final int blocksLeft = syncStatus.blocksLeft;
-
- // ensure at least 1 to prevent math errors
- final int height = max(1, syncStatus.height);
-
- final nodeHeight = height + blocksLeft;
- currentKnownChainHeight = nodeHeight;
-
- final percent = height / nodeHeight;
-
- final highest = max(highestPercentCached, percent);
-
- // update cached
- if (highestPercentCached < percent) {
- highestPercentCached = percent;
- }
-
- GlobalEventBus.instance.fire(
- RefreshPercentChangedEvent(
- highest,
- walletId,
- ),
- );
- GlobalEventBus.instance.fire(
- BlocksRemainingEvent(
- blocksLeft,
- walletId,
- ),
- );
- } else if (syncStatus is SyncedSyncStatus) {
- status = WalletSyncStatus.synced;
- } else if (syncStatus is NotConnectedSyncStatus) {
- status = WalletSyncStatus.unableToSync;
- xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false);
- } else if (syncStatus is StartingSyncStatus) {
- status = WalletSyncStatus.syncing;
- GlobalEventBus.instance.fire(
- RefreshPercentChangedEvent(
- highestPercentCached,
- walletId,
- ),
- );
- } else if (syncStatus is FailedSyncStatus) {
- status = WalletSyncStatus.unableToSync;
- xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false);
- } else if (syncStatus is ConnectingSyncStatus) {
- status = WalletSyncStatus.syncing;
- GlobalEventBus.instance.fire(
- RefreshPercentChangedEvent(
- highestPercentCached,
- walletId,
- ),
- );
- } else if (syncStatus is ConnectedSyncStatus) {
- status = WalletSyncStatus.syncing;
- GlobalEventBus.instance.fire(
- RefreshPercentChangedEvent(
- highestPercentCached,
- walletId,
- ),
- );
- } else if (syncStatus is LostConnectionSyncStatus) {
- status = WalletSyncStatus.unableToSync;
- xmrAndWowSyncSpecificFunctionThatShouldBeGottenRidOfInTheFuture(false);
- }
-
- if (status != null) {
- GlobalEventBus.instance.fire(
- WalletSyncStatusChangedEvent(
- status,
- walletId,
- info.coin,
- ),
- );
- }
- }
- }
-
- @override
- Future checkSaveInitialReceivingAddress() async {
- // this doesn't work without opening the wallet first which takes a while
- }
-
- // ============ Interface ====================================================
-
- U? get cwWalletBase;
- V? get cwWalletService;
-
- Future get availableBalance;
- Future get totalBalance;
-
- Future open();
-
- Address addressFor({required int index, int account = 0});
-
- Future getKeys();
-
- // ============ Private ======================================================
- Future _refreshTxDataHelper() async {
- if (_txRefreshLock) return;
- _txRefreshLock = true;
-
- final syncStatus = cwWalletBase?.syncStatus;
-
- if (syncStatus != null && syncStatus is SyncingSyncStatus) {
- final int blocksLeft = syncStatus.blocksLeft;
- final tenKChange = blocksLeft ~/ 10000;
-
- // only refresh transactions periodically during a sync
- if (_lastCheckedHeight == -1 || tenKChange < _lastCheckedHeight) {
- _lastCheckedHeight = tenKChange;
- await _refreshTxData();
- }
- } else {
- await _refreshTxData();
- }
-
- _txRefreshLock = false;
- }
-
- Future _refreshTxData() async {
- await updateTransactions();
- final count = await mainDB.getTransactions(walletId).count();
-
- if (count > _txCount) {
- _txCount = count;
- await updateBalance();
- GlobalEventBus.instance.fire(
- UpdatedInBackgroundEvent(
- "New transaction data found in $walletId ${info.name}!",
- walletId,
- ),
- );
- }
- }
-
- // ============ Overrides ====================================================
-
- @override
- FilterOperation? get changeAddressFilterOperation => null;
-
- @override
- FilterOperation? get receivingAddressFilterOperation => null;
-
- @override
- Future updateUTXOs() async {
- await cwWalletBase?.updateUTXOs();
-
- final List outputArray = [];
- for (final rawUTXO in (cwWalletBase?.utxos ?? [])) {
- if (!rawUTXO.spent) {
- final current = await mainDB.isar.utxos
- .where()
- .walletIdEqualTo(walletId)
- .filter()
- .voutEqualTo(rawUTXO.vout)
- .and()
- .txidEqualTo(rawUTXO.hash)
- .findFirst();
- final tx = await mainDB.isar.transactions
- .where()
- .walletIdEqualTo(walletId)
- .filter()
- .txidEqualTo(rawUTXO.hash)
- .findFirst();
-
- final otherDataMap = {
- "keyImage": rawUTXO.keyImage,
- "spent": rawUTXO.spent,
- };
-
- final utxo = UTXO(
- address: rawUTXO.address,
- walletId: walletId,
- txid: rawUTXO.hash,
- vout: rawUTXO.vout,
- value: rawUTXO.value,
- name: current?.name ?? "",
- isBlocked: current?.isBlocked ?? rawUTXO.isFrozen,
- blockedReason: current?.blockedReason ?? "",
- isCoinbase: rawUTXO.coinbase,
- blockHash: "",
- blockHeight:
- tx?.height ?? (rawUTXO.height > 0 ? rawUTXO.height : null),
- blockTime: tx?.timestamp,
- otherData: jsonEncode(otherDataMap),
- );
-
- outputArray.add(utxo);
- }
- }
-
- await mainDB.updateUTXOs(walletId, outputArray);
-
- return true;
- }
-
- @override
- Future updateBalance({bool shouldUpdateUtxos = true}) async {
- if (shouldUpdateUtxos) {
- await updateUTXOs();
- }
-
- final total = await totalBalance;
- final available = await availableBalance;
-
- final balance = Balance(
- total: total,
- spendable: available,
- blockedTotal: Amount(
- rawValue: BigInt.zero,
- fractionDigits: cryptoCurrency.fractionDigits,
- ),
- pendingSpendable: total - available,
- );
-
- await info.updateBalance(newBalance: balance, isar: mainDB.isar);
- }
-
- @override
- Future refresh() async {
- // Awaiting this lock could be dangerous.
- // Since refresh is periodic (generally)
- if (refreshMutex.isLocked) {
- return;
- }
-
- // this acquire should be almost instant due to above check.
- // Slight possibility of race but should be irrelevant
- await refreshMutex.acquire();
-
- GlobalEventBus.instance.fire(
- WalletSyncStatusChangedEvent(
- WalletSyncStatus.syncing,
- walletId,
- info.coin,
- ),
- );
-
- await updateTransactions();
- await updateBalance();
-
- if (info.otherData[WalletInfoKeys.reuseAddress] != true) {
- await checkReceivingAddressForTransactions();
- }
-
- if (cwWalletBase?.syncStatus is SyncedSyncStatus) {
- refreshMutex.release();
- GlobalEventBus.instance.fire(
- WalletSyncStatusChangedEvent(
- WalletSyncStatus.synced,
- walletId,
- info.coin,
- ),
- );
- }
- }
-
- @override
- Future exit() async {
- autoSaveTimer?.cancel();
- await cwWalletBase?.save();
- cwWalletBase?.close();
- }
-
- @override
- Future generateNewReceivingAddress() async {
- try {
- final currentReceiving = await getCurrentReceivingAddress();
-
- final newReceivingIndex =
- currentReceiving == null ? 0 : currentReceiving.derivationIndex + 1;
-
- final newReceivingAddress = addressFor(index: newReceivingIndex);
-
- // Add that new receiving address
- await mainDB.putAddress(newReceivingAddress);
- await info.updateReceivingAddress(
- newAddress: newReceivingAddress.value,
- isar: mainDB.isar,
- );
- } catch (e, s) {
- Logging.instance.log(
- "Exception in generateNewAddress(): $e\n$s",
- level: LogLevel.Error,
- );
- }
- }
-
- @override
- Future checkReceivingAddressForTransactions() async {
- if (info.otherData[WalletInfoKeys.reuseAddress] == true) {
- try {
- throw Exception();
- } catch (_, s) {
- Logging.instance.log(
- "checkReceivingAddressForTransactions called but reuse address flag set: $s",
- level: LogLevel.Error,
- );
- }
- }
-
- try {
- int highestIndex = -1;
- final entries = cwWalletBase?.transactionHistory?.transactions?.entries;
- if (entries != null) {
- for (final element in entries) {
- if (element.value.direction == TransactionDirection.incoming) {
- final int curAddressIndex =
- element.value.additionalInfo!['addressIndex'] as int;
- if (curAddressIndex > highestIndex) {
- highestIndex = curAddressIndex;
- }
- }
- }
- }
-
- // Check the new receiving index
- final currentReceiving = await getCurrentReceivingAddress();
- final curIndex = currentReceiving?.derivationIndex ?? -1;
-
- if (highestIndex >= curIndex) {
- // First increment the receiving index
- final newReceivingIndex = curIndex + 1;
-
- // Use new index to derive a new receiving address
- final newReceivingAddress = addressFor(index: newReceivingIndex);
-
- final existing = await mainDB
- .getAddresses(walletId)
- .filter()
- .valueEqualTo(newReceivingAddress.value)
- .findFirst();
- if (existing == null) {
- // Add that new change address
- await mainDB.putAddress(newReceivingAddress);
- } else {
- // we need to update the address
- await mainDB.updateAddress(existing, newReceivingAddress);
- }
- if (info.otherData[WalletInfoKeys.reuseAddress] != true) {
- // keep checking until address with no tx history is set as current
- await checkReceivingAddressForTransactions();
- }
- }
- } on SocketException catch (se, s) {
- Logging.instance.log(
- "SocketException caught in _checkReceivingAddressForTransactions(): $se\n$s",
- level: LogLevel.Error,
- );
- return;
- } catch (e, s) {
- Logging.instance.log(
- "Exception rethrown from _checkReceivingAddressForTransactions(): $e\n$s",
- level: LogLevel.Error,
- );
- rethrow;
- }
- }
-
- @override
- Future get fees async => FeeObject(
- numberOfBlocksFast: 10,
- numberOfBlocksAverage: 15,
- numberOfBlocksSlow: 20,
- fast: MoneroTransactionPriority.fast.raw!,
- medium: MoneroTransactionPriority.regular.raw!,
- slow: MoneroTransactionPriority.slow.raw!,
- );
- @override
- Future updateChainHeight() async {
- await info.updateCachedChainHeight(
- newHeight: currentKnownChainHeight,
- isar: mainDB.isar,
- );
- }
-
- @override
- Future checkChangeAddressForTransactions() async {
- // do nothing
- }
-
- @override
- Future generateNewChangeAddress() async {
- // do nothing
- }
-}
diff --git a/lib/widgets/desktop/desktop_fee_dialog.dart b/lib/widgets/desktop/desktop_fee_dialog.dart
index 90304e80c..322fbb876 100644
--- a/lib/widgets/desktop/desktop_fee_dialog.dart
+++ b/lib/widgets/desktop/desktop_fee_dialog.dart
@@ -1,6 +1,7 @@
-import 'package:cw_core/monero_transaction_priority.dart';
import 'package:flutter/material.dart';
+import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter_riverpod/flutter_riverpod.dart';
+
import '../../models/models.dart';
import '../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart';
import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart';
@@ -61,7 +62,7 @@ class _DesktopFeeDialogState extends ConsumerState {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.fast.raw!,
+ lib_monero.TransactionPriority.high.value,
);
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
} else if (coin is Firo) {
@@ -111,7 +112,7 @@ class _DesktopFeeDialogState extends ConsumerState {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.regular.raw!,
+ lib_monero.TransactionPriority.medium.value,
);
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
} else if (coin is Firo) {
@@ -161,7 +162,7 @@ class _DesktopFeeDialogState extends ConsumerState {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount,
- MoneroTransactionPriority.slow.raw!,
+ lib_monero.TransactionPriority.normal.value,
);
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
} else if (coin is Firo) {
diff --git a/lib/widgets/wallet_card.dart b/lib/widgets/wallet_card.dart
index a2185186c..79ab0d41d 100644
--- a/lib/widgets/wallet_card.dart
+++ b/lib/widgets/wallet_card.dart
@@ -27,8 +27,8 @@ 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/wallet.dart';
-import '../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
import 'conditional_parent.dart';
import 'desktop/primary_button.dart';
import 'dialogs/basic_dialog.dart';
@@ -97,7 +97,7 @@ class SimpleWalletCard extends ConsumerWidget {
if (context.mounted) {
final Future loadFuture;
- if (wallet is CwBasedInterface) {
+ if (wallet is LibMoneroWallet) {
loadFuture = wallet.init().then((value) async => await (wallet).open());
} else {
loadFuture = wallet.init();
diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc
index 499e835f2..df4b140d1 100644
--- a/linux/flutter/generated_plugin_registrant.cc
+++ b/linux/flutter/generated_plugin_registrant.cc
@@ -6,10 +6,10 @@
#include "generated_plugin_registrant.h"
+#include
#include
#include
#include
-#include
#include
#include
#include
@@ -18,6 +18,9 @@
#include
void fl_register_plugins(FlPluginRegistry* registry) {
+ g_autoptr(FlPluginRegistrar) cs_monero_flutter_libs_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "CsMoneroFlutterLibsPlugin");
+ cs_monero_flutter_libs_plugin_register_with_registrar(cs_monero_flutter_libs_registrar);
g_autoptr(FlPluginRegistrar) desktop_drop_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin");
desktop_drop_plugin_register_with_registrar(desktop_drop_registrar);
@@ -27,9 +30,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_libepiccash_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterLibepiccashPlugin");
flutter_libepiccash_plugin_register_with_registrar(flutter_libepiccash_registrar);
- g_autoptr(FlPluginRegistrar) flutter_libmonero_registrar =
- fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterLibmoneroPlugin");
- flutter_libmonero_plugin_register_with_registrar(flutter_libmonero_registrar);
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake
index b4a4986e6..f92bb010e 100644
--- a/linux/flutter/generated_plugins.cmake
+++ b/linux/flutter/generated_plugins.cmake
@@ -3,10 +3,10 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
+ cs_monero_flutter_libs
desktop_drop
devicelocale
flutter_libepiccash
- flutter_libmonero
flutter_secure_storage_linux
isar_flutter_libs
sqlite3_flutter_libs
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index a8e802cea..5886d38ca 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -7,6 +7,7 @@ import Foundation
import camera_macos
import connectivity_plus
+import cs_monero_flutter_libs
import desktop_drop
import device_info_plus
import devicelocale
@@ -28,6 +29,7 @@ import window_size
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
CameraMacosPlugin.register(with: registry.registrar(forPlugin: "CameraMacosPlugin"))
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
+ CsMoneroFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "CsMoneroFlutterLibsPlugin"))
DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index 48bab8292..d436cea3d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -54,14 +54,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.5.0"
- asn1lib:
- dependency: transitive
- description:
- name: asn1lib
- sha256: "2ca377ad4d677bbadca278e0ba4da4e057b80a10b927bfc8f7d8bda8fe2ceb75"
- url: "https://pub.dev"
- source: hosted
- version: "1.5.4"
async:
dependency: "direct main"
description:
@@ -374,6 +366,13 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
+ compat:
+ dependency: "direct main"
+ description:
+ path: "crypto_plugins/cs_monero/compat"
+ relative: true
+ source: path
+ version: "1.0.0"
connectivity_plus:
dependency: "direct main"
description:
@@ -430,6 +429,20 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.7.0"
+ cs_monero:
+ dependency: "direct main"
+ description:
+ path: "crypto_plugins/cs_monero/cs_monero"
+ relative: true
+ source: path
+ version: "1.0.0"
+ cs_monero_flutter_libs:
+ dependency: "direct main"
+ description:
+ path: "crypto_plugins/cs_monero/cs_monero_flutter_libs"
+ relative: true
+ source: path
+ version: "1.0.0"
csslib:
dependency: transitive
description:
@@ -438,27 +451,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
- cw_core:
- dependency: "direct main"
- description:
- path: "crypto_plugins/flutter_libmonero/cw_core"
- relative: true
- source: path
- version: "0.0.1"
- cw_monero:
- dependency: "direct main"
- description:
- path: "crypto_plugins/flutter_libmonero/cw_monero"
- relative: true
- source: path
- version: "0.0.1"
- cw_wownero:
- dependency: "direct main"
- description:
- path: "crypto_plugins/flutter_libmonero/cw_wownero"
- relative: true
- source: path
- version: "0.0.1"
dart_base_x:
dependency: transitive
description:
@@ -628,14 +620,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.9.9"
- encrypt:
- dependency: transitive
- description:
- name: encrypt
- sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2"
- url: "https://pub.dev"
- source: hosted
- version: "5.0.3"
equatable:
dependency: "direct main"
description:
@@ -750,13 +734,6 @@ packages:
relative: true
source: path
version: "0.0.1"
- flutter_libmonero:
- dependency: "direct main"
- description:
- path: "crypto_plugins/flutter_libmonero"
- relative: true
- source: path
- version: "0.0.1"
flutter_libsparkmobile:
dependency: "direct main"
description:
@@ -798,14 +775,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.2.0"
- flutter_mobx:
- dependency: transitive
- description:
- name: flutter_mobx
- sha256: "859fbf452fa9c2519d2700b125dd7fb14c508bbdd7fb65e26ca8ff6c92280e2e"
- url: "https://pub.dev"
- source: hosted
- version: "2.2.1+1"
flutter_native_splash:
dependency: "direct main"
description:
@@ -1217,6 +1186,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.11"
+ logger:
+ dependency: transitive
+ description:
+ name: logger
+ sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.0"
logging:
dependency: transitive
description:
@@ -1281,14 +1258,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.6"
- mobx:
- dependency: transitive
- description:
- name: mobx
- sha256: "63920b27b32ad1910adfe767ab1750e4c212e8923232a1f891597b362074ea5e"
- url: "https://pub.dev"
- source: hosted
- version: "2.3.3+2"
mockingjay:
dependency: "direct dev"
description:
@@ -1338,14 +1307,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
- nested:
- dependency: transitive
- description:
- name: nested
- sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
- url: "https://pub.dev"
- source: hosted
- version: "1.0.0"
nm:
dependency: transitive
description:
@@ -1578,14 +1539,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.0"
- provider:
- dependency: transitive
- description:
- name: provider
- sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
- url: "https://pub.dev"
- source: hosted
- version: "6.1.2"
pub_semver:
dependency: transitive
description:
diff --git a/scripts/android/build_all.sh b/scripts/android/build_all.sh
index 7cb2e083d..e9417b263 100755
--- a/scripts/android/build_all.sh
+++ b/scripts/android/build_all.sh
@@ -14,7 +14,7 @@ PLUGINS_DIR=../../crypto_plugins
(cd "${PLUGINS_DIR}"/flutter_liblelantus/scripts/android && ./build_all.sh )
(cd "${PLUGINS_DIR}"/flutter_libepiccash/scripts/android && ./build_all.sh )
-(cd "${PLUGINS_DIR}"/flutter_libmonero/scripts/android/ && ./build_all.sh )
+(cd "${PLUGINS_DIR}"/cs_monero/tools/build_scripts && ./build_android.sh )
set_rust_to_1720
(cd "${PLUGINS_DIR}"/frostdart/scripts/android && ./build_all.sh )
diff --git a/scripts/android/build_all_campfire.sh b/scripts/android/build_all_campfire.sh
index 7cb2e083d..e9417b263 100755
--- a/scripts/android/build_all_campfire.sh
+++ b/scripts/android/build_all_campfire.sh
@@ -14,7 +14,7 @@ PLUGINS_DIR=../../crypto_plugins
(cd "${PLUGINS_DIR}"/flutter_liblelantus/scripts/android && ./build_all.sh )
(cd "${PLUGINS_DIR}"/flutter_libepiccash/scripts/android && ./build_all.sh )
-(cd "${PLUGINS_DIR}"/flutter_libmonero/scripts/android/ && ./build_all.sh )
+(cd "${PLUGINS_DIR}"/cs_monero/tools/build_scripts && ./build_android.sh )
set_rust_to_1720
(cd "${PLUGINS_DIR}"/frostdart/scripts/android && ./build_all.sh )
diff --git a/scripts/android/build_all_duo.sh b/scripts/android/build_all_duo.sh
index aec2ebbb3..f184a71dd 100755
--- a/scripts/android/build_all_duo.sh
+++ b/scripts/android/build_all_duo.sh
@@ -16,7 +16,7 @@ PLUGINS_DIR=../../crypto_plugins
(cd "${PLUGINS_DIR}"/flutter_liblelantus/scripts/android && ./build_all.sh )
(cd "${PLUGINS_DIR}"/flutter_libepiccash/scripts/android && ./build_all.sh )
-(cd "${PLUGINS_DIR}"/flutter_libmonero/scripts/android/ && ./build_all.sh )
+(cd "${PLUGINS_DIR}"/cs_monero/tools/build_scripts && ./build_android.sh )
set_rust_to_1720
(cd "${PLUGINS_DIR}"/frostdart/scripts/android && ./build_all.sh )
diff --git a/scripts/app_config/templates/android/app/build.gradle b/scripts/app_config/templates/android/app/build.gradle
index 631c1300e..60e622ec9 100644
--- a/scripts/app_config/templates/android/app/build.gradle
+++ b/scripts/app_config/templates/android/app/build.gradle
@@ -45,14 +45,14 @@ android {
abiFilters "x86_64","armeabi-v7a", "arm64-v8a"
}
- externalNativeBuild {
- cmake {
- arguments "-DANDROID_STL=c++_shared", '-DBUILD_TESTING=OFF', "-DANDROID_TOOLCHAIN=clang -v"
- cppFlags "-frtti -fexceptions -v -DANDROID -std=c++17"
-// cppFlags "-std=c++11"
- version "3.10.2"
- }
- }
+// externalNativeBuild {
+// cmake {
+// arguments "-DANDROID_STL=c++_shared", '-DBUILD_TESTING=OFF', "-DANDROID_TOOLCHAIN=clang -v"
+// cppFlags "-frtti -fexceptions -v -DANDROID -std=c++17"
+//// cppFlags "-std=c++11"
+// version "3.10.2"
+// }
+// }
}
signingConfigs {
diff --git a/scripts/app_config/templates/linux/CMakeLists.txt b/scripts/app_config/templates/linux/CMakeLists.txt
index a13bec888..25750ef4f 100644
--- a/scripts/app_config/templates/linux/CMakeLists.txt
+++ b/scripts/app_config/templates/linux/CMakeLists.txt
@@ -134,12 +134,6 @@ install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/monero/x86_64-linux-gnu_libwallet2_api_c.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "monero_libwallet2_api_c.so"
- COMPONENT Runtime)
-
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/wownero/x86_64-linux-gnu_libwallet2_api_c.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "wownero_libwallet2_api_c.so"
- COMPONENT Runtime)
-
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash/scripts/linux/build/rust/target/x86_64-unknown-linux-gnu/release/libepic_cash_wallet.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
diff --git a/scripts/app_config/templates/pubspec.template b/scripts/app_config/templates/pubspec.template
index b0dc23bc4..5626025ac 100644
--- a/scripts/app_config/templates/pubspec.template
+++ b/scripts/app_config/templates/pubspec.template
@@ -37,17 +37,14 @@ dependencies:
url: https://github.com/cypherstack/flutter_libsparkmobile.git
ref: cc7b43b731e4a7906dd25d4364a08e34554cee19
- flutter_libmonero:
- path: ./crypto_plugins/flutter_libmonero
+ cs_monero:
+ path: ./crypto_plugins/cs_monero/cs_monero
- cw_monero:
- path: ./crypto_plugins/flutter_libmonero/cw_monero
+ compat:
+ path: ./crypto_plugins/cs_monero/compat
- cw_wownero:
- path: ./crypto_plugins/flutter_libmonero/cw_wownero
-
- cw_core:
- path: ./crypto_plugins/flutter_libmonero/cw_core
+ cs_monero_flutter_libs:
+ path: ./crypto_plugins/cs_monero/cs_monero_flutter_libs
monero:
git:
diff --git a/scripts/app_config/templates/windows/CMakeLists.txt b/scripts/app_config/templates/windows/CMakeLists.txt
index 795e592f2..b9add856d 100644
--- a/scripts/app_config/templates/windows/CMakeLists.txt
+++ b/scripts/app_config/templates/windows/CMakeLists.txt
@@ -86,27 +86,6 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/windows/build/libmobileliblelantus.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/monero/x86_64-w64-mingw32_libwallet2_api_c.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "monero_libwallet2_api_c.dll"
- COMPONENT Runtime)
-
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/wownero/x86_64-w64-mingw32_libwallet2_api_c.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "wownero_libwallet2_api_c.dll"
- COMPONENT Runtime)
-
-#install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/wownero/x86_64-w64-mingw32_libgcc_s_seh-1.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "libgcc_s_seh-1.dll"
-# COMPONENT Runtime)
-
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/wownero/x86_64-w64-mingw32_libpolyseed.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "libpolyseed.dll"
- COMPONENT Runtime)
-
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/wownero/x86_64-w64-mingw32_libssp-0.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "libssp-0.dll"
- COMPONENT Runtime)
-
-#install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/wownero/x86_64-w64-mingw32_libstdc++-6.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "libstdc++-6.dll"
-# COMPONENT Runtime)
-
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmonero/scripts/monero_c/release/wownero/x86_64-w64-mingw32_libwinpthread-1.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" RENAME "libwinpthread-1.dll"
- COMPONENT Runtime)
-
if(PLUGIN_BUNDLED_LIBRARIES)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
diff --git a/scripts/ios/build_all.sh b/scripts/ios/build_all.sh
index b34724561..74e9721fa 100755
--- a/scripts/ios/build_all.sh
+++ b/scripts/ios/build_all.sh
@@ -16,7 +16,7 @@ rustup target add x86_64-apple-ios
(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/ios && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/ios/ && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_ios.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/ios && ./build_all.sh )
diff --git a/scripts/ios/build_all_campfire.sh b/scripts/ios/build_all_campfire.sh
index b34724561..74e9721fa 100755
--- a/scripts/ios/build_all_campfire.sh
+++ b/scripts/ios/build_all_campfire.sh
@@ -16,7 +16,7 @@ rustup target add x86_64-apple-ios
(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/ios && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/ios/ && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_ios.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/ios && ./build_all.sh )
diff --git a/scripts/ios/build_all_duo.sh b/scripts/ios/build_all_duo.sh
index 387f85f81..bef08e8c8 100755
--- a/scripts/ios/build_all_duo.sh
+++ b/scripts/ios/build_all_duo.sh
@@ -18,7 +18,7 @@ rustup target add x86_64-apple-ios
(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/ios && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/ios/ && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_ios.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/ios && ./build_all.sh )
diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh
index c9542798e..d541cc34f 100755
--- a/scripts/linux/build_all.sh
+++ b/scripts/linux/build_all.sh
@@ -14,7 +14,7 @@ mkdir -p build
./build_secure_storage_deps.sh
(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_linux.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/linux && ./build_all.sh )
diff --git a/scripts/linux/build_all_campfire.sh b/scripts/linux/build_all_campfire.sh
index c9542798e..d541cc34f 100755
--- a/scripts/linux/build_all_campfire.sh
+++ b/scripts/linux/build_all_campfire.sh
@@ -14,7 +14,7 @@ mkdir -p build
./build_secure_storage_deps.sh
(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_linux.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/linux && ./build_all.sh )
diff --git a/scripts/linux/build_all_duo.sh b/scripts/linux/build_all_duo.sh
index e7397bdc5..5dc0e5bb0 100755
--- a/scripts/linux/build_all_duo.sh
+++ b/scripts/linux/build_all_duo.sh
@@ -16,7 +16,7 @@ mkdir -p build
./build_secure_storage_deps.sh &
(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_linux.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/linux && ./build_all.sh )
diff --git a/scripts/macos/build_all.sh b/scripts/macos/build_all.sh
index e3a58b45f..1636db4d3 100755
--- a/scripts/macos/build_all.sh
+++ b/scripts/macos/build_all.sh
@@ -8,7 +8,7 @@ set_rust_to_1671
(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/macos/ && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_macos.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh )
diff --git a/scripts/macos/build_all_campfire.sh b/scripts/macos/build_all_campfire.sh
index e3a58b45f..1636db4d3 100755
--- a/scripts/macos/build_all_campfire.sh
+++ b/scripts/macos/build_all_campfire.sh
@@ -8,7 +8,7 @@ set_rust_to_1671
(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/macos/ && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_macos.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh )
diff --git a/scripts/macos/build_all_duo.sh b/scripts/macos/build_all_duo.sh
index 6f70f4371..7cc31c9d1 100755
--- a/scripts/macos/build_all_duo.sh
+++ b/scripts/macos/build_all_duo.sh
@@ -10,7 +10,7 @@ set_rust_to_1671
(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/macos/ && ./build_all.sh )
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_macos.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh )
diff --git a/scripts/windows/build_all.sh b/scripts/windows/build_all.sh
index fc6ac37b1..d63e408ce 100755
--- a/scripts/windows/build_all.sh
+++ b/scripts/windows/build_all.sh
@@ -9,7 +9,7 @@ set_rust_to_1671
mkdir -p build
(cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./build_all.sh )
(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./build_all.sh)
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_windows.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh )
diff --git a/scripts/windows/build_all_campfire.sh b/scripts/windows/build_all_campfire.sh
index fc6ac37b1..d63e408ce 100755
--- a/scripts/windows/build_all_campfire.sh
+++ b/scripts/windows/build_all_campfire.sh
@@ -9,7 +9,7 @@ set_rust_to_1671
mkdir -p build
(cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./build_all.sh )
(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./build_all.sh)
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_windows.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh )
diff --git a/scripts/windows/build_all_duo.sh b/scripts/windows/build_all_duo.sh
index 80303f28b..7226c4e41 100755
--- a/scripts/windows/build_all_duo.sh
+++ b/scripts/windows/build_all_duo.sh
@@ -11,7 +11,7 @@ set_rust_to_1671
mkdir -p build
(cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./build_all.sh )
(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh )
-(cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./build_all.sh)
+(cd ../../crypto_plugins/cs_monero/tools/build_scripts && ./build_windows.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh )
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index bc627d626..36adbeb1a 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -8,6 +8,7 @@
#include
#include
+#include
#include
#include
#include
@@ -25,6 +26,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("CameraWindows"));
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
+ CsMoneroFlutterLibsPluginCApiRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("CsMoneroFlutterLibsPluginCApi"));
DesktopDropPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
FlutterLibepiccashPluginCApiRegisterWithRegistrar(
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index d25497442..041b049af 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -5,6 +5,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
camera_windows
connectivity_plus
+ cs_monero_flutter_libs
desktop_drop
flutter_libepiccash
flutter_secure_storage_windows