mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-22 11:29:23 +00:00
WIP migrate flutter_libmonero to cs_monero
This commit is contained in:
parent
4109e7ed9f
commit
16b9254761
67 changed files with 1728 additions and 2529 deletions
22
.gitignore
vendored
22
.gitignore
vendored
|
@ -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
|
||||
|
|
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -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
|
||||
|
|
1
crypto_plugins/cs_monero
Submodule
1
crypto_plugins/cs_monero
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit fee51e29e97ee8c1f57082b126173eeaf39a79f1
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 66369ef5b432e4d58e76b6cc4f91a5e24eb6b1ea
|
1
ios/MoneroWallet.framework/.gitignore
vendored
1
ios/MoneroWallet.framework/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
MoneroWallet
|
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>23E224</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>MoneroWallet</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.cypherstack.MoneroWallet</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>MoneroWallet</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>???</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>21E210</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphoneos</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>17.4</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>21E210</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>iphoneos17.4</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1530</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>15E204a</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>16.0</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
1
ios/WowneroWallet.framework/.gitignore
vendored
1
ios/WowneroWallet.framework/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
WowneroWallet
|
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>23E224</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>WowneroWallet</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.cypherstack.WowneroWallet</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>WowneroWallet</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>???</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>21E210</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphoneos</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>17.4</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>21E210</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>iphoneos17.4</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1530</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>15E204a</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>16.0</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -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<Trade>? _boxTradesV2;
|
||||
Box<String>? _boxTradeNotes;
|
||||
Box<String>? _boxFavoriteWallets;
|
||||
Box<xmr.WalletInfo>? _walletInfoSource;
|
||||
Box<lib_monero_compat.WalletInfo>? _walletInfoSource;
|
||||
Box<dynamic>? _boxPrefs;
|
||||
Box<TradeWalletLookup>? _boxTradeLookup;
|
||||
Box<dynamic>? _boxDBInfo;
|
||||
|
@ -85,7 +85,8 @@ class DB {
|
|||
final Map<String, Box<dynamic>> _getSparkUsedCoinsTagsCacheBoxes = {};
|
||||
|
||||
// exposed for monero
|
||||
Box<xmr.WalletInfo> get moneroWalletInfoBox => _walletInfoSource!;
|
||||
Box<lib_monero_compat.WalletInfo> get moneroWalletInfoBox =>
|
||||
_walletInfoSource!;
|
||||
|
||||
// mutex for stack backup
|
||||
final mutex = Mutex();
|
||||
|
@ -147,8 +148,8 @@ class DB {
|
|||
_boxTradesV2 = await hive.openBox<Trade>(boxNameTradesV2);
|
||||
_boxTradeNotes = await hive.openBox<String>(boxNameTradeNotes);
|
||||
_boxTradeLookup = await hive.openBox<TradeWalletLookup>(boxNameTradeLookup);
|
||||
_walletInfoSource =
|
||||
await hive.openBox<xmr.WalletInfo>(xmr.WalletInfo.boxName);
|
||||
_walletInfoSource = await hive.openBox<lib_monero_compat.WalletInfo>(
|
||||
lib_monero_compat.WalletInfo.boxName);
|
||||
_boxFavoriteWallets = await hive.openBox<String>(boxNameFavoriteWallets);
|
||||
|
||||
await Future.wait([
|
||||
|
|
|
@ -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<String> 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<String> 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,
|
||||
|
|
|
@ -67,7 +67,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
|
|||
late final TextEditingController passwordController;
|
||||
|
||||
final bool _nextEnabled = true;
|
||||
DateTime _restoreFromDate = DateTime.fromMillisecondsSinceEpoch(0);
|
||||
DateTime? _restoreFromDate;
|
||||
bool hidePassword = true;
|
||||
bool _expandedAdavnced = false;
|
||||
|
||||
|
|
|
@ -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<RestoreWalletView> {
|
|||
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<RestoreWalletView> {
|
|||
}
|
||||
}
|
||||
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<RestoreWalletView> {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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<SendFromCard> {
|
|||
// 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();
|
||||
}
|
||||
|
|
|
@ -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<LockscreenView> {
|
|||
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
final Future<void> loadFuture;
|
||||
if (wallet is CwBasedInterface) {
|
||||
if (wallet is LibMoneroWallet) {
|
||||
loadFuture =
|
||||
wallet.init().then((value) async => await (wallet).open());
|
||||
} else {
|
||||
|
|
|
@ -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<SendView> {
|
|||
|
||||
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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -272,48 +272,48 @@ class AboutView extends ConsumerWidget {
|
|||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (AppConfig.coins.whereType<Monero>().isNotEmpty)
|
||||
FutureBuilder(
|
||||
future: GitStatus.getMoneroCommitStatus(),
|
||||
builder: (
|
||||
context,
|
||||
AsyncSnapshot<CommitStatus> 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<Monero>().isNotEmpty)
|
||||
// FutureBuilder(
|
||||
// future: GitStatus.getMoneroCommitStatus(),
|
||||
// builder: (
|
||||
// context,
|
||||
// AsyncSnapshot<CommitStatus> 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,
|
||||
|
|
|
@ -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<DebugView> {
|
|||
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<DebugView> {
|
|||
"appName": appName,
|
||||
"firoCommit": firoCommit,
|
||||
"epicCashCommit": epicCashCommit,
|
||||
"moneroCommit": moneroCommit,
|
||||
// "moneroCommit": moneroCommit,
|
||||
"deviceInfoMap": deviceInfoMap,
|
||||
"errorLogs": errorLogs,
|
||||
};
|
||||
|
|
|
@ -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<AddEditNodeView> {
|
|||
|
||||
// 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<NodeForm> {
|
|||
} 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<NodeForm> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (widget.coin is CwBasedInterface)
|
||||
if (widget.coin is LibMoneroWallet)
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
|
|
|
@ -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<void>? restoringFuture;
|
||||
|
||||
if (!(wallet is CwBasedInterface || wallet is EpiccashWallet)) {
|
||||
if (!(wallet is LibMoneroWallet || wallet is EpiccashWallet)) {
|
||||
if (wallet is BitcoinFrostWallet) {
|
||||
restoringFuture = wallet.recover(
|
||||
isRescan: false,
|
||||
|
|
|
@ -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<WalletSettingsView> {
|
|||
KeyDataInterface? keyData;
|
||||
if (wallet is ExtendedKeysInterface) {
|
||||
keyData = await wallet.getXPrivs();
|
||||
} else if (wallet is CwBasedInterface) {
|
||||
} else if (wallet is LibMoneroWallet) {
|
||||
keyData = await wallet.getKeys();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<FavoriteCard> {
|
|||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
|
||||
final Future<void> loadFuture;
|
||||
if (wallet is CwBasedInterface) {
|
||||
if (wallet is LibMoneroWallet) {
|
||||
loadFuture =
|
||||
wallet.init().then((value) async => await (wallet).open());
|
||||
} else {
|
||||
|
|
|
@ -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<void> loadFuture;
|
||||
if (wallet is CwBasedInterface) {
|
||||
if (wallet is LibMoneroWallet) {
|
||||
loadFuture =
|
||||
wallet.init().then((value) async => await (wallet).open());
|
||||
} else {
|
||||
|
|
|
@ -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<void> loadFuture;
|
||||
if (wallet is CwBasedInterface) {
|
||||
if (wallet is LibMoneroWallet) {
|
||||
loadFuture = wallet
|
||||
.init()
|
||||
.then((value) async => await (wallet).open());
|
||||
|
|
|
@ -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<DesktopFeeDropDown> {
|
|||
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<DesktopFeeDropDown> {
|
|||
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<DesktopFeeDropDown> {
|
|||
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) {
|
||||
|
|
|
@ -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<DesktopSend> {
|
|||
if (coin is Monero || coin is Wownero) {
|
||||
final fee = await wallet.estimateFeeFor(
|
||||
amount,
|
||||
MoneroTransactionPriority.regular.raw!,
|
||||
lib_monero.TransactionPriority.medium.value,
|
||||
);
|
||||
ref
|
||||
.read(feeSheetSessionCacheProvider)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -434,63 +434,63 @@ class DesktopAboutView extends ConsumerWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
if (AppConfig.coins
|
||||
.whereType<Monero>()
|
||||
.isNotEmpty)
|
||||
FutureBuilder(
|
||||
future: GitStatus
|
||||
.getMoneroCommitStatus(),
|
||||
builder: (
|
||||
context,
|
||||
AsyncSnapshot<CommitStatus>
|
||||
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<Monero>()
|
||||
// .isNotEmpty)
|
||||
// FutureBuilder(
|
||||
// future: GitStatus
|
||||
// .getMoneroCommitStatus(),
|
||||
// builder: (
|
||||
// context,
|
||||
// AsyncSnapshot<CommitStatus>
|
||||
// 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),
|
||||
|
|
|
@ -1456,7 +1456,7 @@ class RouteGenerator {
|
|||
|
||||
case RestoreWalletView.routeName:
|
||||
if (args
|
||||
is Tuple6<String, CryptoCurrency, int, DateTime, String, bool>) {
|
||||
is Tuple6<String, CryptoCurrency, int, DateTime?, String, bool>) {
|
||||
return getRoute(
|
||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||
builder: (_) => RestoreWalletView(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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<CommitStatus> getMoneroCommitStatus() async {
|
||||
if (_cachedMoneroStatus != null) {
|
||||
return _cachedMoneroStatus!;
|
||||
}
|
||||
|
||||
final List<bool> 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<CommitStatus> getMoneroCommitStatus() async {
|
||||
// if (_cachedMoneroStatus != null) {
|
||||
// return _cachedMoneroStatus!;
|
||||
// }
|
||||
//
|
||||
// final List<bool> 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;
|
||||
|
|
|
@ -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<int>? 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, '
|
||||
|
|
|
@ -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<TorConnectionStatusChangedEvent>().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<TorPreferenceChangedEvent>().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<List<UTXO>> _streamSub;
|
||||
Future<void> _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<void> 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<Amount> 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<bool> pingCheck() async {
|
||||
return await cwWalletBase?.isConnected() ?? false;
|
||||
}
|
||||
bool walletExists(String path) => lib_monero.MoneroWallet.isWalletExist(path);
|
||||
|
||||
@override
|
||||
Future<void> 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<CWKeyData?> 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<void> 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<dynamic>(boxName: walletId, key: 'latest_tx_model')
|
||||
// as TransactionData?;
|
||||
// int latestTxnBlockHeight =
|
||||
// DB.instance.get<dynamic>(boxName: walletId, key: "storedTxnDataHeight")
|
||||
// as int? ??
|
||||
// 0;
|
||||
//
|
||||
// final txidsList = DB.instance
|
||||
// .get<dynamic>(boxName: walletId, key: "cachedTxids") as List? ??
|
||||
// [];
|
||||
//
|
||||
// final Set<String> cachedTxids = Set<String>.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<Tuple2<Transaction, Address?>> 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<void> 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<WalletInfo>(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<void> 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<WalletInfo>(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<TxData> 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<PendingTransaction>? 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<monero_output.Output> 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<lib_monero.Wallet> 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<TxData> 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<lib_monero.Wallet> 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<Amount> 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<Amount> 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<TorConnectionStatusChangedEvent>? _torStatusListener;
|
||||
StreamSubscription<TorPreferenceChangedEvent>? _torPreferenceListener;
|
||||
|
||||
final Mutex _torConnectingLock = Mutex();
|
||||
bool _requireMutex = false;
|
||||
}
|
||||
|
|
|
@ -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<TorConnectionStatusChangedEvent>().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<TorPreferenceChangedEvent>().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<List<UTXO>> _streamSub;
|
||||
Future<void> _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<Amount> 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<void>.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<bool> pingCheck() async {
|
||||
return await cwWalletBase?.isConnected() ?? false;
|
||||
}
|
||||
bool walletExists(String path) =>
|
||||
lib_monero.WowneroWallet.isWalletExist(path);
|
||||
|
||||
@override
|
||||
Future<void> 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<CWKeyData?> 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<void> 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<dynamic>(boxName: walletId, key: 'latest_tx_model')
|
||||
// as TransactionData?;
|
||||
// int latestTxnBlockHeight =
|
||||
// DB.instance.get<dynamic>(boxName: walletId, key: "storedTxnDataHeight")
|
||||
// as int? ??
|
||||
// 0;
|
||||
//
|
||||
// final txidsList = DB.instance
|
||||
// .get<dynamic>(boxName: walletId, key: "cachedTxids") as List? ??
|
||||
// [];
|
||||
//
|
||||
// final Set<String> cachedTxids = Set<String>.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<Tuple2<Transaction, Address?>> 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<void> 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<WalletInfo>(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<void> 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<void> 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<WalletInfo>(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<TxData> 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<PendingTransaction>? 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<wownero_output.Output> 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<lib_monero.Wallet> 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<TxData> 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<lib_monero.Wallet> 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<Amount> 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<Amount> 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<TorConnectionStatusChangedEvent>? _torStatusListener;
|
||||
StreamSubscription<TorPreferenceChangedEvent>? _torPreferenceListener;
|
||||
|
||||
final Mutex _torConnectingLock = Mutex();
|
||||
bool _requireMutex = false;
|
||||
}
|
||||
|
|
1293
lib/wallets/wallet/intermediate/lib_monero_wallet.dart
Normal file
1293
lib/wallets/wallet/intermediate/lib_monero_wallet.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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<T extends CryptonoteCurrency, U extends WalletBase,
|
||||
V extends WalletService> on CryptonoteWallet<T>
|
||||
implements MultiAddressInterface<T> {
|
||||
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<String> 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<String> 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<void> onUTXOsCHanged(List<UTXO> 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<void> checkSaveInitialReceivingAddress() async {
|
||||
// this doesn't work without opening the wallet first which takes a while
|
||||
}
|
||||
|
||||
// ============ Interface ====================================================
|
||||
|
||||
U? get cwWalletBase;
|
||||
V? get cwWalletService;
|
||||
|
||||
Future<Amount> get availableBalance;
|
||||
Future<Amount> get totalBalance;
|
||||
|
||||
Future<void> open();
|
||||
|
||||
Address addressFor({required int index, int account = 0});
|
||||
|
||||
Future<CWKeyData?> getKeys();
|
||||
|
||||
// ============ Private ======================================================
|
||||
Future<void> _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<void> _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<bool> updateUTXOs() async {
|
||||
await cwWalletBase?.updateUTXOs();
|
||||
|
||||
final List<UTXO> outputArray = [];
|
||||
for (final rawUTXO in (cwWalletBase?.utxos ?? <cw.UTXO>[])) {
|
||||
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<void> 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<void> 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<void> exit() async {
|
||||
autoSaveTimer?.cancel();
|
||||
await cwWalletBase?.save();
|
||||
cwWalletBase?.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> 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<void> 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<FeeObject> get fees async => FeeObject(
|
||||
numberOfBlocksFast: 10,
|
||||
numberOfBlocksAverage: 15,
|
||||
numberOfBlocksSlow: 20,
|
||||
fast: MoneroTransactionPriority.fast.raw!,
|
||||
medium: MoneroTransactionPriority.regular.raw!,
|
||||
slow: MoneroTransactionPriority.slow.raw!,
|
||||
);
|
||||
@override
|
||||
Future<void> updateChainHeight() async {
|
||||
await info.updateCachedChainHeight(
|
||||
newHeight: currentKnownChainHeight,
|
||||
isar: mainDB.isar,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> checkChangeAddressForTransactions() async {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> generateNewChangeAddress() async {
|
||||
// do nothing
|
||||
}
|
||||
}
|
|
@ -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<DesktopFeeDialog> {
|
|||
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<DesktopFeeDialog> {
|
|||
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<DesktopFeeDialog> {
|
|||
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) {
|
||||
|
|
|
@ -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<void> loadFuture;
|
||||
if (wallet is CwBasedInterface) {
|
||||
if (wallet is LibMoneroWallet) {
|
||||
loadFuture = wallet.init().then((value) async => await (wallet).open());
|
||||
} else {
|
||||
loadFuture = wallet.init();
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <cs_monero_flutter_libs/cs_monero_flutter_libs_plugin.h>
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
#include <devicelocale/devicelocale_plugin.h>
|
||||
#include <flutter_libepiccash/flutter_libepiccash_plugin.h>
|
||||
#include <flutter_libmonero/flutter_libmonero_plugin.h>
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
||||
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
|
||||
|
@ -18,6 +18,9 @@
|
|||
#include <window_size/window_size_plugin.h>
|
||||
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"))
|
||||
|
|
105
pubspec.lock
105
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:
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <camera_windows/camera_windows.h>
|
||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
#include <cs_monero_flutter_libs/cs_monero_flutter_libs_plugin_c_api.h>
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
#include <flutter_libepiccash/flutter_libepiccash_plugin_c_api.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue