406 lines
13 KiB
Rust

use std::time::Duration;
use anyhow::Result;
use integration_tests::{TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, format_public_account_id};
use log::info;
use tokio::test;
use wallet::cli::{
Command, SubcommandReturnValue,
account::{AccountSubcommand, NewSubcommand},
programs::{amm::AmmProgramAgnosticSubcommand, token::TokenProgramAgnosticSubcommand},
};
#[test]
async fn amm_public() -> Result<()> {
let mut ctx = TestContext::new().await?;
// Create new account for the token definition
let SubcommandReturnValue::RegisterAccount {
account_id: definition_account_id_1,
} = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public { cci: None })),
)
.await?
else {
anyhow::bail!("Expected RegisterAccount return value");
};
// Create new account for the token supply holder
let SubcommandReturnValue::RegisterAccount {
account_id: supply_account_id_1,
} = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public { cci: None })),
)
.await?
else {
anyhow::bail!("Expected RegisterAccount return value");
};
// Create new account for receiving a token transaction
let SubcommandReturnValue::RegisterAccount {
account_id: recipient_account_id_1,
} = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public { cci: None })),
)
.await?
else {
anyhow::bail!("Expected RegisterAccount return value");
};
// Create new account for the token definition
let SubcommandReturnValue::RegisterAccount {
account_id: definition_account_id_2,
} = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public { cci: None })),
)
.await?
else {
anyhow::bail!("Expected RegisterAccount return value");
};
// Create new account for the token supply holder
let SubcommandReturnValue::RegisterAccount {
account_id: supply_account_id_2,
} = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public { cci: None })),
)
.await?
else {
anyhow::bail!("Expected RegisterAccount return value");
};
// Create new account for receiving a token transaction
let SubcommandReturnValue::RegisterAccount {
account_id: recipient_account_id_2,
} = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public { cci: None })),
)
.await?
else {
anyhow::bail!("Expected RegisterAccount return value");
};
// Create new token
let subcommand = TokenProgramAgnosticSubcommand::New {
definition_account_id: format_public_account_id(&definition_account_id_1.to_string()),
supply_account_id: format_public_account_id(&supply_account_id_1.to_string()),
name: "A NAM1".to_string(),
total_supply: 37,
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
// Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_1`
let subcommand = TokenProgramAgnosticSubcommand::Send {
from: format_public_account_id(&supply_account_id_1.to_string()),
to: Some(format_public_account_id(
&recipient_account_id_1.to_string(),
)),
to_npk: None,
to_ipk: None,
amount: 7,
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
// Create new token
let subcommand = TokenProgramAgnosticSubcommand::New {
definition_account_id: format_public_account_id(&definition_account_id_2.to_string()),
supply_account_id: format_public_account_id(&supply_account_id_2.to_string()),
name: "A NAM2".to_string(),
total_supply: 37,
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
// Transfer 7 tokens from `supply_acc` to the account at account_id `recipient_account_id_2`
let subcommand = TokenProgramAgnosticSubcommand::Send {
from: format_public_account_id(&supply_account_id_2.to_string()),
to: Some(format_public_account_id(
&recipient_account_id_2.to_string(),
)),
to_npk: None,
to_ipk: None,
amount: 7,
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
info!("=================== SETUP FINISHED ===============");
// Create new AMM
// Setup accounts
// Create new account for the user holding lp
let SubcommandReturnValue::RegisterAccount {
account_id: user_holding_lp,
} = wallet::cli::execute_subcommand(
ctx.wallet_mut(),
Command::Account(AccountSubcommand::New(NewSubcommand::Public { cci: None })),
)
.await?
else {
anyhow::bail!("Expected RegisterAccount return value");
};
// Send creation tx
let subcommand = AmmProgramAgnosticSubcommand::New {
user_holding_a: format_public_account_id(&recipient_account_id_1.to_string()),
user_holding_b: format_public_account_id(&recipient_account_id_2.to_string()),
user_holding_lp: format_public_account_id(&user_holding_lp.to_string()),
balance_a: 3,
balance_b: 3,
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let user_holding_a_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_1.to_string())
.await?
.account;
let user_holding_b_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_2.to_string())
.await?
.account;
let user_holding_lp_acc = ctx
.sequencer_client()
.get_account(user_holding_lp.to_string())
.await?
.account;
assert_eq!(
u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()),
4
);
assert_eq!(
u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()),
4
);
assert_eq!(
u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()),
3
);
info!("=================== AMM DEFINITION FINISHED ===============");
// Make swap
let subcommand = AmmProgramAgnosticSubcommand::Swap {
user_holding_a: format_public_account_id(&recipient_account_id_1.to_string()),
user_holding_b: format_public_account_id(&recipient_account_id_2.to_string()),
amount_in: 2,
min_amount_out: 1,
token_definition: definition_account_id_1.to_string(),
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let user_holding_a_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_1.to_string())
.await?
.account;
let user_holding_b_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_2.to_string())
.await?
.account;
let user_holding_lp_acc = ctx
.sequencer_client()
.get_account(user_holding_lp.to_string())
.await?
.account;
assert_eq!(
u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()),
2
);
assert_eq!(
u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()),
5
);
assert_eq!(
u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()),
3
);
info!("=================== FIRST SWAP FINISHED ===============");
// Make swap
let subcommand = AmmProgramAgnosticSubcommand::Swap {
user_holding_a: format_public_account_id(&recipient_account_id_1.to_string()),
user_holding_b: format_public_account_id(&recipient_account_id_2.to_string()),
amount_in: 2,
min_amount_out: 1,
token_definition: definition_account_id_2.to_string(),
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let user_holding_a_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_1.to_string())
.await?
.account;
let user_holding_b_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_2.to_string())
.await?
.account;
let user_holding_lp_acc = ctx
.sequencer_client()
.get_account(user_holding_lp.to_string())
.await?
.account;
assert_eq!(
u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()),
4
);
assert_eq!(
u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()),
3
);
assert_eq!(
u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()),
3
);
info!("=================== SECOND SWAP FINISHED ===============");
// Add liquidity
let subcommand = AmmProgramAgnosticSubcommand::AddLiquidity {
user_holding_a: format_public_account_id(&recipient_account_id_1.to_string()),
user_holding_b: format_public_account_id(&recipient_account_id_2.to_string()),
user_holding_lp: format_public_account_id(&user_holding_lp.to_string()),
min_amount_lp: 1,
max_amount_a: 2,
max_amount_b: 2,
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let user_holding_a_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_1.to_string())
.await?
.account;
let user_holding_b_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_2.to_string())
.await?
.account;
let user_holding_lp_acc = ctx
.sequencer_client()
.get_account(user_holding_lp.to_string())
.await?
.account;
assert_eq!(
u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()),
3
);
assert_eq!(
u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()),
1
);
assert_eq!(
u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()),
4
);
info!("=================== ADD LIQ FINISHED ===============");
// Remove liquidity
let subcommand = AmmProgramAgnosticSubcommand::RemoveLiquidity {
user_holding_a: format_public_account_id(&recipient_account_id_1.to_string()),
user_holding_b: format_public_account_id(&recipient_account_id_2.to_string()),
user_holding_lp: format_public_account_id(&user_holding_lp.to_string()),
balance_lp: 2,
min_amount_a: 1,
min_amount_b: 1,
};
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::AMM(subcommand)).await?;
info!("Waiting for next block creation");
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
let user_holding_a_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_1.to_string())
.await?
.account;
let user_holding_b_acc = ctx
.sequencer_client()
.get_account(recipient_account_id_2.to_string())
.await?
.account;
let user_holding_lp_acc = ctx
.sequencer_client()
.get_account(user_holding_lp.to_string())
.await?
.account;
assert_eq!(
u128::from_le_bytes(user_holding_a_acc.data[33..].try_into().unwrap()),
5
);
assert_eq!(
u128::from_le_bytes(user_holding_b_acc.data[33..].try_into().unwrap()),
4
);
assert_eq!(
u128::from_le_bytes(user_holding_lp_acc.data[33..].try_into().unwrap()),
2
);
info!("Success!");
Ok(())
}