Skip to main content

monedero_jup_ag/
lib.rs

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    /// See https://station.jup.ag/docs/old/apis/swap-api#instructions-instead-of-transaction
18    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}