372 lines
13 KiB
Rust
Raw Normal View History

2026-01-23 16:30:54 -05:00
use amm_core::{compute_liquidity_token_pda, compute_pool_pda, compute_vault_pda};
2025-12-16 14:05:34 +02:00
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
2026-01-23 16:30:54 -05:00
use nssa::{AccountId, program::Program};
use token_core::TokenHolding;
2025-12-17 14:21:36 +02:00
use crate::WalletCore;
2025-12-22 04:42:32 +02:00
pub struct Amm<'w>(pub &'w WalletCore);
impl Amm<'_> {
pub async fn send_new_definition(
2025-12-16 14:05:34 +02:00
&self,
2025-12-18 11:44:38 +02:00
user_holding_a: AccountId,
user_holding_b: AccountId,
user_holding_lp: AccountId,
2025-12-17 11:44:52 +02:00
balance_a: u128,
balance_b: u128,
2025-12-16 14:05:34 +02:00
) -> Result<SendTxResponse, ExecutionFailureKind> {
2026-01-23 16:30:54 -05:00
let program = Program::amm();
2025-12-18 11:44:38 +02:00
let amm_program_id = Program::amm().id();
2026-01-23 16:30:54 -05:00
let instruction = amm_core::Instruction::NewDefinition {
token_a_amount: balance_a,
token_b_amount: balance_b,
amm_program_id,
};
2025-12-18 11:44:38 +02:00
2025-12-22 04:42:32 +02:00
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_a))?
.definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_b))?
.definition_id();
2025-12-18 11:44:38 +02:00
let amm_pool =
compute_pool_pda(amm_program_id, definition_token_a_id, definition_token_b_id);
let vault_holding_a = compute_vault_pda(amm_program_id, amm_pool, definition_token_a_id);
let vault_holding_b = compute_vault_pda(amm_program_id, amm_pool, definition_token_b_id);
let pool_lp = compute_liquidity_token_pda(amm_program_id, amm_pool);
let account_ids = vec![
amm_pool,
vault_holding_a,
vault_holding_b,
pool_lp,
user_holding_a,
user_holding_b,
user_holding_lp,
];
2025-12-16 14:05:34 +02:00
2025-12-22 04:42:32 +02:00
let nonces = self
2025-12-18 11:44:38 +02:00
.0
.get_accounts_nonces(vec![user_holding_a, user_holding_b])
.await
2025-12-22 04:42:32 +02:00
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
2025-12-22 04:42:32 +02:00
let signing_key_a = self
2025-12-18 11:44:38 +02:00
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_a)
2025-12-22 04:42:32 +02:00
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
2025-12-18 11:44:38 +02:00
2025-12-22 04:42:32 +02:00
let signing_key_b = self
2025-12-18 11:44:38 +02:00
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_b)
2025-12-22 04:42:32 +02:00
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
2025-12-18 11:44:38 +02:00
let message = nssa::public_transaction::Message::try_new(
program.id(),
account_ids,
nonces,
instruction,
)
.unwrap();
let witness_set = nssa::public_transaction::WitnessSet::for_message(
&message,
&[signing_key_a, signing_key_b],
);
let tx = nssa::PublicTransaction::new(message, witness_set);
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
2025-12-16 14:05:34 +02:00
}
pub async fn send_swap(
&self,
2025-12-18 11:44:38 +02:00
user_holding_a: AccountId,
user_holding_b: AccountId,
2026-01-23 16:30:54 -05:00
swap_amount_in: u128,
2025-12-16 14:05:34 +02:00
min_amount_out: u128,
2026-01-23 16:30:54 -05:00
token_definition_id_in: AccountId,
2025-12-16 14:05:34 +02:00
) -> Result<SendTxResponse, ExecutionFailureKind> {
2026-01-23 16:30:54 -05:00
let instruction = amm_core::Instruction::Swap {
swap_amount_in,
min_amount_out,
token_definition_id_in,
};
let program = Program::amm();
2025-12-18 11:44:38 +02:00
let amm_program_id = Program::amm().id();
2025-12-22 04:42:32 +02:00
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_a))?
.definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_b))?
.definition_id();
2025-12-18 11:44:38 +02:00
let amm_pool =
compute_pool_pda(amm_program_id, definition_token_a_id, definition_token_b_id);
let vault_holding_a = compute_vault_pda(amm_program_id, amm_pool, definition_token_a_id);
let vault_holding_b = compute_vault_pda(amm_program_id, amm_pool, definition_token_b_id);
let account_ids = vec![
amm_pool,
vault_holding_a,
vault_holding_b,
user_holding_a,
user_holding_b,
];
let account_id_auth;
// Checking, which account are associated with TokenDefinition
let token_holder_acc_a = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let token_holder_acc_b = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let token_holder_a = TokenHolding::try_from(&token_holder_acc_a.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_a))?;
let token_holder_b = TokenHolding::try_from(&token_holder_acc_b.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_b))?;
2025-12-18 11:44:38 +02:00
2026-01-23 16:30:54 -05:00
if token_holder_a.definition_id() == token_definition_id_in {
2025-12-18 11:44:38 +02:00
account_id_auth = user_holding_a;
2026-01-23 16:30:54 -05:00
} else if token_holder_b.definition_id() == token_definition_id_in {
2025-12-18 11:44:38 +02:00
account_id_auth = user_holding_b;
} else {
2026-01-23 16:30:54 -05:00
return Err(ExecutionFailureKind::AccountDataError(
token_definition_id_in,
));
2025-12-16 14:05:34 +02:00
}
2025-12-22 04:42:32 +02:00
let nonces = self
.0
.get_accounts_nonces(vec![account_id_auth])
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
2025-12-22 04:42:32 +02:00
let signing_key = self
2025-12-18 11:44:38 +02:00
.0
.storage
.user_data
.get_pub_account_signing_key(&account_id_auth)
2025-12-22 04:42:32 +02:00
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
2025-12-18 11:44:38 +02:00
let message = nssa::public_transaction::Message::try_new(
program.id(),
account_ids,
nonces,
instruction,
)
.unwrap();
let witness_set =
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
let tx = nssa::PublicTransaction::new(message, witness_set);
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
2025-12-16 14:05:34 +02:00
}
2025-12-22 04:42:32 +02:00
pub async fn send_add_liquidity(
2025-12-16 14:05:34 +02:00
&self,
2025-12-18 11:44:38 +02:00
user_holding_a: AccountId,
user_holding_b: AccountId,
user_holding_lp: AccountId,
2026-01-23 16:30:54 -05:00
min_amount_liquidity: u128,
max_amount_to_add_token_a: u128,
max_amount_to_add_token_b: u128,
2025-12-16 14:05:34 +02:00
) -> Result<SendTxResponse, ExecutionFailureKind> {
2026-01-23 16:30:54 -05:00
let instruction = amm_core::Instruction::AddLiquidity {
min_amount_liquidity,
max_amount_to_add_token_a,
max_amount_to_add_token_b,
};
let program = Program::amm();
2025-12-18 11:44:38 +02:00
let amm_program_id = Program::amm().id();
2025-12-22 04:42:32 +02:00
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_a))?
.definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_b))?
.definition_id();
2025-12-18 11:44:38 +02:00
let amm_pool =
compute_pool_pda(amm_program_id, definition_token_a_id, definition_token_b_id);
let vault_holding_a = compute_vault_pda(amm_program_id, amm_pool, definition_token_a_id);
let vault_holding_b = compute_vault_pda(amm_program_id, amm_pool, definition_token_b_id);
let pool_lp = compute_liquidity_token_pda(amm_program_id, amm_pool);
let account_ids = vec![
2025-12-16 14:05:34 +02:00
amm_pool,
vault_holding_a,
vault_holding_b,
pool_lp,
user_holding_a,
user_holding_b,
user_holding_lp,
2025-12-18 11:44:38 +02:00
];
2025-12-16 14:05:34 +02:00
2025-12-22 04:42:32 +02:00
let nonces = self
2025-12-18 11:44:38 +02:00
.0
.get_accounts_nonces(vec![user_holding_a, user_holding_b])
2025-12-16 14:05:34 +02:00
.await
2025-12-22 04:42:32 +02:00
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
2025-12-22 04:42:32 +02:00
let signing_key_a = self
2025-12-18 11:44:38 +02:00
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_a)
2025-12-22 04:42:32 +02:00
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
2025-12-18 11:44:38 +02:00
2025-12-22 04:42:32 +02:00
let signing_key_b = self
2025-12-18 11:44:38 +02:00
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_b)
2025-12-22 04:42:32 +02:00
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
2025-12-18 11:44:38 +02:00
let message = nssa::public_transaction::Message::try_new(
program.id(),
account_ids,
nonces,
instruction,
)
.unwrap();
let witness_set = nssa::public_transaction::WitnessSet::for_message(
&message,
&[signing_key_a, signing_key_b],
);
let tx = nssa::PublicTransaction::new(message, witness_set);
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
2025-12-16 14:05:34 +02:00
}
2025-12-22 04:42:32 +02:00
pub async fn send_remove_liquidity(
2025-12-16 14:05:34 +02:00
&self,
2025-12-18 11:44:38 +02:00
user_holding_a: AccountId,
user_holding_b: AccountId,
user_holding_lp: AccountId,
2026-01-23 16:30:54 -05:00
remove_liquidity_amount: u128,
min_amount_to_remove_token_a: u128,
min_amount_to_remove_token_b: u128,
2025-12-16 14:05:34 +02:00
) -> Result<SendTxResponse, ExecutionFailureKind> {
2026-01-23 16:30:54 -05:00
let instruction = amm_core::Instruction::RemoveLiquidity {
remove_liquidity_amount,
min_amount_to_remove_token_a,
min_amount_to_remove_token_b,
};
let program = Program::amm();
2025-12-18 11:44:38 +02:00
let amm_program_id = Program::amm().id();
2025-12-22 04:42:32 +02:00
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_a))?
.definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_| ExecutionFailureKind::AccountDataError(user_holding_b))?
.definition_id();
2025-12-18 11:44:38 +02:00
let amm_pool =
compute_pool_pda(amm_program_id, definition_token_a_id, definition_token_b_id);
let vault_holding_a = compute_vault_pda(amm_program_id, amm_pool, definition_token_a_id);
let vault_holding_b = compute_vault_pda(amm_program_id, amm_pool, definition_token_b_id);
let pool_lp = compute_liquidity_token_pda(amm_program_id, amm_pool);
let account_ids = vec![
2025-12-16 14:05:34 +02:00
amm_pool,
vault_holding_a,
vault_holding_b,
pool_lp,
user_holding_a,
user_holding_b,
user_holding_lp,
2025-12-18 11:44:38 +02:00
];
2025-12-22 04:42:32 +02:00
let nonces = self
.0
.get_accounts_nonces(vec![user_holding_lp])
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
2025-12-18 11:44:38 +02:00
2025-12-22 04:42:32 +02:00
let signing_key_lp = self
2025-12-18 11:44:38 +02:00
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_lp)
2025-12-22 04:42:32 +02:00
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
2025-12-18 11:44:38 +02:00
let message = nssa::public_transaction::Message::try_new(
program.id(),
account_ids,
nonces,
instruction,
)
.unwrap();
let witness_set =
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key_lp]);
let tx = nssa::PublicTransaction::new(message, witness_set);
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
2025-12-16 14:05:34 +02:00
}
}