← Back

Documentation

How $LP works, from launch and fee collection to autonomous liquidity management.

Overview

What is Liquid Pool?

$LP is a Solana token with an autonomous agent that manages all creator fees. There is no team wallet. There is no manual process. Every single fee generated by trading goes back into strengthening the token.

Pre-migration: fees are used to buy back $LP on the bonding curve, accumulating tokens. Post-migration: fees are used to deepen the liquidity pool on PumpSwap AMM. The agent decides automatically based on on-chain state.

Launch

Create your own token

The launch page lets anyone create a Pump.fun token directly from the browser. You connect a wallet, fill in name, symbol, image and an optional dev-buy, and sign one transaction. Metadata is pinned to IPFS, and the mint is created with an optional initial buy in the same transaction.

launch — createV2AndBuyInstructions
// Launch a new token (v1.36 createV2AndBuyInstructions)
const mint   = Keypair.generate();
const global = await pumpOnline.fetchGlobal();
const solBn  = new BN(Math.floor(devBuySol * 1e9));

const amount = getBuyTokenAmountFromSolAmount({
  global, feeConfig: null, mintSupply: null,
  bondingCurve: null, amount: solBn, quoteMint: NATIVE_MINT,
});

const ix = await pumpOffline.createV2AndBuyInstructions({
  global, mint: mint.publicKey,
  name, symbol, uri,            // uri = uploaded metadata
  creator: user, user,
  amount, solAmount: solBn,
  mayhemMode: false,
});

// user signs in the browser, mint keypair co-signs
await sendTransaction(new Transaction().add(...ix), connection, { signers: [mint] });

SDK setup

Agent initialization

The agent is a TypeScript process built on two official Pump.fun SDKs: pump-sdk (v1.36) for bonding curve operations, and pump-swap-sdk (v1.17) for AMM interactions post-migration. It connects to a Solana RPC, loads the agent keypair, and initializes both online (on-chain reads) and offline (instruction building) SDK instances.

