Skip to content

Commit

Permalink
e2e test
Browse files Browse the repository at this point in the history
  • Loading branch information
wjthieme committed Nov 16, 2024
1 parent f78f475 commit cb41ea7
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 63 deletions.
14 changes: 13 additions & 1 deletion rust-sdk/whirlpool/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use solana_client::{
rpc_filter::{Memcmp, RpcFilterType},
};
use solana_program::pubkey::Pubkey;
use solana_sdk::program_pack::Pack;
use solana_sdk::{program_pack::Pack, rent::Rent};
use spl_token_2022::state::Account;
use std::error::Error;

Expand Down Expand Up @@ -53,3 +53,15 @@ pub(crate) fn get_token_accounts_for_owner(
}
Ok(decoded_accounts)
}

#[cfg(not(test))]
pub(crate) fn get_rent() -> Result<Rent, Box<dyn Error>> {
use solana_sdk::sysvar::Sysvar;
let rent = Rent::get()?;
Ok(rent)
}

#[cfg(test)]
pub(crate) fn get_rent() -> Result<Rent, Box<dyn Error>> {
Ok(Rent::default())
}
5 changes: 2 additions & 3 deletions rust-sdk/whirlpool/src/create_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ use solana_program::sysvar::SysvarId;
use solana_program::{instruction::Instruction, pubkey::Pubkey};
use solana_sdk::signature::Keypair;
use solana_sdk::signer::Signer;
use solana_sdk::sysvar::{Sysvar};
use spl_token::solana_program::program_pack::Pack;
use spl_token_2022::state::{Account, Mint};

use crate::token::order_mints;
use crate::{FUNDER, SPLASH_POOL_TICK_SPACING, WHIRLPOOLS_CONFIG_ADDRESS};
use crate::{get_rent, FUNDER, SPLASH_POOL_TICK_SPACING, WHIRLPOOLS_CONFIG_ADDRESS};

