diff --git a/cw_core/lib/solana_rpc_http_service.dart b/cw_core/lib/solana_rpc_http_service.dart
new file mode 100644
index 000000000..fbe9a29dc
--- /dev/null
+++ b/cw_core/lib/solana_rpc_http_service.dart
@@ -0,0 +1,26 @@
+import 'dart:convert';
+import 'package:http/http.dart';
+import 'package:on_chain/solana/solana.dart';
+
+class SolanaRPCHTTPService implements SolanaJSONRPCService {
+  SolanaRPCHTTPService(
+      {required this.url, Client? client, this.defaultRequestTimeout = const Duration(seconds: 30)})
+      : client = client ?? Client();
+  @override
+  final String url;
+  final Client client;
+  final Duration defaultRequestTimeout;
+
+  @override
+  Future<Map<String, dynamic>> call(SolanaRequestDetails params, [Duration? timeout]) async {
+    final response = await client.post(
+      Uri.parse(url),
+      body: params.toRequestBody(),
+      headers: {
+        'Content-Type': 'application/json',
+      },
+    ).timeout(timeout ?? defaultRequestTimeout);
+    final data = json.decode(response.body) as Map<String, dynamic>;
+    return data;
+  }
+}
diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml
index d59440800..9b38b61a7 100644
--- a/cw_core/pubspec.yaml
+++ b/cw_core/pubspec.yaml
@@ -27,6 +27,10 @@ dependencies:
       version: 1.0.0
   socks5_proxy: ^1.0.4
   unorm_dart: ^0.3.0
+  on_chain:
+    git:
+      url: https://github.com/cake-tech/on_chain.git
+      ref: cake-update-v2
 #  tor:
 #    git:
 #      url: https://github.com/cake-tech/tor.git
