LP Interactions
Two LP tokens — pick one before you deposit:
FLP — auto-compounding (
addCompoundingLiquidityWithAction). Mints a token whose value grows as fees compound automatically. No manual claim step.sFLP — staked (
addLiquidityAndStakeWithAction). Earns a daily yield you claim separately viacollectStakeRewardWithAction.
You can move between the two with migrateStakeWithAction (sFLP → FLP) and migrateFlpWithAction (FLP → sFLP).
Liquidity is pool-scoped — each pool has its own FLP/sFLP mints and custodies (poolConfig.compoundingTokenMint is the FLP mint). Set up flashClient, poolConfig, and walletKeypair as shown on the Flash SDK v2 landing page. Every snippet assumes they're in scope, and that you've loaded the pool's address lookup tables into an alts array (LP transactions are large).
The flow model
Each liquidity operation is a multi-step flow you drive yourself. You submit a *WithAction transaction, wait for its receipt to be ready, submit the matching *Er commit, then wait for settlement and read the outcome. Pass queueErAction: false so you stay in control of every step.
1. submit addCompoundingLiquidityWithAction sendAndConfirmTransaction
2. wait receipt becomes ready
3. commit addCompoundingLiquidityEr sendAndConfirmErTransaction (throwaway payer)
4. settle receipt closes → read the outcomeA confirmed transaction is not a successful deposit. On a slippage or cap miss the program refunds you and the transaction still succeeds. Always read the receipt's decision field before treating the mint/burn as done.
Helper pollers used by every flow (a missing account reads back with zero lamports, not null):
const exists = (info: { lamports: number } | null) => info !== null && info.lamports > 0
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
const pollReady = async (pk: PublicKey, timeoutMs = 30_000) => {
const deadline = Date.now() + timeoutMs
while (Date.now() < deadline) {
if (exists(await flashClient.erConnection!.getAccountInfo(pk).catch(() => null))) return
await sleep(1_000)
}
throw new Error(`receipt ${pk.toBase58()} not ready`)
}
const pollClosed = async (pk: PublicKey, timeoutMs = 60_000) => {
const deadline = Date.now() + timeoutMs
let seen = false
while (Date.now() < deadline) {
const info = await flashClient.connection.getAccountInfo(pk).catch(() => null)
if (exists(info)) seen = true
else if (seen) return // existed, now gone → settled
await sleep(3_000)
}
throw new Error(`receipt ${pk.toBase58()} never closed`)
}Each operation pairs a *WithAction builder with an *Er commit, a *Settle, and a receipt-address finder:
Operation
submit (*WithAction)
commit (*Er)
settle
receipt finder
Mint FLP (compounding)
addCompoundingLiquidityWithAction
addCompoundingLiquidityEr
addCompoundingLiquiditySettle
findCompDepositReceiptAddress
Burn FLP
removeCompoundingLiquidityWithAction
removeCompoundingLiquidityEr
removeCompoundingLiquiditySettle
findCompWithdrawReceiptAddress
Mint sFLP (staked)
addLiquidityAndStakeWithAction
addLiquidityAndStakeEr
addLiquidityAndStakeSettle
findStakingDepositReceiptAddress
Burn sFLP
removeLiquidityWithAction
removeLiquidityEr
removeLiquiditySettle
findStakingWithdrawReceiptAddress
sFLP → FLP
migrateStakeWithAction
migrateStakeEr
migrateStakeSettle
findMigrateStakeReceiptAddress
FLP → sFLP
migrateFlpWithAction
migrateFlpEr
migrateFlpSettle
findMigrateFlpReceiptAddress
Collect sFLP rewards
collectStakeRewardWithAction
—
—
findCollectStakeRewardReceiptAddress
Mint FLP (auto-compounding)
The full four-step flow. Other operations follow the identical shape — only the builders and receipt change.
Mint sFLP (staked)
sFLP isn't minted to an ATA — it's staked. After settlement, activate the stake with refreshStakeEr.
Activating a stake
refreshStakeEr promotes a newly staked amount to active. Call it after minting sFLP, and after either migration. It's a single commit signed by a throwaway payer:
Burn FLP
Burn sFLP
Collect sFLP staking rewards
sFLP earns a daily yield as a claimable balance. FLP holders don't need this — fees auto-compound into the token's value.
Migrate between FLP and sFLP
The migration that produces sFLP (migrateFlpWithAction, FLP → sFLP) — and the reverse — need refreshStakeEr after settlement.
Reading the outcome / resuming
After settlement, read the receipt's decision field from raw account bytes (a refund zeroes it). If a flow is interrupted, re-run it in resume mode: check whether the receipt is still pending its commit (drive the *Er step) or already processed (run the matching *Settle).
Quotes (views)
Quote amounts and fees before depositing, then derive minAmountOut from a slippage tolerance:
Last updated
Was this helpful?

