diff --git a/android/app/build.gradle b/android/app/build.gradle
index 6c299c929..4a8045bb3 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -42,6 +42,14 @@ android {
disable 'InvalidPackage'
}
+ compileOptions {
+ coreLibraryDesugaringEnabled true
+
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+
+
namespace "com.cakewallet.cake_wallet"
defaultConfig {
@@ -73,7 +81,6 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
-
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
@@ -92,6 +99,7 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}
configurations {
implementation.exclude module:'proto-google-common-protos'
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
index 921ee4d4c..a733bae9e 100644
--- a/android/app/proguard-rules.pro
+++ b/android/app/proguard-rules.pro
@@ -6,4 +6,97 @@
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
-dontwarn io.flutter.embedding.**
--dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
\ No newline at end of file
+-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
+
+# start reown
+-dontwarn com.github.luben.zstd.BufferPool
+-dontwarn com.github.luben.zstd.ZstdInputStream
+-dontwarn com.github.luben.zstd.ZstdOutputStream
+-dontwarn com.google.api.client.http.GenericUrl
+-dontwarn com.google.api.client.http.HttpHeaders
+-dontwarn com.google.api.client.http.HttpRequest
+-dontwarn com.google.api.client.http.HttpRequestFactory
+-dontwarn com.google.api.client.http.HttpResponse
+-dontwarn com.google.api.client.http.HttpTransport
+-dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder
+-dontwarn com.google.api.client.http.javanet.NetHttpTransport
+-dontwarn java.awt.Color
+-dontwarn java.awt.Dimension
+-dontwarn java.awt.Graphics2D
+-dontwarn java.awt.Graphics
+-dontwarn java.awt.Image
+-dontwarn java.awt.Point
+-dontwarn java.awt.Polygon
+-dontwarn java.awt.Shape
+-dontwarn java.awt.color.ColorSpace
+-dontwarn java.awt.geom.AffineTransform
+-dontwarn java.awt.image.BufferedImage
+-dontwarn java.awt.image.ColorModel
+-dontwarn java.awt.image.ComponentColorModel
+-dontwarn java.awt.image.ComponentSampleModel
+-dontwarn java.awt.image.DataBuffer
+-dontwarn java.awt.image.DataBufferByte
+-dontwarn java.awt.image.DataBufferInt
+-dontwarn java.awt.image.DataBufferUShort
+-dontwarn java.awt.image.ImageObserver
+-dontwarn java.awt.image.MultiPixelPackedSampleModel
+-dontwarn java.awt.image.Raster
+-dontwarn java.awt.image.RenderedImage
+-dontwarn java.awt.image.SampleModel
+-dontwarn java.awt.image.SinglePixelPackedSampleModel
+-dontwarn java.awt.image.WritableRaster
+-dontwarn java.beans.BeanInfo
+-dontwarn java.beans.FeatureDescriptor
+-dontwarn java.beans.IntrospectionException
+-dontwarn java.beans.Introspector
+-dontwarn java.beans.PropertyDescriptor
+-dontwarn java.lang.reflect.InaccessibleObjectException
+-dontwarn javax.imageio.IIOImage
+-dontwarn javax.imageio.ImageIO
+-dontwarn javax.imageio.ImageWriteParam
+-dontwarn javax.imageio.ImageWriter
+-dontwarn javax.imageio.metadata.IIOMetadata
+-dontwarn javax.imageio.stream.ImageOutputStream
+-dontwarn javax.swing.JComponent
+-dontwarn javax.swing.JFileChooser
+-dontwarn javax.swing.JFrame
+-dontwarn javax.swing.JPanel
+-dontwarn javax.swing.ProgressMonitor
+-dontwarn javax.swing.SwingUtilities
+-dontwarn org.brotli.dec.BrotliInputStream
+-dontwarn org.joda.time.Instant
+-dontwarn org.objectweb.asm.AnnotationVisitor
+-dontwarn org.objectweb.asm.Attribute
+-dontwarn org.objectweb.asm.ClassReader
+-dontwarn org.objectweb.asm.ClassVisitor
+-dontwarn org.objectweb.asm.FieldVisitor
+-dontwarn org.objectweb.asm.Label
+-dontwarn org.objectweb.asm.MethodVisitor
+-dontwarn org.objectweb.asm.Type
+-dontwarn org.tukaani.xz.ARMOptions
+-dontwarn org.tukaani.xz.ARMThumbOptions
+-dontwarn org.tukaani.xz.DeltaOptions
+-dontwarn org.tukaani.xz.FilterOptions
+-dontwarn org.tukaani.xz.FinishableOutputStream
+-dontwarn org.tukaani.xz.FinishableWrapperOutputStream
+-dontwarn org.tukaani.xz.IA64Options
+-dontwarn org.tukaani.xz.LZMA2InputStream
+-dontwarn org.tukaani.xz.LZMA2Options
+-dontwarn org.tukaani.xz.LZMAInputStream
+-dontwarn org.tukaani.xz.LZMAOutputStream
+-dontwarn org.tukaani.xz.MemoryLimitException
+-dontwarn org.tukaani.xz.PowerPCOptions
+-dontwarn org.tukaani.xz.SPARCOptions
+-dontwarn org.tukaani.xz.SingleXZInputStream
+-dontwarn org.tukaani.xz.UnsupportedOptionsException
+-dontwarn org.tukaani.xz.X86Options
+-dontwarn org.tukaani.xz.XZ
+-dontwarn org.tukaani.xz.XZInputStream
+-dontwarn org.tukaani.xz.XZOutputStream
+-dontwarn us.hebi.matlab.mat.ejml.Mat5Ejml
+-dontwarn us.hebi.matlab.mat.format.Mat5
+-dontwarn us.hebi.matlab.mat.format.Mat5File
+-dontwarn us.hebi.matlab.mat.types.Array
+-dontwarn us.hebi.matlab.mat.types.MatFile$Entry
+-dontwarn us.hebi.matlab.mat.types.MatFile
+# end reown
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml
index 4f15370c3..280a45b3c 100644
--- a/android/app/src/main/AndroidManifestBase.xml
+++ b/android/app/src/main/AndroidManifestBase.xml
@@ -24,6 +24,10 @@
+
+
+
+
+
stopSync() async {
if (isBackgroundSyncRunning) {
printV("Stopping background sync");
- await save();
+ monero.Wallet_store(wptr!);
monero.Wallet_stopBackgroundSync(wptr!, '');
+ monero_wallet.store();
isBackgroundSyncRunning = false;
}
await save();
@@ -268,9 +269,9 @@ abstract class MoneroWalletBase extends WalletBase stopBackgroundSync(String password) async {
if (isBackgroundSyncRunning) {
printV("Stopping background sync");
- await save();
+ monero.Wallet_store(wptr!);
monero.Wallet_stopBackgroundSync(wptr!, password);
- await save();
+ monero.Wallet_store(wptr!);
isBackgroundSyncRunning = false;
}
}
diff --git a/cw_shared_external/android/build.gradle b/cw_shared_external/android/build.gradle
index 8d2b1b13d..360f518ff 100644
--- a/cw_shared_external/android/build.gradle
+++ b/cw_shared_external/android/build.gradle
@@ -9,7 +9,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.3.0'
+ classpath 'com.android.tools.build:gradle:8.7.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart
index 858fb25d4..05b0cec82 100644
--- a/cw_solana/lib/solana_client.dart
+++ b/cw_solana/lib/solana_client.dart
@@ -171,37 +171,85 @@ class SolanaWalletClient {
if (programId == SystemProgramConst.programId) {
// For native solana transactions
- if (instruction.accounts.length < 2) continue;
- final senderIndex = instruction.accounts[0];
- final receiverIndex = instruction.accounts[1];
- sender = message.accountKeys[senderIndex].address;
- receiver = message.accountKeys[receiverIndex].address;
+ if (txResponse.version == TransactionType.legacy) {
+ // For legacy transfers, the fee payer (index 0) is the sender.
+ sender = message.accountKeys[0].address;
- final feeForTx = fee / SolanaUtils.lamportsPerSol;
+ final senderPreBalance = meta.preBalances[0];
+ final senderPostBalance = meta.postBalances[0];
+ final feeForTx = fee / SolanaUtils.lamportsPerSol;
- final preBalances = meta.preBalances;
- final postBalances = meta.postBalances;
+ // The loss on the sender's account would include both the transfer amount and the fee.
+ // So we would subtract the fee to calculate the actual amount that was transferred (in lamports).
+ final transferLamports = (senderPreBalance - senderPostBalance) - BigInt.from(fee);
- final amountInString =
- (((preBalances[senderIndex] - postBalances[senderIndex]) / BigInt.from(1e9))
- .toDouble() -
- feeForTx)
- .toStringAsFixed(6);
+ // Next, we attempt to find the receiver by comparing the balance changes.
+ // (The index 0 is for the sender so we skip it.)
+ bool foundReceiver = false;
+ for (int i = 1; i < meta.preBalances.length; i++) {
+ // The increase in balance on the receiver account should correspond to the transfer amount we calculated earlieer.
+ final pre = meta.preBalances[i];
+ final post = meta.postBalances[i];
+ if ((post - pre) == transferLamports) {
+ receiver = message.accountKeys[i].address;
+ foundReceiver = true;
+ break;
+ }
+ }
- final amount = double.parse(amountInString);
+ if (!foundReceiver) {
+ // Optionally (and rarely), if no account shows the exact expected change,
+ // we set the receiver address to unknown.
+ receiver = "unknown";
+ }
- return SolanaTransactionModel(
- isOutgoingTx: sender == walletAddress,
- from: sender,
- to: receiver,
- id: signature,
- amount: amount.abs(),
- programId: SystemProgramConst.programId.address,
- tokenSymbol: 'SOL',
- blockTimeInInt: blockTime?.toInt() ?? 0,
- fee: feeForTx,
- );
+ final amount = transferLamports / BigInt.from(1e9);
+
+ return SolanaTransactionModel(
+ isOutgoingTx: sender == walletAddress,
+ from: sender,
+ to: receiver,
+ id: signature,
+ amount: amount.abs(),
+ programId: SystemProgramConst.programId.address,
+ tokenSymbol: 'SOL',
+ blockTimeInInt: blockTime?.toInt() ?? 0,
+ fee: feeForTx,
+ );
+ } else {
+ if (instruction.accounts.length < 2) continue;
+ final senderIndex = instruction.accounts[0];
+ final receiverIndex = instruction.accounts[1];
+
+ sender = message.accountKeys[senderIndex].address;
+ receiver = message.accountKeys[receiverIndex].address;
+
+ final feeForTx = fee / SolanaUtils.lamportsPerSol;
+
+ final preBalances = meta.preBalances;
+ final postBalances = meta.postBalances;
+
+ final amountInString =
+ (((preBalances[senderIndex] - postBalances[senderIndex]) / BigInt.from(1e9))
+ .toDouble() -
+ feeForTx)
+ .toStringAsFixed(6);
+
+ final amount = double.parse(amountInString);
+
+ return SolanaTransactionModel(
+ isOutgoingTx: sender == walletAddress,
+ from: sender,
+ to: receiver,
+ id: signature,
+ amount: amount.abs(),
+ programId: SystemProgramConst.programId.address,
+ tokenSymbol: 'SOL',
+ blockTimeInInt: blockTime?.toInt() ?? 0,
+ fee: feeForTx,
+ );
+ }
} else if (programId == SPLTokenProgramConst.tokenProgramId) {
// For SPL Token transactions
if (instruction.accounts.length < 2) continue;
@@ -842,6 +890,7 @@ class SolanaWalletClient {
}) async {
/// Sign the transaction with the owner's private key.
final ownerSignature = ownerPrivateKey.sign(transaction.serializeMessage());
+
transaction.addSignature(ownerPrivateKey.publicKey().toAddress(), ownerSignature);
/// Serialize the transaction.
diff --git a/ios/Podfile b/ios/Podfile
index f0a0721a6..cf24cb605 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-platform :ios, '12.0'
+platform :ios, '13.0'
source 'https://github.com/CocoaPods/Specs.git'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
@@ -43,7 +43,7 @@ post_install do |installer|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
- config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
+ config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index d9ff6b66e..794305883 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -501,7 +501,7 @@
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Runner/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -649,7 +649,7 @@
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Runner/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -690,7 +690,7 @@
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Runner/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
diff --git a/lib/core/background_sync.dart b/lib/core/background_sync.dart
index 0098b62b6..12eb81f99 100644
--- a/lib/core/background_sync.dart
+++ b/lib/core/background_sync.dart
@@ -1,26 +1,101 @@
import 'dart:async';
-import 'dart:math';
+import 'dart:io';
import 'package:cake_wallet/core/key_service.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/store/settings_store.dart';
+import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
import 'package:cw_core/sync_status.dart';
+import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_type.dart';
-import 'package:flutter/foundation.dart';
-import 'package:http/http.dart' as http;
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:shared_preferences/shared_preferences.dart';
class BackgroundSync {
+ final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
+ bool _isInitialized = false;
+
+ Future _initializeNotifications() async {
+ if (_isInitialized) return;
+
+ const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
+
+ const iosSettings = DarwinInitializationSettings(
+ requestAlertPermission: true,
+ requestBadgePermission: true,
+ requestSoundPermission: true,
+ );
+
+ const initializationSettings = InitializationSettings(
+ android: androidSettings,
+ iOS: iosSettings,
+ );
+
+ await _notificationsPlugin.initialize(initializationSettings);
+ _isInitialized = true;
+ }
+
+ Future requestPermissions() async {
+ if (Platform.isIOS || Platform.isMacOS) {
+ return await _notificationsPlugin
+ .resolvePlatformSpecificImplementation()
+ ?.requestPermissions(
+ alert: true,
+ badge: true,
+ sound: true,
+ ) ?? false;
+ } else if (Platform.isAndroid) {
+ return await _notificationsPlugin
+ .resolvePlatformSpecificImplementation()
+ ?.areNotificationsEnabled() ?? false;
+ }
+ return false;
+ }
+
+ Future showNotification(String title, String content) async {
+ await _initializeNotifications();
+ final hasPermission = await requestPermissions();
+
+ if (!hasPermission) {
+ printV('Notification permissions not granted');
+ return;
+ }
+
+ const androidDetails = AndroidNotificationDetails(
+ 'transactions',
+ 'Transactions',
+ channelDescription: 'Channel for notifications about transactions',
+ importance: Importance.defaultImportance,
+ priority: Priority.defaultPriority,
+ );
+
+ const iosDetails = DarwinNotificationDetails();
+
+ const notificationDetails = NotificationDetails(
+ android: androidDetails,
+ iOS: iosDetails,
+ );
+
+ await _notificationsPlugin.show(
+ DateTime.now().millisecondsSinceEpoch.hashCode,
+ title,
+ content,
+ notificationDetails,
+ );
+ }
+
Future sync() async {
printV("Background sync started");
- await _syncMonero();
+ await _syncWallets();
printV("Background sync completed");
}
- Future _syncMonero() async {
+ Future _syncWallets() async {
final walletLoadingService = getIt.get();
final walletListViewModel = getIt.get();
final settingsStore = getIt.get();
@@ -28,10 +103,10 @@ class BackgroundSync {
final List moneroWallets = walletListViewModel.wallets
.where((element) => !element.isHardware)
- .where((element) => [WalletType.monero].contains(element.type))
+ .where((element) => ![WalletType.haven, WalletType.decred].contains(element.type))
.toList();
for (int i = 0; i < moneroWallets.length; i++) {
- final wallet = await walletLoadingService.load(moneroWallets[i].type, moneroWallets[i].name);
+ final wallet = await walletLoadingService.load(moneroWallets[i].type, moneroWallets[i].name, isBackground: true);
int syncedTicks = 0;
final keyService = getIt.get();
@@ -75,7 +150,7 @@ class BackgroundSync {
} else {
syncedTicks = 0;
}
- if (kDebugMode) {
+ if (FeatureFlag.hasDevOptions) {
if (syncStatus is SyncingSyncStatus) {
final blocksLeft = syncStatus.blocksLeft;
printV("$blocksLeft Blocks Left");
@@ -100,6 +175,27 @@ class BackgroundSync {
}
}
}
+ final txs = wallet.transactionHistory;
+ final sortedTxs = txs.transactions.values.toList()..sort((a, b) => a.date.compareTo(b.date));
+ final sharedPreferences = await SharedPreferences.getInstance();
+ for (final tx in sortedTxs) {
+ final lastTriggerString = sharedPreferences.getString(PreferencesKey.backgroundSyncLastTrigger(wallet.name));
+ final lastTriggerDate = lastTriggerString != null
+ ? DateTime.parse(lastTriggerString)
+ : DateTime.now();
+ final keys = sharedPreferences.getKeys();
+ if (tx.date.isBefore(lastTriggerDate)) {
+ printV("w: ${wallet.name}, tx: ${tx.date} is before $lastTriggerDate (lastTriggerString: $lastTriggerString) (k: ${keys.length})");
+ continue;
+ }
+ await sharedPreferences.setString(PreferencesKey.backgroundSyncLastTrigger(wallet.name), tx.date.add(Duration(minutes: 1)).toIso8601String());
+ final action = tx.direction == TransactionDirection.incoming ? "Received" : "Sent";
+ if (sharedPreferences.getBool(PreferencesKey.backgroundSyncNotificationsEnabled) ?? false) {
+ await showNotification("$action ${wallet.currency.fullName} in ${wallet.name}", "${tx.amountFormatted()}");
+ }
+ printV("${wallet.currency.fullName} in ${wallet.name}: TX: ${tx.date} ${tx.amount} ${tx.direction}");
+ }
+ wallet.id;
await wallet.stopBackgroundSync(await keyService.getWalletPassword(walletName: wallet.name));
await wallet.close(shouldCleanup: true);
}
diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart
index 94599d5f2..385598060 100644
--- a/lib/core/backup_service.dart
+++ b/lib/core/backup_service.dart
@@ -265,16 +265,24 @@ class $BackupService {
{String keychainSalt = secrets.backupKeychainSalt}) async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final wallets = await Future.wait(walletInfoSource.values.map((walletInfo) async {
- return {
- 'name': walletInfo.name,
- 'type': walletInfo.type.toString(),
- 'password': await keyService.getWalletPassword(walletName: walletInfo.name)
- };
+ try {
+ return {
+ 'name': walletInfo.name,
+ 'type': walletInfo.type.toString(),
+ 'password': await keyService.getWalletPassword(walletName: walletInfo.name)
+ };
+ } catch (e) {
+ return {
+ 'name': walletInfo.name,
+ 'type': walletInfo.type.toString(),
+ 'password': ''
+ };
+ }
}));
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = await _secureStorage.read(key: backupPasswordKey);
final data = utf8.encode(
- json.encode({'wallets': wallets, backupPasswordKey: backupPassword}));
+ json.encode({'wallets': wallets, backupPasswordKey: backupPassword, '_all': await _secureStorage.readAll()}));
final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');
return encrypted;
diff --git a/lib/core/wallet_connect/chain_service/chain_service.dart b/lib/core/wallet_connect/chain_service/chain_service.dart
deleted file mode 100644
index 1e3ce3efd..000000000
--- a/lib/core/wallet_connect/chain_service/chain_service.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-abstract class ChainService {
- String getNamespace();
- String getChainId();
- List getEvents();
-}
diff --git a/lib/core/wallet_connect/chain_service/eth/evm_chain_service.dart b/lib/core/wallet_connect/chain_service/eth/evm_chain_service.dart
deleted file mode 100644
index 6f3c8fa98..000000000
--- a/lib/core/wallet_connect/chain_service/eth/evm_chain_service.dart
+++ /dev/null
@@ -1,304 +0,0 @@
-import 'dart:convert';
-import 'dart:developer';
-import 'dart:typed_data';
-
-import 'package:cake_wallet/core/wallet_connect/eth_transaction_model.dart';
-import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart';
-import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
-import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/reactions/wallet_connect.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart';
-import 'package:cake_wallet/store/app_store.dart';
-import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
-import 'package:cake_wallet/core/wallet_connect/models/connection_model.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/utils/string_parsing.dart';
-import 'package:convert/convert.dart';
-import 'package:eth_sig_util/eth_sig_util.dart';
-import 'package:eth_sig_util/util/utils.dart';
-import 'package:http/http.dart' as http;
-import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
-import 'package:web3dart/web3dart.dart';
-import '../chain_service.dart';
-import '../../wallet_connect_key_service.dart';
-
-class EvmChainServiceImpl implements ChainService {
- final AppStore appStore;
- final BottomSheetService bottomSheetService;
- final Web3Wallet wallet;
- final WalletConnectKeyService wcKeyService;
-
- static const namespace = 'eip155';
- static const pSign = 'personal_sign';
- static const eSign = 'eth_sign';
- static const eSignTransaction = 'eth_signTransaction';
- static const eSignTypedData = 'eth_signTypedData_v4';
- static const eSendTransaction = 'eth_sendTransaction';
-
- final EVMChainId reference;
-
- final Web3Client ethClient;
-
- EvmChainServiceImpl({
- required this.reference,
- required this.appStore,
- required this.wcKeyService,
- required this.bottomSheetService,
- required this.wallet,
- Web3Client? web3Client,
- }) : ethClient = web3Client ??
- Web3Client(
- appStore.settingsStore.getCurrentNode(appStore.wallet!.type).uri.toString(),
- http.Client(),
- ) {
- for (final String event in getEvents()) {
- wallet.registerEventEmitter(chainId: getChainId(), event: event);
- }
- wallet.registerRequestHandler(
- chainId: getChainId(),
- method: pSign,
- handler: personalSign,
- );
- wallet.registerRequestHandler(
- chainId: getChainId(),
- method: eSign,
- handler: ethSign,
- );
- wallet.registerRequestHandler(
- chainId: getChainId(),
- method: eSignTransaction,
- handler: ethSignTransaction,
- );
- wallet.registerRequestHandler(
- chainId: getChainId(),
- method: eSendTransaction,
- handler: ethSignTransaction,
- );
- wallet.registerRequestHandler(
- chainId: getChainId(),
- method: eSignTypedData,
- handler: ethSignTypedData,
- );
- }
-
- @override
- String getNamespace() {
- return namespace;
- }
-
- @override
- String getChainId() {
- return reference.chain();
- }
-
- @override
- List getEvents() {
- return ['chainChanged', 'accountsChanged'];
- }
-
- Future requestAuthorization(String? text) async {
- // Show the bottom sheet
- final bool? isApproved = await bottomSheetService.queueBottomSheet(
- widget: Web3RequestModal(
- child: ConnectionWidget(
- title: S.current.signTransaction,
- info: [
- ConnectionModel(
- text: text,
- ),
- ],
- ),
- ),
- ) as bool?;
-
- if (isApproved != null && isApproved == false) {
- return 'User rejected signature';
- }
-
- return null;
- }
-
- Future personalSign(String topic, dynamic parameters) async {
- log('received personal sign request: $parameters');
-
- final String message;
- if (parameters[0] == null) {
- message = '';
- } else {
- message = parameters[0].toString().utf8Message;
- }
-
- final String? authError = await requestAuthorization(message);
-
- if (authError != null) {
- return authError;
- }
-
- try {
- // Load the private key
- final List keys = wcKeyService
- .getKeysForChain(appStore.wallet!);
-
- final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
-
- final String signature = hex.encode(
- credentials.signPersonalMessageToUint8List(Uint8List.fromList(utf8.encode(message))),
- );
-
- return '0x$signature';
- } catch (e) {
- log(e.toString());
- bottomSheetService.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(
- message: '${S.current.errorGettingCredentials} ${e.toString()}',
- ),
- );
- return 'Failed: Error while getting credentials';
- }
- }
-
- Future ethSign(String topic, dynamic parameters) async {
- log('received eth sign request: $parameters');
-
- final String message;
- if (parameters[1] == null) {
- message = '';
- } else {
- message = parameters[1].toString().utf8Message;
- }
-
- final String? authError = await requestAuthorization(message);
- if (authError != null) {
- return authError;
- }
-
- try {
- // Load the private key
- final List keys = wcKeyService
- .getKeysForChain(appStore.wallet!);
-
- final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey);
-
- final String signature = hex.encode(
- credentials.signPersonalMessageToUint8List(
- Uint8List.fromList(utf8.encode(message)),
- chainId: getChainIdBasedOnWalletType(appStore.wallet!.type),
- ),
- );
- log(signature);
-
- return '0x$signature';
- } catch (e) {
- log('error: ${e.toString()}');
- bottomSheetService.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(message: '${S.current.error}: ${e.toString()}'),
- );
- return 'Failed';
- }
- }
-
- Future ethSignTransaction(String topic, dynamic parameters) async {
- log('received eth sign transaction request: $parameters');
-
- final paramsData = parameters[0] as Map;
-
- final message = _convertToReadable(paramsData);
-
- final String? authError = await requestAuthorization(message);
-
- if (authError != null) {
- return authError;
- }
-
- // Load the private key
- final List keys = wcKeyService
- .getKeysForChain(appStore.wallet!);
-
- final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
-
- WCEthereumTransactionModel ethTransaction =
- WCEthereumTransactionModel.fromJson(parameters[0] as Map);
-
- final transaction = Transaction(
- from: EthereumAddress.fromHex(ethTransaction.from),
- to: EthereumAddress.fromHex(ethTransaction.to),
- maxGas: ethTransaction.gasLimit != null ? int.tryParse(ethTransaction.gasLimit ?? "") : null,
- gasPrice: ethTransaction.gasPrice != null
- ? EtherAmount.inWei(BigInt.parse(ethTransaction.gasPrice ?? ""))
- : null,
- value: EtherAmount.inWei(BigInt.parse(ethTransaction.value)),
- data: hexToBytes(ethTransaction.data ?? ""),
- nonce: ethTransaction.nonce != null ? int.tryParse(ethTransaction.nonce ?? "") : null,
- );
-
- try {
- final result = await ethClient.sendTransaction(
- credentials,
- transaction,
- chainId: getChainIdBasedOnWalletType(appStore.wallet!.type),
- );
-
- log('Result: $result');
-
- bottomSheetService.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(
- message: S.current.awaitDAppProcessing,
- isError: false,
- ),
- );
-
- return result;
- } catch (e) {
- log('An error has occurred while signing transaction: ${e.toString()}');
- bottomSheetService.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(
- message: '${S.current.errorSigningTransaction}: ${e.toString()}',
- ),
- );
- return 'Failed';
- }
- }
-
- Future ethSignTypedData(String topic, dynamic parameters) async {
- log('received eth sign typed data request: $parameters');
- final String? data = parameters[1] as String?;
-
- final String? authError = await requestAuthorization(data);
-
- if (authError != null) {
- return authError;
- }
-
- final List keys = wcKeyService
- .getKeysForChain(appStore.wallet!);
-
- return EthSigUtil.signTypedData(
- privateKey: keys[0].privateKey,
- jsonData: data ?? '',
- version: TypedDataVersion.V4,
- );
- }
-
- String _convertToReadable(Map data) {
- final tokenName = getTokenNameBasedOnWalletType(appStore.wallet!.type);
- String gas = int.parse((data['gas'] as String).substring(2), radix: 16).toString();
- String value = data['value'] != null
- ? (int.parse((data['value'] as String).substring(2), radix: 16) / 1e18).toString() +
- ' $tokenName'
- : '0 $tokenName';
- String from = data['from'] as String;
- String to = data['to'] as String;
-
- return '''
- Gas: $gas\n
- Value: $value\n
- From: $from\n
- To: $to
- ''';
- }
-}
diff --git a/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart b/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart
deleted file mode 100644
index e462adbb5..000000000
--- a/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-class SolanaSignMessage {
- final String pubkey;
- final String message;
-
- SolanaSignMessage({
- required this.pubkey,
- required this.message,
- });
-
- factory SolanaSignMessage.fromJson(Map json) {
- return SolanaSignMessage(
- pubkey: json['pubkey'] as String,
- message: json['message'] as String,
- );
- }
-
- Map toJson() {
- return {
- 'pubkey': pubkey,
- 'message': message,
- };
- }
-
- @override
- String toString() {
- return 'SolanaSignMessage(pubkey: $pubkey, message: $message)';
- }
-}
diff --git a/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_transaction.dart b/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_transaction.dart
deleted file mode 100644
index 2cdf4697e..000000000
--- a/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_transaction.dart
+++ /dev/null
@@ -1,106 +0,0 @@
-class SolanaSignTransaction {
- final String? feePayer;
- final String? recentBlockhash;
- final String transaction;
- final List? instructions;
-
- SolanaSignTransaction({
- required this.feePayer,
- required this.recentBlockhash,
- required this.instructions,
- required this.transaction,
- });
-
- factory SolanaSignTransaction.fromJson(Map json) {
- return SolanaSignTransaction(
- feePayer:json['feePayer'] !=null ? json['feePayer'] as String: null,
- recentBlockhash: json['recentBlockhash']!=null? json['recentBlockhash'] as String: null,
- instructions:json['instructions']!=null? (json['instructions'] as List)
- .map((e) => SolanaInstruction.fromJson(e as Map))
- .toList(): null,
- transaction: json['transaction'] as String,
- );
- }
-
- Map toJson() {
- return {
- 'feePayer': feePayer,
- 'recentBlockhash': recentBlockhash,
- 'instructions': instructions,
- 'transaction': transaction,
- };
- }
-
- @override
- String toString() {
- return 'SolanaSignTransaction(feePayer: $feePayer, recentBlockhash: $recentBlockhash, instructions: $instructions, transaction: $transaction)';
- }
-}
-
-class SolanaInstruction {
- final String programId;
- final List keys;
- final List data;
-
- SolanaInstruction({
- required this.programId,
- required this.keys,
- required this.data,
- });
-
- factory SolanaInstruction.fromJson(Map json) {
- return SolanaInstruction(
- programId: json['programId'] as String,
- keys: (json['keys'] as List)
- .map((e) => SolanaKeyMetadata.fromJson(e as Map))
- .toList(),
- data: (json['data'] as List).map((e) => e as int).toList(),
- );
- }
-
- Map toJson() {
- return {
- 'programId': programId,
- 'keys': keys,
- 'data': data,
- };
- }
-
- @override
- String toString() {
- return 'SolanaInstruction(programId: $programId, keys: $keys, data: $data)';
- }
-}
-
-class SolanaKeyMetadata {
- final String pubkey;
- final bool isSigner;
- final bool isWritable;
-
- SolanaKeyMetadata({
- required this.pubkey,
- required this.isSigner,
- required this.isWritable,
- });
-
- factory SolanaKeyMetadata.fromJson(Map json) {
- return SolanaKeyMetadata(
- pubkey: json['pubkey'] as String,
- isSigner: json['isSigner'] as bool,
- isWritable: json['isWritable'] as bool,
- );
- }
-
- Map toJson() {
- return {
- 'pubkey': pubkey,
- 'isSigner': isSigner,
- 'isWritable': isWritable,
- };
- }
-
- @override
- String toString() {
- return 'SolanaKeyMetadata(pubkey: $pubkey, isSigner: $isSigner, isWritable: $isWritable)';
- }
-}
diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart
deleted file mode 100644
index ed80a4f3f..000000000
--- a/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-import 'solana_chain_service.dart';
-
-enum SolanaChainId {
- mainnet,
- // testnet,
- // devnet,
-}
-
-extension SolanaChainIdX on SolanaChainId {
- String chain() {
- String name = '';
-
- switch (this) {
- case SolanaChainId.mainnet:
- name = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ';
- // solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
- break;
- // case SolanaChainId.devnet:
- // name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K';
- // // solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
- // break;
- // case SolanaChainId.testnet:
- // name = '';
- // // solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z
- // break;
- }
-
- return '${SolanaChainServiceImpl.namespace}:$name';
- }
-}
diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart
deleted file mode 100644
index ca4017b98..000000000
--- a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart
+++ /dev/null
@@ -1,170 +0,0 @@
-import 'dart:convert';
-import 'dart:developer';
-
-import 'package:blockchain_utils/blockchain_utils.dart';
-import 'package:cake_wallet/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart';
-import 'package:cake_wallet/core/wallet_connect/chain_service/solana/solana_chain_id.dart';
-import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
-import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart';
-import 'package:cake_wallet/core/wallet_connect/models/connection_model.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
-import 'package:cw_core/solana_rpc_http_service.dart';
-import 'package:cw_core/utils/print_verbose.dart';
-import 'package:on_chain/solana/solana.dart';
-import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
-import '../chain_service.dart';
-import '../../wallet_connect_key_service.dart';
-import 'entities/solana_sign_transaction.dart';
-
-class SolanaChainServiceImpl implements ChainService {
- final BottomSheetService bottomSheetService;
- final Web3Wallet wallet;
- final WalletConnectKeyService wcKeyService;
-
- static const namespace = 'solana';
- static const solSignTransaction = 'solana_signTransaction';
- static const solSignMessage = 'solana_signMessage';
-
- final SolanaChainId reference;
-
- final SolanaRPC solanaProvider;
-
- final SolanaPrivateKey? ownerPrivateKey;
-
- SolanaChainServiceImpl({
- required this.reference,
- required this.wcKeyService,
- required this.bottomSheetService,
- required this.wallet,
- required this.ownerPrivateKey,
- required String formattedRPCUrl,
- SolanaRPC? solanaProvider,
- }) : solanaProvider = solanaProvider ?? SolanaRPC(SolanaRPCHTTPService(url: formattedRPCUrl)) {
- for (final String event in getEvents()) {
- wallet.registerEventEmitter(chainId: getChainId(), event: event);
- }
- wallet.registerRequestHandler(
- chainId: getChainId(),
- method: solSignTransaction,
- handler: solanaSignTransaction,
- );
- wallet.registerRequestHandler(
- chainId: getChainId(),
- method: solSignMessage,
- handler: solanaSignMessage,
- );
- }
-
- @override
- String getNamespace() {
- return namespace;
- }
-
- @override
- String getChainId() {
- return reference.chain();
- }
-
- @override
- List getEvents() {
- return ['chainChanged', 'accountsChanged'];
- }
-
- Future requestAuthorization(String? text) async {
- // Show the bottom sheet
- final bool? isApproved = await bottomSheetService.queueBottomSheet(
- widget: Web3RequestModal(
- child: ConnectionWidget(
- title: S.current.signTransaction,
- info: [
- ConnectionModel(
- text: text,
- ),
- ],
- ),
- ),
- ) as bool?;
-
- if (isApproved != null && isApproved == false) {
- return 'User rejected signature';
- }
-
- return null;
- }
-
- Future solanaSignTransaction(String topic, dynamic parameters) async {
- log('received solana sign transaction request $parameters');
-
- final solanaSignTx = SolanaSignTransaction.fromJson(parameters as Map);
-
- final String? authError = await requestAuthorization('Confirm request to sign transaction?');
-
- if (authError != null) {
- return authError;
- }
-
- try {
- // Convert transaction string to bytes
- List transactionBytes = base64Decode(solanaSignTx.transaction);
-
- final message = SolanaTransactionUtils.deserializeMessageLegacy(transactionBytes);
-
- final sign = ownerPrivateKey!.sign(message.serialize());
-
- final signature = solanaProvider.request(
- SolanaRPCSendTransaction(
- encodedTransaction: Base58Encoder.encode(sign),
- commitment: Commitment.confirmed,
- ),
- );
-
- bottomSheetService.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(
- message: S.current.awaitDAppProcessing,
- isError: false,
- ),
- );
-
- return signature;
- } catch (e) {
- log('An error has occurred while signing transaction: ${e.toString()}');
- bottomSheetService.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(
- message: '${S.current.errorSigningTransaction}: ${e.toString()}',
- ),
- );
- return 'Failed';
- }
- }
-
- Future solanaSignMessage(String topic, dynamic parameters) async {
- log('received solana sign message request: $parameters');
-
- final solanaSignMessage = SolanaSignMessage.fromJson(parameters as Map);
-
- final String? authError = await requestAuthorization('Confirm request to sign message?');
-
- if (authError != null) {
- return authError;
- }
- List? sign;
-
- try {
- sign = ownerPrivateKey!.sign(Base58Decoder.decode(solanaSignMessage.message));
- } catch (e) {
- printV(e);
- }
-
- if (sign == null) {
- return '';
- }
-
- final signature = Base58Encoder.encode(sign);
-
- return signature;
- }
-}
diff --git a/lib/core/wallet_connect/eth_transaction_model.dart b/lib/core/wallet_connect/eth_transaction_model.dart
deleted file mode 100644
index deb33586f..000000000
--- a/lib/core/wallet_connect/eth_transaction_model.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-class WCEthereumTransactionModel {
- final String from;
- final String to;
- final String value;
- final String? nonce;
- final String? gasPrice;
- final String? maxFeePerGas;
- final String? maxPriorityFeePerGas;
- final String? gas;
- final String? gasLimit;
- final String? data;
-
- WCEthereumTransactionModel({
- required this.from,
- required this.to,
- required this.value,
- this.nonce,
- this.gasPrice,
- this.maxFeePerGas,
- this.maxPriorityFeePerGas,
- this.gas,
- this.gasLimit,
- this.data,
- });
-
- factory WCEthereumTransactionModel.fromJson(Map json) {
- return WCEthereumTransactionModel(
- from: json['from'] as String,
- to: json['to'] as String,
- value: json['value'] as String,
- nonce: json['nonce'] as String?,
- gasPrice: json['gasPrice'] as String?,
- maxFeePerGas: json['maxFeePerGas'] as String?,
- maxPriorityFeePerGas: json['maxPriorityFeePerGas'] as String?,
- gas: json['gas'] as String?,
- gasLimit: json['gasLimit'] as String?,
- data: json['data'] as String?,
- );
- }
-
- Map toJson() {
- return {
- 'from': from,
- 'to': to,
- 'value': value,
- 'nonce': nonce,
- 'gasPrice': gasPrice,
- 'maxFeePerGas': maxFeePerGas,
- 'maxPriorityFeePerGas': maxPriorityFeePerGas,
- 'gas': gas,
- 'gasLimit': gasLimit,
- 'data': data,
- };
- }
-
- @override
- String toString() {
- return 'EthereumTransactionModel(from: $from, to: $to, nonce: $nonce, gasPrice: $gasPrice, maxFeePerGas: $maxFeePerGas, maxPriorityFeePerGas: $maxPriorityFeePerGas, gas: $gas, gasLimit: $gasLimit, value: $value, data: $data)';
- }
-}
diff --git a/lib/core/wallet_connect/models/auth_request_model.dart b/lib/core/wallet_connect/models/auth_request_model.dart
deleted file mode 100644
index f7fd984c8..000000000
--- a/lib/core/wallet_connect/models/auth_request_model.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
-
-class AuthRequestModel {
- final String iss;
- final AuthRequest request;
-
- AuthRequestModel({
- required this.iss,
- required this.request,
- });
-
- @override
- String toString() {
- return 'AuthRequestModel(iss: $iss, request: $request)';
- }
-}
diff --git a/lib/core/wallet_connect/models/chain_key_model.dart b/lib/core/wallet_connect/models/chain_key_model.dart
deleted file mode 100644
index 5cd2764da..000000000
--- a/lib/core/wallet_connect/models/chain_key_model.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-class ChainKeyModel {
- final List chains;
- final String privateKey;
- final String publicKey;
-
- ChainKeyModel({
- required this.chains,
- required this.privateKey,
- required this.publicKey,
- });
-
- @override
- String toString() {
- return 'ChainKeyModel(chains: $chains, privateKey: $privateKey, publicKey: $publicKey)';
- }
-}
diff --git a/lib/core/wallet_connect/models/session_request_model.dart b/lib/core/wallet_connect/models/session_request_model.dart
deleted file mode 100644
index 0c7a5d876..000000000
--- a/lib/core/wallet_connect/models/session_request_model.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
-
-class SessionRequestModel {
- final ProposalData request;
-
- SessionRequestModel({
- required this.request,
- });
-
- @override
- String toString() {
- return 'SessionRequestModel(request: $request)';
- }
-}
diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart
deleted file mode 100644
index 898433c62..000000000
--- a/lib/core/wallet_connect/web3wallet_service.dart
+++ /dev/null
@@ -1,416 +0,0 @@
-import 'dart:async';
-import 'dart:convert';
-import 'dart:developer';
-import 'dart:typed_data';
-
-import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart';
-import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_service.dart';
-import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart';
-import 'package:cake_wallet/entities/preferences_key.dart';
-import 'package:cake_wallet/generated/i18n.dart';
-import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart';
-import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
-import 'package:cake_wallet/core/wallet_connect/models/session_request_model.dart';
-import 'package:cake_wallet/reactions/wallet_connect.dart';
-import 'package:cake_wallet/solana/solana.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_request_widget.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart';
-import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
-import 'package:cake_wallet/store/app_store.dart';
-import 'package:cw_core/utils/print_verbose.dart';
-import 'package:cw_core/wallet_type.dart';
-import 'package:eth_sig_util/eth_sig_util.dart';
-import 'package:flutter/material.dart';
-import 'package:mobx/mobx.dart';
-import 'package:on_chain/solana/solana.dart' hide Store;
-import 'package:shared_preferences/shared_preferences.dart';
-import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
-
-import 'chain_service/solana/solana_chain_id.dart';
-import 'chain_service/solana/solana_chain_service.dart';
-import 'wc_bottom_sheet_service.dart';
-import 'package:cake_wallet/.secrets.g.dart' as secrets;
-
-part 'web3wallet_service.g.dart';
-
-class Web3WalletService = Web3WalletServiceBase with _$Web3WalletService;
-
-abstract class Web3WalletServiceBase with Store {
- final AppStore appStore;
- final SharedPreferences sharedPreferences;
- final BottomSheetService _bottomSheetHandler;
- final WalletConnectKeyService walletKeyService;
-
- late Web3Wallet _web3Wallet;
-
- @observable
- bool isInitialized;
-
- /// The list of requests from the dapp
- /// Potential types include, but aren't limited to:
- /// [SessionProposalEvent], [AuthRequest]
- @observable
- ObservableList pairings;
-
- @observable
- ObservableList sessions;
-
- @observable
- ObservableList auth;
-
- Web3WalletServiceBase(
- this._bottomSheetHandler, this.walletKeyService, this.appStore, this.sharedPreferences)
- : pairings = ObservableList(),
- sessions = ObservableList(),
- auth = ObservableList(),
- isInitialized = false;
-
- @action
- void create() {
- // Create the web3wallet client
- _web3Wallet = Web3Wallet(
- core: Core(projectId: secrets.walletConnectProjectId),
- metadata: const PairingMetadata(
- name: 'Cake Wallet',
- description: 'Cake Wallet',
- url: 'https://cakewallet.com',
- icons: ['https://cakewallet.com/assets/image/cake_logo.png'],
- ),
- );
-
- // Setup our accounts
- List chainKeys = walletKeyService.getKeys(appStore.wallet!);
- for (final chainKey in chainKeys) {
- for (final chainId in chainKey.chains) {
- _web3Wallet.registerAccount(
- chainId: chainId,
- accountAddress: chainKey.publicKey,
- );
- }
- }
-
- // Setup our listeners
- log('Created instance of web3wallet');
- _web3Wallet.core.pairing.onPairingInvalid.subscribe(_onPairingInvalid);
- _web3Wallet.core.pairing.onPairingCreate.subscribe(_onPairingCreate);
- _web3Wallet.core.pairing.onPairingDelete.subscribe(_onPairingDelete);
- _web3Wallet.core.pairing.onPairingExpire.subscribe(_onPairingDelete);
- _web3Wallet.pairings.onSync.subscribe(_onPairingsSync);
- _web3Wallet.onSessionProposal.subscribe(_onSessionProposal);
- _web3Wallet.onSessionProposalError.subscribe(_onSessionProposalError);
- _web3Wallet.onSessionConnect.subscribe(_onSessionConnect);
- _web3Wallet.onAuthRequest.subscribe(_onAuthRequest);
- }
-
- @action
- Future init() async {
- // Await the initialization of the web3wallet
- log('Intializing web3wallet');
- if (!isInitialized) {
- try {
- await _web3Wallet.init();
- log('Initialized');
- isInitialized = true;
- } catch (e) {
- log('Experimentallllll: $e');
- isInitialized = false;
- }
- }
-
- _refreshPairings();
-
- final newSessions = _web3Wallet.sessions.getAll();
- sessions.addAll(newSessions);
-
- final newAuthRequests = _web3Wallet.completeRequests.getAll();
- auth.addAll(newAuthRequests);
-
- if (isEVMCompatibleChain(appStore.wallet!.type)) {
- for (final cId in EVMChainId.values) {
- EvmChainServiceImpl(
- reference: cId,
- appStore: appStore,
- wcKeyService: walletKeyService,
- bottomSheetService: _bottomSheetHandler,
- wallet: _web3Wallet,
- );
- }
- }
-
- if (appStore.wallet!.type == WalletType.solana) {
- for (final cId in SolanaChainId.values) {
- final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type);
-
- String formattedUrl;
- String protocolUsed = node.isSSL ? "https" : "http";
-
- if (node.uriRaw == 'rpc.ankr.com') {
- String ankrApiKey = secrets.ankrApiKey;
-
- formattedUrl = '$protocolUsed://${node.uriRaw}/$ankrApiKey';
- } else if (node.uriRaw == 'solana-mainnet.core.chainstack.com') {
- String chainStackApiKey = secrets.chainStackApiKey;
-
- formattedUrl = '$protocolUsed://${node.uriRaw}/$chainStackApiKey';
- } else {
- formattedUrl = '$protocolUsed://${node.uriRaw}';
- }
-
- SolanaChainServiceImpl(
- reference: cId,
- formattedRPCUrl: formattedUrl,
- wcKeyService: walletKeyService,
- bottomSheetService: _bottomSheetHandler,
- wallet: _web3Wallet,
- ownerPrivateKey: SolanaPrivateKey.fromSeedHex(solana!.getPrivateKey(appStore.wallet!)),
- );
- }
- }
- }
-
- @action
- FutureOr onDispose() {
- log('web3wallet dispose');
- _web3Wallet.core.pairing.onPairingInvalid.unsubscribe(_onPairingInvalid);
- _web3Wallet.pairings.onSync.unsubscribe(_onPairingsSync);
- _web3Wallet.onSessionProposal.unsubscribe(_onSessionProposal);
- _web3Wallet.onSessionProposalError.unsubscribe(_onSessionProposalError);
- _web3Wallet.onSessionConnect.unsubscribe(_onSessionConnect);
- _web3Wallet.onAuthRequest.unsubscribe(_onAuthRequest);
- _web3Wallet.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete);
- _web3Wallet.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete);
- isInitialized = false;
- }
-
- Web3Wallet getWeb3Wallet() {
- return _web3Wallet;
- }
-
- void _onPairingsSync(StoreSyncEvent? args) {
- if (args != null) {
- _refreshPairings();
- }
- }
-
- void _onPairingDelete(PairingEvent? event) {
- _refreshPairings();
- }
-
- Future _onSessionProposalError(SessionProposalErrorEvent? args) async {
- log(args.toString());
- }
-
- void _onSessionProposal(SessionProposalEvent? args) async {
- if (args != null) {
- final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type);
- final Widget modalWidget = Web3RequestModal(
- child: ConnectionRequestWidget(
- chaindIdNamespace: chaindIdNamespace,
- wallet: _web3Wallet,
- sessionProposal: SessionRequestModel(request: args.params),
- ),
- );
- // show the bottom sheet
- final bool? isApproved = await _bottomSheetHandler.queueBottomSheet(
- widget: modalWidget,
- ) as bool?;
-
- if (isApproved != null && isApproved) {
- _web3Wallet.approveSession(
- id: args.id,
- namespaces: args.params.generatedNamespaces!,
- );
- } else {
- _web3Wallet.rejectSession(
- id: args.id,
- reason: Errors.getSdkError(
- Errors.USER_REJECTED,
- ),
- );
- }
- }
- }
-
- @action
- void _onPairingInvalid(PairingInvalidEvent? args) {
- log('Pairing Invalid Event: $args');
- _bottomSheetHandler.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(message: '${S.current.pairingInvalidEvent}: $args'),
- );
- }
-
- @action
- Future pairWithUri(Uri uri) async {
- try {
- log('Pairing with URI: $uri');
- await _web3Wallet.pair(uri: uri);
- } on WalletConnectError catch (e) {
- _bottomSheetHandler.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(message: e.message),
- );
- } catch (e) {
- _bottomSheetHandler.queueBottomSheet(
- isModalDismissible: true,
- widget: BottomSheetMessageDisplayWidget(message: e.toString()),
- );
- }
- }
-
- @action
- void _refreshPairings() {
- printV('Refreshing pairings');
- pairings.clear();
-
- final allPairings = _web3Wallet.pairings.getAll();
-
- final keyForWallet = getKeyForStoringTopicsForWallet();
-
- if (keyForWallet.isEmpty) return;
-
- final currentTopicsForWallet = getPairingTopicsForWallet(keyForWallet);
-
- final filteredPairings =
- allPairings.where((pairing) => currentTopicsForWallet.contains(pairing.topic)).toList();
-
- pairings.addAll(filteredPairings);
- }
-
- void _onPairingCreate(PairingEvent? args) {
- log('Pairing Create Event: $args');
- }
-
- @action
- Future _onSessionConnect(SessionConnect? args) async {
- if (args != null) {
- log('Session Connected $args');
-
- await savePairingTopicToLocalStorage(args.session.pairingTopic);
-
- sessions.add(args.session);
-
- _refreshPairings();
- }
- }
-
- @action
- Future _onAuthRequest(AuthRequest? args) async {
- if (args != null) {
- final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type);
- List chainKeys = walletKeyService.getKeysForChain(appStore.wallet!);
- // Create the message to be signed
- final String iss = 'did:pkh:$chaindIdNamespace:${chainKeys.first.publicKey}';
- final Widget modalWidget = Web3RequestModal(
- child: ConnectionRequestWidget(
- chaindIdNamespace: chaindIdNamespace,
- wallet: _web3Wallet,
- authRequest: AuthRequestModel(iss: iss, request: args),
- ),
- );
- final bool? isAuthenticated = await _bottomSheetHandler.queueBottomSheet(
- widget: modalWidget,
- ) as bool?;
-
- if (isAuthenticated != null && isAuthenticated) {
- final String message = _web3Wallet.formatAuthMessage(
- iss: iss,
- cacaoPayload: CacaoRequestPayload.fromPayloadParams(
- args.payloadParams,
- ),
- );
-
- final String sig = EthSigUtil.signPersonalMessage(
- message: Uint8List.fromList(message.codeUnits),
- privateKey: chainKeys.first.privateKey,
- );
-
- await _web3Wallet.respondAuthRequest(
- id: args.id,
- iss: iss,
- signature: CacaoSignature(
- t: CacaoSignature.EIP191,
- s: sig,
- ),
- );
- } else {
- await _web3Wallet.respondAuthRequest(
- id: args.id,
- iss: iss,
- error: Errors.getSdkError(
- Errors.USER_REJECTED_AUTH,
- ),
- );
- }
- }
- }
-
- @action
- Future disconnectSession(String topic) async {
- final session = sessions.firstWhere((element) => element.pairingTopic == topic);
-
- await _web3Wallet.core.pairing.disconnect(topic: topic);
- await _web3Wallet.disconnectSession(
- topic: session.topic, reason: Errors.getSdkError(Errors.USER_DISCONNECTED));
- }
-
- @action
- List getSessionsForPairingInfo(PairingInfo pairing) {
- return sessions.where((element) => element.pairingTopic == pairing.topic).toList();
- }
-
- String getKeyForStoringTopicsForWallet() {
- List chainKeys = walletKeyService.getKeysForChain(appStore.wallet!);
-
- if (chainKeys.isEmpty) {
- return '';
- }
-
- final keyForPairingTopic =
- PreferencesKey.walletConnectPairingTopicsListForWallet(chainKeys.first.publicKey);
-
- return keyForPairingTopic;
- }
-
- List getPairingTopicsForWallet(String key) {
- // Get the JSON-encoded string from shared preferences
- final jsonString = sharedPreferences.getString(key);
-
- // If the string is null, return an empty list
- if (jsonString == null) {
- return [];
- }
-
- // Decode the JSON string to a list of strings
- final List jsonList = jsonDecode(jsonString) as List;
-
- // Cast each item to a string
- return jsonList.map((item) => item as String).toList();
- }
-
- Future savePairingTopicToLocalStorage(String pairingTopic) async {
- // Get key specific to the current wallet
- final key = getKeyForStoringTopicsForWallet();
-
- if (key.isEmpty) return;
-
- // Get all pairing topics attached to this key
- final pairingTopicsForWallet = getPairingTopicsForWallet(key);
-
- printV(pairingTopicsForWallet);
-
- bool isPairingTopicAlreadySaved = pairingTopicsForWallet.contains(pairingTopic);
- printV('Is Pairing Topic Saved: $isPairingTopicAlreadySaved');
-
- if (!isPairingTopicAlreadySaved) {
- // Update the list with the most recent pairing topic
- pairingTopicsForWallet.add(pairingTopic);
-
- // Convert the list of updated pairing topics to a JSON-encoded string
- final jsonString = jsonEncode(pairingTopicsForWallet);
-
- // Save the encoded string to shared preferences
- await sharedPreferences.setString(key, jsonString);
- }
- }
-}
diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart
index f1996bae8..49f366808 100644
--- a/lib/core/wallet_loading_service.dart
+++ b/lib/core/wallet_loading_service.dart
@@ -52,8 +52,11 @@ class WalletLoadingService {
}
}
- Future load(WalletType type, String name, {String? password}) async {
+ Future load(WalletType type, String name, {String? password, bool isBackground = false}) async {
try {
+ if (!isBackground) {
+ await sharedPreferences.setString(PreferencesKey.backgroundSyncLastTrigger(name), DateTime.now().toIso8601String());
+ }
final walletService = walletServiceFactory.call(type);
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
final wallet = await walletService.openWallet(name, walletPassword);
diff --git a/lib/di.dart b/lib/di.dart
index 6354a0c0f..05f2c3f77 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -20,9 +20,6 @@ import 'package:cake_wallet/core/new_wallet_type_arguments.dart';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/core/selectable_option.dart';
import 'package:cake_wallet/core/totp_request_details.dart';
-import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart';
-import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
-import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cake_wallet/core/yat_service.dart';
@@ -33,10 +30,16 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
+import 'package:cake_wallet/haven/cw_haven.dart';
import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart';
import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart';
+import 'package:cake_wallet/src/screens/dev/shared_preferences_page.dart';
import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
+import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
+import 'package:cake_wallet/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart';
+import 'package:cake_wallet/src/screens/wallet_connect/services/walletkit_service.dart';
import 'package:cake_wallet/view_model/dev/monero_background_sync.dart';
+import 'package:cake_wallet/view_model/dev/shared_preferences.dart';
import 'package:cake_wallet/view_model/link_view_model.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
@@ -265,6 +268,8 @@ import 'buy/kryptonim/kryptonim.dart';
import 'buy/meld/meld_buy_provider.dart';
import 'src/screens/buy/buy_sell_page.dart';
import 'cake_pay/cake_pay_payment_credantials.dart';
+import 'package:cake_wallet/view_model/dev/background_sync_logs_view_model.dart';
+import 'package:cake_wallet/src/screens/dev/background_sync_logs_page.dart';
final getIt = GetIt.instance;
@@ -635,11 +640,15 @@ Future setup({
getIt.registerLazySingleton(() => KeyServiceImpl());
- getIt.registerLazySingleton(() {
- final Web3WalletService web3WalletService = Web3WalletService(getIt.get(),
- getIt.get(), appStore, getIt.get());
- web3WalletService.create();
- return web3WalletService;
+ getIt.registerLazySingleton(() {
+ final WalletKitService walletKitService = WalletKitService(
+ getIt.get(),
+ getIt.get(),
+ appStore,
+ getIt.get(),
+ );
+ walletKitService.create();
+ return walletKitService;
});
getIt.registerFactory(() => BalancePage(
@@ -878,9 +887,8 @@ Future setup({
nanoAccountCreationViewModel:
getIt.get(param1: account)));
- getIt.registerFactory(() {
- return DisplaySettingsViewModel(getIt.get());
- });
+ getIt.registerFactory(() =>
+ DisplaySettingsViewModel(getIt.get()));
getIt.registerFactory(() =>
SilentPaymentsSettingsViewModel(getIt.get(), getIt.get().wallet!));
@@ -888,22 +896,20 @@ Future setup({
getIt.registerFactory(
() => MwebSettingsViewModel(getIt.get(), getIt.get().wallet!));
- getIt.registerFactory(() {
- return PrivacySettingsViewModel(getIt.get(), getIt.get().wallet!);
- });
+ getIt.registerFactory(() =>
+ PrivacySettingsViewModel(getIt.get(), getIt.get().wallet!));
getIt.registerFactory(() => TrocadorExchangeProvider());
getIt.registerFactory(() => TrocadorProvidersViewModel(
getIt.get(), getIt.get()));
- getIt.registerFactory(() {
- return OtherSettingsViewModel(getIt.get(), getIt.get().wallet!,
- getIt.get());});
+ getIt.registerFactory(() =>
+ OtherSettingsViewModel(getIt.get(), getIt.get().wallet!,
+ getIt.get()));
- getIt.registerFactory(() {
- return SecuritySettingsViewModel(getIt.get());
- });
+ getIt.registerFactory(() =>
+ SecuritySettingsViewModel(getIt.get()));
getIt.registerFactory(() => WalletSeedViewModel(getIt.get().wallet!));
@@ -911,6 +917,8 @@ Future setup({
getIt.registerFactory(() => DevMoneroBackgroundSync(getIt.get().wallet!));
+ getIt.registerFactory(() => DevSharedPreferences());
+
getIt.registerFactoryParam((bool isWalletCreated, _) =>
WalletSeedPage(getIt.get(), isNewWalletCreated: isWalletCreated));
@@ -1115,8 +1123,9 @@ Future setup({
return zano!.createZanoWalletService(_walletInfoSource);
case WalletType.decred:
return decred!.createDecredWalletService(_walletInfoSource, _unspentCoinsInfoSource);
- case WalletType.none:
case WalletType.haven:
+ return HavenWalletService(_walletInfoSource);
+ case WalletType.none:
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
}
});
@@ -1439,7 +1448,8 @@ Future setup({
});
getIt.registerFactory(
- () => WalletConnectConnectionsView(web3walletService: getIt.get()));
+ () => WalletConnectConnectionsView(walletKitService: getIt.get()),
+ );
getIt.registerFactory(() => NFTViewModel(appStore, getIt.get()));
getIt.registerFactory(() => TorPage(getIt.get()));
@@ -1449,6 +1459,14 @@ Future setup({
getIt.registerFactory(() => SeedVerificationPage(getIt.get()));
getIt.registerFactory(() => DevMoneroBackgroundSyncPage(getIt.get()));
+
getIt.registerFactory(() => DevMoneroCallProfilerPage());
+
+ getIt.registerFactory(() => DevSharedPreferencesPage(getIt.get()));
+
+ getIt.registerFactory(() => BackgroundSyncLogsViewModel());
+
+ getIt.registerFactory(() => DevBackgroundSyncLogsPage(getIt.get()));
+
_isSetupFinished = true;
}
diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart
index 9e889ff46..59989ba14 100644
--- a/lib/entities/preferences_key.dart
+++ b/lib/entities/preferences_key.dart
@@ -105,4 +105,6 @@ class PreferencesKey {
static const walletConnectPairingTopicsList = 'wallet_connect_pairing_topics_list';
static String walletConnectPairingTopicsListForWallet(String publicKey) =>
'${PreferencesKey.walletConnectPairingTopicsList}_${publicKey}';
+ static String backgroundSyncLastTrigger(String walletId) => 'background_sync_last_trigger_${walletId}';
+ static const backgroundSyncNotificationsEnabled = 'background_sync_notifications_enabled';
}
diff --git a/lib/exchange/trade_state.dart b/lib/exchange/trade_state.dart
index e1c4470b4..d09751604 100644
--- a/lib/exchange/trade_state.dart
+++ b/lib/exchange/trade_state.dart
@@ -41,8 +41,8 @@ class TradeState extends EnumerableItem with Serializable {
static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging');
static const sending = TradeState(raw: 'sending', title: 'Sending');
static const success = TradeState(raw: 'success', title: 'Success');
- static TradeState deserialize({required String raw}) {
+ static TradeState deserialize({required String raw}) {
switch (raw) {
case '1':
return unpaid;
@@ -138,7 +138,7 @@ class TradeState extends EnumerableItem with Serializable {
case 'awaiting':
return awaiting;
default:
- throw Exception('Unexpected token: $raw in TradeState deserialize');
+ return TradeState(raw: raw, title: raw);
}
}
diff --git a/lib/haven/cw_haven.dart b/lib/haven/cw_haven.dart
index c54e47eb4..b69e733c3 100644
--- a/lib/haven/cw_haven.dart
+++ b/lib/haven/cw_haven.dart
@@ -1,348 +1,78 @@
-part of 'haven.dart';
+import 'dart:io';
-class CWHavenAccountList extends HavenAccountList {
- CWHavenAccountList(this._wallet);
+import 'package:cw_core/balance.dart';
+import 'package:cw_core/pathForWallet.dart';
+import 'package:cw_core/transaction_history.dart';
+import 'package:cw_core/transaction_info.dart';
+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_service.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:hive/hive.dart';
- final Object _wallet;
+class HavenWalletService extends WalletService {
+ final Box walletInfoSource;
+
+ HavenWalletService(this.walletInfoSource);
@override
- @computed
- ObservableList get accounts {
- final havenWallet = _wallet as HavenWallet;
- final accounts = havenWallet.walletAddresses.accountList.accounts
- .map((acc) => Account(id: acc.id, label: acc.label))
- .toList();
- return ObservableList.of(accounts);
- }
+ WalletType getType() => WalletType.haven;
@override
- void update(Object wallet) {
- final havenWallet = wallet as HavenWallet;
- havenWallet.walletAddresses.accountList.update();
- }
+ Future remove(String wallet) async {
+ final path = await pathForWalletDir(name: wallet, type: WalletType.haven);
- @override
- void refresh(Object wallet) {
- final havenWallet = wallet as HavenWallet;
- havenWallet.walletAddresses.accountList.refresh();
- }
+ final file = Directory(path);
+ final isExist = file.existsSync();
- @override
- List getAll(Object wallet) {
- final havenWallet = wallet as HavenWallet;
- return havenWallet.walletAddresses.accountList
- .getAll()
- .map((acc) => Account(id: acc.id, label: acc.label))
- .toList();
- }
-
- @override
- Future addAccount(Object wallet, {required String label}) async {
- final havenWallet = wallet as HavenWallet;
- await havenWallet.walletAddresses.accountList.addAccount(label: label);
- }
-
- @override
- Future setLabelAccount(Object wallet,
- {required int accountIndex, required String label}) async {
- final havenWallet = wallet as HavenWallet;
- await havenWallet.walletAddresses.accountList
- .setLabelAccount(accountIndex: accountIndex, label: label);
- }
-}
-
-class CWHavenSubaddressList extends MoneroSubaddressList {
- CWHavenSubaddressList(this._wallet);
-
- final Object _wallet;
-
- @override
- @computed
- ObservableList get subaddresses {
- final havenWallet = _wallet as HavenWallet;
- final subAddresses = havenWallet.walletAddresses.subaddressList.subaddresses
- .map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label))
- .toList();
- return ObservableList.of(subAddresses);
- }
-
- @override
- void update(Object wallet, {required int accountIndex}) {
- final havenWallet = wallet as HavenWallet;
- havenWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
- }
-
- @override
- void refresh(Object wallet, {required int accountIndex}) {
- final havenWallet = wallet as HavenWallet;
- havenWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
- }
-
- @override
- List getAll(Object wallet) {
- final havenWallet = wallet as HavenWallet;
- return havenWallet.walletAddresses.subaddressList
- .getAll()
- .map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
- .toList();
- }
-
- @override
- Future addSubaddress(Object wallet,
- {required int accountIndex, required String label}) async {
- final havenWallet = wallet as HavenWallet;
- await havenWallet.walletAddresses.subaddressList
- .addSubaddress(accountIndex: accountIndex, label: label);
- }
-
- @override
- Future setLabelSubaddress(Object wallet,
- {required int accountIndex, required int addressIndex, required String label}) async {
- final havenWallet = wallet as HavenWallet;
- await havenWallet.walletAddresses.subaddressList
- .setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
- }
-}
-
-class CWHavenWalletDetails extends HavenWalletDetails {
- CWHavenWalletDetails(this._wallet);
-
- final Object _wallet;
-
- @computed
- @override
- Account get account {
- final havenWallet = _wallet as HavenWallet;
- final acc = havenWallet.walletAddresses.account as monero_account.Account;
- return Account(id: acc.id, label: acc.label);
- }
-
- @computed
- @override
- HavenBalance get balance {
- final havenWallet = _wallet as HavenWallet;
- final balance = havenWallet.balance;
- throw Exception('Unimplemented');
- //return HavenBalance(
- // fullBalance: balance.fullBalance,
- // unlockedBalance: balance.unlockedBalance);
- }
-}
-
-class CWHaven extends Haven {
- @override
- HavenAccountList getAccountList(Object wallet) {
- return CWHavenAccountList(wallet);
- }
-
- @override
- MoneroSubaddressList getSubaddressList(Object wallet) {
- return CWHavenSubaddressList(wallet);
- }
-
- @override
- TransactionHistoryBase getTransactionHistory(Object wallet) {
- final havenWallet = wallet as HavenWallet;
- return havenWallet.transactionHistory;
- }
-
- @override
- HavenWalletDetails getMoneroWalletDetails(Object wallet) {
- return CWHavenWalletDetails(wallet);
- }
-
- @override
- int getHeightByDate({required DateTime date}) => getHavenHeightByDate(date: date);
-
- @override
- Future getCurrentHeight() => getHavenCurrentHeight();
-
- @override
- TransactionPriority getDefaultTransactionPriority() {
- return MoneroTransactionPriority.automatic;
- }
-
- @override
- TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
- return MoneroTransactionPriority.deserialize(raw: raw);
- }
-
- @override
- List getTransactionPriorities() {
- return MoneroTransactionPriority.all;
- }
-
- @override
- List getMoneroWordList(String language) {
- switch (language.toLowerCase()) {
- case 'english':
- return EnglishMnemonics.words;
- case 'chinese (simplified)':
- return ChineseSimplifiedMnemonics.words;
- case 'dutch':
- return DutchMnemonics.words;
- case 'german':
- return GermanMnemonics.words;
- case 'japanese':
- return JapaneseMnemonics.words;
- case 'portuguese':
- return PortugueseMnemonics.words;
- case 'russian':
- return RussianMnemonics.words;
- case 'spanish':
- return SpanishMnemonics.words;
- case 'french':
- return FrenchMnemonics.words;
- case 'italian':
- return ItalianMnemonics.words;
- default:
- return EnglishMnemonics.words;
+ if (isExist) {
+ await file.delete(recursive: true);
}
+
+ final walletInfo = walletInfoSource.values
+ .firstWhere((info) => info.id == WalletBase.idFor(wallet, getType()));
+ await walletInfoSource.delete(walletInfo.key);
}
@override
- WalletCredentials createHavenRestoreWalletFromKeysCredentials(
- {required String name,
- required String spendKey,
- required String viewKey,
- required String address,
- required String password,
- required String language,
- required int height}) {
- return HavenRestoreWalletFromKeysCredentials(
- name: name,
- spendKey: spendKey,
- viewKey: viewKey,
- address: address,
- password: password,
- language: language,
- height: height);
+ Future, TransactionInfo>> create(
+ WalletCredentials credentials,
+ {bool? isTestnet}) {
+ throw UnimplementedError();
}
@override
- WalletCredentials createHavenRestoreWalletFromSeedCredentials(
- {required String name,
- required String password,
- required int height,
- required String mnemonic}) {
- return HavenRestoreWalletFromSeedCredentials(
- name: name, password: password, height: height, mnemonic: mnemonic);
+ Future isWalletExit(String name) {
+ throw UnimplementedError();
}
@override
- WalletCredentials createHavenNewWalletCredentials(
- {required String name, required String language, String? password}) {
- return HavenNewWalletCredentials(name: name, password: password, language: language);
+ Future, TransactionInfo>> openWallet(
+ String name, String password) {
+ throw UnimplementedError();
}
@override
- Map getKeys(Object wallet) {
- final havenWallet = wallet as HavenWallet;
- final keys = havenWallet.keys;
- return {
- 'privateSpendKey': keys.privateSpendKey,
- 'privateViewKey': keys.privateViewKey,
- 'publicSpendKey': keys.publicSpendKey,
- 'publicViewKey': keys.publicViewKey
- };
+ Future rename(String currentName, String password, String newName) {
+ throw UnimplementedError();
}
@override
- Object createHavenTransactionCreationCredentials(
- {required List