npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@paul.lumberwork/bonding-curve-sdk

v1.5.0

Published

SDK for Kick.fun clone - Solana bonding curve launchpad

Downloads

664

Readme

Kick.fun SDK

Solana program with Linear Bonding Curve for token launches. SDK package: @paul.lumberwork/bonding-curve-sdk

Overview

  • Program ID: 6o7oTqg2CfvcMCJTLNEJsef7c875zGpTvcnFctNAjudL
  • Admin Wallet: 7eGpbyRpcM7WpNKQtd6XkteNQWHbWXP7icZjKzNK2aTk
  • Network: Devnet / Localnet

Token Allocation

| Allocation | Percent | Description | |------------|---------|-------------| | Bonding Curve | 70% | Available for trading | | LP Reserve | 20% | Reserved for DEX migration | | Treasury | 10% | Platform treasury |

Trading Fees (Hardcoded)

| Fee | Percent | Recipient | |-----|---------|-----------| | Accumulated Fee | 0.5% | Accumulated in curve (withdrawn by admin) | | Admin Fee | 0.5% | Platform admin (immediate) | | Total | 1% | |

Bonding Curve Formula

Price = K x sold_supply
Cost  = K x (s2² - s1²) / 2 / K_SCALE

Where K_SCALE = 10^22

K Value Reference

| K Value | Target SOL | Use Case | |---------|------------|----------| | 60 | ~2 SOL | Testing | | 312 | ~10 SOL | Small launch | | 2156 | ~69 SOL | pump.fun style | | 3125 | ~100 SOL | Large launch |

Formula: Target SOL = K x 0.032

Note: total_supply and k are configured by admin in the Launchpad contract. Creators do not set these values.


SDK Usage

Installation

npm install @paul.lumberwork/bonding-curve-sdk

Setup

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import { KickFunSDK, formatTokens, formatSol, PROGRAM_ID } from "@paul.lumberwork/bonding-curve-sdk";
import idl from "@paul.lumberwork/bonding-curve-sdk/idl/kick_fun_program.json";

// Setup connection and wallet
const connection = new Connection("https://api.devnet.solana.com", "confirmed");
const wallet = new anchor.Wallet(keypair);
const provider = new anchor.AnchorProvider(connection, wallet, { commitment: "confirmed" });

// Create program instance
const program = new Program(idl as anchor.Idl, provider);

// Create SDK instance
const sdk = new KickFunSDK(program, wallet);

1. Initialize Launchpad (one-time, admin only)

const result = await sdk.initializeLaunchpad();
// Returns: "already_initialized" or transaction signature

2. Create Token Launch

const { txSignature, addresses, mintKeypair } = await sdk.createTokenLaunch({
  name: "My Token",
  symbol: "MTK",
  uri: "https://example.com/metadata.json",
});

const mint = mintKeypair.publicKey;
console.log("Mint:", mint.toString());
console.log("Token Launch PDA:", addresses.tokenLaunch.toString());

With Custom Creator Wallet:

const { txSignature, addresses, mintKeypair } = await sdk.createTokenLaunch({
  name: "My Token",
  symbol: "MTK",
  uri: "https://example.com/metadata.json",
  creatorWallet: new PublicKey("YourCreatorWalletAddress..."),
});

Parameters:

  • name: Token name
  • symbol: Token symbol
  • uri: Metadata URI (Metaplex standard)
  • creatorWallet: (Optional) Custom creator wallet. Defaults to SDK wallet.

Returns:

  • txSignature: Transaction hash
  • addresses.tokenLaunch: Token launch PDA
  • addresses.bondingCurve: Bonding curve PDA
  • addresses.vault: SOL vault PDA
  • addresses.curveTokenAccount: Token account for curve
  • addresses.metadata: Metaplex metadata PDA
  • mintKeypair: Keypair of the new token

3. Buy Tokens

const result = await sdk.buy(mint, 0.5, { computeUnits: 400_000 });

console.log("Tokens received:", formatTokens(result.tokensTraded));
console.log("Progress:", result.newProgress.toFixed(2) + "%");
console.log("Curve complete:", result.isCurveComplete);

