Skip to main content
LP price is based on effective NAV, not raw token balance. Use LP price helpers when possible. For raw/display units, see Units and Fees.

LP Price

lpPrice=effectiveNAV+1NAVtotalLpSupply+1\text{lpPrice} = \left\lfloor \frac{\text{effectiveNAV} + 1_{\text{NAV}}}{\text{totalLpSupply} + 1} \right\rfloor The virtual terms make empty-supply and first-deposit cases well-defined. In raw SDK bigint values, 1_NAV is 1_000_000_000_000.

TypeScript Reads

await market.reload(); // Refetches local account state only.

const seniorLpPrice = market.getSrLpPriceNetAsset();
const juniorLpPrice = market.getJrLpPriceNetAsset();

const seniorEffectiveNav = market.getSrEffNetAssetValue();
const juniorEffectiveNav = market.getJrEffNetAssetValue();
market.reload() refreshes the SDK’s local account state. It does not run market sync onchain. The LP price helpers use the effective NAV and LP supply already stored in the loaded market account.

Rust Account Reads

Oracle, lending, and risk integrations can read LP pricing inputs directly from the ExponentTranchingMarket account. Use the same fields that back the SDK helpers. These fields are the latest values written to the market account. Plain SPL transfers do not change them, and market.reload() only re-fetches the stored account data. Deposit and withdrawal instructions run the market-update path before they calculate outputs.
InputRust account fieldRaw dimension
Senior effective NAVmarket.financials.sr_effective_net_assetNumber fixed-point NAV
Junior effective NAVmarket.financials.jr_effective_net_assetNumber fixed-point NAV
Senior raw NAVmarket.financials.sr_raw_net_assetNumber fixed-point NAV
Junior raw NAVmarket.financials.jr_raw_net_assetNumber fixed-point NAV
Senior LP supplymarket.tranche_supply_state.total_senior_lp_supplyRaw LP mint units
Junior LP supplymarket.tranche_supply_state.total_junior_lp_supplyRaw LP mint units
Last sync timestampmarket.financials.last_sync_tsUnix timestamp seconds
See TranchingMarketFinancials and TrancheSupplyState for the full account layout. Import the fixed-point NAV type from the public number crate as precise_number::Number.
use exponent_tranching::ExponentTranchingMarket;
use precise_number::Number;

// `market` is the deserialized ExponentTranchingMarket account.
fn calculate_lp_price_net_asset(
    total_lp_supply: u64,
    effective_nav: Number,
) -> Option<Number> {
    let virtual_total_supply = (total_lp_supply as u128).checked_add(1)?;
    let virtual_total_assets = effective_nav.checked_add(&Number::ONE)?;

    virtual_total_assets.checked_div(&Number::from(virtual_total_supply))
}

fn senior_lp_price_from_market(market: &ExponentTranchingMarket) -> Option<Number> {
    calculate_lp_price_net_asset(
        market.tranche_supply_state.total_senior_lp_supply,
        market.financials.sr_effective_net_asset,
    )
}

fn junior_lp_price_from_market(market: &ExponentTranchingMarket) -> Option<Number> {
    calculate_lp_price_net_asset(
        market.tranche_supply_state.total_junior_lp_supply,
        market.financials.jr_effective_net_asset,
    )
}
Number uses 1_000_000_000_000 as one unit. Converting the Number scale does not apply LP or SY mint decimals. LP mints use the same decimals as the linked SY mint.

Position NAV

For collateral or portfolio integrations, price LP balances from effective NAV: positionNAV=lpBalance×lpPrice\text{positionNAV} = \text{lpBalance} \times \text{lpPrice} In raw SDK values, lpPrice is already NAV per raw LP share, so lpBalanceRaw * lpPriceRaw returns raw fixed-point NAV units. If your system normalizes token amounts for display, normalize both LP balance and NAV consistently at the display layer. For transaction preview formulas, see Deposit Previews and Withdrawal Previews.