diff --git a/cw_solana/lib/default_spl_tokens.dart b/cw_solana/lib/default_spl_tokens.dart
index 21b5ef79d..f7ce60aac 100644
--- a/cw_solana/lib/default_spl_tokens.dart
+++ b/cw_solana/lib/default_spl_tokens.dart
@@ -26,7 +26,7 @@ class DefaultSPLTokens {
       decimal: 5,
       mint: 'Bonk',
       iconPath: 'assets/images/bonk_icon.png',
-      enabled: true,
+      enabled: false,
     ),
     SPLToken(
       name: 'Raydium',
@@ -35,7 +35,7 @@ class DefaultSPLTokens {
       decimal: 6,
       mint: 'ray',
       iconPath: 'assets/images/ray_icon.png',
-      enabled: true,
+      enabled: false,
     ),
     SPLToken(
       name: 'Wrapped Ethereum (Sollet)',
diff --git a/cw_solana/lib/pending_solana_transaction.dart b/cw_solana/lib/pending_solana_transaction.dart
index e01446000..5102ea51f 100644
--- a/cw_solana/lib/pending_solana_transaction.dart
+++ b/cw_solana/lib/pending_solana_transaction.dart
@@ -1,9 +1,8 @@
 import 'package:cw_core/pending_transaction.dart';
-import 'package:solana/encoder.dart';
 
 class PendingSolanaTransaction with PendingTransaction {
   final double amount;
-  final SignedTx signedTransaction;
+  final String serializedTransaction;
   final String destinationAddress;
   final Function sendTransaction;
   final double fee;
@@ -11,7 +10,7 @@ class PendingSolanaTransaction with PendingTransaction {
   PendingSolanaTransaction({
     required this.fee,
     required this.amount,
-    required this.signedTransaction,
+    required this.serializedTransaction,
     required this.destinationAddress,
     required this.sendTransaction,
   });
@@ -36,7 +35,7 @@ class PendingSolanaTransaction with PendingTransaction {
   String get feeFormatted => fee.toString();
 
   @override
-  String get hex => signedTransaction.encode();
+  String get hex => serializedTransaction;
 
   @override
   String get id => '';
diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart
index 431f5f7fb..0e08f9abb 100644
--- a/cw_solana/lib/solana_client.dart
+++ b/cw_solana/lib/solana_client.dart
@@ -4,54 +4,59 @@ import 'dart:math' as math;
 
 import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/node.dart';
+import 'package:cw_core/solana_rpc_http_service.dart';
 import 'package:cw_core/utils/print_verbose.dart';
 import 'package:cw_solana/pending_solana_transaction.dart';
 import 'package:cw_solana/solana_balance.dart';
 import 'package:cw_solana/solana_exceptions.dart';
 import 'package:cw_solana/solana_transaction_model.dart';
+import 'package:cw_solana/spl_token.dart';
 import 'package:http/http.dart' as http;
-import 'package:solana/dto.dart';
-import 'package:solana/encoder.dart';
-import 'package:solana/solana.dart';
+import 'package:on_chain/solana/solana.dart';
+import 'package:on_chain/solana/src/models/pda/pda.dart';
+import 'package:blockchain_utils/blockchain_utils.dart';
 import '.secrets.g.dart' as secrets;
 
 class SolanaWalletClient {
   final httpClient = http.Client();
-  SolanaClient? _client;
+  SolanaRPC? _provider;
 
   bool connect(Node node) {
     try {
-      Uri rpcUri = node.uri;
-      String webSocketUrl = 'wss://${node.uriRaw}';
+      String formattedUrl;
+      String protocolUsed = node.isSSL ? "https" : "http";
 
       if (node.uriRaw == 'rpc.ankr.com') {
         String ankrApiKey = secrets.ankrApiKey;
 
-        rpcUri = Uri.https(node.uriRaw, '/solana/$ankrApiKey');
-        webSocketUrl = 'wss://${node.uriRaw}/solana/ws/$ankrApiKey';
+        formattedUrl = '$protocolUsed://${node.uriRaw}/$ankrApiKey';
       } else if (node.uriRaw == 'solana-mainnet.core.chainstack.com') {
         String chainStackApiKey = secrets.chainStackApiKey;
 
-        rpcUri = Uri.https(node.uriRaw, '/$chainStackApiKey');
-        webSocketUrl = 'wss://${node.uriRaw}/$chainStackApiKey';
+        formattedUrl = '$protocolUsed://${node.uriRaw}/$chainStackApiKey';
+      } else {
+        formattedUrl = '$protocolUsed://${node.uriRaw}';
       }
 
-      _client = SolanaClient(
-        rpcUrl: rpcUri,
-        websocketUrl: Uri.parse(webSocketUrl),
-        timeout: const Duration(minutes: 2),
-      );
+      _provider = SolanaRPC(SolanaRPCHTTPService(url: formattedUrl));
+
       return true;
     } catch (e) {
       return false;
     }
   }
 
-  Future<double> getBalance(String address) async {
+  Future<double> getBalance(String walletAddress) async {
     try {
-      final balance = await _client!.rpcClient.getBalance(address);
+      final balance = await _provider!.requestWithContext(
+        SolanaRPCGetBalance(
+          account: SolAddress(walletAddress),
+        ),
+      );
 
-      final solBalance = balance.value / lamportsPerSol;
+      final balInLamp = balance.result.toDouble();
+
+      final solBalance = balInLamp / SolanaUtils.lamportsPerSol;
 
       return solBalance;
     } catch (_) {
@@ -59,37 +64,42 @@ class SolanaWalletClient {
     }
   }
 
-  Future<ProgramAccountsResult?> getSPLTokenAccounts(String mintAddress, String publicKey) async {
+  Future<List<TokenAccountResponse>?> getSPLTokenAccounts(
+      String mintAddress, String publicKey) async {
     try {
-      final tokenAccounts = await _client!.rpcClient.getTokenAccountsByOwner(
-        publicKey,
-        TokenAccountsFilter.byMint(mintAddress),
-        commitment: Commitment.confirmed,
-        encoding: Encoding.jsonParsed,
+      final result = await _provider!.request(
+        SolanaRPCGetTokenAccountsByOwner(
+          account: SolAddress(publicKey),
+          mint: SolAddress(mintAddress),
+          commitment: Commitment.confirmed,
+          encoding: SolanaRPCEncoding.base64,
+        ),
       );
-      return tokenAccounts;
+
+      return result;
     } catch (e) {
       return null;
     }
   }
 
-  Future<SolanaBalance?> getSplTokenBalance(String mintAddress, String publicKey) async {
+  Future<SolanaBalance?> getSplTokenBalance(String mintAddress, String walletAddress) async {
     // Fetch the token accounts (a token can have multiple accounts for various uses)
-    final tokenAccounts = await getSPLTokenAccounts(mintAddress, publicKey);
+    final tokenAccounts = await getSPLTokenAccounts(mintAddress, walletAddress);
 
     // Handle scenario where there is no token account
-    if (tokenAccounts == null || tokenAccounts.value.isEmpty) {
+    if (tokenAccounts == null || tokenAccounts.isEmpty) {
       return null;
     }
 
     // Sum the balances of all accounts with the specified mint address
     double totalBalance = 0.0;
 
-    for (var programAccount in tokenAccounts.value) {
-      final tokenAmountResult =
-          await _client!.rpcClient.getTokenAccountBalance(programAccount.pubkey);
+    for (var tokenAccount in tokenAccounts) {
+      final tokenAmountResult = await _provider!.request(
+        SolanaRPCGetTokenAccountBalance(account: tokenAccount.pubkey),
+      );
 
-      final balance = tokenAmountResult.value.uiAmountString;
+      final balance = tokenAmountResult.uiAmountString;
 
       final balanceAsDouble = double.tryParse(balance ?? '0.0') ?? 0.0;
 
@@ -101,198 +111,318 @@ class SolanaWalletClient {
 
   Future<double> getFeeForMessage(String message, Commitment commitment) async {
     try {
-      final feeForMessage =
-          await _client!.rpcClient.getFeeForMessage(message, commitment: commitment);
-      final fee = (feeForMessage ?? 0.0) / lamportsPerSol;
+      final feeForMessage = await _provider!.request(
+        SolanaRPCGetFeeForMessage(
+          encodedMessage: message,
+          commitment: commitment,
+        ),
+      );
+
+      final fee = (feeForMessage?.toDouble() ?? 0.0) / SolanaUtils.lamportsPerSol;
       return fee;
     } catch (_) {
       return 0.0;
     }
   }
 
-  Future<double> getEstimatedFee(Ed25519HDKeyPair ownerKeypair) async {
-    const commitment = Commitment.confirmed;
+  Future<double> getEstimatedFee(SolanaPublicKey publicKey, Commitment commitment) async {
+    final message = await _getMessageForNativeTransaction(
+      publicKey: publicKey,
+      destinationAddress: publicKey.toAddress().address,
+      lamports: SolanaUtils.lamportsPerSol,
+      commitment: commitment,
+    );
 
-    final message =
-        _getMessageForNativeTransaction(ownerKeypair, ownerKeypair.address, lamportsPerSol);
-
-    final latestBlockhash = await _getLatestBlockhash(commitment);
-
-    final estimatedFee = _getFeeFromCompiledMessage(
+    final estimatedFee = await _getFeeFromCompiledMessage(
       message,
-      ownerKeypair.publicKey,
-      latestBlockhash,
       commitment,
     );
     return estimatedFee;
   }
 
+  Future<SolanaTransactionModel?> parseTransaction({
+    VersionedTransactionResponse? txResponse,
+    required String walletAddress,
+    String? splTokenSymbol,
+  }) async {
+    if (txResponse == null) return null;
+
+    try {
+      final blockTime = txResponse.blockTime;
+      final meta = txResponse.meta;
+      final transaction = txResponse.transaction;
+
+      if (meta == null || transaction == null) return null;
+
+      final int fee = meta.fee;
+
+      final message = transaction.message;
+      final instructions = message.compiledInstructions;
+
+      String sender = "";
+      String receiver = "";
+
+      String signature = (txResponse.transaction?.signatures.isEmpty ?? true)
+          ? ""
+          : Base58Encoder.encode(txResponse.transaction!.signatures.first);
+
+      for (final instruction in instructions) {
+        final programId = message.accountKeys[instruction.programIdIndex];
+
+        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;
+
+          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;
+
+          final preBalances = meta.preTokenBalances;
+          final postBalances = meta.postTokenBalances;
+
+          double amount = 0.0;
+          bool isOutgoing = false;
+          String? mintAddress;
+
+          double userPreAmount = 0.0;
+          if (preBalances != null && preBalances.isNotEmpty) {
+            for (final preBal in preBalances) {
+              if (preBal.owner?.address == walletAddress) {
+                userPreAmount = preBal.uiTokenAmount.uiAmount ?? 0.0;
+
+                mintAddress = preBal.mint.address;
+                break;
+              }
+            }
+          }
+
+          double userPostAmount = 0.0;
+          if (postBalances != null && postBalances.isNotEmpty) {
+            for (final postBal in postBalances) {
+              if (postBal.owner?.address == walletAddress) {
+                userPostAmount = postBal.uiTokenAmount.uiAmount ?? 0.0;
+
+                mintAddress ??= postBal.mint.address;
+                break;
+              }
+            }
+          }
+
+          final diff = userPreAmount - userPostAmount;
+          final rawAmount = diff.abs();
+
+          final amountInString = rawAmount.toStringAsFixed(6);
+          amount = double.parse(amountInString);
+
+          isOutgoing = diff > 0;
+
+          if (mintAddress == null && instruction.accounts.length >= 4) {
+            final mintIndex = instruction.accounts[3];
+            mintAddress = message.accountKeys[mintIndex].address;
+          }
+
+          final sender = message.accountKeys[instruction.accounts[0]].address;
+          final receiver = message.accountKeys[instruction.accounts[1]].address;
+
+          String? tokenSymbol = splTokenSymbol;
+          if (tokenSymbol == null && mintAddress != null) {
+            final token = await fetchSPLTokenInfo(mintAddress);
+            tokenSymbol = token?.symbol;
+          }
+
+          return SolanaTransactionModel(
+            isOutgoingTx: isOutgoing,
+            from: sender,
+            to: receiver,
+            id: signature,
+            amount: amount,
+            programId: SPLTokenProgramConst.tokenProgramId.address,
+            blockTimeInInt: blockTime?.toInt() ?? 0,
+            tokenSymbol: tokenSymbol ?? '',
+            fee: fee / SolanaUtils.lamportsPerSol,
+          );
+        } else {
+          return null;
+        }
+      }
+    } catch (e, s) {
+      printV("Error parsing transaction: $e\n$s");
+    }
+
+    return null;
+  }
+
   /// Load the Address's transactions into the account
   Future<List<SolanaTransactionModel>> fetchTransactions(
-    Ed25519HDPublicKey publicKey, {
+    SolAddress address, {
     String? splTokenSymbol,
     int? splTokenDecimal,
+    Commitment? commitment,
+    SolAddress? walletAddress,
   }) async {
     List<SolanaTransactionModel> transactions = [];
 
     try {
-      final signatures = await _client!.rpcClient.getSignaturesForAddress(
-        publicKey.toBase58(),
-        commitment: Commitment.confirmed,
+      final signatures = await _provider!.request(
+        SolanaRPCGetSignaturesForAddress(
+          account: address,
+          commitment: commitment,
+        ),
       );
 
-      final List<TransactionDetails> transactionDetails = [];
+      final List<VersionedTransactionResponse?> transactionDetails = [];
+
       for (int i = 0; i < signatures.length; i += 20) {
-        final response = await _client!.rpcClient.getMultipleTransactions(
-          signatures.sublist(i, math.min(i + 20, signatures.length)),
-          commitment: Commitment.confirmed,
-          encoding: Encoding.jsonParsed,
-        );
-        transactionDetails.addAll(response);
+        final batch = signatures.skip(i).take(20).toList(); // Get the next 20 signatures
+
+        final batchResponses = await Future.wait(batch.map((signature) async {
+          try {
+            return await _provider!.request(
+              SolanaRPCGetTransaction(
+                transactionSignature: signature['signature'],
+                encoding: SolanaRPCEncoding.jsonParsed,
+                maxSupportedTransactionVersion: 0,
+              ),
+            );
+          } catch (e) {
+            printV("Error fetching transaction: $e");
+            return null;
+          }
+        }));
+
+        transactionDetails.addAll(batchResponses.whereType<VersionedTransactionResponse>());
 
         // to avoid reaching the node RPS limit
-        await Future.delayed(Duration(milliseconds: 500));
+        if (i + 20 < signatures.length) {
+          await Future.delayed(const Duration(milliseconds: 500));
+        }
       }
 
       for (final tx in transactionDetails) {
-        if (tx.transaction is ParsedTransaction) {
-          final parsedTx = (tx.transaction as ParsedTransaction);
-          final message = parsedTx.message;
-
-          final fee = (tx.meta?.fee ?? 0) / lamportsPerSol;
-
-          for (final instruction in message.instructions) {
-            if (instruction is ParsedInstruction) {
-              instruction.map(
-                system: (systemData) {
-                  systemData.parsed.map(
-                    transfer: (transferData) {
-                      ParsedSystemTransferInformation transfer = transferData.info;
-                      bool isOutgoingTx = transfer.source == publicKey.toBase58();
-
-                      double amount = transfer.lamports.toDouble() / lamportsPerSol;
-
-                      transactions.add(
-                        SolanaTransactionModel(
-                          id: parsedTx.signatures.first,
-                          from: transfer.source,
-                          to: transfer.destination,
-                          amount: amount,
-                          isOutgoingTx: isOutgoingTx,
-                          blockTimeInInt: tx.blockTime!,
-                          fee: fee,
-                          programId: SystemProgram.programId,
-                          tokenSymbol: 'SOL',
-                        ),
-                      );
-                    },
-                    transferChecked: (_) {},
-                    unsupported: (_) {},
-                  );
-                },
-                splToken: (splTokenData) {
-                  if (splTokenSymbol != null) {
-                    splTokenData.parsed.map(
-                      transfer: (transferData) {
-                        SplTokenTransferInfo transfer = transferData.info;
-                        bool isOutgoingTx = transfer.source == publicKey.toBase58();
-
-                        double amount = (double.tryParse(transfer.amount) ?? 0.0) /
-                            math.pow(10, splTokenDecimal ?? 9);
-
-                        transactions.add(
-                          SolanaTransactionModel(
-                            id: parsedTx.signatures.first,
-                            fee: fee,
-                            from: transfer.source,
-                            to: transfer.destination,
-                            amount: amount,
-                            isOutgoingTx: isOutgoingTx,
-                            programId: TokenProgram.programId,
-                            blockTimeInInt: tx.blockTime!,
-                            tokenSymbol: splTokenSymbol,
-                          ),
-                        );
-                      },
-                      transferChecked: (transferCheckedData) {
-                        SplTokenTransferCheckedInfo transfer = transferCheckedData.info;
-                        bool isOutgoingTx = transfer.source == publicKey.toBase58();
-                        double amount =
-                            double.tryParse(transfer.tokenAmount.uiAmountString ?? '0.0') ?? 0.0;
-
-                        transactions.add(
-                          SolanaTransactionModel(
-                            id: parsedTx.signatures.first,
-                            fee: fee,
-                            from: transfer.source,
-                            to: transfer.destination,
-                            amount: amount,
-                            isOutgoingTx: isOutgoingTx,
-                            programId: TokenProgram.programId,
-                            blockTimeInInt: tx.blockTime!,
-                            tokenSymbol: splTokenSymbol,
-                          ),
-                        );
-                      },
-                      generic: (genericData) {},
-                    );
-                  }
-                },
-                memo: (_) {},
-                unsupported: (a) {},
-              );
-            }
-          }
+        final parsedTx = await parseTransaction(
+          txResponse: tx,
+          splTokenSymbol: splTokenSymbol,
+          walletAddress: walletAddress?.address ?? address.address,
+        );
+        if (parsedTx != null) {
+          transactions.add(parsedTx);
         }
       }
 
       return transactions;
-    } catch (err) {
+    } catch (err, s) {
+      printV('Error fetching transactions: $err \n$s');
       return [];
     }
   }
 
-  Future<List<SolanaTransactionModel>> getSPLTokenTransfers(
-    String address,
-    String splTokenSymbol,
-    int splTokenDecimal,
-    Ed25519HDKeyPair ownerKeypair,
-  ) async {
-    final tokenMint = Ed25519HDPublicKey.fromBase58(address);
-
-    ProgramAccount? associatedTokenAccount;
-
+  Future<List<SolanaTransactionModel>> getSPLTokenTransfers({
+    required String mintAddress,
+    required String splTokenSymbol,
+    required int splTokenDecimal,
+    required SolanaPrivateKey privateKey,
+  }) async {
+    ProgramDerivedAddress? associatedTokenAccount;
+    final ownerWalletAddress = privateKey.publicKey().toAddress();
     try {
-      associatedTokenAccount = await _client!.getAssociatedTokenAccount(
-        mint: tokenMint,
-        owner: ownerKeypair.publicKey,
-        commitment: Commitment.confirmed,
+      associatedTokenAccount = await _getOrCreateAssociatedTokenAccount(
+        payerPrivateKey: privateKey,
+        mintAddress: SolAddress(mintAddress),
+        ownerAddress: ownerWalletAddress,
+        shouldCreateATA: false,
       );
-    } catch (_) {}
+    } catch (e, s) {
+      printV('$e \n $s');
+    }
 
     if (associatedTokenAccount == null) return [];
 
-    final accountPublicKey = Ed25519HDPublicKey.fromBase58(associatedTokenAccount.pubkey);
+    final accountPublicKey = associatedTokenAccount.address;
 
     final tokenTransactions = await fetchTransactions(
       accountPublicKey,
       splTokenSymbol: splTokenSymbol,
       splTokenDecimal: splTokenDecimal,
+      walletAddress: ownerWalletAddress,
     );
 
     return tokenTransactions;
   }
 
+  Future<SPLToken?> fetchSPLTokenInfo(String mintAddress) async {
+    final programAddress =
+        MetaplexTokenMetaDataProgramUtils.findMetadataPda(mint: SolAddress(mintAddress));
+
+    final token = await _provider!.request(
+      SolanaRPCGetMetadataAccount(
+        account: programAddress.address,
+        commitment: Commitment.confirmed,
+      ),
+    );
+
+    if (token == null) {
+      return null;
+    }
+
+    final metadata = token.data;
+
+    String? iconPath;
+    //TODO(Further explore fetching images)
+    // try {
+    //   iconPath = await _client.getIconImageFromTokenUri(metadata.uri);
+    // } catch (_) {}
+
+    String filteredTokenSymbol =
+        metadata.symbol.replaceFirst(RegExp('^\\\$'), '').replaceAll('\u0000', '');
+
+    return SPLToken.fromMetadata(
+      name: metadata.name,
+      mint: metadata.symbol,
+      symbol: filteredTokenSymbol,
+      mintAddress: token.mint.address,
+      iconPath: iconPath,
+    );
+  }
+
   void stop() {}
 
-  SolanaClient? get getSolanaClient => _client;
+  SolanaRPC? get getSolanaProvider => _provider;
 
   Future<PendingSolanaTransaction> signSolanaTransaction({
     required String tokenTitle,
     required int tokenDecimals,
     required double inputAmount,
     required String destinationAddress,
-    required Ed25519HDKeyPair ownerKeypair,
+    required SolanaPrivateKey ownerPrivateKey,
     required bool isSendAll,
     required double solBalance,
     String? tokenMint,
@@ -302,11 +432,9 @@ class SolanaWalletClient {
 
     if (tokenTitle == CryptoCurrency.sol.title) {
       final pendingNativeTokenTransaction = await _signNativeTokenTransaction(
-        tokenTitle: tokenTitle,
-        tokenDecimals: tokenDecimals,
         inputAmount: inputAmount,
         destinationAddress: destinationAddress,
-        ownerKeypair: ownerKeypair,
+        ownerPrivateKey: ownerPrivateKey,
         commitment: commitment,
         isSendAll: isSendAll,
         solBalance: solBalance,
@@ -314,12 +442,11 @@ class SolanaWalletClient {
       return pendingNativeTokenTransaction;
     } else {
       final pendingSPLTokenTransaction = _signSPLTokenTransaction(
-        tokenTitle: tokenTitle,
         tokenDecimals: tokenDecimals,
         tokenMint: tokenMint!,
         inputAmount: inputAmount,
+        ownerPrivateKey: ownerPrivateKey,
         destinationAddress: destinationAddress,
-        ownerKeypair: ownerKeypair,
         commitment: commitment,
         solBalance: solBalance,
       );
@@ -327,47 +454,72 @@ class SolanaWalletClient {
     }
   }
 
-  Future<LatestBlockhash> _getLatestBlockhash(Commitment commitment) async {
-    final latestBlockHashResult =
-        await _client!.rpcClient.getLatestBlockhash(commitment: commitment).value;
-
-    final latestBlockhash = LatestBlockhash(
-      blockhash: latestBlockHashResult.blockhash,
-      lastValidBlockHeight: latestBlockHashResult.lastValidBlockHeight,
+  Future<SolAddress> _getLatestBlockhash(Commitment commitment) async {
+    final latestBlockhash = await _provider!.request(
+      const SolanaRPCGetLatestBlockhash(),
     );
 
-    return latestBlockhash;
+    return latestBlockhash.blockhash;
   }
 
-  Message _getMessageForNativeTransaction(
-    Ed25519HDKeyPair ownerKeypair,
-    String destinationAddress,
-    int lamports,
-  ) {
+  Future<Message> _getMessageForNativeTransaction({
+    required SolanaPublicKey publicKey,
+    required String destinationAddress,
+    required int lamports,
+    required Commitment commitment,
+  }) async {
     final instructions = [
-      SystemInstruction.transfer(
-        fundingAccount: ownerKeypair.publicKey,
-        recipientAccount: Ed25519HDPublicKey.fromBase58(destinationAddress),
-        lamports: lamports,
+      SystemProgram.transfer(
+        from: publicKey.toAddress(),
+        layout: SystemTransferLayout(lamports: BigInt.from(lamports)),
+        to: SolAddress(destinationAddress),
       ),
     ];
 
-    final message = Message(instructions: instructions);
+    final latestBlockhash = await _getLatestBlockhash(commitment);
+
+    final message = Message.compile(
+      transactionInstructions: instructions,
+      payer: publicKey.toAddress(),
+      recentBlockhash: latestBlockhash,
+    );
     return message;
   }
 
-  Future<double> _getFeeFromCompiledMessage(
-    Message message,
-    Ed25519HDPublicKey feePayer,
-    LatestBlockhash latestBlockhash,
-    Commitment commitment,
-  ) async {
-    final compile = message.compile(
-      recentBlockhash: latestBlockhash.blockhash,
-      feePayer: feePayer,
-    );
+  Future<Message> _getMessageForSPLTokenTransaction({
+    required SolAddress ownerAddress,
+    required SolAddress destinationAddress,
+    required int tokenDecimals,
+    required SolAddress mintAddress,
+    required SolAddress sourceAccount,
+    required int amount,
+    required Commitment commitment,
+  }) async {
+    final instructions = [
+      SPLTokenProgram.transferChecked(
+        layout: SPLTokenTransferCheckedLayout(
+          amount: BigInt.from(amount),
+          decimals: tokenDecimals,
+        ),
+        mint: mintAddress,
+        source: sourceAccount,
+        destination: destinationAddress,
+        owner: ownerAddress,
+      )
+    ];
 
-    final base64Message = base64Encode(compile.toByteArray().toList());
+    final latestBlockhash = await _getLatestBlockhash(commitment);
+
+    final message = Message.compile(
+      transactionInstructions: instructions,
+      payer: ownerAddress,
+      recentBlockhash: latestBlockhash,
+    );
+    return message;
+  }
+
+  Future<double> _getFeeFromCompiledMessage(Message message, Commitment commitment) async {
+    final base64Message = base64Encode(message.serialize());
 
     final fee = await getFeeForMessage(base64Message, commitment);
 
@@ -379,43 +531,43 @@ class SolanaWalletClient {
     required double solBalance,
     required double fee,
   }) async {
-    return true;
-    // TODO: this is not doing what the name inclines
-    // final rent =
-    //     await _client!.getMinimumBalanceForMintRentExemption(commitment: Commitment.confirmed);
-    //
-    // final rentInSol = (rent / lamportsPerSol).toDouble();
-    //
-    // final remnant = solBalance - (inputAmount + fee);
-    //
-    // if (remnant > rentInSol) return true;
-    //
-    // return false;
+    final rent = await _provider!.request(
+      SolanaRPCGetMinimumBalanceForRentExemption(
+        size: SolanaTokenAccountUtils.accountSize,
+      ),
+    );
+
+    final rentInSol = (rent.toDouble() / SolanaUtils.lamportsPerSol).toDouble();
+
+    final remnant = solBalance - (inputAmount + fee);
+
+    if (remnant > rentInSol) return true;
+
+    return false;
   }
 
   Future<PendingSolanaTransaction> _signNativeTokenTransaction({
-    required String tokenTitle,
-    required int tokenDecimals,
     required double inputAmount,
     required String destinationAddress,
-    required Ed25519HDKeyPair ownerKeypair,
+    required SolanaPrivateKey ownerPrivateKey,
     required Commitment commitment,
     required bool isSendAll,
     required double solBalance,
   }) async {
     // Convert SOL to lamport
-    int lamports = (inputAmount * lamportsPerSol).toInt();
+    int lamports = (inputAmount * SolanaUtils.lamportsPerSol).toInt();
 
-    Message message = _getMessageForNativeTransaction(ownerKeypair, destinationAddress, lamports);
+    Message message = await _getMessageForNativeTransaction(
+      publicKey: ownerPrivateKey.publicKey(),
+      destinationAddress: destinationAddress,
+      lamports: lamports,
+      commitment: commitment,
+    );
 
-    final signers = [ownerKeypair];
-
-    LatestBlockhash latestBlockhash = await _getLatestBlockhash(commitment);
+    SolAddress latestBlockhash = await _getLatestBlockhash(commitment);
 
     final fee = await _getFeeFromCompiledMessage(
       message,
-      signers.first.publicKey,
-      latestBlockhash,
       commitment,
     );
 
@@ -429,37 +581,44 @@ class SolanaWalletClient {
       throw SolanaSignNativeTokenTransactionRentException();
     }
 
-    SignedTx signedTx;
+    String serializedTransaction;
     if (isSendAll) {
-      final feeInLamports = (fee * lamportsPerSol).toInt();
+      final feeInLamports = (fee * SolanaUtils.lamportsPerSol).toInt();
       final updatedLamports = lamports - feeInLamports;
 
-      final updatedMessage =
-          _getMessageForNativeTransaction(ownerKeypair, destinationAddress, updatedLamports);
-
-      signedTx = await _signTransactionInternal(
-        message: updatedMessage,
-        signers: signers,
-        commitment: commitment,
+      final transaction = _constructNativeTransaction(
+        ownerPrivateKey: ownerPrivateKey,
+        destinationAddress: destinationAddress,
         latestBlockhash: latestBlockhash,
+        lamports: updatedLamports,
+      );
+
+      serializedTransaction = await _signTransactionInternal(
+        ownerPrivateKey: ownerPrivateKey,
+        transaction: transaction,
       );
     } else {
-      signedTx = await _signTransactionInternal(
-        message: message,
-        signers: signers,
-        commitment: commitment,
+      final transaction = _constructNativeTransaction(
+        ownerPrivateKey: ownerPrivateKey,
+        destinationAddress: destinationAddress,
         latestBlockhash: latestBlockhash,
+        lamports: lamports,
+      );
+
+      serializedTransaction = await _signTransactionInternal(
+        ownerPrivateKey: ownerPrivateKey,
+        transaction: transaction,
       );
     }
 
     sendTx() async => await sendTransaction(
-          signedTransaction: signedTx,
+          serializedTransaction: serializedTransaction,
           commitment: commitment,
         );
 
     final pendingTransaction = PendingSolanaTransaction(
       amount: inputAmount,
-      signedTransaction: signedTx,
+      serializedTransaction: serializedTransaction,
       destinationAddress: destinationAddress,
       sendTransaction: sendTx,
       fee: fee,
@@ -468,108 +627,170 @@ class SolanaWalletClient {
     return pendingTransaction;
   }
 
+  SolanaTransaction _constructNativeTransaction({
+    required SolanaPrivateKey ownerPrivateKey,
+    required String destinationAddress,
+    required SolAddress latestBlockhash,
+    required int lamports,
+  }) {
+    final owner = ownerPrivateKey.publicKey().toAddress();
+
+    /// Create a transfer instruction to move funds from the owner to the receiver.
+    final transferInstruction = SystemProgram.transfer(
+      from: owner,
+      layout: SystemTransferLayout(lamports: BigInt.from(lamports)),
+      to: SolAddress(destinationAddress),
+    );
+
+    /// Construct a Solana transaction with the transfer instruction.
+    return SolanaTransaction(
+      instructions: [transferInstruction],
+      recentBlockhash: latestBlockhash,
+      payerKey: ownerPrivateKey.publicKey().toAddress(),
+      type: TransactionType.v0,
+    );
+  }
+
+  Future<ProgramDerivedAddress?> _getOrCreateAssociatedTokenAccount({
+    required SolanaPrivateKey payerPrivateKey,
+    required SolAddress ownerAddress,
+    required SolAddress mintAddress,
+    required bool shouldCreateATA,
+  }) async {
+    final associatedTokenAccount = AssociatedTokenAccountProgramUtils.associatedTokenAccount(
+      mint: mintAddress,
+      owner: ownerAddress,
+    );
+
+    SolanaAccountInfo? accountInfo;
+    try {
+      accountInfo = await _provider!.request(
+        SolanaRPCGetAccountInfo(account: associatedTokenAccount.address),
+      );
+    } catch (e) {
+      accountInfo = null;
+    }
+
+    // If aacountInfo is null, signifies that the associatedTokenAccount has only been created locally and not been broadcasted to the blockchain.
+    if (accountInfo != null) return associatedTokenAccount;
+
+    if (!shouldCreateATA) return null;
+
+    final createAssociatedTokenAccount = AssociatedTokenAccountProgram.associatedTokenAccount(
+      payer: payerPrivateKey.publicKey().toAddress(),
+      associatedToken: associatedTokenAccount.address,
+      owner: ownerAddress,
+      mint: mintAddress,
+    );
+
+    final blockhash = await _getLatestBlockhash(Commitment.confirmed);
+
+    final transaction = SolanaTransaction(
+      payerKey: payerPrivateKey.publicKey().toAddress(),
+      instructions: [createAssociatedTokenAccount],
+      recentBlockhash: blockhash,
+    );
+
+    transaction.sign([payerPrivateKey]);
+
+    await sendTransaction(
+      serializedTransaction: transaction.serializeString(),
+      commitment: Commitment.confirmed,
+    );
+
+    // Delay for propagation on the blockchain for newly created associated token addresses
+    await Future.delayed(const Duration(seconds: 2));
+
+    return associatedTokenAccount;
+  }
+
   Future<PendingSolanaTransaction> _signSPLTokenTransaction({
-    required String tokenTitle,
     required int tokenDecimals,
     required String tokenMint,
     required double inputAmount,
     required String destinationAddress,
-    required Ed25519HDKeyPair ownerKeypair,
+    required SolanaPrivateKey ownerPrivateKey,
     required Commitment commitment,
     required double solBalance,
   }) async {
-    final destinationOwner = Ed25519HDPublicKey.fromBase58(destinationAddress);
-    final mint = Ed25519HDPublicKey.fromBase58(tokenMint);
+    final mintAddress = SolAddress(tokenMint);
 
     // Input by the user
     final amount = (inputAmount * math.pow(10, tokenDecimals)).toInt();
-
-    ProgramAccount? associatedRecipientAccount;
-    ProgramAccount? associatedSenderAccount;
-
-    associatedRecipientAccount = await _client!.getAssociatedTokenAccount(
-      mint: mint,
-      owner: destinationOwner,
-      commitment: commitment,
-    );
-
-    associatedSenderAccount = await _client!.getAssociatedTokenAccount(
-      owner: ownerKeypair.publicKey,
-      mint: mint,
-      commitment: commitment,
-    );
+    ProgramDerivedAddress? associatedSenderAccount;
+    try {
+      associatedSenderAccount = AssociatedTokenAccountProgramUtils.associatedTokenAccount(
+        mint: mintAddress,
+        owner: ownerPrivateKey.publicKey().toAddress(),
+      );
+    } catch (e) {
+      associatedSenderAccount = null;
+    }
 
     // Throw an appropriate exception if the sender has no associated
     // token account
     if (associatedSenderAccount == null) {
-      throw SolanaNoAssociatedTokenAccountException(ownerKeypair.address, mint.toBase58());
+      throw SolanaNoAssociatedTokenAccountException(
+        ownerPrivateKey.publicKey().toAddress().address,
+        mintAddress.address,
+      );
     }
 
+    ProgramDerivedAddress? associatedRecipientAccount;
     try {
-      if (associatedRecipientAccount == null) {
-        final derivedAddress = await findAssociatedTokenAddress(
-          owner: destinationOwner,
-          mint: mint,
-        );
-
-        final instruction = AssociatedTokenAccountInstruction.createAccount(
-          mint: mint,
-          address: derivedAddress,
-          owner: destinationOwner,
-          funder: ownerKeypair.publicKey,
-        );
-
-        final _signedTx = await _signTransactionInternal(
-          message: Message.only(instruction),
-          signers: [ownerKeypair],
-          commitment: commitment,
-          latestBlockhash: await _getLatestBlockhash(commitment),
-        );
-
-        await sendTransaction(
-          signedTransaction: _signedTx,
-          commitment: commitment,
-        );
-
-        associatedRecipientAccount = ProgramAccount(
-          pubkey: derivedAddress.toBase58(),
-          account: Account(
-            owner: destinationOwner.toBase58(),
-            lamports: 0,
-            executable: false,
-            rentEpoch: BigInt.zero,
-            data: null,
-          ),
-        );
-
-        await Future.delayed(Duration(seconds: 5));
-      }
+      associatedRecipientAccount = await _getOrCreateAssociatedTokenAccount(
+        payerPrivateKey: ownerPrivateKey,
+        mintAddress: mintAddress,
+        ownerAddress: SolAddress(destinationAddress),
+        shouldCreateATA: true,
+      );
     } catch (e) {
-      throw SolanaCreateAssociatedTokenAccountException(e.toString());
+      associatedRecipientAccount = null;
+
+      throw SolanaCreateAssociatedTokenAccountException(
+        'Error fetching recipient associated token account: ${e.toString()}',
+      );
     }
 
-    final instruction = TokenInstruction.transfer(
-      source: Ed25519HDPublicKey.fromBase58(associatedSenderAccount.pubkey),
-      destination: Ed25519HDPublicKey.fromBase58(associatedRecipientAccount.pubkey),
-      owner: ownerKeypair.publicKey,
+    if (associatedRecipientAccount == null) {
+      throw SolanaCreateAssociatedTokenAccountException(
+        'Error fetching recipient associated token account',
+      );
+    }
+
+    final transferInstructions = SPLTokenProgram.transferChecked(
+      layout: SPLTokenTransferCheckedLayout(
+        amount: BigInt.from(amount),
+        decimals: tokenDecimals,
+      ),
+      mint: mintAddress,
+      source: associatedSenderAccount.address,
+      destination: associatedRecipientAccount.address,
+      owner: ownerPrivateKey.publicKey().toAddress(),
+    );
+
+    final latestBlockHash = await _getLatestBlockhash(commitment);
+
+    final transaction = SolanaTransaction(
+      payerKey: ownerPrivateKey.publicKey().toAddress(),
+      instructions: [transferInstructions],
+      recentBlockhash: latestBlockHash,
+    );
+
+    final message = await _getMessageForSPLTokenTransaction(
+      ownerAddress: ownerPrivateKey.publicKey().toAddress(),
+      tokenDecimals: tokenDecimals,
+      mintAddress: mintAddress,
+      destinationAddress: associatedRecipientAccount.address,
+      sourceAccount: associatedSenderAccount.address,
       amount: amount,
+      commitment: commitment,
     );
 
-    final message = Message(instructions: [instruction]);
-
-    final signers = [ownerKeypair];
-
-    LatestBlockhash latestBlockhash = await _getLatestBlockhash(commitment);
-
-    final fee = await _getFeeFromCompiledMessage(
-      message,
-      signers.first.publicKey,
-      latestBlockhash,
-      commitment,
-    );
+    final fee = await _getFeeFromCompiledMessage(message, commitment);
 
     bool hasSufficientFundsLeft = await hasSufficientFundsLeftForRent(
-      inputAmount: inputAmount,
+      inputAmount: 0,
       fee: fee,
       solBalance: solBalance,
     );
@@ -578,25 +799,19 @@ class SolanaWalletClient {
       throw SolanaSignSPLTokenTransactionRentException();
     }
 
-    final signedTx = await _signTransactionInternal(
-      message: message,
-      signers: signers,
-      commitment: commitment,
-      latestBlockhash: latestBlockhash,
+    final serializedTransaction = await _signTransactionInternal(
+      ownerPrivateKey: ownerPrivateKey,
+      transaction: transaction,
     );
 
-    sendTx() async {
-      await Future.delayed(Duration(seconds: 3));
-
-      return await sendTransaction(
-          signedTransaction: signedTx,
+    sendTx() async => await sendTransaction(
+          serializedTransaction: serializedTransaction,
           commitment: commitment,
         );
-    }
 
     final pendingTransaction = PendingSolanaTransaction(
       amount: inputAmount,
-      signedTransaction: signedTx,
+      serializedTransaction: serializedTransaction,
       destinationAddress: destinationAddress,
       sendTransaction: sendTx,
       fee: fee,
@@ -604,37 +819,41 @@ class SolanaWalletClient {
     return pendingTransaction;
   }
 
-  Future<SignedTx> _signTransactionInternal({
-    required Message message,
-    required List<Ed25519HDKeyPair> signers,
-    required Commitment commitment,
-    required LatestBlockhash latestBlockhash,
+  Future<String> _signTransactionInternal({
+    required SolanaPrivateKey ownerPrivateKey,
+    required SolanaTransaction transaction,
   }) async {
-    final signedTx = await signTransaction(latestBlockhash, message, signers);
+    /// Sign the transaction with the owner's private key.
+    final ownerSignature = ownerPrivateKey.sign(transaction.serializeMessage());
+    transaction.addSignature(ownerPrivateKey.publicKey().toAddress(), ownerSignature);
 
-    return signedTx;
+    /// Serialize the transaction.
+    final serializedTransaction = transaction.serializeString();
+
+    return serializedTransaction;
   }
 
   Future<String> sendTransaction({
-    required SignedTx signedTransaction,
+    required String serializedTransaction,
     required Commitment commitment,
   }) async {
     try {
-      final signature = await _client!.rpcClient.sendTransaction(
-        signedTransaction.encode(),
-        preflightCommitment: commitment,
+      /// Send the transaction to the Solana network.
+      final signature = await _provider!.request(
+        SolanaRPCSendTransaction(
+          encodedTransaction: serializedTransaction,
+          commitment: commitment,
+        ),
       );
-
-      _client!.waitForSignatureStatus(signature, status: commitment);
-
       return signature;
     } catch (e) {
-      printV('Error while sending transaction: ${e.toString()}');
       throw Exception(e);
     }
   }
 
   Future<String?> getIconImageFromTokenUri(String uri) async {
+    if (uri.isEmpty || uri == '…') return null;
+
     try {
       final response = await httpClient.get(Uri.parse(uri));
 
diff --git a/cw_solana/lib/solana_transaction_info.dart b/cw_solana/lib/solana_transaction_info.dart
index 7a0844e52..f51c55dad 100644
--- a/cw_solana/lib/solana_transaction_info.dart
+++ b/cw_solana/lib/solana_transaction_info.dart
@@ -34,7 +34,9 @@ class SolanaTransactionInfo extends TransactionInfo {
   @override
   String amountFormatted() {
     String stringBalance = solAmount.toString();
-    
+    if (stringBalance.toString().length >= 12) {
+      stringBalance = stringBalance.substring(0, 12);
+    }
     return '$stringBalance $tokenSymbol';
   }
 
diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart
index 248f1282b..e6888cf91 100644
--- a/cw_solana/lib/solana_wallet.dart
+++ b/cw_solana/lib/solana_wallet.dart
@@ -30,9 +30,9 @@ import 'package:hex/hex.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:shared_preferences/shared_preferences.dart';
-import 'package:solana/base58.dart';
-import 'package:solana/metaplex.dart' as metaplex;
-import 'package:solana/solana.dart';
+import 'package:on_chain/solana/solana.dart' hide Store;
+import 'package:bip39/bip39.dart' as bip39;
+import 'package:blockchain_utils/blockchain_utils.dart';
 
 part 'solana_wallet.g.dart';
 
@@ -77,14 +77,6 @@ abstract class SolanaWalletBase
   final String? _hexPrivateKey;
   final EncryptionFileUtils encryptionFileUtils;
 
-  // The Solana WalletPair
-  Ed25519HDKeyPair? _walletKeyPair;
-
-  Ed25519HDKeyPair? get walletKeyPair => _walletKeyPair;
-
-  // To access the privateKey bytes.
-  Ed25519HDKeyPairData? _keyPairData;
-
   late final SolanaWalletClient _client;
 
   @observable
@@ -108,29 +100,23 @@ abstract class SolanaWalletBase
   final Completer<SharedPreferences> _sharedPrefs = Completer();
 
   @override
-  Ed25519HDKeyPairData get keys {
-    if (_keyPairData == null) {
-      return Ed25519HDKeyPairData([], publicKey: const Ed25519HDPublicKey([]));
-    }
+  Object get keys => throw UnimplementedError("keys");
 
-    return _keyPairData!;
-  }
+  late final SolanaPrivateKey _solanaPrivateKey;
+
+  late final SolanaPublicKey _solanaPublicKey;
+
+  SolanaPublicKey get solanaPublicKey => _solanaPublicKey;
+
+  SolanaPrivateKey get solanaPrivateKey => _solanaPrivateKey;
+
+  String get solanaAddress => _solanaPublicKey.toAddress().address;
 
   @override
   String? get seed => _mnemonic;
 
   @override
-  String get privateKey {
-    final privateKeyBytes = _keyPairData!.bytes;
-
-    final publicKeyBytes = _keyPairData!.publicKey.bytes;
-
-    final encodedBytes = privateKeyBytes + publicKeyBytes;
-
-    final privateKey = base58encode(encodedBytes);
-
-    return privateKey;
-  }
+  String get privateKey => _solanaPrivateKey.seedHex();
 
   @override
   WalletKeysData get walletKeysData => WalletKeysData(mnemonic: _mnemonic, privateKey: privateKey);
@@ -140,35 +126,47 @@ abstract class SolanaWalletBase
 
     splTokensBox = await CakeHive.openBox<SPLToken>(boxName);
 
-    // Create WalletPair using either the mnemonic or the privateKey
-    _walletKeyPair = await getWalletPair(
+    // Create the privatekey using either the mnemonic or the privateKey
+    _solanaPrivateKey = await getPrivateKey(
       mnemonic: _mnemonic,
       privateKey: _hexPrivateKey,
+      passphrase: passphrase,
     );
 
-    // Extract the keyPairData containing both the privateKey bytes and the publicKey hex.
-    _keyPairData = await _walletKeyPair!.extract();
+    // Extract the public key and wallet address
+    _solanaPublicKey = _solanaPrivateKey.publicKey();
 
-    walletInfo.address = _walletKeyPair!.address;
+    walletInfo.address = _solanaPublicKey.toAddress().address;
 
     await walletAddresses.init();
     await transactionHistory.init();
     await save();
   }
 
-  Future<Wallet> getWalletPair({String? mnemonic, String? privateKey}) async {
+  Future<SolanaPrivateKey> getPrivateKey({
+    String? mnemonic,
+    String? privateKey,
+    String? passphrase,
+  }) async {
     assert(mnemonic != null || privateKey != null);
 
     if (mnemonic != null) {
-      return Wallet.fromMnemonic(mnemonic, account: 0, change: 0);
+      final seed = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? '');
+
+      // Derive a Solana private key from the seed
+      final bip44 = Bip44.fromSeed(seed, Bip44Coins.solana);
+
+      final childKey = bip44.deriveDefaultPath.change(Bip44Changes.chainExt);
+
+      return SolanaPrivateKey.fromSeed(childKey.privateKey.raw);
     }
 
     try {
-      final privateKeyBytes = base58decode(privateKey!);
-      return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes.take(32).toList());
+      final keypairBytes = Base58Decoder.decode(privateKey!);
+      return SolanaPrivateKey.fromSeed(keypairBytes);
     } catch (_) {
       final privateKeyBytes = HEX.decode(privateKey!);
-      return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes);
+      return SolanaPrivateKey.fromBytes(privateKeyBytes);
     }
   }
 
@@ -206,7 +204,8 @@ abstract class SolanaWalletBase
 
   Future<void> _getEstimatedFees() async {
     try {
-      estimatedFee = await _client.getEstimatedFee(_walletKeyPair!);
+      estimatedFee = await _client.getEstimatedFee(_solanaPublicKey, Commitment.confirmed);
+      printV(estimatedFee.toString());
     } catch (e) {
       estimatedFee = 0.0;
     }
@@ -274,7 +273,7 @@ abstract class SolanaWalletBase
       tokenMint: tokenMint,
       tokenTitle: transactionCurrency.title,
       inputAmount: totalAmount,
-      ownerKeypair: _walletKeyPair!,
+      ownerPrivateKey: _solanaPrivateKey,
       tokenDecimals: transactionCurrency.decimals,
       destinationAddress: solCredentials.outputs.first.isParsedAddress
           ? solCredentials.outputs.first.extractedAddress!
@@ -291,9 +290,7 @@ abstract class SolanaWalletBase
 
   /// Fetches the native SOL transactions linked to the wallet Public Key
   Future<void> _updateNativeSOLTransactions() async {
-    final address = Ed25519HDPublicKey.fromBase58(_walletKeyPair!.address);
-
-    final transactions = await _client.fetchTransactions(address);
+    final transactions = await _client.fetchTransactions(_solanaPublicKey.toAddress());
 
     await _addTransactionsToTransactionHistory(transactions);
   }
@@ -308,10 +305,10 @@ abstract class SolanaWalletBase
     for (var token in tokenKeys) {
       if (token is SPLToken) {
         final tokenTxs = await _client.getSPLTokenTransfers(
-          token.mintAddress,
-          token.symbol,
-          token.decimal,
-          _walletKeyPair!,
+          mintAddress: token.mintAddress,
+          splTokenSymbol: token.symbol,
+          splTokenDecimal: token.decimal,
+          privateKey: _solanaPrivateKey,
         );
 
         // splTokenTransactions.addAll(tokenTxs);
@@ -387,6 +384,7 @@ abstract class SolanaWalletBase
         'mnemonic': _mnemonic,
         'private_key': _hexPrivateKey,
         'balance': balance[currency]!.toJSON(),
+        'passphrase': passphrase,
       });
 
   static Future<SolanaWallet> open({
@@ -414,8 +412,9 @@ abstract class SolanaWalletBase
     if (!hasKeysFile) {
       final mnemonic = data!['mnemonic'] as String?;
       final privateKey = data['private_key'] as String?;
+      final passphrase = data['passphrase'] as String?;
 
-      keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
+      keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase);
     } else {
       keysData = await WalletKeysFile.readKeysFile(
         name,
@@ -428,6 +427,7 @@ abstract class SolanaWalletBase
     return SolanaWallet(
       walletInfo: walletInfo,
       password: password,
+      passphrase: keysData.passphrase,
       mnemonic: keysData.mnemonic,
       privateKey: keysData.privateKey,
       initialBalance: balance,
@@ -442,7 +442,7 @@ abstract class SolanaWalletBase
   }
 
   Future<SolanaBalance> _fetchSOLBalance() async {
-    final balance = await _client.getBalance(_walletKeyPair!.address);
+    final balance = await _client.getBalance(solanaAddress);
 
     return SolanaBalance(balance);
   }
@@ -451,10 +451,9 @@ abstract class SolanaWalletBase
     for (var token in splTokensBox.values) {
       if (token.enabled) {
         try {
-          final tokenBalance =
-              await _client.getSplTokenBalance(token.mintAddress, _walletKeyPair!.address) ??
-                  balance[token] ??
-                  SolanaBalance(0.0);
+          final tokenBalance = await _client.getSplTokenBalance(token.mintAddress, solanaAddress) ??
+              balance[token] ??
+              SolanaBalance(0.0);
           balance[token] = tokenBalance;
         } catch (e) {
           printV('Error fetching spl token (${token.symbol}) balance ${e.toString()}');
@@ -482,10 +481,9 @@ abstract class SolanaWalletBase
     await splTokensBox.put(token.mintAddress, token);
 
     if (token.enabled) {
-      final tokenBalance =
-          await _client.getSplTokenBalance(token.mintAddress, _walletKeyPair!.address) ??
-              balance[token] ??
-              SolanaBalance(0.0);
+      final tokenBalance = await _client.getSplTokenBalance(token.mintAddress, solanaAddress) ??
+          balance[token] ??
+          SolanaBalance(0.0);
 
       balance[token] = tokenBalance;
     } else {
@@ -507,37 +505,10 @@ abstract class SolanaWalletBase
   }
 
   Future<SPLToken?> getSPLToken(String mintAddress) async {
-    // Convert SPL token mint address to public key
-    final Ed25519HDPublicKey mintPublicKey;
     try {
-      mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress);
-    } catch (_) {
-      return null;
-    }
-
-    // Fetch token's metadata account
-    try {
-      final token = await solanaClient!.rpcClient.getMetadata(mint: mintPublicKey);
-
-      if (token == null) {
-        return null;
-      }
-
-      String? iconPath;
-      try {
-        iconPath = await _client.getIconImageFromTokenUri(token.uri);
-      } catch (_) {}
-
-      String filteredTokenSymbol = token.symbol.replaceFirst(RegExp('^\\\$'), '');
-
-      return SPLToken.fromMetadata(
-        name: token.name,
-        mint: token.mint,
-        symbol: filteredTokenSymbol,
-        mintAddress: mintAddress,
-        iconPath: iconPath,
-      );
-    } catch (e) {
+      return await _client.fetchSPLTokenInfo(mintAddress);
+    } catch (e, s) {
+      printV('Error fetching token: ${e.toString()}, ${s.toString()}');
       return null;
     }
   }
@@ -582,7 +553,7 @@ abstract class SolanaWalletBase
     final messageBytes = utf8.encode(message);
 
     // Sign the message bytes with the wallet's private key
-    final signature = (await _walletKeyPair!.sign(messageBytes)).toString();
+    final signature = (_solanaPrivateKey.sign(messageBytes)).toString();
 
     return HEX.encode(utf8.encode(signature)).toUpperCase();
   }
@@ -596,7 +567,7 @@ abstract class SolanaWalletBase
       final base58EncodedPublicKeyString = match.group(2)!;
       final sigBytes = bytesString.split(', ').map(int.parse).toList();
 
-      List<int> pubKeyBytes = base58decode(base58EncodedPublicKeyString);
+      List<int> pubKeyBytes = SolAddrDecoder().decodeAddr(base58EncodedPublicKeyString);
 
       return [sigBytes, pubKeyBytes];
     } else {
@@ -619,19 +590,18 @@ abstract class SolanaWalletBase
     }
 
     // make sure the address derived from the public key provided matches the one we expect
-    final pub = Ed25519HDPublicKey(pubKeyBytes);
-    if (address != pub.toBase58()) {
+    final pub = SolanaPublicKey.fromBytes(pubKeyBytes);
+    if (address != pub.toAddress().address) {
       return false;
     }
 
-    return await verifySignature(
+    return pub.verify(
       message: messageBytes,
       signature: sigBytes,
-      publicKey: Ed25519HDPublicKey(pubKeyBytes),
     );
   }
 
-  SolanaClient? get solanaClient => _client.getSolanaClient;
+  SolanaRPC? get solanaProvider => _client.getSolanaProvider;
 
   @override
   String get password => _password;
diff --git a/cw_solana/lib/solana_wallet_service.dart b/cw_solana/lib/solana_wallet_service.dart
index aff75373e..a33cebb3a 100644
--- a/cw_solana/lib/solana_wallet_service.dart
+++ b/cw_solana/lib/solana_wallet_service.dart
@@ -33,6 +33,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
       walletInfo: credentials.walletInfo!,
       mnemonic: mnemonic,
       password: credentials.password!,
+      passphrase: credentials.passphrase,
       encryptionFileUtils: encryptionFileUtilsFor(isDirect),
     );
 
@@ -118,6 +119,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
       password: credentials.password!,
       mnemonic: credentials.mnemonic,
       walletInfo: credentials.walletInfo!,
+      passphrase: credentials.passphrase,
       encryptionFileUtils: encryptionFileUtilsFor(isDirect),
     );
 
diff --git a/cw_solana/lib/spl_token.dart b/cw_solana/lib/spl_token.dart
index a40eb0b86..97538a706 100644
--- a/cw_solana/lib/spl_token.dart
+++ b/cw_solana/lib/spl_token.dart
@@ -1,7 +1,6 @@
 import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/hive_type_ids.dart';
 import 'package:hive/hive.dart';
-import 'package:solana/metaplex.dart';
 
 part 'spl_token.g.dart';
 
@@ -55,7 +54,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
     required String mint,
     required String symbol,
     required String mintAddress,
-    String? iconPath
+    String? iconPath,
   }) {
     return SPLToken(
       name: name,
@@ -117,31 +116,3 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
   @override
   int get hashCode => mintAddress.hashCode;
 }
-
-class NFT extends SPLToken {
-  final ImageInfo? imageInfo;
-
-  NFT(
-    String mint,
-    String name,
-    String symbol,
-    String mintAddress,
-    int decimal,
-    String iconPath,
-    this.imageInfo,
-  ) : super(
-          name: name,
-          symbol: symbol,
-          mintAddress: mintAddress,
-          decimal: decimal,
-          mint: mint,
-          iconPath: iconPath,
-        );
-}
-
-class ImageInfo {
-  final String uri;
-  final OffChainMetadata? data;
-
-  const ImageInfo(this.uri, this.data);
-}
diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml
index 807acdca8..82b5a2bc0 100644
--- a/cw_solana/pubspec.yaml
+++ b/cw_solana/pubspec.yaml
@@ -11,7 +11,6 @@ environment:
 dependencies:
   flutter:
     sdk: flutter
-  solana: ^0.31.0+1
   cw_core:
     path: ../cw_core
   http: ^1.1.0
@@ -21,6 +20,14 @@ dependencies:
   shared_preferences: ^2.0.15
   bip32: ^2.0.0
   hex: ^0.2.0
+  on_chain:
+    git:
+      url: https://github.com/cake-tech/on_chain.git
+      ref: cake-update-v2
+  blockchain_utils:
+    git:
+      url: https://github.com/cake-tech/blockchain_utils
+      ref: cake-update-v2
 
 dev_dependencies:
   flutter_test:
diff --git a/cw_tron/pubspec.yaml b/cw_tron/pubspec.yaml
index e69fd7ca0..80ea7ee51 100644
--- a/cw_tron/pubspec.yaml
+++ b/cw_tron/pubspec.yaml
@@ -17,7 +17,7 @@ dependencies:
     path: ../cw_evm
   on_chain:
     git:
-      url: https://github.com/cake-tech/On_chain
+      url: https://github.com/cake-tech/on_chain.git
       ref: cake-update-v2
   blockchain_utils:
     git:
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 120194ee0..5f8a14daa 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -3,38 +3,8 @@ PODS:
     - Flutter
     - ReachabilitySwift
   - CryptoSwift (1.8.3)
-  - cw_haven (0.0.1):
-    - cw_haven/Boost (= 0.0.1)
-    - cw_haven/Haven (= 0.0.1)
-    - cw_haven/OpenSSL (= 0.0.1)
-    - cw_haven/Sodium (= 0.0.1)
-    - cw_shared_external
-    - Flutter
-  - cw_haven/Boost (0.0.1):
-    - cw_shared_external
-    - Flutter
-  - cw_haven/Haven (0.0.1):
-    - cw_shared_external
-    - Flutter
-  - cw_haven/OpenSSL (0.0.1):
-    - cw_shared_external
-    - Flutter
-  - cw_haven/Sodium (0.0.1):
-    - cw_shared_external
-    - Flutter
   - cw_mweb (0.0.1):
     - Flutter
-  - cw_shared_external (0.0.1):
-    - cw_shared_external/Boost (= 0.0.1)
-    - cw_shared_external/OpenSSL (= 0.0.1)
-    - cw_shared_external/Sodium (= 0.0.1)
-    - Flutter
-  - cw_shared_external/Boost (0.0.1):
-    - Flutter
-  - cw_shared_external/OpenSSL (0.0.1):
-    - Flutter
-  - cw_shared_external/Sodium (0.0.1):
-    - Flutter
   - device_display_brightness (0.0.1):
     - Flutter
   - device_info_plus (0.0.1):
@@ -136,9 +106,7 @@ PODS:
 DEPENDENCIES:
   - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
   - CryptoSwift
-  - cw_haven (from `.symlinks/plugins/cw_haven/ios`)
   - cw_mweb (from `.symlinks/plugins/cw_mweb/ios`)
-  - cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
   - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
   - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
   - devicelocale (from `.symlinks/plugins/devicelocale/ios`)
@@ -179,12 +147,8 @@ SPEC REPOS:
 EXTERNAL SOURCES:
   connectivity_plus:
     :path: ".symlinks/plugins/connectivity_plus/ios"
-  cw_haven:
-    :path: ".symlinks/plugins/cw_haven/ios"
   cw_mweb:
     :path: ".symlinks/plugins/cw_mweb/ios"
-  cw_shared_external:
-    :path: ".symlinks/plugins/cw_shared_external/ios"
   device_display_brightness:
     :path: ".symlinks/plugins/device_display_brightness/ios"
   device_info_plus:
@@ -239,9 +203,7 @@ EXTERNAL SOURCES:
 SPEC CHECKSUMS:
   connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
   CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
-  cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
   cw_mweb: 22cd01dfb8ad2d39b15332006f22046aaa8352a3
-  cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
   device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
   device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
   devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926
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
index d7fe53c73..ca4017b98 100644
--- a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart
+++ b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart
@@ -1,5 +1,7 @@
+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';
@@ -8,9 +10,9 @@ import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_w
 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:solana/base58.dart';
-import 'package:solana/solana.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';
@@ -27,25 +29,19 @@ class SolanaChainServiceImpl implements ChainService {
 
   final SolanaChainId reference;
 
-  final SolanaClient solanaClient;
+  final SolanaRPC solanaProvider;
 
-  final Ed25519HDKeyPair? ownerKeyPair;
+  final SolanaPrivateKey? ownerPrivateKey;
 
   SolanaChainServiceImpl({
     required this.reference,
     required this.wcKeyService,
     required this.bottomSheetService,
     required this.wallet,
-    required this.ownerKeyPair,
-    required String webSocketUrl,
-    required Uri rpcUrl,
-    SolanaClient? solanaClient,
-  }) : solanaClient = solanaClient ??
-            SolanaClient(
-              rpcUrl: rpcUrl,
-              websocketUrl: Uri.parse(webSocketUrl),
-              timeout: const Duration(minutes: 5),
-            ) {
+    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);
     }
@@ -110,26 +106,20 @@ class SolanaChainServiceImpl implements ChainService {
     }
 
     try {
-      final message =
-          await solanaClient.rpcClient.getMessageFromEncodedTx(solanaSignTx.transaction);
+      // Convert transaction string to bytes
+      List<int> transactionBytes = base64Decode(solanaSignTx.transaction);
 
-      final sign = await ownerKeyPair?.signMessage(
-        message: message,
-        recentBlockhash: solanaSignTx.recentBlockhash ?? '',
+      final message = SolanaTransactionUtils.deserializeMessageLegacy(transactionBytes);
+
+      final sign = ownerPrivateKey!.sign(message.serialize());
+
+      final signature = solanaProvider.request(
+        SolanaRPCSendTransaction(
+          encodedTransaction: Base58Encoder.encode(sign),
+          commitment: Commitment.confirmed,
+        ),
       );
 
-      if (sign == null) {
-        return '';
-      }
-
-      String signature = await solanaClient.sendAndConfirmTransaction(
-        message: message,
-        signers: [ownerKeyPair!],
-        commitment: Commitment.confirmed,
-      );
-
-      printV(signature);
-
       bottomSheetService.queueBottomSheet(
         isModalDismissible: true,
         widget: BottomSheetMessageDisplayWidget(
@@ -161,10 +151,10 @@ class SolanaChainServiceImpl implements ChainService {
     if (authError != null) {
       return authError;
     }
-    Signature? sign;
+    List<int>? sign;
 
     try {
-      sign = await ownerKeyPair?.sign(base58decode(solanaSignMessage.message));
+      sign = ownerPrivateKey!.sign(Base58Decoder.decode(solanaSignMessage.message));
     } catch (e) {
       printV(e);
     }
@@ -173,7 +163,7 @@ class SolanaChainServiceImpl implements ChainService {
       return '';
     }
 
-    String signature = sign.toBase58();
+    final signature = Base58Encoder.encode(sign);
 
     return signature;
   }
diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart
index 3740d3dfe..898433c62 100644
--- a/lib/core/wallet_connect/web3wallet_service.dart
+++ b/lib/core/wallet_connect/web3wallet_service.dart
@@ -22,6 +22,7 @@ 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';
 
@@ -140,29 +141,28 @@ abstract class Web3WalletServiceBase with Store {
       for (final cId in SolanaChainId.values) {
         final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type);
 
-        Uri rpcUri = node.uri;
-        String webSocketUrl = 'wss://${node.uriRaw}';
+        String formattedUrl;
+        String protocolUsed = node.isSSL ? "https" : "http";
 
         if (node.uriRaw == 'rpc.ankr.com') {
           String ankrApiKey = secrets.ankrApiKey;
 
-          rpcUri = Uri.https(node.uriRaw, '/solana/$ankrApiKey');
-          webSocketUrl = 'wss://${node.uriRaw}/solana/ws/$ankrApiKey';
+          formattedUrl = '$protocolUsed://${node.uriRaw}/$ankrApiKey';
         } else if (node.uriRaw == 'solana-mainnet.core.chainstack.com') {
           String chainStackApiKey = secrets.chainStackApiKey;
 
-          rpcUri = Uri.https(node.uriRaw, '/$chainStackApiKey');
-          webSocketUrl = 'wss://${node.uriRaw}/$chainStackApiKey';
+          formattedUrl = '$protocolUsed://${node.uriRaw}/$chainStackApiKey';
+        } else {
+          formattedUrl = '$protocolUsed://${node.uriRaw}';
         }
 
         SolanaChainServiceImpl(
           reference: cId,
-          rpcUrl: rpcUri,
-          webSocketUrl: webSocketUrl,
+          formattedRPCUrl: formattedUrl,
           wcKeyService: walletKeyService,
           bottomSheetService: _bottomSheetHandler,
           wallet: _web3Wallet,
-          ownerKeyPair: solana!.getWalletKeyPair(appStore.wallet!),
+          ownerPrivateKey: SolanaPrivateKey.fromSeedHex(solana!.getPrivateKey(appStore.wallet!)),
         );
       }
     }
diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart
index f0df5fba1..937b5b3bf 100644
--- a/lib/solana/cw_solana.dart
+++ b/lib/solana/cw_solana.dart
@@ -52,11 +52,8 @@ class CWSolana extends Solana {
   String getPrivateKey(WalletBase wallet) => (wallet as SolanaWallet).privateKey;
 
   @override
-  String getPublicKey(WalletBase wallet) => (wallet as SolanaWallet).keys.publicKey.toBase58();
-
-  @override
-  Ed25519HDKeyPair? getWalletKeyPair(WalletBase wallet) => (wallet as SolanaWallet).walletKeyPair;
-
+  String getPublicKey(WalletBase wallet) =>
+      (wallet as SolanaWallet).solanaPublicKey.toAddress().address;
   Object createSolanaTransactionCredentials(
     List<Output> outputs, {
     required CryptoCurrency currency,
diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart
index ab6762f8d..be1972106 100644
--- a/lib/src/screens/wallet_keys/wallet_keys_page.dart
+++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart
@@ -326,7 +326,7 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
       ),
     );
   }
-
+  
   Widget _buildBottomActionPanel({
     required String titleForClipboard,
     required String dataToCopy,
diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart
index 14d7ad566..3959afe01 100644
--- a/lib/view_model/advanced_privacy_settings_view_model.dart
+++ b/lib/view_model/advanced_privacy_settings_view_model.dart
@@ -78,6 +78,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
         WalletType.ethereum,
         WalletType.polygon,
         WalletType.tron,
+        WalletType.solana,
         WalletType.monero,
         WalletType.wownero,
         WalletType.zano,
diff --git a/pubspec_base.yaml b/pubspec_base.yaml
index 72c17a079..767f0b1f3 100644
--- a/pubspec_base.yaml
+++ b/pubspec_base.yaml
@@ -106,12 +106,19 @@ dependencies:
   flutter_svg: ^2.0.9
   polyseed: ^0.0.6
   nostr_tools: ^1.0.9
-  solana: ^0.31.0+1
   ledger_flutter_plus:
     git:
       url: https://github.com/vespr-wallet/ledger-flutter-plus
       ref: c2e341d8038f1108690ad6f80f7b4b7156aacc76
   hashlib: ^1.19.2
+  on_chain:
+    git:
+      url: https://github.com/cake-tech/on_chain.git
+      ref: cake-update-v2
+  blockchain_utils:
+    git:
+      url: https://github.com/cake-tech/blockchain_utils
+      ref: cake-update-v2
 
 dev_dependencies:
   flutter_test:
diff --git a/tool/configure.dart b/tool/configure.dart
index c26e3f44b..259a5d9a0 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -1261,7 +1261,6 @@ import 'package:cw_core/wallet_credentials.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_service.dart';
 import 'package:hive/hive.dart';
-import 'package:solana/solana.dart';
 
 """;
   const solanaCWHeaders = """
@@ -1289,7 +1288,6 @@ abstract class Solana {
   String getAddress(WalletBase wallet);
   String getPrivateKey(WalletBase wallet);
   String getPublicKey(WalletBase wallet);
-  Ed25519HDKeyPair? getWalletKeyPair(WalletBase wallet);
 
   Object createSolanaTransactionCredentials(
     List<Output> outputs, {