feat: Integrate Jupiter DEX (#2761)

* feat: Integrate Jupiter DEX

* feat: Enable internal swaps

* feat: implement Jupiter swap execution api and enhance trade handling

- Added executeSwap method to handle signed swap transactions via the execute endpoint.
- Updated signAndPrepareJupiterSwapTransaction to include request ID and handle swap execution response.
- Modified trade details to use txId instead of id for Jupiter trades.
- Enhanced error handling for swap execution with user-friendly messages.
- Updated sendviewmodel to manage trade state updates after transaction commitment.

* fix: null error after successfully swapping

* fix: Finallyyy fixed the annoying tx history issue for solana dex swaps

* fix: update inputAddress to use toAddress in JupiterExchangeProvider

* feat: enhance transaction handling and token balance updates

- Cut down tx fetch/update time for transactions update after swapping
- Added TransactionFetchResult class to hold parsed transactions and token mints.
- Added pollForTransaction method to handle transaction polling with exponential backoff.
- Conditionally hide the external send button based on provider type.

* feat: add fees to trade object and handle null case

* feat: add Jupiter referral fee and account configuration

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
David Adegoke
2026-01-16 23:28:36 +01:00
committed by GitHub
co-authored by Omar Hatem
parent 368777514e
commit cf795bcc48
16 changed files with 1509 additions and 67 deletions
+53 -1
View File
@@ -904,15 +904,16 @@ Future<void> generateSolana(bool hasImplementation) async {
final outputFile = File(solanaOutputPath);
const solanaCommonHeaders = """
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cake_wallet/exchange/provider/jupiter_exchange_provider.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/output_info.dart';
import 'package:cw_core/pending_transaction.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/spl_token.dart';
import 'package:hive/hive.dart';
""";
const solanaCWHeaders = """
@@ -920,9 +921,14 @@ import 'package:cw_solana/solana_wallet.dart';
import 'package:cw_solana/solana_mnemonics.dart';
import 'package:cw_solana/solana_wallet_service.dart';
import 'package:cw_solana/solana_transaction_info.dart';
import 'package:cw_solana/pending_solana_transaction.dart';
import 'package:cw_solana/solana_transaction_credentials.dart';
import 'package:cw_solana/solana_wallet_creation_credentials.dart';
import 'package:cw_solana/default_spl_tokens.dart';
import 'dart:convert';
import 'dart:typed_data';
import 'package:on_chain/solana/solana.dart' hide Store;
""";
const solanaCwPart = "part 'cw_solana.dart';";
const solanaContent = """
@@ -965,6 +971,52 @@ abstract class Solana {
double? getEstimateFees(WalletBase wallet);
List<String> getDefaultTokenContractAddresses();
bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
// Jupiter swap transaction handling
// Signs and prepares a base64-encoded unsigned transaction for sending
Future<PendingTransaction> signAndPrepareJupiterSwapTransaction(
WalletBase wallet,
String base64Transaction,
String requestId,
String destinationAddress,
double amount,
double fee,
);
// Fast transaction update after sending
// Polls for a specific transaction by signature with exponential backoff
// Falls back to full refresh if transaction is not found after max retries
Future<void> pollForTransaction(
WalletBase wallet,
String signature, {
Duration initialDelay = const Duration(seconds: 1),
int maxRetries = 5,
});
// Updates balances for specific tokens by mint addresses
// Also updates native SOL balance
// If tokenMints is null or empty, updates all tokens (full refresh)
Future<void> updateTokenBalances(
WalletBase wallet, {
List<String>? tokenMints,
});
}
class JupiterSwapFailedException implements Exception {
final String message;
final String signature;
final num? errorCode;
final String? errorMessage;
JupiterSwapFailedException({
required this.message,
required this.signature,
this.errorCode,
this.errorMessage,
});
@override
String toString() => message;
}
""";
+3
View File
@@ -85,6 +85,9 @@ class SecretKey {
SecretKey('kryptonimApiKey', () => ''),
SecretKey('walletGroupSalt', () => hex.encode(encrypt.Key.fromSecureRandom(16).bytes)),
SecretKey('swapsXyzApiKey', () => ''),
SecretKey('jupiterApiKey', () => ''),
SecretKey('jupiterReferralFeeBps', () => ''),
SecretKey('jupiterReferralAccount', () => ''),
SecretKey('nearIntentsBearerToken', () => ''),
SecretKey('nearIntentsAppFee', () => ''),
SecretKey('nearIntentsAppFeeRecipient', () => ''),