1mod error;
2mod jup_ag;
3pub use {error::Error, jup_ag::*};
4use {solana_pubkey::Pubkey, solana_sdk::instruction::Instruction};
5pub type Result<T> = std::result::Result<T, Error>;
6
7#[derive(Clone)]
8pub struct JupiterInstructor {
9 owner: Pubkey,
10}
11
12impl JupiterInstructor {
13 pub fn new(owner: &Pubkey) -> Self {
14 Self { owner: *owner }
15 }
16
17 pub async fn swap(
19 &self,
20 from: &Pubkey,
21 to: &Pubkey,
22 amount: u64,
23 quote: QuoteConfig,
24 wrap_and_unwrap_sol: bool,
25 ) -> Result<(Vec<Instruction>, Vec<Pubkey>)> {
26 let quotes = jup_ag::quote(*from, *to, amount, quote).await?;
27 let mut request: SwapRequest = SwapRequest::new(self.owner, quotes);
28 request.wrap_and_unwrap_sol = Some(wrap_and_unwrap_sol);
29 let mut swap_instructions = jup_ag::swap_instructions(request).await?;
30
31 let mut instructions = Vec::with_capacity(
32 swap_instructions.compute_budget_instructions.len()
33 + swap_instructions.setup_instructions.len()
34 + 6,
35 );
36 instructions.append(&mut swap_instructions.compute_budget_instructions);
37 instructions.append(&mut swap_instructions.setup_instructions);
38 if let Some(i) = swap_instructions.token_ledger_instruction.take() {
39 instructions.push(i);
40 }
41 instructions.push(swap_instructions.swap_instruction);
42 if let Some(cleanup) = swap_instructions.cleanup_instruction.take() {
43 instructions.push(cleanup);
44 }
45 Ok((
46 instructions,
47 swap_instructions.address_lookup_table_addresses,
48 ))
49 }
50}
51
52#[cfg(test)]
53mod test {
54 use {
55 crate::{jup_ag::QuoteConfig, JupiterInstructor},
56 solana_pubkey::Pubkey,
57 solana_sdk::native_token::sol_to_lamports,
58 spl_token::native_mint::id,
59 std::str::FromStr,
60 test_utils::setup,
61 };
62
63 #[tokio::test]
64 async fn swap_wsol() -> anyhow::Result<()> {
65 setup();
66 let usdc = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")?;
67 let jup = JupiterInstructor::new(&test_utils::OWNER);
68 let quote = QuoteConfig {
69 slippage_bps: Some(1),
70 ..Default::default()
71 };
72 let (instructions, lookups) = jup
73 .swap(&id(), &usdc, sol_to_lamports(1.0), quote, true)
74 .await?;
75 assert!(!instructions.is_empty());
76 assert!(!lookups.is_empty());
77 Ok(())
78 }
79
80 #[tokio::test]
81 async fn swap_sol() -> anyhow::Result<()> {
82 setup();
83 let usdc = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")?;
84 let jup = JupiterInstructor::new(&test_utils::OWNER);
85 let quote = QuoteConfig {
86 slippage_bps: Some(1),
87 ..Default::default()
88 };
89 let (instructions, lookups) = jup
90 .swap(&id(), &usdc, sol_to_lamports(1.0), quote, false)
91 .await?;
92 assert!(!instructions.is_empty());
93 assert!(!lookups.is_empty());
94 Ok(())
95 }
96}