src/run.ts — initialization
import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js";
import { TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
import { OnlinePumpSdk, PumpSdk, getBuyTokenAmountFromSolAmount } from "@pump-fun/pump-sdk";
import { OnlinePumpAmmSdk, PumpAmmSdk, canonicalPumpPoolPda } from "@pump-fun/pump-swap-sdk";
import BN from "bn.js";
import bs58 from "bs58";

const connection   = new Connection(process.env.RPC_URL, "confirmed");
const agent        = Keypair.fromSecretKey(bs58.decode(process.env.AGENT_PRIVATE_KEY));
const mint         = new PublicKey(process.env.MINT_ADDRESS);

const pumpOnline     = new OnlinePumpSdk(connection);
const pumpOffline    = new PumpSdk();
const pumpAmmOnline  = new OnlinePumpAmmSdk(connection);
const pumpAmmOffline = new PumpAmmSdk();

Fee collection

Step 1: Claim creator fees

Every cycle starts by checking the creator fee vault. Pump.fun accumulates trading fees in a vault PDA tied to the token creator. The agent calls getCreatorVaultBalanceBothPrograms to check both the bonding curve vault and the AMM vault in a single call.

If the vault holds more than 0.01 SOL, the agent claims everything. It measures actual SOL received by comparing wallet balance before and after — not the vault estimate.

src/run.ts — claimFees()
// check vault balance across both programs
const lamports = await pumpOnline
  .getCreatorVaultBalanceBothPrograms(agent.publicKey);

if (lamports.toNumber() / LAMPORTS_PER_SOL < 0.01) return; // wait

// claim all accumulated creator fees
const solBefore = await connection.getBalance(agent.publicKey);

const claimIx = await pumpOnline
  .collectCoinCreatorFeeInstructions(agent.publicKey, agent.publicKey);

await sendAndConfirm(connection, new Transaction().add(...claimIx), agent);

const solAfter = await connection.getBalance(agent.publicKey);
const claimed  = (solAfter - solBefore) / LAMPORTS_PER_SOL;

Pre-migration

Step 2a: Buyback on bonding curve

While the token is on the bonding curve, the agent uses 100% of claimed fees to buy $LP directly through the Pump.fun bonding curve program. In v1.36, getBuyTokenAmountFromSolAmount requires the quoteMint (WSOL) and computes the output using the constant-product formula adjusted for protocol and creator fees.

src/run.ts — doBuyback()
// fetch on-chain bonding curve state
const global = await pumpOnline.fetchGlobal();
const { bondingCurveAccountInfo, bondingCurve, associatedUserAccountInfo } =
  await pumpOnline.fetchBuyState(mint, agent.publicKey, TOKEN_2022_PROGRAM_ID);

// calculate how many tokens we get for our SOL (v1.36 — quoteMint required)
const solBn  = new BN(Math.floor(solAmount * 1e9));
const amount = getBuyTokenAmountFromSolAmount({
  global,
  feeConfig: null,
  mintSupply: bondingCurve.tokenTotalSupply,
  bondingCurve,
  amount: solBn,
  quoteMint: NATIVE_MINT,
});

// execute buy through bonding curve program
const buyIx = await pumpOffline.buyInstructions({
  global, bondingCurveAccountInfo, bondingCurve, associatedUserAccountInfo,
  mint, user: agent.publicKey, solAmount: solBn, amount,
  slippage: 2, tokenProgram: TOKEN_2022_PROGRAM_ID,
});

await sendAndConfirm(connection, new Transaction().add(...buyIx), agent);

Post-migration

Step 2b: Add liquidity to AMM

Once $LP migrates to PumpSwap AMM, the strategy shifts entirely. Instead of buybacks, 100% of fees go into deepening the liquidity pool. 65% of the SOL buys tokens through the AMM, then the remaining 35% SOL plus the bought tokens are deposited together as balanced liquidity.

src/run.ts — add liquidity
// Post-migration: 65% buy + 35% LP deposit
const poolKey   = canonicalPumpPoolPda(mint);
const swapState = await pumpAmmOnline.swapSolanaState(poolKey, agent.publicKey);
const buyIx     = await pumpAmmOffline.buyQuoteInput(swapState, buySolBn, 5);
await sendAndConfirm(connection, new Transaction().add(...buyIx), agent);

await new Promise(r => setTimeout(r, 4000));

const liquidityState = await pumpAmmOnline.liquiditySolanaState(poolKey, agent.publicKey);
const { lpToken } = pumpAmmOffline
  .depositAutocompleteBaseAndLpTokenFromQuote(liquidityState, depositSolBn, 10);
const depositIx = await pumpAmmOffline.depositInstructions(liquidityState, lpToken, 10);
await sendAndConfirm(connection, new Transaction().add(...depositIx), agent);

The loop

Agent cycle

The agent runs an infinite loop. Each iteration: check vault, claim if possible, detect migration status, execute the right strategy, log results, wait. Default cycle interval is 60 seconds. The agent always keeps 0.02 SOL in the wallet as a reserve for transaction fees.

src/run.ts — main loop
while (true) {
  const vault = await checkVaultBalance();
  if (vault < 0.01) { await sleep(60_000); continue; }

  await claimFees();
  const migrated = await isTokenMigrated();

  if (!migrated) await doBuyback(claimed);   // bonding curve buy
  else           await doAddLp(claimed);      // 65% buy + 35% LP deposit

  await logCycle();                           // save to supabase
  await sleep(60_000);
}

Architecture

Data flow

Solana blockchain: the agent interacts directly with Pump.fun's on-chain programs — the bonding curve program (6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P) and the PumpSwap AMM program (PSwapMdSai8tjrEXcxFeQth87xC4rRsa4VA5mhGhXkP).

Supabase stores cumulative stats, the activity feed, and the latest agent thought. The website fetches data from Supabase and displays it read-only. Only the anon key is exposed to the frontend.