For the complete documentation index, see llms.txt. This page is also available as Markdown.

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 via collectStakeRewardWithAction.

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 outcome

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

Operations that produce staked sFLP — minting sFLP, and the FLP → sFLP / sFLP → FLP migrations — need one extra step after settlement: refreshStakeEr, which activates the newly staked amount. See Activating a stake below.

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).

A still-open receipt blocks new operations of the same type for that wallet, so always finalize (or resume) before retrying.

Quotes (views)

Quote amounts and fees before depositing, then derive minAmountOut from a slippage tolerance:

Last updated

Was this helpful?