Program IDs
JustPump consists of two main programs for token launching and trading.
Mainnet (Coming Soon)
Devnet
Launchpad Program:AMM Program:Mainnet deployment pending. Use devnet for development and testing.
Launchpad Program:3cFH7XveLjWZehiAfFeWYKEnch2n6NzCxYAVvRNEwhTq
AMM Program:56Sx4pQJYsksMBNo75KXctKfTvvsBrrdfZCAiJS91SDK
These are active devnet addresses for testing integrations.
Quick Start
What You Can Do
Create Tokens
Launch new tokens with bonding curves
Buy/Sell
Trade on bonding curves before graduation
Swap
Trade graduated tokens on JustSwap AMM
Query State
Read token info, prices, and liquidity
Creating a Token
Create a new token with bonding curve trading enabled immediately.
Instruction: create_coin
Parameters:
name (string): Token name, max 32 characters
symbol (string): Token symbol, max 10 characters
uri (string): Metadata URI (JSON), max 200 characters
vanity_nonce (u64): Nonce for vanity mint address (must result in ‘JP’ prefix)
Key Accounts:
creator (signer, writable): Your wallet
mint (PDA): Token mint address - derive with ["mint", creator, vanity_nonce]
coin (PDA): Coin metadata - derive with ["coin", mint]
bonding_curve (PDA): Bonding curve state - derive with ["bonding-curve", mint]
Fees: Only transaction fee (~0.01 SOL), no creation fee
Example
import * as anchor from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";
const LAUNCHPAD_PROGRAM_ID = new PublicKey(
"3cFH7XveLjWZehiAfFeWYKEnch2n6NzCxYAVvRNEwhTq",
);
// Find vanity nonce that creates mint starting with 'JP'
let vanityNonce = 0;
let mint;
do {
[mint] = PublicKey.findProgramAddressSync(
[
Buffer.from("mint"),
creator.publicKey.toBuffer(),
Buffer.from([vanityNonce]),
],
LAUNCHPAD_PROGRAM_ID,
);
vanityNonce++;
} while (!mint.toBase58().startsWith("JP"));
// Derive PDAs
const [coin] = PublicKey.findProgramAddressSync(
[Buffer.from("coin"), mint.toBuffer()],
LAUNCHPAD_PROGRAM_ID,
);
const [bondingCurve] = PublicKey.findProgramAddressSync(
[Buffer.from("bonding-curve"), mint.toBuffer()],
LAUNCHPAD_PROGRAM_ID,
);
// Create token
await program.methods
.createCoin(
"My Token",
"MTKN",
"https://arweave.net/your-metadata-hash",
vanityNonce - 1,
)
.accounts({
creator: creator.publicKey,
mint,
coin,
bondingCurve,
// ... see full account list in IDL
})
.signers([creator])
.rpc();
Token metadata should follow Metaplex standards. Upload JSON to Arweave or
IPFS first.
Buying Tokens (Bonding Curve)
Buy tokens on the bonding curve before graduation.
Instruction: buy_exact_quote_in
Parameters:
spendable_quote_in (u64): Maximum SOL to spend (in lamports)
min_tokens_out (u64): Minimum tokens to receive (slippage protection)
Key Accounts:
buyer (signer, writable): Your wallet
mint: Token mint address
coin (PDA): Derive with ["coin", mint]
bonding_curve (PDA): Derive with ["bonding-curve", mint]
buyer_quote: Your WSOL token account
buyer_token: Your token account for the mint
Fees: 1.3% total (60 BPS platform, 50 BPS creator, 20 BPS insurance)
Example
const solAmount = 1_000_000_000; // 1 SOL
const slippage = 0.01; // 1%
// Calculate minimum tokens with slippage
const expectedTokens = calculateBondingCurveOutput(
solAmount,
bondingCurveState,
);
const minTokensOut = Math.floor(expectedTokens * (1 - slippage));
await program.methods
.buyExactQuoteIn(new anchor.BN(solAmount), new anchor.BN(minTokensOut))
.accounts({
buyer: buyer.publicKey,
mint,
coin,
bondingCurve,
buyerQuote: buyerWsolAccount,
buyerToken: buyerTokenAccount,
// ... see full account list in IDL
})
.signers([buyer])
.rpc();
You need to wrap SOL to WSOL first using SystemProgram.transfer +
Token.syncNative.
Selling Tokens (Bonding Curve)
Sell tokens on the bonding curve. Limited to 10% of circulating supply per transaction.
Instruction: sell_on_curve
Parameters:
tokens_in (u64): Amount of tokens to sell
Key Accounts:
seller (signer, writable): Your wallet
mint: Token mint address
coin (PDA): Derive with ["coin", mint]
bonding_curve (PDA): Derive with ["bonding-curve", mint]
seller_token: Your token account
seller_quote: Your WSOL token account
Constraint: tokens_in <= (bonding_curve.tokens_sold * 1000) / 10000 (10% max)
Example
const tokensToSell = 100_000_000_000; // 100 tokens with 9 decimals
// Check 10% constraint
const bondingCurveData = await program.account.bondingCurve.fetch(bondingCurve);
const maxSell = (bondingCurveData.tokensSold * 1000n) / 10000n;
if (BigInt(tokensToSell) > maxSell) {
throw new Error(`Exceeds 10% max sell. Max: ${maxSell}`);
}
await program.methods
.sellOnCurve(new anchor.BN(tokensToSell))
.accounts({
seller: seller.publicKey,
mint,
coin,
bondingCurve,
sellerToken: sellerTokenAccount,
sellerQuote: sellerWsolAccount,
// ... see full account list in IDL
})
.signers([seller])
.rpc();
Selling more than 10% of circulating supply will fail. Split large sells into
multiple transactions.
Swapping on JustSwap (AMM)
Trade graduated tokens on the constant product AMM.
Instruction: swap_quote_for_base (SOL → Token)
Parameters:
quote_in (u64): Amount of SOL to swap (in lamports)
min_base_out (u64): Minimum tokens to receive (slippage protection)
Key Accounts:
trader (signer, writable): Your wallet
pool (PDA): Derive with ["pool", base_mint, quote_mint]
trader_quote: Your WSOL account
trader_base: Your token account
Instruction: swap_base_for_quote (Token → SOL)
Parameters:
base_in (u64): Amount of tokens to swap
min_quote_out (u64): Minimum SOL to receive (slippage protection)
Key Accounts: Same as above, reversed
Fees: 1.3% total (same as bonding curve)
Example
const AMM_PROGRAM_ID = new PublicKey(
"56Sx4pQJYsksMBNo75KXctKfTvvsBrrdfZCAiJS91SDK",
);
// Derive pool PDA
const [pool] = PublicKey.findProgramAddressSync(
[Buffer.from("pool"), baseMint.toBuffer(), quoteMint.toBuffer()],
AMM_PROGRAM_ID,
);
// Swap SOL for tokens
const quoteAmount = 500_000_000; // 0.5 SOL
const poolData = await ammProgram.account.pool.fetch(pool);
// Calculate output with constant product formula: dy = (y * dx) / (x + dx)
const dx = quoteAmount * 0.987; // After 1.3% fee
const dy = (poolData.baseReserve * dx) / (poolData.quoteReserve + dx);
const minBaseOut = Math.floor(dy * 0.99); // 1% slippage
await ammProgram.methods
.swapQuoteForBase(new anchor.BN(quoteAmount), new anchor.BN(minBaseOut))
.accounts({
trader: trader.publicKey,
pool,
traderQuote: traderWsolAccount,
traderBase: traderTokenAccount,
// ... see full account list in IDL
})
.signers([trader])
.rpc();
PDA Derivations
All Program Derived Addresses use deterministic seeds.
Launchpad Program PDAs
const LAUNCHPAD = new PublicKey("3cFH7XveLjWZehiAfFeWYKEnch2n6NzCxYAVvRNEwhTq");
// Global config
const [globalConfig] = PublicKey.findProgramAddressSync(
[Buffer.from("global")],
LAUNCHPAD,
);
// Coin metadata
const [coin] = PublicKey.findProgramAddressSync(
[Buffer.from("coin"), mint.toBuffer()],
LAUNCHPAD,
);
// Bonding curve
const [bondingCurve] = PublicKey.findProgramAddressSync(
[Buffer.from("bonding-curve"), mint.toBuffer()],
LAUNCHPAD,
);
// Vanity mint (must start with 'JP')
const [mint] = PublicKey.findProgramAddressSync(
[Buffer.from("mint"), creator.toBuffer(), Buffer.from([nonce])],
LAUNCHPAD,
);
// Token vaults
const [vaultToken] = PublicKey.findProgramAddressSync(
[Buffer.from("vault-token"), mint.toBuffer()],
LAUNCHPAD,
);
const [vaultQuote] = PublicKey.findProgramAddressSync(
[Buffer.from("vault-quote"), mint.toBuffer()],
LAUNCHPAD,
);
AMM Program PDAs
const AMM = new PublicKey("56Sx4pQJYsksMBNo75KXctKfTvvsBrrdfZCAiJS91SDK");
// AMM config
const [ammConfig] = PublicKey.findProgramAddressSync(
[Buffer.from("amm-config")],
AMM,
);
// Pool
const [pool] = PublicKey.findProgramAddressSync(
[Buffer.from("pool"), baseMint.toBuffer(), quoteMint.toBuffer()],
AMM,
);
// Pool vaults
const [poolVaultBase] = PublicKey.findProgramAddressSync(
[Buffer.from("pool-vault-base"), baseMint.toBuffer(), quoteMint.toBuffer()],
AMM,
);
const [poolVaultQuote] = PublicKey.findProgramAddressSync(
[Buffer.from("pool-vault-quote"), baseMint.toBuffer(), quoteMint.toBuffer()],
AMM,
);
Reading State
Fetch on-chain data to display prices, liquidity, and token info.
Get Token Info
// Fetch coin metadata
const coinData = await program.account.coin.fetch(coin);
console.log({
name: coinData.name,
symbol: coinData.symbol,
creator: coinData.creator.toBase58(),
status: coinData.status, // { onCurve: {} } | { readyToMigrate: {} } | { migrated: {} }
totalSupply: coinData.totalSupply.toString(),
ammPool: coinData.ammPool?.toBase58() || null,
});
Get Bonding Curve State
// Fetch bonding curve data
const curveData = await program.account.bondingCurve.fetch(bondingCurve);
console.log({
tokensSold: curveData.tokensSold.toString(),
collectedQuote: curveData.collectedQuote.toString(), // SOL collected
virtualSolReserves: curveData.virtualSolReserves.toString(),
virtualTokenReserves: curveData.virtualTokenReserves.toString(),
});
// Calculate current price
const price =
(curveData.virtualSolReserves * 1e9) / curveData.virtualTokenReserves;
console.log(`Current price: ${price} SOL per token`);
Get Pool State
// Fetch AMM pool data
const poolData = await ammProgram.account.pool.fetch(pool);
console.log({
baseReserve: poolData.baseReserve.toString(),
quoteReserve: poolData.quoteReserve.toString(),
canonical: poolData.canonical,
creator: poolData.creator.toBase58(),
});
// Calculate current price
const price = (poolData.quoteReserve * 1e9) / poolData.baseReserve;
console.log(`Current price: ${price} SOL per token`);
Token Programs
Token-2022
Program ID: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEbUsed For: All user-created tokensFeatures: Metadata Extension support
SPL Token
Program ID: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DAUsed For: WSOL (quote token) and LP tokensStandard: Original SPL Token program
Common Errors
| Error | Cause | Solution |
|---|
ExceedsMaxSellImpact | Trying to sell > 10% of supply | Split into multiple transactions |
SlippageExceeded | Price moved beyond min output | Increase slippage tolerance |
NotReadyToMigrate | Trying to migrate < 85 SOL | Wait until 85 SOL collected |
AlreadyMigrated | Token already graduated | Use AMM swap instead of bonding curve |
InvalidVanityMint | Mint doesn’t start with ‘JP’ | Iterate vanity nonce until valid |
Helper Functions
Calculate Bonding Curve Output
function calculateBondingCurveOutput(
solIn: number,
curve: { virtualSolReserves: BN; virtualTokenReserves: BN },
): number {
const k = curve.virtualSolReserves.mul(curve.virtualTokenReserves);
const newSolReserves = curve.virtualSolReserves.add(new BN(solIn));
const newTokenReserves = k.div(newSolReserves);
const tokensOut = curve.virtualTokenReserves.sub(newTokenReserves);
// Apply 1.3% fee
return tokensOut.muln(987).divn(1000).toNumber();
}
Calculate AMM Output
function calculateAmmOutput(
amountIn: number,
reserveIn: BN,
reserveOut: BN,
): number {
// Constant product: x * y = k
// dy = (y * dx) / (x + dx)
// Apply 1.3% fee
const amountInWithFee = Math.floor(amountIn * 0.987);
const numerator = reserveOut.muln(amountInWithFee);
const denominator = reserveIn.addn(amountInWithFee);
return numerator.div(denominator).toNumber();
}
Resources
Support
For developer support: