wp-solana-pool-traits 0.1.1

Traits and utilities for Solana liquidity pool operations: PoolViewer, PoolInfuser, PositionViewer
Documentation
use solana_sdk::{pubkey::Pubkey, signature::Signature};

use super::CurrencyAmount;

/// Liquidity parameter specifying how much to add (TokenA, TokenB, both, or
/// Liquidity amount)
///
/// This enum allows specifying liquidity in different ways:
/// - `TokenA`: Amount of token A to add (token B will be calculated)
/// - `TokenB`: Amount of token B to add (token A will be calculated)
/// - `TokenAAndB`: Both token A and token B amounts specified
/// - `Liquidity`: Direct liquidity amount to add
///
/// The SDK will calculate the remaining values based on the provided input.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IncreaseLiquidityParam {
    /// Specifies the amount of token A to add to the position
    TokenA(u64),
    /// Specifies the amount of token B to add to the position
    TokenB(u64),
    /// Specifies both token A and token B amounts to add to the position
    TokenAAndB(u64, u64),
    /// Specifies the amount of liquidity to add to the position
    Liquidity(u128),
}

impl IncreaseLiquidityParam {
    /// Create a new `IncreaseLiquidityParam` from token A amount
    pub fn token_a(amount: u64) -> Self {
        Self::TokenA(amount)
    }

    /// Create a new `IncreaseLiquidityParam` from token B amount
    pub fn token_b(amount: u64) -> Self {
        Self::TokenB(amount)
    }

    /// Create a new `IncreaseLiquidityParam` from both token A and token B
    /// amounts
    pub fn token_a_and_b(amount_a: u64, amount_b: u64) -> Self {
        Self::TokenAAndB(amount_a, amount_b)
    }

    /// Create a new `IncreaseLiquidityParam` from liquidity amount
    pub fn liquidity(amount: u128) -> Self {
        Self::Liquidity(amount)
    }

    /// Get the token A amount
    ///
    /// Returns `Some(amount)` if this variant contains token A amount,
    /// otherwise `None`
    pub fn token_a_amount(&self) -> Option<u64> {
        match self {
            Self::TokenA(amount) => Some(*amount),
            Self::TokenAAndB(amount_a, _) => Some(*amount_a),
            _ => None,
        }
    }

    /// Get the token B amount
    ///
    /// Returns `Some(amount)` if this variant contains token B amount,
    /// otherwise `None`
    pub fn token_b_amount(&self) -> Option<u64> {
        match self {
            Self::TokenB(amount) => Some(*amount),
            Self::TokenAAndB(_, amount_b) => Some(*amount_b),
            _ => None,
        }
    }

    /// Get both token A and token B amounts if both are specified
    ///
    /// Returns `Some((amount_a, amount_b))` if both amounts are available,
    /// otherwise `None`
    pub fn token_amounts(&self) -> Option<(u64, u64)> {
        match self {
            Self::TokenAAndB(amount_a, amount_b) => Some((*amount_a, *amount_b)),
            _ => None,
        }
    }

    /// Get the liquidity amount if this is `Liquidity`, otherwise `None`
    pub fn liquidity_amount(&self) -> Option<u128> {
        match self {
            Self::Liquidity(amount) => Some(*amount),
            _ => None,
        }
    }

    /// Check if this is a `TokenA` variant
    pub fn is_token_a(&self) -> bool {
        matches!(self, Self::TokenA(_))
    }

    /// Check if this is a `TokenB` variant
    pub fn is_token_b(&self) -> bool {
        matches!(self, Self::TokenB(_))
    }

    /// Check if this is a `TokenAAndB` variant
    pub fn is_token_a_and_b(&self) -> bool {
        matches!(self, Self::TokenAAndB(_, _))
    }

    /// Check if this is a `Liquidity` variant
    pub fn is_liquidity(&self) -> bool {
        matches!(self, Self::Liquidity(_))
    }
}

/// Result of adding liquidity (opening a new position or increasing existing)
#[derive(Clone, Debug)]
pub struct AddLiquidityResult {
    /// Position address (Pubkey)
    pub position_address: Pubkey,
    /// Amount of liquidity added
    pub liquidity: u128,
    /// Amount of token A added
    pub amount_a: CurrencyAmount,
    /// Amount of token B added
    pub amount_b: CurrencyAmount,
    /// Upper tick of the position
    pub tick_upper: i32,
    /// Lower tick of the position
    pub tick_lower: i32,
    /// Transaction signature
    pub signature: Signature,
}

/// Individual position result item (without transaction, used in batch results)
#[derive(Clone, Debug)]
pub struct AddLiquidityResultItem {
    /// Position address
    pub position_address: Pubkey,
    /// Amount of liquidity added
    pub liquidity: u128,
    /// Amount of token A added
    pub amount_a: CurrencyAmount,
    /// Amount of token B added
    pub amount_b: CurrencyAmount,
    /// Upper tick of the position
    pub tick_upper: i32,
    /// Lower tick of the position
    pub tick_lower: i32,
}

/// Result of adding batch liquidity (multiple positions in one transaction)
#[derive(Clone, Debug)]
pub struct AddBatchLiquidityResult {
    /// Results for each position added
    pub results: Vec<AddLiquidityResultItem>,
    /// Transaction signature for the batch operation
    pub signature: Signature,
}

/// Result of removing liquidity from a position
#[derive(Clone, Debug)]
pub struct RemoveLiquidityResult {
    /// Position address
    pub position_address: Pubkey,
    /// Amount of liquidity removed
    pub liquidity: u128,
    /// Amount of token A removed
    pub amount_a: CurrencyAmount,
    /// Amount of token B removed
    pub amount_b: CurrencyAmount,
    /// Amount of token A from liquidity removal (fees collected)
    pub amount_a_from_liquidity: CurrencyAmount,
    /// Amount of token B from liquidity removal (fees collected)
    pub amount_b_from_liquidity: CurrencyAmount,
    /// Recipient address that received the tokens
    pub recipient: Pubkey,
    /// Transaction signature
    pub signature: Signature,
}

/// Individual position result item for remove liquidity (without transaction,
/// used in batch results)
#[derive(Clone, Debug)]
pub struct RemoveLiquidityResultItem {
    /// Position address
    pub position_address: Pubkey,
    /// Amount of liquidity removed
    pub liquidity: u128,
    /// Amount of token A removed
    pub amount_a: CurrencyAmount,
    /// Amount of token B removed
    pub amount_b: CurrencyAmount,
    /// Amount of token A from liquidity removal (fees collected)
    pub amount_a_from_liquidity: CurrencyAmount,
    /// Amount of token B from liquidity removal (fees collected)
    pub amount_b_from_liquidity: CurrencyAmount,
    /// Recipient address that received the tokens
    pub recipient: Pubkey,
}

/// Result of removing batch liquidity (multiple positions in one transaction)
#[derive(Clone, Debug)]
pub struct RemoveBatchLiquidityResult {
    /// Results for each position removed
    pub results: Vec<RemoveLiquidityResultItem>,
    /// Transaction signature for the batch operation
    pub signature: Signature,
}

/// Result of collecting fees from a position
#[derive(Clone, Debug)]
pub struct CollectResult {
    /// Position address
    pub position_address: Pubkey,
    /// Amount of token A collected
    pub amount_a: CurrencyAmount,
    /// Amount of token B collected
    pub amount_b: CurrencyAmount,
    /// Recipient address that received the fees
    pub recipient: Pubkey,
    /// Transaction signature
    pub signature: Signature,
}

/// Result of simulating an add liquidity transaction
#[cfg(feature = "rpc")]
#[derive(Clone, Debug)]
pub struct SimulateAddLiquidityResult {
    /// Raw RPC simulation result containing execution status, logs, and compute
    /// units
    pub simulation: solana_client::rpc_response::RpcSimulateTransactionResult,
    /// Parsed LiquidityIncreased event from simulation logs (if available)
    pub liquidity_increased_event: Option<LiquidityIncreasedEvent>,
    /// Quote data from instruction building (fallback if event not found)
    pub quote: Option<AddLiquidityQuoteData>,
}

/// Parsed LiquidityIncreased event data
#[derive(Clone, Debug)]
pub struct LiquidityIncreasedEvent {
    /// Position address
    pub position: Pubkey,
    /// Amount of liquidity added
    pub liquidity: u128,
    /// Amount of token A added
    pub token_a_amount: u64,
    /// Amount of token B added
    pub token_b_amount: u64,
    /// Lower tick index
    pub tick_lower_index: i32,
    /// Upper tick index
    pub tick_upper_index: i32,
}

/// Quote data for add liquidity operation
#[derive(Clone, Debug)]
pub struct AddLiquidityQuoteData {
    /// Liquidity delta
    pub liquidity_delta: u128,
    /// Estimated token A amount
    pub token_est_a: u64,
    /// Estimated token B amount
    pub token_est_b: u64,
}

/// Result of simulating a remove liquidity transaction
#[cfg(feature = "rpc")]
#[derive(Clone, Debug)]
pub struct SimulateRemoveLiquidityResult {
    /// Raw RPC simulation result containing execution status, logs, and compute
    /// units
    pub simulation: solana_client::rpc_response::RpcSimulateTransactionResult,
    /// Parsed LiquidityDecreased event from simulation logs (if available)
    pub liquidity_decreased_event: Option<LiquidityDecreasedEvent>,
    /// Quote data from instruction building (fallback if event not found)
    pub quote: Option<RemoveLiquidityQuoteData>,
}

/// Parsed LiquidityDecreased event data
#[derive(Clone, Debug)]
pub struct LiquidityDecreasedEvent {
    /// Position address
    pub position: Pubkey,
    /// Amount of liquidity removed
    pub liquidity: u128,
    /// Amount of token A removed
    pub token_a_amount: u64,
    /// Amount of token B removed
    pub token_b_amount: u64,
    /// Lower tick index
    pub tick_lower_index: i32,
    /// Upper tick index
    pub tick_upper_index: i32,
}

/// Quote data for remove liquidity operation
#[derive(Clone, Debug)]
pub struct RemoveLiquidityQuoteData {
    /// Liquidity delta (negative for removal)
    pub liquidity_delta: i128,
    /// Minimum token A amount
    pub token_min_a: u64,
    /// Minimum token B amount
    pub token_min_b: u64,
    /// Fees quote
    pub fees_quote: CollectFeesQuoteData,
}

/// Fees quote data
#[derive(Clone, Debug)]
pub struct CollectFeesQuoteData {
    /// Fee owed in token A
    pub fee_owed_a: u64,
    /// Fee owed in token B
    pub fee_owed_b: u64,
}

/// Result of simulating a collect fees transaction
#[cfg(feature = "rpc")]
#[derive(Clone, Debug)]
pub struct SimulateCollectResult {
    /// Raw RPC simulation result containing execution status, logs, and compute
    /// units
    pub simulation: solana_client::rpc_response::RpcSimulateTransactionResult,
    /// Fees quote from instruction building
    pub fees_quote: CollectFeesQuoteData,
}