LP Interactions

Creating LP Transactions

Add Liquidity / Mint sFLP

const addLiquidityAndStake = async () => {
    const usdcInputAmount = new BN(1_000_000); // $1
    
    // this can be any other token available in the pool, for instance SOL, BTC and ETH
    const usdcCustody = POOL_CONFIG.custodies.find(c => c.symbol === 'USDC')!;
    const slippageBps: number = 800 // 0.8%
    let instructions: TransactionInstruction[] = []
    let additionalSigners: Signer[] = []

    await flashClient.loadAddressLookupTable(POOL_CONFIG)

    // flash-sdk version >= 2.31.6
    const { amount: minLpAmountOut, fee } = await flashClient.getAddLiquidityAmountAndFeeView(usdcInputAmount, POOL_CONFIG.poolAddress, usdcCustody.custodyAccount, POOL_CONFIG);

    const minLpAmountOutAfterSlippage = minLpAmountOut
        .mul(new BN(10 ** BPS_DECIMALS - slippageBps))
        .div(new BN(10 ** BPS_DECIMALS))

    const setCULimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 }) // addLiquidity

    const addLiquidityAndStakeData = await flashClient.addLiquidityAndStake('USDC', usdcInputAmount, minLpAmountOutAfterSlippage, POOL_CONFIG);
    instructions.push(...addLiquidityAndStakeData.instructions)
    additionalSigners.push(...addLiquidityAndStakeData.additionalSigners)

    const flpStakeAccountPK = PublicKey.findProgramAddressSync(
        [Buffer.from('stake'), flashClient.provider.publicKey.toBuffer(), POOL_CONFIG.poolAddress.toBuffer()],
        POOL_CONFIG.programId
    )[0]

    const refreshStakeInstruction = await flashClient.refreshStake('USDC', POOL_CONFIG, [flpStakeAccountPK])

    instructions.push(refreshStakeInstruction)

    const trxId = await flashClient.sendTransaction([setCULimitIx, ...instructions])

    console.log('addLiquidityAndStake trx :>> ', trxId);
}

Add Compounding Liquidity / Mint FLP

const addCompoundingLiquidity = async () => {
    // USDC with its decimals 
    const usdcInputAmount = new BN(1_000_000); // $1
    
    // this can be any other token available in the pool, for instance SOL, BTC and ETH
    const usdcCustody = POOL_CONFIG.custodies.find(c => c.symbol === 'USDC')!;
    const slippageBps: number = 800 // 0.8%
    let instructions: TransactionInstruction[] = []
    let additionalSigners: Signer[] = []

    await flashClient.loadAddressLookupTable(POOL_CONFIG)

    // flash-sdk version >= 2.31.6
    const { amount: minLpAmountOut, fee } = await flashClient.getAddCompoundingLiquidityAmountAndFeeView(usdcInputAmount, POOL_CONFIG.poolAddress, usdcCustody.custodyAccount, POOL_CONFIG);

    const minLpAmountOutAfterSlippage = minLpAmountOut
        .mul(new BN(10 ** BPS_DECIMALS - slippageBps))
        .div(new BN(10 ** BPS_DECIMALS))

    const setCULimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 }) // addLiquidity

    const addCompoundingLiquidityData = await flashClient.addCompoundingLiquidity(
        usdcInputAmount,
        minLpAmountOutAfterSlippage,
        'USDC',
        usdcCustody.mintKey,
        POOL_CONFIG
    )

    instructions.push(...addCompoundingLiquidityData.instructions)
    additionalSigners.push(...addCompoundingLiquidityData.additionalSigners)

    const trxId = await flashClient.sendTransaction([setCULimitIx, ...instructions])

    console.log('addCompoundingLiquidity trx :>> ', trxId);
}

Remove Liquidity / Burn sFLP

const removeSflpLiquidity = async () => {
    const usdcCustody = POOL_CONFIG.custodies.find(c => c.symbol === 'USDC')!;
    const slippageBps: number = 800 // 0.8%
    let instructions: TransactionInstruction[] = []
    let additionalSigners: Signer[] = []

    await flashClient.loadAddressLookupTable(POOL_CONFIG)

    const flpStakeAccountPK = PublicKey.findProgramAddressSync(
        [Buffer.from('stake'), flashClient.provider.publicKey.toBuffer(), POOL_CONFIG.poolAddress.toBuffer()],
        POOL_CONFIG.programId
    )[0]

    const flpStakeAccount = await flashClient.program.account.flpStake.fetch(flpStakeAccountPK);

    const flpWithPendingAndActive =
        flpStakeAccount?.stakeStats.activeAmount.add(flpStakeAccount?.stakeStats.pendingActivation) ??
        BN_ZERO

    // flash-sdk version >= 2.31.6
    const { amount: minTokenAmountOut, fee } = await flashClient.getRemoveLiquidityAmountAndFeeView(flpWithPendingAndActive, POOL_CONFIG.poolAddress, usdcCustody.custodyAccount, POOL_CONFIG);

    const { instructions: unstakeInstantInstructions, additionalSigners: unstakeInstantAdditionalSigners } =
        await flashClient.unstakeInstant('USDC', flpWithPendingAndActive, POOL_CONFIG)

    const { instructions: withdrawStakeInstructions, additionalSigners: withdrawStakeAdditionalSigners } =
        await flashClient.withdrawStake(POOL_CONFIG, true, true)

    instructions.push(...unstakeInstantInstructions)
    additionalSigners.push(...unstakeInstantAdditionalSigners)

    instructions.push(...withdrawStakeInstructions)
    additionalSigners.push(...withdrawStakeAdditionalSigners)

    const minTokenAmountOutAfterSlippage = minTokenAmountOut
        .mul(new BN(10 ** BPS_DECIMALS - slippageBps))
        .div(new BN(10 ** BPS_DECIMALS))

    const removeLiquidityData = await flashClient.removeLiquidity(
        'USDC',
        flpWithPendingAndActive,
        minTokenAmountOutAfterSlippage,
        POOL_CONFIG
    )

    instructions.push(...removeLiquidityData.instructions)
    additionalSigners.push(...removeLiquidityData.additionalSigners)

    const setCULimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 }) // addLiquidity

    const trxId = await flashClient.sendTransaction([setCULimitIx, ...instructions])

    console.log('trx :>> ', trxId);
}

