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=⌊totalLpSupply+1effectiveNAV+1NAV⌋
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.
| Input | Rust account field | Raw dimension |
|---|
| Senior effective NAV | market.financials.sr_effective_net_asset | Number fixed-point NAV |
| Junior effective NAV | market.financials.jr_effective_net_asset | Number fixed-point NAV |
| Senior raw NAV | market.financials.sr_raw_net_asset | Number fixed-point NAV |
| Junior raw NAV | market.financials.jr_raw_net_asset | Number fixed-point NAV |
| Senior LP supply | market.tranche_supply_state.total_senior_lp_supply | Raw LP mint units |
| Junior LP supply | market.tranche_supply_state.total_junior_lp_supply | Raw LP mint units |
| Last sync timestamp | market.financials.last_sync_ts | Unix 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
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.