Parameters:

  • mint: Token mint address (PublicKey)
  • solAmount: SOL to spend (number, e.g., 0.5 for 0.5 SOL)
  • options.computeUnits: Optional compute budget (default: none)

4. Sell Tokens

const result = await sdk.sell(mint, 10_000_000, 0, { computeUnits: 400_000 });

console.log("SOL received:", formatSol(result.solTraded));
console.log("Progress:", result.newProgress.toFixed(2) + "%");

Parameters:

  • mint: Token mint address (PublicKey)
  • tokenAmount: Tokens to sell (number, e.g., 10_000_000 for 10M)
  • minSolOut: Minimum SOL to receive, slippage protection (default: 0)
  • options.computeUnits: Optional compute budget

5. Estimate Buy (SOL -> Tokens)

const estimate = await sdk.estimateBuy(mint, 0.5);

console.log("Tokens out:", formatTokens(estimate.tokensOut));
console.log("SOL in (total):", formatSol(estimate.solIn));
console.log("SOL after fee:", formatSol(estimate.solAfterFee));
console.log("Fee:", formatSol(estimate.fee));
console.log("Price impact:", estimate.priceImpactBps, "bps");

6. Estimate Buy by Tokens (Tokens -> SOL needed)

const estimate = await sdk.estimateBuyByTokens(mint, 1_000_000); // 1M tokens

console.log("SOL needed:", formatSol(estimate.solIn));
console.log("SOL to curve:", formatSol(estimate.solAfterFee));
console.log("Fee:", formatSol(estimate.fee));
console.log("Tokens out:", formatTokens(estimate.tokensOut));

7. Estimate Sell (Tokens -> SOL)

const estimate = await sdk.estimateSell(mint, 10_000_000);

console.log("SOL before fee:", formatSol(estimate.solBeforeFee));
console.log("SOL out (net):", formatSol(estimate.solOut));
console.log("Fee:", formatSol(estimate.fee));
console.log("Tokens in:", formatTokens(estimate.tokensIn));

8. Estimate Sell by SOL (SOL desired -> Tokens to sell)

const estimate = await sdk.estimateSellBySol(mint, 0.5); // want 0.5 SOL

console.log("Tokens to sell:", formatTokens(estimate.tokensIn));
console.log("SOL before fee:", formatSol(estimate.solBeforeFee));
console.log("SOL out (net):", formatSol(estimate.solOut));
console.log("Fee:", formatSol(estimate.fee));

9. Get Progress

const progress = await sdk.getProgress(mint);

console.log("Progress:", progress.percent + "%");
console.log("SOL raised:", formatSol(progress.solRaised));
console.log("Current price:", progress.currentPrice.toString(), "lamports/token");
console.log("Complete:", progress.isComplete);

10. Get Curve State

const curve = await sdk.getCurveState(mint);

console.log("K:", curve.k.toString());
console.log("Sold:", formatTokens(curve.soldSupply));
console.log("For curve:", formatTokens(curve.tokensForCurve));
console.log("SOL reserves:", formatSol(curve.realSolReserves));
console.log("Complete:", curve.complete);

11. Get Token Launch State

const launch = await sdk.getTokenLaunchState(mint);

console.log("Name:", launch.name, `(${launch.symbol})`);
console.log("Creator:", launch.creator.toString());
console.log("Trading active:", launch.tradingActive);
console.log("Migrated:", launch.migrated);

12. Admin Withdraw (Admin Only)

if (wallet.publicKey.equals(ADMIN_WALLET)) {
  const result = await sdk.adminWithdraw(mint);
  console.log("SOL withdrawn:", formatSol(result.solWithdrawn));
  console.log("LP tokens:", formatTokens(result.tokensWithdrawn));
  console.log("Fees to treasury:", formatSol(result.feesToTreasury));
  console.log("Treasury tokens:", formatTokens(result.treasuryTokens));
}

