lssa/programs/amm/src/tests.rs
jonesmarvin8 1035893fd9 fix lint
2026-03-17 19:09:25 -04:00

3175 lines
111 KiB
Rust

use std::num::NonZero;
use amm_core::{
PoolDefinition, compute_liquidity_token_pda, compute_liquidity_token_pda_seed,
compute_pool_pda, compute_vault_pda, compute_vault_pda_seed,
};
#[cfg(feature = "nssa")]
use nssa::{
PrivateKey, PublicKey, PublicTransaction, V02State, program::Program, public_transaction,
};
use nssa_core::{
account::{Account, AccountId, AccountWithMetadata, Data},
program::{ChainedCall, ProgramId},
};
use token_core::{TokenDefinition, TokenHolding};
use crate::{
add::add_liquidity, new_definition::new_definition, remove::remove_liquidity, swap::swap,
};
const TOKEN_PROGRAM_ID: ProgramId = [15; 8];
const AMM_PROGRAM_ID: ProgramId = [42; 8];
struct BalanceForTests;
struct ChainedCallForTests;
struct IdForTests;
struct AccountWithMetadataForTests;
#[cfg(feature = "nssa")]
struct PrivateKeysForTests;
#[cfg(feature = "nssa")]
struct IdForExeTests;
#[cfg(feature = "nssa")]
struct BalanceForExeTests;
#[cfg(feature = "nssa")]
struct AccountsForExeTests;
#[cfg(feature = "nssa")]
impl PrivateKeysForTests {
fn user_token_a_key() -> PrivateKey {
PrivateKey::try_new([31; 32]).expect("Keys constructor expects valid private key")
}
fn user_token_b_key() -> PrivateKey {
PrivateKey::try_new([32; 32]).expect("Keys constructor expects valid private key")
}
fn user_token_lp_key() -> PrivateKey {
PrivateKey::try_new([33; 32]).expect("Keys constructor expects valid private key")
}
}
impl BalanceForTests {
fn vault_a_reserve_init() -> u128 {
1_000
}
fn vault_b_reserve_init() -> u128 {
500
}
fn vault_a_reserve_low() -> u128 {
10
}
fn vault_b_reserve_low() -> u128 {
10
}
fn vault_a_reserve_high() -> u128 {
500_000
}
fn vault_b_reserve_high() -> u128 {
500_000
}
fn user_token_a_balance() -> u128 {
1_000
}
fn user_token_b_balance() -> u128 {
500
}
fn user_token_lp_balance() -> u128 {
100
}
fn remove_min_amount_a() -> u128 {
50
}
fn remove_min_amount_b() -> u128 {
100
}
fn remove_actual_a_successful() -> u128 {
141
}
fn remove_min_amount_b_low() -> u128 {
50
}
fn remove_amount_lp() -> u128 {
100
}
fn remove_amount_lp_1() -> u128 {
30
}
fn add_max_amount_a() -> u128 {
500
}
fn add_max_amount_b() -> u128 {
200
}
fn add_max_amount_a_low() -> u128 {
10
}
fn add_max_amount_b_low() -> u128 {
10
}
fn add_min_amount_lp() -> u128 {
20
}
fn lp_supply_init() -> u128 {
// sqrt(vault_a_reserve_init * vault_b_reserve_init) = sqrt(1000 * 500) = 707
(Self::vault_a_reserve_init() * Self::vault_b_reserve_init()).isqrt()
}
fn vault_a_swap_test_1() -> u128 {
1_500
}
fn vault_a_swap_test_2() -> u128 {
715
}
fn vault_b_swap_test_1() -> u128 {
334
}
fn vault_b_swap_test_2() -> u128 {
700
}
fn min_amount_out() -> u128 {
200
}
fn vault_a_add_successful() -> u128 {
1_400
}
fn vault_b_add_successful() -> u128 {
700
}
fn add_successful_amount_a() -> u128 {
400
}
fn add_successful_amount_b() -> u128 {
200
}
fn vault_a_remove_successful() -> u128 {
859
}
fn vault_b_remove_successful() -> u128 {
430
}
}
impl ChainedCallForTests {
fn cc_swap_token_a_test_1() -> ChainedCall {
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::vault_a_init(),
],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::add_max_amount_a(),
},
)
}
fn cc_swap_token_b_test_1() -> ChainedCall {
let swap_amount: u128 = 166;
let mut vault_b_auth = AccountWithMetadataForTests::vault_b_init();
vault_b_auth.is_authorized = true;
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![vault_b_auth, AccountWithMetadataForTests::user_holding_b()],
&token_core::Instruction::Transfer {
amount_to_transfer: swap_amount,
},
)
.with_pda_seeds(vec![compute_vault_pda_seed(
IdForTests::pool_definition_id(),
IdForTests::token_b_definition_id(),
)])
}
fn cc_swap_token_a_test_2() -> ChainedCall {
let swap_amount: u128 = 285;
let mut vault_a_auth = AccountWithMetadataForTests::vault_a_init();
vault_a_auth.is_authorized = true;
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![vault_a_auth, AccountWithMetadataForTests::user_holding_a()],
&token_core::Instruction::Transfer {
amount_to_transfer: swap_amount,
},
)
.with_pda_seeds(vec![compute_vault_pda_seed(
IdForTests::pool_definition_id(),
IdForTests::token_a_definition_id(),
)])
}
fn cc_swap_token_b_test_2() -> ChainedCall {
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::vault_b_init(),
],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::add_max_amount_b(),
},
)
}
fn cc_add_token_a() -> ChainedCall {
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::vault_a_init(),
],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::add_successful_amount_a(),
},
)
}
fn cc_add_token_b() -> ChainedCall {
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::vault_b_init(),
],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::add_successful_amount_b(),
},
)
}
fn cc_add_pool_lp() -> ChainedCall {
let mut pool_lp_auth = AccountWithMetadataForTests::pool_lp_init();
pool_lp_auth.is_authorized = true;
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
pool_lp_auth,
AccountWithMetadataForTests::user_holding_lp_init(),
],
&token_core::Instruction::Mint {
amount_to_mint: 282,
},
)
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
IdForTests::pool_definition_id(),
)])
}
fn cc_remove_token_a() -> ChainedCall {
let mut vault_a_auth = AccountWithMetadataForTests::vault_a_init();
vault_a_auth.is_authorized = true;
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![vault_a_auth, AccountWithMetadataForTests::user_holding_a()],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::remove_actual_a_successful(),
},
)
.with_pda_seeds(vec![compute_vault_pda_seed(
IdForTests::pool_definition_id(),
IdForTests::token_a_definition_id(),
)])
}
fn cc_remove_token_b() -> ChainedCall {
let mut vault_b_auth = AccountWithMetadataForTests::vault_b_init();
vault_b_auth.is_authorized = true;
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![vault_b_auth, AccountWithMetadataForTests::user_holding_b()],
&token_core::Instruction::Transfer {
amount_to_transfer: 70,
},
)
.with_pda_seeds(vec![compute_vault_pda_seed(
IdForTests::pool_definition_id(),
IdForTests::token_b_definition_id(),
)])
}
fn cc_remove_pool_lp() -> ChainedCall {
let mut pool_lp_auth = AccountWithMetadataForTests::pool_lp_init();
pool_lp_auth.is_authorized = true;
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
pool_lp_auth,
AccountWithMetadataForTests::user_holding_lp_init(),
],
&token_core::Instruction::Burn {
amount_to_burn: BalanceForTests::remove_amount_lp(),
},
)
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
IdForTests::pool_definition_id(),
)])
}
fn cc_new_definition_token_a() -> ChainedCall {
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::vault_a_init(),
],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::add_successful_amount_a(),
},
)
}
fn cc_new_definition_token_b() -> ChainedCall {
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::vault_b_init(),
],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::add_successful_amount_b(),
},
)
}
fn cc_new_definition_token_lp() -> ChainedCall {
ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
],
&token_core::Instruction::Mint {
amount_to_mint: BalanceForTests::lp_supply_init(),
},
)
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
IdForTests::pool_definition_id(),
)])
}
}
impl IdForTests {
fn token_a_definition_id() -> AccountId {
AccountId::new([42; 32])
}
fn token_b_definition_id() -> AccountId {
AccountId::new([43; 32])
}
fn token_lp_definition_id() -> AccountId {
compute_liquidity_token_pda(AMM_PROGRAM_ID, Self::pool_definition_id())
}
fn user_token_a_id() -> AccountId {
AccountId::new([45; 32])
}
fn user_token_b_id() -> AccountId {
AccountId::new([46; 32])
}
fn user_token_lp_id() -> AccountId {
AccountId::new([47; 32])
}
fn pool_definition_id() -> AccountId {
compute_pool_pda(
AMM_PROGRAM_ID,
Self::token_a_definition_id(),
Self::token_b_definition_id(),
)
}
fn vault_a_id() -> AccountId {
compute_vault_pda(
AMM_PROGRAM_ID,
Self::pool_definition_id(),
Self::token_a_definition_id(),
)
}
fn vault_b_id() -> AccountId {
compute_vault_pda(
AMM_PROGRAM_ID,
Self::pool_definition_id(),
Self::token_b_definition_id(),
)
}
}
impl AccountWithMetadataForTests {
fn user_holding_a() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::user_token_a_balance(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::user_token_a_id(),
}
}
fn user_holding_b() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::user_token_b_balance(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::user_token_b_id(),
}
}
fn vault_a_init() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_reserve_init(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_a_id(),
}
}
fn vault_b_init() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_reserve_init(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_b_id(),
}
}
fn vault_a_init_high() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_reserve_high(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_a_id(),
}
}
fn vault_b_init_high() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_reserve_high(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_b_id(),
}
}
fn vault_a_init_low() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_reserve_low(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_a_id(),
}
}
fn vault_b_init_low() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_reserve_low(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_b_id(),
}
}
fn vault_a_init_zero() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: 0,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_a_id(),
}
}
fn vault_b_init_zero() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: 0,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_b_id(),
}
}
fn pool_lp_init() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForTests::lp_supply_init(),
metadata_id: None,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::token_lp_definition_id(),
}
}
fn pool_lp_with_wrong_id() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForTests::lp_supply_init(),
metadata_id: None,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::vault_a_id(),
}
}
fn user_holding_lp_uninit() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: 0,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::user_token_lp_id(),
}
}
fn user_holding_lp_init() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: BalanceForTests::user_token_lp_balance(),
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::user_token_lp_id(),
}
}
fn pool_definition_init() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_init_reserve_a_zero() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: 0,
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_init_reserve_b_zero() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: 0,
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_init_reserve_a_low() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_low(),
reserve_a: BalanceForTests::vault_a_reserve_low(),
reserve_b: BalanceForTests::vault_b_reserve_high(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_init_reserve_b_low() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_high(),
reserve_a: BalanceForTests::vault_a_reserve_high(),
reserve_b: BalanceForTests::vault_b_reserve_low(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_swap_test_1() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_swap_test_1(),
reserve_b: BalanceForTests::vault_b_swap_test_1(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_swap_test_2() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_swap_test_2(),
reserve_b: BalanceForTests::vault_b_swap_test_2(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_add_zero_lp() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_low(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_add_successful() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: 989,
reserve_a: BalanceForTests::vault_a_add_successful(),
reserve_b: BalanceForTests::vault_b_add_successful(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_remove_successful() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: 607,
reserve_a: BalanceForTests::vault_a_remove_successful(),
reserve_b: BalanceForTests::vault_b_remove_successful(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_inactive() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0_u128,
active: false,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
fn pool_definition_with_wrong_id() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0_u128,
active: false,
}),
nonce: 0,
},
is_authorized: true,
account_id: AccountId::new([4; 32]),
}
}
fn vault_a_with_wrong_id() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_reserve_init(),
}),
nonce: 0,
},
is_authorized: true,
account_id: AccountId::new([4; 32]),
}
}
fn vault_b_with_wrong_id() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: TOKEN_PROGRAM_ID,
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_reserve_init(),
}),
nonce: 0,
},
is_authorized: true,
account_id: AccountId::new([4; 32]),
}
}
fn pool_definition_active() -> AccountWithMetadata {
AccountWithMetadata {
account: Account {
program_owner: ProgramId::default(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForTests::token_a_definition_id(),
definition_token_b_id: IdForTests::token_b_definition_id(),
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0_u128,
active: true,
}),
nonce: 0,
},
is_authorized: true,
account_id: IdForTests::pool_definition_id(),
}
}
}
#[cfg(feature = "nssa")]
impl BalanceForExeTests {
fn user_token_a_holding_init() -> u128 {
10_000
}
fn user_token_b_holding_init() -> u128 {
10_000
}
fn user_token_lp_holding_init() -> u128 {
2_000
}
fn vault_a_balance_init() -> u128 {
5_000
}
fn vault_b_balance_init() -> u128 {
2_500
}
fn pool_lp_supply_init() -> u128 {
5_000
}
fn token_a_supply() -> u128 {
100_000
}
fn token_b_supply() -> u128 {
100_000
}
fn token_lp_supply() -> u128 {
5_000
}
fn remove_lp() -> u128 {
1_000
}
fn remove_min_amount_a() -> u128 {
500
}
fn remove_min_amount_b() -> u128 {
500
}
fn add_min_amount_lp() -> u128 {
1_000
}
fn add_max_amount_a() -> u128 {
2_000
}
fn add_max_amount_b() -> u128 {
1_000
}
fn swap_amount_in() -> u128 {
1_000
}
fn swap_min_amount_out() -> u128 {
200
}
fn vault_a_balance_swap_1() -> u128 {
3_572
}
fn vault_b_balance_swap_1() -> u128 {
3_500
}
fn user_token_a_holding_swap_1() -> u128 {
11_428
}
fn user_token_b_holding_swap_1() -> u128 {
9_000
}
fn vault_a_balance_swap_2() -> u128 {
6_000
}
fn vault_b_balance_swap_2() -> u128 {
2_084
}
fn user_token_a_holding_swap_2() -> u128 {
9_000
}
fn user_token_b_holding_swap_2() -> u128 {
10_416
}
fn vault_a_balance_add() -> u128 {
7_000
}
fn vault_b_balance_add() -> u128 {
3_500
}
fn user_token_a_holding_add() -> u128 {
8_000
}
fn user_token_b_holding_add() -> u128 {
9_000
}
fn user_token_lp_holding_add() -> u128 {
4_000
}
fn token_lp_supply_add() -> u128 {
7_000
}
fn vault_a_balance_remove() -> u128 {
4_000
}
fn vault_b_balance_remove() -> u128 {
2_000
}
fn user_token_a_holding_remove() -> u128 {
11_000
}
fn user_token_b_holding_remove() -> u128 {
10_500
}
fn user_token_lp_holding_remove() -> u128 {
1_000
}
fn token_lp_supply_remove() -> u128 {
4_000
}
fn user_token_a_holding_new_definition() -> u128 {
5_000
}
fn user_token_b_holding_new_definition() -> u128 {
7_500
}
fn lp_supply_init() -> u128 {
// isqrt(vault_a_balance_init * vault_b_balance_init) = isqrt(5_000 * 2_500) = 3535
(Self::vault_a_balance_init() * Self::vault_b_balance_init()).isqrt()
}
}
#[cfg(feature = "nssa")]
impl IdForExeTests {
fn pool_definition_id() -> AccountId {
amm_core::compute_pool_pda(
Program::amm().id(),
Self::token_a_definition_id(),
Self::token_b_definition_id(),
)
}
fn token_lp_definition_id() -> AccountId {
amm_core::compute_liquidity_token_pda(Program::amm().id(), Self::pool_definition_id())
}
fn token_a_definition_id() -> AccountId {
AccountId::new([3; 32])
}
fn token_b_definition_id() -> AccountId {
AccountId::new([4; 32])
}
fn user_token_a_id() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(
&PrivateKeysForTests::user_token_a_key(),
))
}
fn user_token_b_id() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(
&PrivateKeysForTests::user_token_b_key(),
))
}
fn user_token_lp_id() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(
&PrivateKeysForTests::user_token_lp_key(),
))
}
fn vault_a_id() -> AccountId {
amm_core::compute_vault_pda(
Program::amm().id(),
Self::pool_definition_id(),
Self::token_a_definition_id(),
)
}
fn vault_b_id() -> AccountId {
amm_core::compute_vault_pda(
Program::amm().id(),
Self::pool_definition_id(),
Self::token_b_definition_id(),
)
}
}
#[cfg(feature = "nssa")]
impl AccountsForExeTests {
fn user_token_a_holding() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::user_token_a_holding_init(),
}),
nonce: 0,
}
}
fn user_token_b_holding() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::user_token_b_holding_init(),
}),
nonce: 0,
}
}
fn pool_definition_init() -> Account {
Account {
program_owner: Program::amm().id(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForExeTests::token_a_definition_id(),
definition_token_b_id: IdForExeTests::token_b_definition_id(),
vault_a_id: IdForExeTests::vault_a_id(),
vault_b_id: IdForExeTests::vault_b_id(),
liquidity_pool_id: IdForExeTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForExeTests::pool_lp_supply_init(),
reserve_a: BalanceForExeTests::vault_a_balance_init(),
reserve_b: BalanceForExeTests::vault_b_balance_init(),
fees: 0_u128,
active: true,
}),
nonce: 0,
}
}
fn token_a_definition_account() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForExeTests::token_a_supply(),
metadata_id: None,
}),
nonce: 0,
}
}
fn token_b_definition_acc() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForExeTests::token_b_supply(),
metadata_id: None,
}),
nonce: 0,
}
}
fn token_lp_definition_acc() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForExeTests::token_lp_supply(),
metadata_id: None,
}),
nonce: 0,
}
}
fn vault_a_init() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::vault_a_balance_init(),
}),
nonce: 0,
}
}
fn vault_b_init() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::vault_b_balance_init(),
}),
nonce: 0,
}
}
fn user_token_lp_holding() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_lp_definition_id(),
balance: BalanceForExeTests::user_token_lp_holding_init(),
}),
nonce: 0,
}
}
fn vault_a_swap_1() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::vault_a_balance_swap_1(),
}),
nonce: 0,
}
}
fn vault_b_swap_1() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::vault_b_balance_swap_1(),
}),
nonce: 0,
}
}
fn pool_definition_swap_1() -> Account {
Account {
program_owner: Program::amm().id(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForExeTests::token_a_definition_id(),
definition_token_b_id: IdForExeTests::token_b_definition_id(),
vault_a_id: IdForExeTests::vault_a_id(),
vault_b_id: IdForExeTests::vault_b_id(),
liquidity_pool_id: IdForExeTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForExeTests::pool_lp_supply_init(),
reserve_a: BalanceForExeTests::vault_a_balance_swap_1(),
reserve_b: BalanceForExeTests::vault_b_balance_swap_1(),
fees: 0_u128,
active: true,
}),
nonce: 0,
}
}
fn user_token_a_holding_swap_1() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::user_token_a_holding_swap_1(),
}),
nonce: 0,
}
}
fn user_token_b_holding_swap_1() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::user_token_b_holding_swap_1(),
}),
nonce: 1,
}
}
fn vault_a_swap_2() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::vault_a_balance_swap_2(),
}),
nonce: 0,
}
}
fn vault_b_swap_2() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::vault_b_balance_swap_2(),
}),
nonce: 0,
}
}
fn pool_definition_swap_2() -> Account {
Account {
program_owner: Program::amm().id(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForExeTests::token_a_definition_id(),
definition_token_b_id: IdForExeTests::token_b_definition_id(),
vault_a_id: IdForExeTests::vault_a_id(),
vault_b_id: IdForExeTests::vault_b_id(),
liquidity_pool_id: IdForExeTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForExeTests::pool_lp_supply_init(),
reserve_a: BalanceForExeTests::vault_a_balance_swap_2(),
reserve_b: BalanceForExeTests::vault_b_balance_swap_2(),
fees: 0_u128,
active: true,
}),
nonce: 0,
}
}
fn user_token_a_holding_swap_2() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::user_token_a_holding_swap_2(),
}),
nonce: 1,
}
}
fn user_token_b_holding_swap_2() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::user_token_b_holding_swap_2(),
}),
nonce: 0,
}
}
fn vault_a_add() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::vault_a_balance_add(),
}),
nonce: 0,
}
}
fn vault_b_add() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::vault_b_balance_add(),
}),
nonce: 0,
}
}
fn pool_definition_add() -> Account {
Account {
program_owner: Program::amm().id(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForExeTests::token_a_definition_id(),
definition_token_b_id: IdForExeTests::token_b_definition_id(),
vault_a_id: IdForExeTests::vault_a_id(),
vault_b_id: IdForExeTests::vault_b_id(),
liquidity_pool_id: IdForExeTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForExeTests::token_lp_supply_add(),
reserve_a: BalanceForExeTests::vault_a_balance_add(),
reserve_b: BalanceForExeTests::vault_b_balance_add(),
fees: 0_u128,
active: true,
}),
nonce: 0,
}
}
fn user_token_a_holding_add() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::user_token_a_holding_add(),
}),
nonce: 1,
}
}
fn user_token_b_holding_add() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::user_token_b_holding_add(),
}),
nonce: 1,
}
}
fn user_token_lp_holding_add() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_lp_definition_id(),
balance: BalanceForExeTests::user_token_lp_holding_add(),
}),
nonce: 0,
}
}
fn token_lp_definition_add() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForExeTests::token_lp_supply_add(),
metadata_id: None,
}),
nonce: 0,
}
}
fn vault_a_remove() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::vault_a_balance_remove(),
}),
nonce: 0,
}
}
fn vault_b_remove() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::vault_b_balance_remove(),
}),
nonce: 0,
}
}
fn pool_definition_remove() -> Account {
Account {
program_owner: Program::amm().id(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForExeTests::token_a_definition_id(),
definition_token_b_id: IdForExeTests::token_b_definition_id(),
vault_a_id: IdForExeTests::vault_a_id(),
vault_b_id: IdForExeTests::vault_b_id(),
liquidity_pool_id: IdForExeTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForExeTests::token_lp_supply_remove(),
reserve_a: BalanceForExeTests::vault_a_balance_remove(),
reserve_b: BalanceForExeTests::vault_b_balance_remove(),
fees: 0_u128,
active: true,
}),
nonce: 0,
}
}
fn user_token_a_holding_remove() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::user_token_a_holding_remove(),
}),
nonce: 0,
}
}
fn user_token_b_holding_remove() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::user_token_b_holding_remove(),
}),
nonce: 0,
}
}
fn user_token_lp_holding_remove() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_lp_definition_id(),
balance: BalanceForExeTests::user_token_lp_holding_remove(),
}),
nonce: 1,
}
}
fn token_lp_definition_remove() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForExeTests::token_lp_supply_remove(),
metadata_id: None,
}),
nonce: 0,
}
}
fn token_lp_definition_init_inactive() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: 0,
metadata_id: None,
}),
nonce: 0,
}
}
fn vault_a_init_inactive() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: 0,
}),
nonce: 0,
}
}
fn vault_b_init_inactive() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: 0,
}),
nonce: 0,
}
}
fn pool_definition_inactive() -> Account {
Account {
program_owner: Program::amm().id(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForExeTests::token_a_definition_id(),
definition_token_b_id: IdForExeTests::token_b_definition_id(),
vault_a_id: IdForExeTests::vault_a_id(),
vault_b_id: IdForExeTests::vault_b_id(),
liquidity_pool_id: IdForExeTests::token_lp_definition_id(),
liquidity_pool_supply: 0,
reserve_a: 0,
reserve_b: 0,
fees: 0_u128,
active: false,
}),
nonce: 0,
}
}
fn user_token_a_holding_new_init() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_a_definition_id(),
balance: BalanceForExeTests::user_token_a_holding_new_definition(),
}),
nonce: 1,
}
}
fn user_token_b_holding_new_init() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_b_definition_id(),
balance: BalanceForExeTests::user_token_b_holding_new_definition(),
}),
nonce: 1,
}
}
fn user_token_lp_holding_new_init() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_lp_definition_id(),
balance: BalanceForExeTests::lp_supply_init(),
}),
nonce: 0,
}
}
fn token_lp_definition_new_init() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForExeTests::lp_supply_init(),
metadata_id: None,
}),
nonce: 0,
}
}
fn pool_definition_new_init() -> Account {
Account {
program_owner: Program::amm().id(),
balance: 0_u128,
data: Data::from(&PoolDefinition {
definition_token_a_id: IdForExeTests::token_a_definition_id(),
definition_token_b_id: IdForExeTests::token_b_definition_id(),
vault_a_id: IdForExeTests::vault_a_id(),
vault_b_id: IdForExeTests::vault_b_id(),
liquidity_pool_id: IdForExeTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForExeTests::lp_supply_init(),
reserve_a: BalanceForExeTests::vault_a_balance_init(),
reserve_b: BalanceForExeTests::vault_b_balance_init(),
fees: 0_u128,
active: true,
}),
nonce: 0,
}
}
fn user_token_lp_holding_init_zero() -> Account {
Account {
program_owner: Program::token().id(),
balance: 0_u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForExeTests::token_lp_definition_id(),
balance: 0,
}),
nonce: 0,
}
}
}
#[test]
fn pool_pda_produces_unique_id_for_token_pair() {
assert!(
amm_core::compute_pool_pda(
AMM_PROGRAM_ID,
IdForTests::token_a_definition_id(),
IdForTests::token_b_definition_id()
) == compute_pool_pda(
AMM_PROGRAM_ID,
IdForTests::token_b_definition_id(),
IdForTests::token_a_definition_id()
)
);
}
#[should_panic(expected = "Vault A was not provided")]
#[test]
fn call_add_liquidity_vault_a_omitted() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_with_wrong_id(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_b(),
);
}
#[should_panic(expected = "Vault B was not provided")]
#[test]
fn call_add_liquidity_vault_b_omitted() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_with_wrong_id(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_b(),
);
}
#[should_panic(expected = "LP definition mismatch")]
#[test]
fn call_add_liquidity_lp_definition_mismatch() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_with_wrong_id(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_b(),
);
}
#[should_panic(expected = "Both max-balances must be nonzero")]
#[test]
fn call_add_liquidity_zero_balance_1() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
0,
BalanceForTests::add_max_amount_b(),
);
}
#[should_panic(expected = "Both max-balances must be nonzero")]
#[test]
fn call_add_liquidity_zero_balance_2() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
0,
BalanceForTests::add_max_amount_a(),
);
}
#[should_panic(expected = "Vaults' balances must be at least the reserve amounts")]
#[test]
fn call_add_liquidity_vault_insufficient_balance_1() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init_zero(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_max_amount_a()).unwrap(),
BalanceForTests::add_max_amount_b(),
BalanceForTests::add_min_amount_lp(),
);
}
#[should_panic(expected = "Vaults' balances must be at least the reserve amounts")]
#[test]
fn call_add_liquidity_vault_insufficient_balance_2() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init_zero(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_max_amount_a()).unwrap(),
BalanceForTests::add_max_amount_b(),
BalanceForTests::add_min_amount_lp(),
);
}
#[should_panic(expected = "A trade amount is 0")]
#[test]
fn call_add_liquidity_actual_amount_zero_1() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init_reserve_a_low(),
AccountWithMetadataForTests::vault_a_init_low(),
AccountWithMetadataForTests::vault_b_init_high(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_b(),
);
}
#[should_panic(expected = "A trade amount is 0")]
#[test]
fn call_add_liquidity_actual_amount_zero_2() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init_reserve_b_low(),
AccountWithMetadataForTests::vault_a_init_high(),
AccountWithMetadataForTests::vault_b_init_low(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a_low(),
BalanceForTests::add_max_amount_b_low(),
);
}
#[should_panic(expected = "Reserves must be nonzero")]
#[test]
fn call_add_liquidity_reserves_zero_1() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init_reserve_a_zero(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_b(),
);
}
#[should_panic(expected = "Reserves must be nonzero")]
#[test]
fn call_add_liquidity_reserves_zero_2() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_init_reserve_b_zero(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_b(),
);
}
#[should_panic(expected = "Payable LP must be nonzero")]
#[test]
fn call_add_liquidity_payable_lp_zero() {
let _post_states = add_liquidity(
AccountWithMetadataForTests::pool_definition_add_zero_lp(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a_low(),
BalanceForTests::add_max_amount_b_low(),
);
}
#[test]
fn call_add_liquidity_chained_call_successsful() {
let (post_states, chained_calls) = add_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_b(),
);
let pool_post = post_states[0].clone();
assert!(
AccountWithMetadataForTests::pool_definition_add_successful().account
== *pool_post.account()
);
let chained_call_lp = chained_calls[0].clone();
let chained_call_b = chained_calls[1].clone();
let chained_call_a = chained_calls[2].clone();
assert!(chained_call_a == ChainedCallForTests::cc_add_token_a());
assert!(chained_call_b == ChainedCallForTests::cc_add_token_b());
assert!(chained_call_lp == ChainedCallForTests::cc_add_pool_lp());
}
#[should_panic(expected = "Vault A was not provided")]
#[test]
fn call_remove_liquidity_vault_a_omitted() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_with_wrong_id(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b(),
);
}
#[should_panic(expected = "Vault B was not provided")]
#[test]
fn call_remove_liquidity_vault_b_omitted() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_with_wrong_id(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b(),
);
}
#[should_panic(expected = "LP definition mismatch")]
#[test]
fn call_remove_liquidity_lp_def_mismatch() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_with_wrong_id(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b(),
);
}
#[should_panic(expected = "Invalid liquidity account provided")]
#[test]
fn call_remove_liquidity_insufficient_liquidity_amount() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_a(), /* different token account than lp to
* create desired
* error */
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b(),
);
}
#[should_panic(
expected = "Insufficient minimal withdraw amount (Token A) provided for liquidity amount"
)]
#[test]
fn call_remove_liquidity_insufficient_balance_1() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp_1()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b(),
);
}
#[should_panic(
expected = "Insufficient minimal withdraw amount (Token B) provided for liquidity amount"
)]
#[test]
fn call_remove_liquidity_insufficient_balance_2() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b(),
);
}
#[should_panic(expected = "Minimum withdraw amount must be nonzero")]
#[test]
fn call_remove_liquidity_min_bal_zero_1() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
0,
BalanceForTests::remove_min_amount_b(),
);
}
#[should_panic(expected = "Minimum withdraw amount must be nonzero")]
#[test]
fn call_remove_liquidity_min_bal_zero_2() {
let _post_states = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
0,
);
}
#[test]
fn call_remove_liquidity_chained_call_successful() {
let (post_states, chained_calls) = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_init(),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b_low(),
);
let pool_post = post_states[0].clone();
assert!(
AccountWithMetadataForTests::pool_definition_remove_successful().account
== *pool_post.account()
);
let chained_call_lp = chained_calls[0].clone();
let chained_call_b = chained_calls[1].clone();
let chained_call_a = chained_calls[2].clone();
assert!(chained_call_a == ChainedCallForTests::cc_remove_token_a());
assert!(chained_call_b == ChainedCallForTests::cc_remove_token_b());
assert!(chained_call_lp == ChainedCallForTests::cc_remove_pool_lp());
}
#[should_panic(expected = "Balances must be nonzero")]
#[test]
fn call_new_definition_with_zero_balance_1() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(0).expect("Balances must be nonzero"),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Balances must be nonzero")]
#[test]
fn call_new_definition_with_zero_balance_2() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(0).expect("Balances must be nonzero"),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Cannot set up a swap for a token with itself")]
#[test]
fn call_new_definition_same_token_definition() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Liquidity pool Token Definition Account ID does not match PDA")]
#[test]
fn call_new_definition_wrong_liquidity_id() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_with_wrong_id(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Pool Definition Account ID does not match PDA")]
#[test]
fn call_new_definition_wrong_pool_id() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_with_wrong_id(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Vault ID does not match PDA")]
#[test]
fn call_new_definition_wrong_vault_id_1() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_with_wrong_id(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Vault ID does not match PDA")]
#[test]
fn call_new_definition_wrong_vault_id_2() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_with_wrong_id(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Cannot initialize an active Pool Definition")]
#[test]
fn call_new_definition_cannot_initialize_active_pool() {
let _post_states = new_definition(
AccountWithMetadataForTests::pool_definition_active(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
}
#[should_panic(expected = "Cannot initialize an active Pool Definition")]
#[test]
fn call_new_definition_chained_call_successful() {
let (post_states, chained_calls) = new_definition(
AccountWithMetadataForTests::pool_definition_active(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
let pool_post = post_states[0].clone();
assert!(
AccountWithMetadataForTests::pool_definition_add_successful().account
== *pool_post.account()
);
let chained_call_lp = chained_calls[0].clone();
let chained_call_b = chained_calls[1].clone();
let chained_call_a = chained_calls[2].clone();
assert!(chained_call_a == ChainedCallForTests::cc_new_definition_token_a());
assert!(chained_call_b == ChainedCallForTests::cc_new_definition_token_b());
assert!(chained_call_lp == ChainedCallForTests::cc_new_definition_token_lp());
}
#[should_panic(expected = "AccountId is not a token type for the pool")]
#[test]
fn call_swap_incorrect_token_type() {
let _post_states = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::min_amount_out(),
IdForTests::token_lp_definition_id(),
);
}
#[should_panic(expected = "Vault A was not provided")]
#[test]
fn call_swap_vault_a_omitted() {
let _post_states = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_with_wrong_id(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::min_amount_out(),
IdForTests::token_a_definition_id(),
);
}
#[should_panic(expected = "Vault B was not provided")]
#[test]
fn call_swap_vault_b_omitted() {
let _post_states = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_with_wrong_id(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::min_amount_out(),
IdForTests::token_a_definition_id(),
);
}
#[should_panic(expected = "Reserve for Token A exceeds vault balance")]
#[test]
fn call_swap_reserves_vault_mismatch_1() {
let _post_states = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init_low(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::min_amount_out(),
IdForTests::token_a_definition_id(),
);
}
#[should_panic(expected = "Reserve for Token B exceeds vault balance")]
#[test]
fn call_swap_reserves_vault_mismatch_2() {
let _post_states = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init_low(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::min_amount_out(),
IdForTests::token_a_definition_id(),
);
}
#[should_panic(expected = "Pool is inactive")]
#[test]
fn call_swap_ianctive() {
let _post_states = swap(
AccountWithMetadataForTests::pool_definition_inactive(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::min_amount_out(),
IdForTests::token_a_definition_id(),
);
}
#[should_panic(expected = "Withdraw amount is less than minimal amount out")]
#[test]
fn call_swap_below_min_out() {
let _post_states = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::min_amount_out(),
IdForTests::token_a_definition_id(),
);
}
#[test]
fn call_swap_chained_call_successful_1() {
let (post_states, chained_calls) = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_a(),
BalanceForTests::add_max_amount_a_low(),
IdForTests::token_a_definition_id(),
);
let pool_post = post_states[0].clone();
assert!(
AccountWithMetadataForTests::pool_definition_swap_test_1().account == *pool_post.account()
);
let chained_call_a = chained_calls[0].clone();
let chained_call_b = chained_calls[1].clone();
assert_eq!(
chained_call_a,
ChainedCallForTests::cc_swap_token_a_test_1()
);
assert_eq!(
chained_call_b,
ChainedCallForTests::cc_swap_token_b_test_1()
);
}
#[test]
fn call_swap_chained_call_successful_2() {
let (post_states, chained_calls) = swap(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
BalanceForTests::add_max_amount_b(),
BalanceForTests::min_amount_out(),
IdForTests::token_b_definition_id(),
);
let pool_post = post_states[0].clone();
assert!(
AccountWithMetadataForTests::pool_definition_swap_test_2().account == *pool_post.account()
);
let chained_call_a = chained_calls[1].clone();
let chained_call_b = chained_calls[0].clone();
assert_eq!(
chained_call_a,
ChainedCallForTests::cc_swap_token_a_test_2()
);
assert_eq!(
chained_call_b,
ChainedCallForTests::cc_swap_token_b_test_2()
);
}
#[test]
fn new_definition_lp_asymmetric_amounts() {
let (post_states, chained_calls) = new_definition(
AccountWithMetadataForTests::pool_definition_inactive(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
// check the minted LP amount
let pool_post = post_states[0].clone();
let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap();
assert_eq!(
pool_def.liquidity_pool_supply,
BalanceForTests::lp_supply_init()
);
let chained_call_lp = chained_calls[0].clone();
assert!(chained_call_lp == ChainedCallForTests::cc_new_definition_token_lp());
}
#[test]
fn new_definition_lp_symmetric_amounts() {
// token_a=100, token_b=100 → LP=sqrt(10_000)=100
let token_a_amount = 100_u128;
let token_b_amount = 100_u128;
let expected_lp = (token_a_amount * token_b_amount).isqrt();
assert_eq!(expected_lp, 100);
let (post_states, chained_calls) = new_definition(
AccountWithMetadataForTests::pool_definition_inactive(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
NonZero::new(token_a_amount).unwrap(),
NonZero::new(token_b_amount).unwrap(),
AMM_PROGRAM_ID,
);
let pool_post = post_states[0].clone();
let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap();
assert_eq!(pool_def.liquidity_pool_supply, expected_lp);
let chained_call_lp = chained_calls[0].clone();
let expected_lp_call = ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_lp_uninit(),
],
&token_core::Instruction::Mint {
amount_to_mint: expected_lp,
},
)
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
IdForTests::pool_definition_id(),
)]);
assert_eq!(chained_call_lp, expected_lp_call);
}
#[cfg(feature = "nssa")]
fn state_for_amm_tests() -> V02State {
let initial_data = [];
let mut state = V02State::new_with_genesis_accounts(&initial_data, &[]);
state.force_insert_account(
IdForExeTests::pool_definition_id(),
AccountsForExeTests::pool_definition_init(),
);
state.force_insert_account(
IdForExeTests::token_a_definition_id(),
AccountsForExeTests::token_a_definition_account(),
);
state.force_insert_account(
IdForExeTests::token_b_definition_id(),
AccountsForExeTests::token_b_definition_acc(),
);
state.force_insert_account(
IdForExeTests::token_lp_definition_id(),
AccountsForExeTests::token_lp_definition_acc(),
);
state.force_insert_account(
IdForExeTests::user_token_a_id(),
AccountsForExeTests::user_token_a_holding(),
);
state.force_insert_account(
IdForExeTests::user_token_b_id(),
AccountsForExeTests::user_token_b_holding(),
);
state.force_insert_account(
IdForExeTests::user_token_lp_id(),
AccountsForExeTests::user_token_lp_holding(),
);
state.force_insert_account(
IdForExeTests::vault_a_id(),
AccountsForExeTests::vault_a_init(),
);
state.force_insert_account(
IdForExeTests::vault_b_id(),
AccountsForExeTests::vault_b_init(),
);
state
}
#[cfg(feature = "nssa")]
fn state_for_amm_tests_with_new_def() -> V02State {
let initial_data = [];
let mut state = V02State::new_with_genesis_accounts(&initial_data, &[]);
state.force_insert_account(
IdForExeTests::token_a_definition_id(),
AccountsForExeTests::token_a_definition_account(),
);
state.force_insert_account(
IdForExeTests::token_b_definition_id(),
AccountsForExeTests::token_b_definition_acc(),
);
state.force_insert_account(
IdForExeTests::user_token_a_id(),
AccountsForExeTests::user_token_a_holding(),
);
state.force_insert_account(
IdForExeTests::user_token_b_id(),
AccountsForExeTests::user_token_b_holding(),
);
state
}
#[cfg(feature = "nssa")]
#[test]
fn simple_amm_remove() {
let mut state = state_for_amm_tests();
let instruction = amm_core::Instruction::RemoveLiquidity {
remove_liquidity_amount: BalanceForExeTests::remove_lp(),
min_amount_to_remove_token_a: BalanceForExeTests::remove_min_amount_a(),
min_amount_to_remove_token_b: BalanceForExeTests::remove_min_amount_b(),
};
let message = public_transaction::Message::try_new(
Program::amm().id(),
vec![
IdForExeTests::pool_definition_id(),
IdForExeTests::vault_a_id(),
IdForExeTests::vault_b_id(),
IdForExeTests::token_lp_definition_id(),
IdForExeTests::user_token_a_id(),
IdForExeTests::user_token_b_id(),
IdForExeTests::user_token_lp_id(),
],
vec![0],
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(
&message,
&[&PrivateKeysForTests::user_token_lp_key()],
);
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
let pool_post = state.get_account_by_id(IdForExeTests::pool_definition_id());
let vault_a_post = state.get_account_by_id(IdForExeTests::vault_a_id());
let vault_b_post = state.get_account_by_id(IdForExeTests::vault_b_id());
let token_lp_post = state.get_account_by_id(IdForExeTests::token_lp_definition_id());
let user_token_a_post = state.get_account_by_id(IdForExeTests::user_token_a_id());
let user_token_b_post = state.get_account_by_id(IdForExeTests::user_token_b_id());
let user_token_lp_post = state.get_account_by_id(IdForExeTests::user_token_lp_id());
let expected_pool = AccountsForExeTests::pool_definition_remove();
let expected_vault_a = AccountsForExeTests::vault_a_remove();
let expected_vault_b = AccountsForExeTests::vault_b_remove();
let expected_token_lp = AccountsForExeTests::token_lp_definition_remove();
let expected_user_token_a = AccountsForExeTests::user_token_a_holding_remove();
let expected_user_token_b = AccountsForExeTests::user_token_b_holding_remove();
let expected_user_token_lp = AccountsForExeTests::user_token_lp_holding_remove();
assert_eq!(pool_post, expected_pool);
assert_eq!(vault_a_post, expected_vault_a);
assert_eq!(vault_b_post, expected_vault_b);
assert_eq!(token_lp_post, expected_token_lp);
assert_eq!(user_token_a_post, expected_user_token_a);
assert_eq!(user_token_b_post, expected_user_token_b);
assert_eq!(user_token_lp_post, expected_user_token_lp);
}
#[cfg(feature = "nssa")]
#[test]
fn simple_amm_new_definition_inactive_initialized_pool_and_uninit_user_lp() {
let mut state = state_for_amm_tests_with_new_def();
// Uninitialized in constructor
state.force_insert_account(
IdForExeTests::vault_a_id(),
AccountsForExeTests::vault_a_init_inactive(),
);
state.force_insert_account(
IdForExeTests::vault_b_id(),
AccountsForExeTests::vault_b_init_inactive(),
);
state.force_insert_account(
IdForExeTests::pool_definition_id(),
AccountsForExeTests::pool_definition_inactive(),
);
state.force_insert_account(
IdForExeTests::token_lp_definition_id(),
AccountsForExeTests::token_lp_definition_init_inactive(),
);
let instruction = amm_core::Instruction::NewDefinition {
token_a_amount: BalanceForExeTests::vault_a_balance_init(),
token_b_amount: BalanceForExeTests::vault_b_balance_init(),
amm_program_id: Program::amm().id(),
};
let message = public_transaction::Message::try_new(
Program::amm().id(),
vec![
IdForExeTests::pool_definition_id(),
IdForExeTests::vault_a_id(),
IdForExeTests::vault_b_id(),
IdForExeTests::token_lp_definition_id(),
IdForExeTests::user_token_a_id(),
IdForExeTests::user_token_b_id(),
IdForExeTests::user_token_lp_id(),
],
vec![0, 0],
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(
&message,
&[
&PrivateKeysForTests::user_token_a_key(),
&PrivateKeysForTests::user_token_b_key(),
],
);
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
let pool_post = state.get_account_by_id(IdForExeTests::pool_definition_id());
let vault_a_post = state.get_account_by_id(IdForExeTests::vault_a_id());
let vault_b_post = state.get_account_by_id(IdForExeTests::vault_b_id());
let token_lp_post = state.get_account_by_id(IdForExeTests::token_lp_definition_id());
let user_token_a_post = state.get_account_by_id(IdForExeTests::user_token_a_id());
let user_token_b_post = state.get_account_by_id(IdForExeTests::user_token_b_id());
let user_token_lp_post = state.get_account_by_id(IdForExeTests::user_token_lp_id());
let expected_pool = AccountsForExeTests::pool_definition_new_init();
let expected_vault_a = AccountsForExeTests::vault_a_init();
let expected_vault_b = AccountsForExeTests::vault_b_init();
let expected_token_lp = AccountsForExeTests::token_lp_definition_new_init();
let expected_user_token_a = AccountsForExeTests::user_token_a_holding_new_init();
let expected_user_token_b = AccountsForExeTests::user_token_b_holding_new_init();
let expected_user_token_lp = AccountsForExeTests::user_token_lp_holding_new_init();
assert_eq!(pool_post, expected_pool);
assert_eq!(vault_a_post, expected_vault_a);
assert_eq!(vault_b_post, expected_vault_b);
assert_eq!(token_lp_post, expected_token_lp);
assert_eq!(user_token_a_post, expected_user_token_a);
assert_eq!(user_token_b_post, expected_user_token_b);
assert_eq!(user_token_lp_post, expected_user_token_lp);
}
#[cfg(feature = "nssa")]
#[test]
fn simple_amm_new_definition_inactive_initialized_pool_init_user_lp() {
let mut state = state_for_amm_tests_with_new_def();
// Uninitialized in constructor
state.force_insert_account(
IdForExeTests::vault_a_id(),
AccountsForExeTests::vault_a_init_inactive(),
);
state.force_insert_account(
IdForExeTests::vault_b_id(),
AccountsForExeTests::vault_b_init_inactive(),
);
state.force_insert_account(
IdForExeTests::pool_definition_id(),
AccountsForExeTests::pool_definition_inactive(),
);
state.force_insert_account(
IdForExeTests::token_lp_definition_id(),
AccountsForExeTests::token_lp_definition_init_inactive(),
);
state.force_insert_account(
IdForExeTests::user_token_lp_id(),
AccountsForExeTests::user_token_lp_holding_init_zero(),
);
let instruction = amm_core::Instruction::NewDefinition {
token_a_amount: BalanceForExeTests::vault_a_balance_init(),
token_b_amount: BalanceForExeTests::vault_b_balance_init(),
amm_program_id: Program::amm().id(),
};
let message = public_transaction::Message::try_new(
Program::amm().id(),
vec![
IdForExeTests::pool_definition_id(),
IdForExeTests::vault_a_id(),
IdForExeTests::vault_b_id(),
IdForExeTests::token_lp_definition_id(),
IdForExeTests::user_token_a_id(),
IdForExeTests::user_token_b_id(),
IdForExeTests::user_token_lp_id(),
],
vec![0, 0],
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(
&message,
&[
&PrivateKeysForTests::user_token_a_key(),
&PrivateKeysForTests::user_token_b_key(),
],
);
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
let pool_post = state.get_account_by_id(IdForExeTests::pool_definition_id());
let vault_a_post = state.get_account_by_id(IdForExeTests::vault_a_id());
let vault_b_post = state.get_account_by_id(IdForExeTests::vault_b_id());
let token_lp_post = state.get_account_by_id(IdForExeTests::token_lp_definition_id());
let user_token_a_post = state.get_account_by_id(IdForExeTests::user_token_a_id());
let user_token_b_post = state.get_account_by_id(IdForExeTests::user_token_b_id());
let user_token_lp_post = state.get_account_by_id(IdForExeTests::user_token_lp_id());
let expected_pool = AccountsForExeTests::pool_definition_new_init();
let expected_vault_a = AccountsForExeTests::vault_a_init();
let expected_vault_b = AccountsForExeTests::vault_b_init();
let expected_token_lp = AccountsForExeTests::token_lp_definition_new_init();
let expected_user_token_a = AccountsForExeTests::user_token_a_holding_new_init();
let expected_user_token_b = AccountsForExeTests::user_token_b_holding_new_init();
let expected_user_token_lp = AccountsForExeTests::user_token_lp_holding_new_init();
assert_eq!(pool_post, expected_pool);
assert_eq!(vault_a_post, expected_vault_a);
assert_eq!(vault_b_post, expected_vault_b);
assert_eq!(token_lp_post, expected_token_lp);
assert_eq!(user_token_a_post, expected_user_token_a);
assert_eq!(user_token_b_post, expected_user_token_b);
assert_eq!(user_token_lp_post, expected_user_token_lp);
}
#[cfg(feature = "nssa")]
#[test]
fn simple_amm_new_definition_uninitialized_pool() {
let mut state = state_for_amm_tests_with_new_def();
// Uninitialized in constructor
state.force_insert_account(
IdForExeTests::vault_a_id(),
AccountsForExeTests::vault_a_init_inactive(),
);
state.force_insert_account(
IdForExeTests::vault_b_id(),
AccountsForExeTests::vault_b_init_inactive(),
);
let instruction = amm_core::Instruction::NewDefinition {
token_a_amount: BalanceForExeTests::vault_a_balance_init(),
token_b_amount: BalanceForExeTests::vault_b_balance_init(),
amm_program_id: Program::amm().id(),
};
let message = public_transaction::Message::try_new(
Program::amm().id(),
vec![
IdForExeTests::pool_definition_id(),
IdForExeTests::vault_a_id(),
IdForExeTests::vault_b_id(),
IdForExeTests::token_lp_definition_id(),
IdForExeTests::user_token_a_id(),
IdForExeTests::user_token_b_id(),
IdForExeTests::user_token_lp_id(),
],
vec![0, 0],
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(
&message,
&[
&PrivateKeysForTests::user_token_a_key(),
&PrivateKeysForTests::user_token_b_key(),
],
);
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
let pool_post = state.get_account_by_id(IdForExeTests::pool_definition_id());
let vault_a_post = state.get_account_by_id(IdForExeTests::vault_a_id());
let vault_b_post = state.get_account_by_id(IdForExeTests::vault_b_id());
let token_lp_post = state.get_account_by_id(IdForExeTests::token_lp_definition_id());
let user_token_a_post = state.get_account_by_id(IdForExeTests::user_token_a_id());
let user_token_b_post = state.get_account_by_id(IdForExeTests::user_token_b_id());
let user_token_lp_post = state.get_account_by_id(IdForExeTests::user_token_lp_id());
let expected_pool = AccountsForExeTests::pool_definition_new_init();
let expected_vault_a = AccountsForExeTests::vault_a_init();
let expected_vault_b = AccountsForExeTests::vault_b_init();
let expected_token_lp = AccountsForExeTests::token_lp_definition_new_init();
let expected_user_token_a = AccountsForExeTests::user_token_a_holding_new_init();
let expected_user_token_b = AccountsForExeTests::user_token_b_holding_new_init();
let expected_user_token_lp = AccountsForExeTests::user_token_lp_holding_new_init();
assert_eq!(pool_post, expected_pool);
assert_eq!(vault_a_post, expected_vault_a);
assert_eq!(vault_b_post, expected_vault_b);
assert_eq!(token_lp_post, expected_token_lp);
assert_eq!(user_token_a_post, expected_user_token_a);
assert_eq!(user_token_b_post, expected_user_token_b);
assert_eq!(user_token_lp_post, expected_user_token_lp);
}
#[cfg(feature = "nssa")]
#[test]
fn simple_amm_add() {
let mut state = state_for_amm_tests();
let instruction = amm_core::Instruction::AddLiquidity {
min_amount_liquidity: BalanceForExeTests::add_min_amount_lp(),
max_amount_to_add_token_a: BalanceForExeTests::add_max_amount_a(),
max_amount_to_add_token_b: BalanceForExeTests::add_max_amount_b(),
};
let message = public_transaction::Message::try_new(
Program::amm().id(),
vec![
IdForExeTests::pool_definition_id(),
IdForExeTests::vault_a_id(),
IdForExeTests::vault_b_id(),
IdForExeTests::token_lp_definition_id(),
IdForExeTests::user_token_a_id(),
IdForExeTests::user_token_b_id(),
IdForExeTests::user_token_lp_id(),
],
vec![0, 0],
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(
&message,
&[
&PrivateKeysForTests::user_token_a_key(),
&PrivateKeysForTests::user_token_b_key(),
],
);
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
let pool_post = state.get_account_by_id(IdForExeTests::pool_definition_id());
let vault_a_post = state.get_account_by_id(IdForExeTests::vault_a_id());
let vault_b_post = state.get_account_by_id(IdForExeTests::vault_b_id());
let token_lp_post = state.get_account_by_id(IdForExeTests::token_lp_definition_id());
let user_token_a_post = state.get_account_by_id(IdForExeTests::user_token_a_id());
let user_token_b_post = state.get_account_by_id(IdForExeTests::user_token_b_id());
let user_token_lp_post = state.get_account_by_id(IdForExeTests::user_token_lp_id());
let expected_pool = AccountsForExeTests::pool_definition_add();
let expected_vault_a = AccountsForExeTests::vault_a_add();
let expected_vault_b = AccountsForExeTests::vault_b_add();
let expected_token_lp = AccountsForExeTests::token_lp_definition_add();
let expected_user_token_a = AccountsForExeTests::user_token_a_holding_add();
let expected_user_token_b = AccountsForExeTests::user_token_b_holding_add();
let expected_user_token_lp = AccountsForExeTests::user_token_lp_holding_add();
assert_eq!(pool_post, expected_pool);
assert_eq!(vault_a_post, expected_vault_a);
assert_eq!(vault_b_post, expected_vault_b);
assert_eq!(token_lp_post, expected_token_lp);
assert_eq!(user_token_a_post, expected_user_token_a);
assert_eq!(user_token_b_post, expected_user_token_b);
assert_eq!(user_token_lp_post, expected_user_token_lp);
}
#[cfg(feature = "nssa")]
#[test]
fn simple_amm_swap_1() {
let mut state = state_for_amm_tests();
let instruction = amm_core::Instruction::Swap {
swap_amount_in: BalanceForExeTests::swap_amount_in(),
min_amount_out: BalanceForExeTests::swap_min_amount_out(),
token_definition_id_in: IdForExeTests::token_b_definition_id(),
};
let message = public_transaction::Message::try_new(
Program::amm().id(),
vec![
IdForExeTests::pool_definition_id(),
IdForExeTests::vault_a_id(),
IdForExeTests::vault_b_id(),
IdForExeTests::user_token_a_id(),
IdForExeTests::user_token_b_id(),
],
vec![0],
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(
&message,
&[&PrivateKeysForTests::user_token_b_key()],
);
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
let pool_post = state.get_account_by_id(IdForExeTests::pool_definition_id());
let vault_a_post = state.get_account_by_id(IdForExeTests::vault_a_id());
let vault_b_post = state.get_account_by_id(IdForExeTests::vault_b_id());
let user_token_a_post = state.get_account_by_id(IdForExeTests::user_token_a_id());
let user_token_b_post = state.get_account_by_id(IdForExeTests::user_token_b_id());
let expected_pool = AccountsForExeTests::pool_definition_swap_1();
let expected_vault_a = AccountsForExeTests::vault_a_swap_1();
let expected_vault_b = AccountsForExeTests::vault_b_swap_1();
let expected_user_token_a = AccountsForExeTests::user_token_a_holding_swap_1();
let expected_user_token_b = AccountsForExeTests::user_token_b_holding_swap_1();
assert_eq!(pool_post, expected_pool);
assert_eq!(vault_a_post, expected_vault_a);
assert_eq!(vault_b_post, expected_vault_b);
assert_eq!(user_token_a_post, expected_user_token_a);
assert_eq!(user_token_b_post, expected_user_token_b);
}
#[cfg(feature = "nssa")]
#[test]
fn simple_amm_swap_2() {
let mut state = state_for_amm_tests();
let instruction = amm_core::Instruction::Swap {
swap_amount_in: BalanceForExeTests::swap_amount_in(),
min_amount_out: BalanceForExeTests::swap_min_amount_out(),
token_definition_id_in: IdForExeTests::token_a_definition_id(),
};
let message = public_transaction::Message::try_new(
Program::amm().id(),
vec![
IdForExeTests::pool_definition_id(),
IdForExeTests::vault_a_id(),
IdForExeTests::vault_b_id(),
IdForExeTests::user_token_a_id(),
IdForExeTests::user_token_b_id(),
],
vec![0],
instruction,
)
.unwrap();
let witness_set = public_transaction::WitnessSet::for_message(
&message,
&[&PrivateKeysForTests::user_token_a_key()],
);
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
let pool_post = state.get_account_by_id(IdForExeTests::pool_definition_id());
let vault_a_post = state.get_account_by_id(IdForExeTests::vault_a_id());
let vault_b_post = state.get_account_by_id(IdForExeTests::vault_b_id());
let user_token_a_post = state.get_account_by_id(IdForExeTests::user_token_a_id());
let user_token_b_post = state.get_account_by_id(IdForExeTests::user_token_b_id());
let expected_pool = AccountsForExeTests::pool_definition_swap_2();
let expected_vault_a = AccountsForExeTests::vault_a_swap_2();
let expected_vault_b = AccountsForExeTests::vault_b_swap_2();
let expected_user_token_a = AccountsForExeTests::user_token_a_holding_swap_2();
let expected_user_token_b = AccountsForExeTests::user_token_b_holding_swap_2();
assert_eq!(pool_post, expected_pool);
assert_eq!(vault_a_post, expected_vault_a);
assert_eq!(vault_b_post, expected_vault_b);
assert_eq!(user_token_a_post, expected_user_token_a);
assert_eq!(user_token_b_post, expected_user_token_b);
}