use anyhow::Result;
use solana_sdk::pubkey::Pubkey;
use crate::common::SolanaRpcClient;
#[derive(Clone, Debug)]
pub struct MeteoraDlmmParams {
pub lb_pair: Pubkey,
pub bitmap_extension: Option<Pubkey>,
pub reserve_x: Pubkey,
pub reserve_y: Pubkey,
pub token_x_mint: Pubkey,
pub token_y_mint: Pubkey,
pub oracle: Pubkey,
pub token_x_program: Pubkey,
pub token_y_program: Pubkey,
pub bin_arrays: Vec<Pubkey>,
}
impl MeteoraDlmmParams {
pub fn new(
lb_pair: Pubkey,
reserve_x: Pubkey,
reserve_y: Pubkey,
token_x_mint: Pubkey,
token_y_mint: Pubkey,
oracle: Pubkey,
token_x_program: Pubkey,
token_y_program: Pubkey,
bin_arrays: Vec<Pubkey>,
) -> Self {
Self {
lb_pair,
bitmap_extension: None,
reserve_x,
reserve_y,
token_x_mint,
token_y_mint,
oracle,
token_x_program,
token_y_program,
bin_arrays,
}
}
pub fn with_bitmap_extension(mut self, ext: Pubkey) -> Self {
self.bitmap_extension = Some(ext);
self
}
pub async fn from_pool_address_by_rpc(
rpc: &SolanaRpcClient,
lb_pair: &Pubkey,
input_mint: &Pubkey,
output_mint: &Pubkey,
) -> Result<Self> {
use crate::instruction::utils::meteora_dlmm::{fetch_lb_pair, resolve_swap_snapshot};
let state = fetch_lb_pair(rpc, lb_pair).await?;
let swap_for_y = if input_mint == &state.token_x_mint && output_mint == &state.token_y_mint
{
true
} else if input_mint == &state.token_y_mint && output_mint == &state.token_x_mint {
false
} else {
anyhow::bail!("DLMM swap mints do not match pool");
};
let (current, bitmap_extension, bin_arrays) =
resolve_swap_snapshot(rpc, lb_pair, swap_for_y).await?;
if current.token_x_mint != state.token_x_mint || current.token_y_mint != state.token_y_mint
{
anyhow::bail!("DLMM mints changed during snapshot refresh");
}
let state = current;
let mint_accounts =
rpc.get_multiple_accounts(&[state.token_x_mint, state.token_y_mint]).await?;
let token_x_program = mint_accounts
.first()
.and_then(|a| a.as_ref())
.map(|a| a.owner)
.ok_or_else(|| anyhow::anyhow!("token_x mint missing"))?;
let token_y_program = mint_accounts
.get(1)
.and_then(|a| a.as_ref())
.map(|a| a.owner)
.ok_or_else(|| anyhow::anyhow!("token_y mint missing"))?;
Ok(Self {
lb_pair: *lb_pair,
bitmap_extension,
reserve_x: state.reserve_x,
reserve_y: state.reserve_y,
token_x_mint: state.token_x_mint,
token_y_mint: state.token_y_mint,
oracle: state.oracle,
token_x_program,
token_y_program,
bin_arrays,
})
}
}