Requirements:

  • Caller must be ADMIN_WALLET
  • Curve must be complete (70% sold)
  • Token not already migrated

Estimate Return Types

EstimateBuyResult

interface EstimateBuyResult {
  solIn: bigint;          // Total SOL user pays (including fee)
  solAfterFee: bigint;    // SOL that goes into the curve (after fee)
  tokensOut: bigint;      // Tokens user receives
  fee: bigint;            // Fee in SOL (lamports)
  pricePerToken: bigint;
  priceImpactBps: number;
}

Used by: estimateBuy(), estimateBuyByTokens()

EstimateSellResult

interface EstimateSellResult {
  tokensIn: bigint;       // Tokens user sells
  solBeforeFee: bigint;   // Gross SOL from curve (before fee)
  solOut: bigint;         // Net SOL user receives (after fee)
  fee: bigint;            // Fee in SOL (lamports)
  pricePerToken: bigint;
  priceImpactBps: number;
}

Used by: estimateSell(), estimateSellBySol()

Note: Fee is always denominated in SOL (lamports).


Event Listeners

Subscribe to real-time events from the program.

Available Events

| Event | Description | |-------|-------------| | LaunchCreated | New token launch created | | TokensPurchased | Tokens bought on bonding curve | | TokensSold | Tokens sold on bonding curve | | CurveComplete | Bonding curve reached 100% | | AdminWithdraw | Admin withdrew SOL + LP tokens |

Listen for Token Purchases

const listenerId = sdk.onTokensPurchased((event, slot, signature) => {
  console.log("Buy Event:", {
    buyer: event.buyer.toString(),
    mint: event.mint.toString(),
    solAmount: formatSol(event.solAmount),
    solAfterFees: formatSol(event.solAfterFees),
    tokensReceived: formatTokens(event.tokensReceived),
    curveFee: formatSol(event.curveFee),
    adminFee: formatSol(event.adminFee),
    progress: event.progress + "%",
    complete: event.isCurveComplete,
  });
});

// Unsubscribe when done
await sdk.removeEventListener(listenerId);

Listen for Token Sales

const listenerId = sdk.onTokensSold((event, slot, signature) => {
  console.log("Sell Event:", {
    seller: event.seller.toString(),
    tokensSold: formatTokens(event.tokensSold),
    grossSolRefund: formatSol(event.grossSolRefund),
    netSolRefund: formatSol(event.netSolRefund),
    curveFee: formatSol(event.curveFee),
    adminFee: formatSol(event.adminFee),
    progress: event.progress + "%",
  });
});

Listen for New Launches

sdk.onLaunchCreated((event, slot, signature) => {
  console.log("New Launch:", {
    name: event.name,
    symbol: event.symbol,
    mint: event.mint.toString(),
    creator: event.creator.toString(),
    totalSupply: formatTokens(event.totalSupply),
    curveAllocation: formatTokens(event.curveAllocation),
    lpAllocation: formatTokens(event.lpAllocation),
    treasuryAllocation: formatTokens(event.treasuryAllocation),
    initialK: event.initialK.toString(),
  });
});

Listen for Curve Completion

sdk.onCurveComplete((event, slot, signature) => {
  console.log("Curve Complete!", {
    mint: event.mint.toString(),
    totalSolRaised: formatSol(event.totalSolRaised),
    finalPrice: event.finalPrice.toString(),
  });
});

Listen for Admin Withdrawals

sdk.onAdminWithdraw((event, slot, signature) => {
  console.log("Admin Withdrawal:", {
    mint: event.mint.toString(),
    solWithdrawn: formatSol(event.solWithdrawn),
    tokensWithdrawn: formatTokens(event.tokensWithdrawn),
    feesToTreasury: formatSol(event.feesToTreasury),
    treasuryTokens: formatTokens(event.treasuryTokens),
  });
});

Utility Functions

import { formatTokens, formatSol, parseSol, parseTokens } from "@paul.lumberwork/bonding-curve-sdk";

// Format raw values to readable strings
formatTokens(1000000000000n);  // "1,000,000" (1M tokens)
formatSol(500000000n);          // "0.5000" (0.5 SOL)