Remove Compounding Liquidity / Burn FLP

const removeFlpLiquidity = async () => {
    const usdcCustody = POOL_CONFIG.custodies.find(c => c.symbol === 'USDC')!;
    const slippageBps: number = 800 // 0.8%
    let instructions: TransactionInstruction[] = []
    let additionalSigners: Signer[] = []
    const usdcToken = POOL_CONFIG.tokens.find(t => t.symbol === 'USDC')!;

    await flashClient.loadAddressLookupTable(POOL_CONFIG)

    const account = getAssociatedTokenAddressSync(POOL_CONFIG.compoundingTokenMint, flashClient.provider.publicKey, true)

    const walletBalance = await flashClient.provider.connection.getTokenAccountBalance(account, 'processed')
    const compoundingTokenBalance = new BN(walletBalance.value.amount)

    // flash-sdk version >= 2.31.6
    const { amount: minTokenAmountOut, fee } = await flashClient.getRemoveCompoundingLiquidityAmountAndFeeView(compoundingTokenBalance, POOL_CONFIG.poolAddress, usdcCustody.custodyAccount, POOL_CONFIG);

    const minTokenAmountOutAfterSlippage = minTokenAmountOut
        .mul(new BN(10 ** BPS_DECIMALS - slippageBps))
        .div(new BN(10 ** BPS_DECIMALS))

    const removeCompoundingLiquidityData = await flashClient.removeCompoundingLiquidity(
        compoundingTokenBalance,
        minTokenAmountOutAfterSlippage,
        'USDC',
        usdcToken.mintKey,
        POOL_CONFIG,
        true
    )

    instructions.push(...removeCompoundingLiquidityData.instructions)
    additionalSigners.push(...removeCompoundingLiquidityData.additionalSigners)

    const setCULimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 }) // addLiquidity

    const trxId = await flashClient.sendTransaction([setCULimitIx, ...instructions])

    console.log('trx :>> ', trxId);
}

Get FLP/sFLP token prices

1) Using SDK (Advanced Integration)

const getLpTokenPrices = async () => {
    await flashClient.loadAddressLookupTable(POOL_CONFIG)
    const stakedLpPrice = await flashClient.getStakedLpTokenPrice(POOL_CONFIG.poolAddress, POOL_CONFIG); // sFLP price
    const compoundingLPTokenPrice = await flashClient.getCompoundingLPTokenPrice(POOL_CONFIG.poolAddress, POOL_CONFIG); // FLP price

    console.log('stakedLpPrice :>> ', stakedLpPrice);
    console.log('compoundingLPTokenPrice :>> ', compoundingLPTokenPrice);
}

2) Using API (Quick & Easy)

Query the following endpoint to get price data for all pools:

https://api.prod.flash.trade/earn-page/data

✅ Response Format (Example)

The response is a JSON object containing an array of pools, each representing a unique FLP pool. Here's what each key means:

Field
Description

poolAddress

The unique on-chain address of the liquidity pool

aum

Assets under management (in USD) for this pool

flpTokenSymbol

Symbol for the compounding FLP token (e.g., FLP.1, FLP.2)

sFlpTokenSymbol

Symbol for the staked FLP token (e.g., sFLP.1, sFLP.2)

flpDailyApy

Daily APY for compounding FLP token (auto-reinvested)

flpWeeklyApy

Weekly APY for compounding FLP token

flpWeeklyApr

Weekly APR for compounding FLP token (non-compounding)

sFlpDailyApr

Daily APR for staked FLP token (non-compounding)

sFlpPrice

Current price of staked FLP token

flpPrice

Current price of compounding FLP token

sFlpPriceWithYield

Derived price of sFLP token if yield is included in valuation

🔎 How to Use

To get token prices:

  • Match the flpTokenSymbol (e.g., "FLP.1") or poolAddress to identify your desired pool.

  • Use flpPrice for the compounding FLP token and sFlpPrice for the staked version.

This is the easiest method for frontends and dashboards needing real-time pricing and yield data without setting up the SDK or querying the blockchain.

Last updated

Was this helpful?