/// Represents the instructions and metadata for creating a pool.
pub struct CreatePoolInstructions {
Expand Down Expand Up @@ -76,7 +75,7 @@ pub fn create_concentrated_liquidity_pool_instructions(
return Err("Token order needs to be flipped to match the canonical ordering (i.e. sorted on the byte repr. of the mint pubkeys)".into());
}

let rent = Rent::get()?;
let rent = get_rent()?;

let account_infos = rpc.get_multiple_accounts(&[token_a, token_b])?;
let mint_a_info = account_infos[0]
Expand Down
10 changes: 5 additions & 5 deletions rust-sdk/whirlpool/src/decrease_liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub fn decrease_liquidity_instructions(
let slippage_tolerance_bps =
slippage_tolerance_bps.unwrap_or(*SLIPPAGE_TOLERANCE_BPS.try_lock()?);
let authority = authority.unwrap_or(*FUNDER.try_lock()?);
if authority != Pubkey::default() {
if authority == Pubkey::default() {
return Err("Authority must be provided".into());
}

Expand Down Expand Up @@ -199,7 +199,7 @@ pub fn close_position_instructions(
let slippage_tolerance_bps =
slippage_tolerance_bps.unwrap_or(*SLIPPAGE_TOLERANCE_BPS.try_lock()?);
let authority = authority.unwrap_or(*FUNDER.try_lock()?);
if authority != Pubkey::default() {
if authority == Pubkey::default() {
return Err("Authority must be provided".into());
}

Expand Down Expand Up @@ -233,11 +233,11 @@ pub fn close_position_instructions(
.reward_infos
.iter()
.enumerate()
.flat_map(|(i, x)| {
.map(|(i, x)| {
if x.mint == Pubkey::default() {
None
} else {
Some(mint_infos[i + 3].clone())
mint_infos[i + 3].clone()
}
})
.collect();
Expand Down Expand Up @@ -437,7 +437,7 @@ pub fn close_position_instructions(
);
}

match position_info.owner {
match position_mint_info.owner {
spl_token::ID => {
instructions.push(
ClosePosition {
Expand Down
218 changes: 200 additions & 18 deletions rust-sdk/whirlpool/src/e2e.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::error::Error;

use lazy_static::lazy_static;
use orca_whirlpools_client::{Position, Whirlpool};
use orca_whirlpools_client::{get_position_address, Position, Whirlpool};
use solana_sdk::{program_pack::Pack, pubkey::Pubkey};
use spl_token_2022::state::Account;

use crate::{
create_concentrated_liquidity_pool_instructions, create_splash_pool_instructions, open_full_range_position_instructions, tests::{send_transaction_with_signers, setup_ata_with_amount, setup_mint_with_decimals, RPC}, IncreaseLiquidityParam, SPLASH_POOL_TICK_SPACING
close_position_instructions, create_concentrated_liquidity_pool_instructions, create_splash_pool_instructions, decrease_liquidity_instructions, harvest_position_instructions, increase_liquidity_instructions, open_full_range_position_instructions, position, swap_instructions, tests::{send_transaction_with_signers, setup_ata_with_amount, setup_mint_with_decimals, RPC}, DecreaseLiquidityParam, IncreaseLiquidityParam, SwapQuote, SwapType, SPLASH_POOL_TICK_SPACING
};

lazy_static! {
Expand Down Expand Up @@ -58,7 +58,8 @@ fn open_position(pool: Pubkey) -> Result<Pubkey, Box<dyn Error>> {

send_transaction_with_signers(position.instructions, position.additional_signers.iter().collect())?;

let infos_after = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B, position.position_mint])?;
let position_address = get_position_address(&position.position_mint)?.0;
let infos_after = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B, position_address])?;
let token_a_after = Account::unpack(&infos_after[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&infos_after[1].as_ref().unwrap().data)?;
let position_after = Position::from_bytes(&infos_after[2].as_ref().unwrap().data)?;
Expand All @@ -76,62 +77,243 @@ fn open_position(pool: Pubkey) -> Result<Pubkey, Box<dyn Error>> {
Ok(position.position_mint)
}

fn increase_liquidity(position: Pubkey) -> Result<(), Box<dyn Error>> {
fn increase_liquidity(position_mint: Pubkey) -> Result<(), Box<dyn Error>> {
let position_address = get_position_address(&position_mint)?.0;
let infos_before = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B, position_address])?;
let token_a_before = Account::unpack(&infos_before[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&infos_before[1].as_ref().unwrap().data)?;
let position_before = Position::from_bytes(&infos_before[2].as_ref().unwrap().data)?;

let increase_liquidity = increase_liquidity_instructions(&RPC, position_mint, IncreaseLiquidityParam::Liquidity(1000000000), None, None)?;
send_transaction_with_signers(increase_liquidity.instructions, increase_liquidity.additional_signers.iter().collect())?;

let infos_after = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B, position_address])?;
let token_a_after = Account::unpack(&infos_after[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&infos_after[1].as_ref().unwrap().data)?;
let position_after = Position::from_bytes(&infos_after[2].as_ref().unwrap().data)?;

assert_eq!(position_after.liquidity - position_before.liquidity, increase_liquidity.quote.liquidity_delta);
assert_eq!(
token_a_before.amount - token_a_after.amount,
increase_liquidity.quote.token_est_a,
);
assert_eq!(
token_b_before.amount - token_b_after.amount,
increase_liquidity.quote.token_est_b,
);
Ok(())
}

fn decrease_liquidity(position: Pubkey) -> Result<(), Box<dyn Error>> {
fn decrease_liquidity(position_mint: Pubkey) -> Result<(), Box<dyn Error>> {
let position_address = get_position_address(&position_mint)?.0;
let infos_before = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B, position_address])?;
let token_a_before = Account::unpack(&infos_before[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&infos_before[1].as_ref().unwrap().data)?;
let position_before = Position::from_bytes(&infos_before[2].as_ref().unwrap().data)?;

let decrease_liquidity = decrease_liquidity_instructions(&RPC, position_mint, DecreaseLiquidityParam::Liquidity(10000), None, None)?;
send_transaction_with_signers(decrease_liquidity.instructions, decrease_liquidity.additional_signers.iter().collect())?;

let infos_after = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B, position_address])?;
let token_a_after = Account::unpack(&infos_after[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&infos_after[1].as_ref().unwrap().data)?;
let position_after = Position::from_bytes(&infos_after[2].as_ref().unwrap().data)?;

assert_eq!(position_before.liquidity - position_after.liquidity, decrease_liquidity.quote.liquidity_delta);
assert_eq!(
token_a_after.amount - token_a_before.amount,
decrease_liquidity.quote.token_est_a,
);
assert_eq!(
token_b_after.amount - token_b_before.amount,
decrease_liquidity.quote.token_est_b,
);
Ok(())
}

fn harvest_position(position: Pubkey) -> Result<(), Box<dyn Error>> {
Ok(())
fn harvest_position(position_mint: Pubkey) -> Result<(), Box<dyn Error>> {
let before_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_before = Account::unpack(&before_infos[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&before_infos[1].as_ref().unwrap().data)?;

let harvest_position = harvest_position_instructions(&RPC, position_mint, None)?;
send_transaction_with_signers(harvest_position.instructions, harvest_position.additional_signers.iter().collect())?;

let after_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_after = Account::unpack(&after_infos[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&after_infos[1].as_ref().unwrap().data)?;

assert_eq!(
token_a_after.amount - token_a_before.amount,
harvest_position.fees_quote.fee_owed_a,
);
assert_eq!(
token_b_after.amount - token_b_before.amount,
harvest_position.fees_quote.fee_owed_b,
);
Ok(())
}

fn close_position(position: Pubkey) -> Result<(), Box<dyn Error>> {
fn close_position(position_mint: Pubkey) -> Result<(), Box<dyn Error>> {
let before_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_before = Account::unpack(&before_infos[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&before_infos[1].as_ref().unwrap().data)?;

let close_position = close_position_instructions(&RPC, position_mint, None, None)?;
send_transaction_with_signers(close_position.instructions, close_position.additional_signers.iter().collect())?;

let position_address = get_position_address(&position_mint)?.0;
let after_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B, position_address])?;
let token_a_after = Account::unpack(&after_infos[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&after_infos[1].as_ref().unwrap().data)?;

assert_eq!(after_infos[2].is_none(), true);
assert_eq!(
token_a_after.amount - token_a_before.amount,
close_position.quote.token_est_a + close_position.fees_quote.fee_owed_a,
);
assert_eq!(
token_b_after.amount - token_b_before.amount,
close_position.quote.token_est_b + close_position.fees_quote.fee_owed_b,
);
Ok(())
}

fn swap_a_exact_in(pool: Pubkey) -> Result<(), Box<dyn Error>> {
let before_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_before = Account::unpack(&before_infos[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&before_infos[1].as_ref().unwrap().data)?;

let swap = swap_instructions(&RPC, pool, 100000, *MINT_A, SwapType::ExactIn, None, None)?;
send_transaction_with_signers(swap.instructions, swap.additional_signers.iter().collect())?;

let after_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_after = Account::unpack(&after_infos[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&after_infos[1].as_ref().unwrap().data)?;

if let SwapQuote::ExactIn(quote) = swap.quote {
assert_eq!(
token_a_before.amount - token_a_after.amount,
quote.token_in,
);
assert_eq!(
token_b_after.amount - token_b_before.amount,
quote.token_est_out,
);
} else {
return Err("Swap quote is not ExactIn".into());
}

Ok(())
}

fn swap_a_exact_out(pool: Pubkey) -> Result<(), Box<dyn Error>> {
let before_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_before = Account::unpack(&before_infos[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&before_infos[1].as_ref().unwrap().data)?;

let swap = swap_instructions(&RPC, pool, 100000, *MINT_A, SwapType::ExactOut, None, None)?;
send_transaction_with_signers(swap.instructions, swap.additional_signers.iter().collect())?;

let after_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_after = Account::unpack(&after_infos[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&after_infos[1].as_ref().unwrap().data)?;

if let SwapQuote::ExactOut(quote) = swap.quote {
assert_eq!(
token_a_after.amount - token_a_before.amount,
quote.token_out,
);
assert_eq!(
token_b_before.amount - token_b_after.amount,
quote.token_est_in,
);
} else {
return Err("Swap quote is not ExactOut".into());
}

Ok(())
}

fn swap_b_exact_in(pool: Pubkey) -> Result<(), Box<dyn Error>> {
let before_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_before = Account::unpack(&before_infos[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&before_infos[1].as_ref().unwrap().data)?;

let swap = swap_instructions(&RPC, pool, 100, *MINT_B, SwapType::ExactIn, None, None)?;
send_transaction_with_signers(swap.instructions, swap.additional_signers.iter().collect())?;

let after_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_after = Account::unpack(&after_infos[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&after_infos[1].as_ref().unwrap().data)?;

if let SwapQuote::ExactIn(quote) = swap.quote {
assert_eq!(
token_a_after.amount - token_a_before.amount,
quote.token_est_out,
);
assert_eq!(
token_b_before.amount - token_b_after.amount,
quote.token_in,
);
} else {
return Err("Swap quote is not ExactIn".into());
}

Ok(())
}

fn swap_b_exact_out(pool: Pubkey) -> Result<(), Box<dyn Error>> {
let before_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_before = Account::unpack(&before_infos[0].as_ref().unwrap().data)?;
let token_b_before = Account::unpack(&before_infos[1].as_ref().unwrap().data)?;

let swap = swap_instructions(&RPC, pool, 100, *MINT_B, SwapType::ExactOut, None, None)?;
send_transaction_with_signers(swap.instructions, swap.additional_signers.iter().collect())?;

let after_infos = RPC.get_multiple_accounts(&[*ATA_A, *ATA_B])?;
let token_a_after = Account::unpack(&after_infos[0].as_ref().unwrap().data)?;
let token_b_after = Account::unpack(&after_infos[1].as_ref().unwrap().data)?;

if let SwapQuote::ExactOut(quote) = swap.quote {
assert_eq!(
token_a_before.amount - token_a_after.amount,
quote.token_est_in,
);
assert_eq!(
token_b_after.amount - token_b_before.amount,
quote.token_out,
);
} else {
return Err("Swap quote is not ExactOut".into());
}
Ok(())
}

#[test]
fn test_splash_pool() {
let pool = init_splash_pool().unwrap();
let position = open_position(pool).unwrap();
let position_mint = open_position(pool).unwrap();
swap_a_exact_in(pool).unwrap();
increase_liquidity(position).unwrap();
increase_liquidity(position_mint).unwrap();
swap_a_exact_out(pool).unwrap();
harvest_position(position).unwrap();
harvest_position(position_mint).unwrap();
swap_b_exact_in(pool).unwrap();
decrease_liquidity(position).unwrap();
decrease_liquidity(position_mint).unwrap();
swap_b_exact_out(pool).unwrap();
close_position(position).unwrap();
close_position(position_mint).unwrap();
}

#[test]
fn test_concentrated_liquidity_pool() {
let pool = init_concentrated_liquidity_pool().unwrap();
let position = open_position(pool).unwrap();
let position_mint = open_position(pool).unwrap();
swap_a_exact_in(pool).unwrap();
increase_liquidity(position).unwrap();
increase_liquidity(position_mint).unwrap();
swap_a_exact_out(pool).unwrap();
harvest_position(position).unwrap();
harvest_position(position_mint).unwrap();
swap_b_exact_in(pool).unwrap();
decrease_liquidity(position).unwrap();
decrease_liquidity(position_mint).unwrap();
swap_b_exact_out(pool).unwrap();
close_position(position).unwrap();
close_position(position_mint).unwrap();
}
Loading

0 comments on commit cb41ea7

Please sign in to comment.