// Parse human values to raw
parseSol(0.5);                  // 500000000n (lamports)
parseTokens(1000000);           // 1000000000000n (raw with 6 decimals)

Constants

import { ADMIN_WALLET, K_SCALE, TOKEN_DECIMALS, FEE_BPS, PROGRAM_ID } from "@paul.lumberwork/bonding-curve-sdk";

PROGRAM_ID      // PublicKey: "6o7oTqg2CfvcMCJTLNEJsef7c875zGpTvcnFctNAjudL"
ADMIN_WALLET    // PublicKey: "7eGpbyRpcM7WpNKQtd6XkteNQWHbWXP7icZjKzNK2aTk"
K_SCALE         // 10^22 (bigint)
TOKEN_DECIMALS  // 6
FEE_BPS         // 100 (1%)
CURVE_PERCENT   // 70
LP_PERCENT      // 20
TREASURY_PERCENT // 10

PDA Seeds

| PDA | Seeds | |-----|-------| | Launchpad | ["launchpad"] | | Token Launch | ["token_launch", mint] | | Bonding Curve | ["bonding_curve", token_launch] | | Vault | ["vault", token_launch] | | User Position | ["user_position", token_launch, user] |


Full Example

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Connection, Keypair } from "@solana/web3.js";
import { KickFunSDK, formatTokens, formatSol, ADMIN_WALLET } from "@paul.lumberwork/bonding-curve-sdk";
import idl from "@paul.lumberwork/bonding-curve-sdk/idl/kick_fun_program.json";

async function main() {
  const connection = new Connection("https://api.devnet.solana.com", "confirmed");
  const wallet = new anchor.Wallet(keypair);
  const provider = new anchor.AnchorProvider(connection, wallet, { commitment: "confirmed" });
  const program = new Program(idl as anchor.Idl, provider) as any;
  const sdk = new KickFunSDK(program, wallet);

  // 1. Initialize launchpad (admin only, one-time)
  await sdk.initializeLaunchpad();

  // 2. Create token (total_supply and k are set by admin)
  const { addresses, mintKeypair } = await sdk.createTokenLaunch({
    name: "Test Token",
    symbol: "TEST",
    uri: "https://example.com/metadata.json",
  });
  const mint = mintKeypair.publicKey;

  // 3. Estimate before buying
  const buyEstimate = await sdk.estimateBuy(mint, 0.5);
  console.log("Will receive:", formatTokens(buyEstimate.tokensOut), "tokens");
  console.log("Fee:", formatSol(buyEstimate.fee));

  // 4. Buy tokens
  const buy = await sdk.buy(mint, 0.5, { computeUnits: 400_000 });
  console.log("Bought:", formatTokens(buy.tokensTraded));

  // 5. Estimate sell by desired SOL
  const sellEstimate = await sdk.estimateSellBySol(mint, 0.3);
  console.log("Need to sell:", formatTokens(sellEstimate.tokensIn), "tokens to get 0.3 SOL");

  // 6. Sell tokens
  const sell = await sdk.sell(mint, 10_000_000, 0, { computeUnits: 400_000 });
  console.log("Sold for:", formatSol(sell.solTraded), "SOL");

  // 7. Check progress
  const progress = await sdk.getProgress(mint);
  console.log("Progress:", progress.percent + "%");

  // 8. Admin withdraw (when curve complete)
  if (progress.isComplete && wallet.publicKey.equals(ADMIN_WALLET)) {
    const withdraw = await sdk.adminWithdraw(mint);
    console.log("Withdrawn:", formatSol(withdraw.solWithdrawn), "SOL");
  }
}

main().catch(console.error);

Running Tests

# Start local validator
solana-test-validator --reset

# In another terminal
cd kick_fun_program
anchor build && anchor deploy

# Run test
ANCHOR_PROVIDER_URL=http://127.0.0.1:8899 \
ANCHOR_WALLET=./test-keypair.json \
npx ts-node test-sdk.ts

License

MIT