Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] INF pool #1

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
487 changes: 476 additions & 11 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ solana-program-test = "~1.16"
tokio = { version = "1", features = ["full"] }

anchor-gen = { git = "https://github.com/jup-ag/anchor-gen.git", rev = "26c04a10d20509f360ab176d003bea4c625b16f2" }
jupiter-amm-interface = "~0.3.2"
jupiter-amm-interface = { git = "https://github.com/jup-ag/jupiter-amm-interface.git", branch = "feat/sanctum-s" }

# SPL
spl-token = { version = "3.5", features = ["no-entrypoint"] }
Expand All @@ -25,4 +25,4 @@ spl-associated-token-account = { version = "2.1.0", features = [
] }
spl-token-2022 = { git = "https://github.com/solana-labs/solana-program-library.git", rev = "79a575fb7af56d26deeda94fef8f55bde7a90df3", features = [
"no-entrypoint",
] }
] }
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ Add your amm to `test_exact_in_amms` and run the tests `cargo test`...
## Jupiter AMM Interface

Most importantly, the [Jupiter AMM Interface](https://docs.rs/crate/jupiter-amm-interface) is the main crate this integration depends on and must be used to be compatible with Jupiter. Do check it out.

## S Infinity Pool Notes

- Also had to clone the stake pool program accounts into `jupiter-core/tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/` for the calculator programs to work correctly since they need to read the program and program data accounts. To be resolved by allowing `Amm` trait to read account data subslice. Use `./fetch-stake-pool-prog-accounts.sh` in `jupiter-core/`
6 changes: 5 additions & 1 deletion jupiter-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ solana-sdk = { workspace = true }
solana-client = { workspace = true }
solana-account-decoder = { workspace = true }
solana-program-test = "~1.16"
solana-rpc-client-api = "^1"
spl-token-swap = { version = "3.0.0", features = ["no-entrypoint"] }
serde_json = "1.0.82"
anyhow = "1.0"
serde = "1.0.140"
serde = "^1.0.197"
lazy_static = "1.2.0"
rust_decimal = "1.26.1"
jupiter-amm-interface = { workspace = true }
Expand All @@ -33,3 +34,6 @@ spl-associated-token-account = { workspace = true, features = [
"no-entrypoint",
] }
spl-token-2022 = { workspace = true, features = ["no-entrypoint"] }

# sanctum S
s-jup-interface = { git = "https://github.com/igneous-labs/S.git", branch = "fix/jup-integration" }
17 changes: 17 additions & 0 deletions jupiter-core/fetch-stake-pool-prog-accounts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/sh

# SPL
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy.json --output json SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/EmiU8AQkB2sswTxVB6aCmsAJftoowZGGDXuytm6X65R3.json --output json EmiU8AQkB2sswTxVB6aCmsAJftoowZGGDXuytm6X65R3
# Sanctum SPL
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY.json --output json SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/Cn5fegqLh8Fmvffisr4Wk3LmuaUgMMzTFfEuidpZFsvV.json --output json Cn5fegqLh8Fmvffisr4Wk3LmuaUgMMzTFfEuidpZFsvV
# Sanctum SPL Multi
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn.json --output json SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/HxBTMuB7cFBPVWVJjTi9iBF8MPd7mfY1QnrrWfLAySFd.json --output json HxBTMuB7cFBPVWVJjTi9iBF8MPd7mfY1QnrrWfLAySFd
# Marinade
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD.json --output json MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/4PQH9YmfuKrVyZaibkLYpJZPv2FPaybhq2GAuBcWMSBf.json --output json 4PQH9YmfuKrVyZaibkLYpJZPv2FPaybhq2GAuBcWMSBf
# Lido
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/CrX7kMhLC3cSsXJdT7JDgqrRVWGnUpX3gfEfxxU2NVLi.json --output json CrX7kMhLC3cSsXJdT7JDgqrRVWGnUpX3gfEfxxU2NVLi
solana account -o tests/fixtures/accounts/Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS/CHZNLhDXKrsXBmmv947RFciquwBsn2NdABmhpxoX3wgZ.json --output json CHZNLhDXKrsXBmmv947RFciquwBsn2NdABmhpxoX3wgZ
5 changes: 5 additions & 0 deletions jupiter-core/src/amms/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::collections::HashSet;

use anyhow::{anyhow, Result};
use jupiter_amm_interface::{Amm, KeyedAccount};
use s_jup_interface::SPool;
use solana_sdk::pubkey::Pubkey;

use super::spl_token_swap_amm::{SplTokenSwapAmm, SPL_TOKEN_SWAP_PROGRAMS};
Expand All @@ -17,6 +18,10 @@ pub fn amm_factory(
Ok(Box::new(SplTokenSwapAmm::from_keyed_account(
keyed_account,
)?))
} else if keyed_account.account.owner
== solana_sdk::pubkey!("5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx")
{
Ok(Box::new(SPool::from_keyed_account(keyed_account)?))
} else {
Err(anyhow!(
"Unsupported pool {}, from owner {}",
Expand Down
97 changes: 81 additions & 16 deletions jupiter-core/src/amms/test_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use solana_sdk::{
use spl_associated_token_account::get_associated_token_address_with_program_id;
use spl_token_2022::extension::StateWithExtensions;
// use stakedex_sdk::test_utils::spl_stake_pool;
use std::fs::remove_dir_all;
use std::hint::black_box;
use std::str::FromStr;
use std::time::Instant;
Expand All @@ -33,6 +32,7 @@ use std::{
io::Write,
path::Path,
};
use std::{fs::remove_dir_all, num::NonZeroUsize};

use crate::{
build_swap_transaction::{
Expand All @@ -41,6 +41,7 @@ use crate::{
},
constants,
route::get_token_mints_permutations,
solana_rpc_utils::ExtendedSolanaRpcClient,
};
use jupiter::find_jupiter_open_orders;
use jupiter_amm_interface::{
Expand All @@ -51,18 +52,74 @@ use solana_sdk::pubkey;

use super::loader::amm_factory;

const BONKSOL_MINT: Pubkey = pubkey!("BonK1YhkXEGLZzwtcvRTip3gAL9nCeQD7ppZBLXhtTs");
const JUICYSOL_MINT: Pubkey = pubkey!("jucy5XJ76pHVvtPZb5TKRcGQExkwit2P5s4vY8UzmpC");
const STRONGSOL_MINT: Pubkey = pubkey!("strng7mqqc1MBJJV6vMzYbEqnwVGvKKGKedeCvtktWA");
const STSOL_MINT: Pubkey = pubkey!("7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj");
const STAKESOL_MINT: Pubkey = pubkey!("st8QujHLPsX3d6HG9uQg9kJ91jFxUgruwsb1hyYXSNd");
const LANTERNSOL_MINT: Pubkey = pubkey!("LnTRntk2kTfWEY6cVB8K9649pgJbt6dJLS1Ns1GZCWg");
const EDGESOL_MINT: Pubkey = pubkey!("edge86g9cVz87xcpKpy3J77vbp4wYd9idEV562CCntt");
const CLOCKSOL_MINT: Pubkey = pubkey!("GRJQtWwdJmp5LLpy8JWjPgn5FnLyqSJGNhn5ZnCTFUwM");
const MSOL_MINT: Pubkey = pubkey!("mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So");
const DSOL_MINT: Pubkey = pubkey!("Dso1bDeDjCQxTrWHqUUi63oBvV7Mdm6WaobLbQ7gnPQ");
const LAINESOL_MINT: Pubkey = pubkey!("LAinEtNLgpmCP9Rvsf5Hn8W6EhNiKLZQti1xfWMLy6X");
const JUPSOL_MINT: Pubkey = pubkey!("jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v");
const HUBSOL_MINT: Pubkey = pubkey!("HUBsveNpjo5pWqNkH57QzxjQASdTVXcSK7bVKTSZtcSX");
const SUPERFASTSOL_MINT: Pubkey = pubkey!("suPer8CPwxoJPQ7zksGMwFvjBQhjAHwUMmPV4FVatBw");
const VAULTSOL_MINT: Pubkey = pubkey!("vSoLxydx6akxyMD9XEcPvGYNGq6Nn66oqVb3UkGkei7");
const BSOL_MINT: Pubkey = pubkey!("bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1");
const CGNTSOL_MINT: Pubkey = pubkey!("CgnTSoL3DgY9SFHxcLj6CgCgKKoTBr6tp4CPAEWy25DE");
const COMPASSSOL_MINT: Pubkey = pubkey!("Comp4ssDzXcLeu2MnLuGNNFC4cmLPMng8qWHPvzAMU1h");
const PWRSOL_MINT: Pubkey = pubkey!("pWrSoLAhue6jUxUkbWgmEy5rD9VJzkFmvfTDV5KgNuu");
const LST_MINT: Pubkey = pubkey!("LSTxxxnJzKDFSLr4dUkPcmCf5VyryEqzPLz5j4bpxFp");
const DAOSOL_MINT: Pubkey = pubkey!("GEJpt3Wjmr628FqXxTgxMce1pLntcPV4uFi8ksxMyPQh");
const JSOL_MINT: Pubkey = pubkey!("7Q2afV64in6N6SeZsAAB81TJzwDoD6zpqmHkzi9Dcavn");
const PICOSOL_MINT: Pubkey = pubkey!("picobAEvs6w7QEknPce34wAE4gknZA9v5tTonnmHYdX");
const ZIPPYSOL_MINT: Pubkey = pubkey!("Zippybh3S5xYYam2nvL6hVJKz1got6ShgV4DyD1XQYF");
const INF_MINT: Pubkey = pubkey!("5oVNBeEEQvYi1cX3ir8Dx5n1P7pdxydbGF2X4TxVusJm");
const JITOSOL_MINT: Pubkey = pubkey!("J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn");

// 0.1 SOL, JSOL has smol liquidity of <1 SOL
const SWAP_AMOUNT: u64 = 100_000_000;

lazy_static! {
pub static ref TOKEN_MINT_AND_IN_AMOUNT: [(Pubkey, u64); 5] = [
(spl_token::native_mint::ID, 25_000_000_000),
(JITOSOL_MINT, 8_000_000_000),
(
pubkey!("bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1"),
100_000_000_000
),
(constants::USDC_MINT, 1_110_000_000),
(constants::USDT_MINT, 1_110_000_000),
pub static ref TOKEN_MINT_AND_IN_AMOUNT: [(Pubkey, u64); 27] = [
(spl_token::native_mint::ID, SWAP_AMOUNT),
(BONKSOL_MINT, SWAP_AMOUNT),
(JUICYSOL_MINT, SWAP_AMOUNT),
(STRONGSOL_MINT, SWAP_AMOUNT),
(STSOL_MINT, SWAP_AMOUNT),
(STAKESOL_MINT, SWAP_AMOUNT),
(LANTERNSOL_MINT, SWAP_AMOUNT),
(EDGESOL_MINT, SWAP_AMOUNT),
(CLOCKSOL_MINT, SWAP_AMOUNT),
(MSOL_MINT, SWAP_AMOUNT),
(DSOL_MINT, SWAP_AMOUNT),
(LAINESOL_MINT, SWAP_AMOUNT),
(JUPSOL_MINT, SWAP_AMOUNT),
(HUBSOL_MINT, SWAP_AMOUNT),
(SUPERFASTSOL_MINT, SWAP_AMOUNT),
(VAULTSOL_MINT, SWAP_AMOUNT),
(BSOL_MINT, SWAP_AMOUNT),
(CGNTSOL_MINT, SWAP_AMOUNT),
(COMPASSSOL_MINT, SWAP_AMOUNT),
(PWRSOL_MINT, SWAP_AMOUNT),
(LST_MINT, SWAP_AMOUNT),
(DAOSOL_MINT, SWAP_AMOUNT),
(JSOL_MINT, SWAP_AMOUNT),
(PICOSOL_MINT, SWAP_AMOUNT),
(ZIPPYSOL_MINT, SWAP_AMOUNT),
(INF_MINT, SWAP_AMOUNT),
(JITOSOL_MINT, SWAP_AMOUNT),
];
pub static ref RESTRICTED_TOKEN_MINTS: [Pubkey; 7] = [
spl_token::native_mint::ID,
COMPASSSOL_MINT,
MSOL_MINT,
JUPSOL_MINT,
LAINESOL_MINT,
INF_MINT,
STSOL_MINT,
];
pub static ref TOKEN2022_MINT_AND_IN_AMOUNT: [(Pubkey, u64); 0] = [];
pub static ref TOKEN_MINT_TO_IN_AMOUNT: HashMap<Pubkey, u64> = {
Expand Down Expand Up @@ -256,6 +313,7 @@ impl AmmTestHarnessProgramTest {
in_amount: amount,
out_amount: amount,
jupiter_program_id: &jupiter::ID,
missing_dynamic_accounts_as_default: false,
};
let SwapAndAccountMetas {
swap,
Expand Down Expand Up @@ -652,8 +710,14 @@ impl AmmTestHarness {
}

pub fn update_amm(&self, amm: &mut dyn Amm) {
let accounts_to_update = amm.get_accounts_to_update();

let mut accounts_to_update = amm.get_accounts_to_update();
accounts_to_update.sort();
accounts_to_update.dedup();
eprintln!(
"{} accounts to update: {}",
amm.label(),
accounts_to_update.len()
);
let account_map = self
.client
.get_multiple_accounts(&accounts_to_update)
Expand Down Expand Up @@ -737,9 +801,9 @@ impl AmmTestHarness {
if address == &sysvar::clock::ID {
clock = Some(bincode::deserialize::<Clock>(&account.data).unwrap());
}
if !account.executable {
pt.add_account(*address, account.clone());
}
//if !account.executable {
pt.add_account(*address, account.clone());
//}
}

for _ in 0..3 {
Expand Down Expand Up @@ -828,6 +892,7 @@ impl AmmTestHarness {
.get(&source_mint)
.unwrap_or_else(|| panic!("No in amount for mint: {}", destination_mint)),
jupiter_program_id: &placeholder,
missing_dynamic_accounts_as_default: false,
})?;

addresses_for_snapshot.extend(
Expand Down Expand Up @@ -858,7 +923,7 @@ impl AmmTestHarness {

let addresses = addresses_for_snapshot.into_iter().collect::<Vec<_>>();
self.client
.get_multiple_accounts(&addresses)
.get_multiple_accounts_chunked(&addresses, NonZeroUsize::new(100).unwrap())
.unwrap()
.iter()
.zip(addresses)
Expand Down
1 change: 1 addition & 0 deletions jupiter-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod amms;
mod math;
mod solana_rpc_utils;

pub mod build_swap_transaction;
pub mod config;
Expand Down
30 changes: 30 additions & 0 deletions jupiter-core/src/solana_rpc_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use std::num::NonZeroUsize;

use itertools::Itertools;
use solana_client::rpc_client::RpcClient;
use solana_rpc_client_api::client_error::Error as ClientError;
use solana_sdk::{account::Account, pubkey::Pubkey};

pub trait ExtendedSolanaRpcClient {
fn get_multiple_accounts_chunked(
&self,
accounts: &[Pubkey],
chunk_size: NonZeroUsize,
) -> Result<Vec<Option<Account>>, ClientError>;
}

impl ExtendedSolanaRpcClient for RpcClient {
fn get_multiple_accounts_chunked(
&self,
accounts: &[Pubkey],
chunk_size: NonZeroUsize,
) -> Result<Vec<Option<Account>>, ClientError> {
let chunk_size = chunk_size.get();
accounts
.chunks(chunk_size)
.into_iter()
.map(|pk_chunk| self.get_multiple_accounts(pk_chunk))
.flatten_ok()
.collect()
}
}
Binary file not shown.
Binary file modified jupiter-core/tests/fixtures/jupiter.so
100755 → 100644
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/lido.so
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/lido_calculator.so
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/marinade.so
Binary file not shown.
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/s_controller.so
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/sanctum_infinity.so
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/socean_migration.so
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/spl_calculator.so
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/spl_stake_pool.so
Binary file not shown.
Binary file added jupiter-core/tests/fixtures/wsol_calculator.so
Binary file not shown.
45 changes: 34 additions & 11 deletions jupiter-core/tests/test_amms.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
use std::collections::HashMap;

use anyhow::Error;
use itertools::Itertools;
use jupiter_amm_interface::{KeyedAccount, SwapMode};
#[cfg(target_arch = "x86_64")]
use jupiter_core::amms::openbook_v2_amm::OpenBookV2Amm;
use jupiter_core::test_harness::RESTRICTED_TOKEN_MINTS;
use jupiter_core::{
amm::Amm,
amms::{spl_token_swap_amm::SplTokenSwapAmm, test_harness::AmmTestHarness},
route::get_token_mints_permutations,
amm::Amm, amms::test_harness::AmmTestHarness, route::get_token_mints_permutations,
test_harness::AmmTestSwapParams,
};
use s_jup_interface::SPool;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::{account::Account, pubkey};

fn reserve_token_mint_permutations() -> Vec<(Pubkey, Pubkey)> {
RESTRICTED_TOKEN_MINTS
.into_iter()
.permutations(2)
.map(|p| (p[0], p[1]))
.collect()
}

/// Loads AMM from snapshot and tests quoting
async fn test_quoting_for_amm_key<T: Amm + 'static>(
amm_key: Pubkey,
Expand Down Expand Up @@ -62,7 +69,16 @@ macro_rules! test_exact_in_amms {
_ => Some($option.to_string()),
};
let before_test_setup: Option<fn(&dyn Amm, &mut HashMap<Pubkey, Account>)> = None;
test_quoting_for_amm_key::<$amm_struct>($amm_key, SwapMode::ExactIn, false, $tolerance, option, before_test_setup, None, None).await
test_quoting_for_amm_key::<$amm_struct>(
$amm_key,
SwapMode::ExactIn,
false,
$tolerance,
option,
before_test_setup,
None,
Some(reserve_token_mint_permutations())
).await
}
#[tokio::test]
async fn [<test_quote_ $amm_key:lower _ $option:lower _ with_shared_accounts>] () {
Expand All @@ -71,7 +87,16 @@ macro_rules! test_exact_in_amms {
_ => Some($option.to_string()),
};
let before_test_setup: Option<fn(&dyn Amm, &mut HashMap<Pubkey, Account>)> = None;
test_quoting_for_amm_key::<$amm_struct>($amm_key, SwapMode::ExactIn, true, $tolerance, option, before_test_setup, None, None).await
test_quoting_for_amm_key::<$amm_struct>(
$amm_key,
SwapMode::ExactIn,
true,
$tolerance,
option,
before_test_setup,
None,
Some(reserve_token_mint_permutations())
).await
}
}
)*
Expand Down Expand Up @@ -104,14 +129,12 @@ macro_rules! test_exact_out_amms {
};
}

const ORCA_V2_SOL_USDC_POOL: Pubkey = pubkey!("EGZ7tiLeH62TPV1gL8WwbXGzEPa9zmcpVnnkPKKnrE2U");
const ORCA_V2_USDC_USDT_POOL: Pubkey = pubkey!("F13xvvx45jVGd84ynK3c8T89UejQVxjCLtmHfPmAXAHP");
const INF_AMM_KEY: Pubkey = pubkey!("Gb7m4daakbVbrFLR33FKMDVMHAprRZ66CSYt4bpFwUgS");

// You can run a single test by doing: `cargo test test_quote_<lower_case_constant>_<default | option_name> -- --nocapture`

test_exact_in_amms! {
(ORCA_V2_SOL_USDC_POOL, SplTokenSwapAmm, 0),
(ORCA_V2_USDC_USDT_POOL, SplTokenSwapAmm, 0),
(INF_AMM_KEY, SPool<Account, Account>, 0),
}

async fn test_quoting_with_amm(
Expand Down