Skip to main content

Pump.fun Jito Bundles

Jito bundles let you execute multiple Solana transactions atomically in the same block. On Pump.fun, this means you can launch a token and have multiple wallets buy it simultaneously — no front-running, no failed partial executions, and guaranteed transaction ordering.

PumpDev supports Jito bundles across token creation, trading, and Lightning APIs:

API EndpointBundle TypeDescription
POST /api/bundleLocal-Sign BundleUnsigned bundle — you sign locally + send to Jito
POST /api/bundle-lightningLightning BundleOne-call server-signed bundle (buy/sell/create) — sends via Jito
POST /api/createCreate + Dev BuySplit create + buy into Jito bundle for faster landing
POST /api/create-bundleMulti-Buyer LaunchCreator + up to 3 additional buyers atomically
POST /api/trade-bundleMulti-Wallet TradeMultiple wallets buy or sell in one bundle
Bundle APIs
  • /api/bundle — returns unsigned txs. You sign locally and send to Jito (uses publicKey). Full control over signing and submission.
  • /api/bundle-lightning — server signs AND sends via Jito. One call, fully managed (uses apiKey).

Why Use Jito Bundles on Pump.fun?​

Without Bundles (Standard RPC)​

When you send transactions individually via standard RPC:

  • Transactions land in different blocks (or never land)
  • Other bots can front-run your buy after seeing the token creation
  • No guarantee of execution order — buyer 2 might execute before buyer 1
  • If one transaction fails, others may still execute (partial state)

With Jito Bundles​

All transactions in a bundle execute atomically in one block:

  • Atomic Execution — All transactions succeed or all fail together
  • No Front-Running — Creator + buyers land in the same block, in order
  • Guaranteed Ordering — Transaction 1 always executes before transaction 2
  • Faster Landing — Jito validators prioritize bundles with tips
  • Up to 5 Transactions — Enough for creator + 3 buyers + tip

How Jito Bundles Work​

┌──────────────────────────────────────────────────────┐
│ Jito Bundle │
│ │
│ TX 1: Create Token (signed: creator + mint) │
│ TX 2: Creator Buy (signed: creator) │
│ TX 3: Buyer 1 Buy (signed: buyer1) │
│ TX 4: Buyer 2 Buy (signed: buyer2) │
│ │
│ All execute atomically in ONE Solana block │
└──────────────────────────────────────────────────────┘
  1. PumpDev API builds all transactions with a shared blockhash
  2. You sign each transaction with the appropriate keypair(s)
  3. You send all signed transactions to a Jito block engine endpoint
  4. Jito validators execute them atomically in sequence

Local-Sign Bundle: POST /api/bundle​

POST /api/bundle builds a Jito bundle and returns unsigned transactions for client-side signing. Same flexible request format as /api/bundle-lightning (buy, sell, create — up to 5 transactions), but you sign with your own private keys and send to Jito yourself.

Use this when you keep your private keys local and want full control over signing and bundle submission.

Request​

Same structure as bundle-lightning, but uses publicKey instead of apiKey per account:

{
"accounts": [
{ "publicKey": "WalletPublicKey", "type": "buy", "amount": 0.1, "denominatedInSol": "true" }
],
"mint": "TokenMintAddress",
"jitoTip": 0.01
}

All top-level parameters and account entry types from Lightning Bundle apply — just swap apiKey for publicKey.

Response​

{
"transactions": [
{
"transaction": "base58_unsigned_tx",
"signers": ["WalletPublicKey"],
"type": "buy",
"publicKey": "WalletPublicKey",
"error": null
}
],
"mint": "TokenMintAddress"
}

For create bundles, the response also includes mintSecretKey and the create transaction lists both the creator and mint public keys in signers:

{
"transactions": [
{
"transaction": "base58_unsigned_tx",
"signers": ["CreatorPublicKey", "MintPublicKey"],
"type": "create",
"publicKey": "CreatorPublicKey",
"mint": "MintPublicKey",
"metadataUri": "https://..."
},
{
"transaction": "base58_unsigned_tx",
"signers": ["CreatorPublicKey"],
"type": "buy",
"publicKey": "CreatorPublicKey"
}
],
"mint": "MintPublicKey",
"mintSecretKey": "base58_mint_secret_key"
}

Example: Build, Sign, and Send to Jito​

import { VersionedTransaction, Keypair } from '@solana/web3.js';
import bs58 from 'bs58';

const API_URL = 'https://pumpdev.io';
const JITO_URL = 'https://mainnet.block-engine.jito.wtf';
const wallet1 = Keypair.fromSecretKey(bs58.decode('WALLET1_PRIVATE_KEY'));
const wallet2 = Keypair.fromSecretKey(bs58.decode('WALLET2_PRIVATE_KEY'));
const wallet3 = Keypair.fromSecretKey(bs58.decode('WALLET3_PRIVATE_KEY'));
const wallet4 = Keypair.fromSecretKey(bs58.decode('WALLET4_PRIVATE_KEY'));

const walletMap = {
[wallet1.publicKey.toBase58()]: wallet1,
[wallet2.publicKey.toBase58()]: wallet2,
[wallet3.publicKey.toBase58()]: wallet3,
[wallet4.publicKey.toBase58()]: wallet4,
};

// 1. Build unsigned bundle via PumpDev
const res = await fetch(`${API_URL}/api/bundle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
accounts: [
{ publicKey: wallet1.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
{ publicKey: wallet2.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
{ publicKey: wallet3.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
{ publicKey: wallet4.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
],
mint: 'TokenMintAddress',
jitoTip: 0.01
})
});
const data = await res.json();

// 2. Sign each transaction with the correct wallet
const signedTxs = data.transactions.map((entry) => {
const tx = VersionedTransaction.deserialize(bs58.decode(entry.transaction));
const signer = walletMap[entry.publicKey];
tx.sign([signer]);
return bs58.encode(tx.serialize());
});

// 3. Send to Jito yourself
const bundleRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});
const bundleResult = await bundleRes.json();
console.log('Bundle ID:', bundleResult.result);
Create bundles need the mint keypair

For create transactions, sign with both your wallet keypair and the mint keypair (from mintSecretKey):

const mintKeypair = Keypair.fromSecretKey(bs58.decode(data.mintSecretKey));
// For create tx:
tx.sign([wallet, mintKeypair]);
// For buy tx:
tx.sign([wallet]);

Token Creation Bundles​

Create + Dev Buy via Jito​

When you add jitoTip to the /api/create endpoint, the API returns separate transactions for create and buy that you send as a Jito bundle:

import { VersionedTransaction, Keypair } from '@solana/web3.js';
import bs58 from 'bs58';

const API_URL = 'https://pumpdev.io';
const JITO_URL = 'https://mainnet.block-engine.jito.wtf';

async function createWithJitoBundle(metadataUri) {
const creator = Keypair.fromSecretKey(bs58.decode('CREATOR_PRIVATE_KEY'));

// 1. Request bundle-format transactions from API
const response = await fetch(`${API_URL}/api/create`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
publicKey: creator.publicKey.toBase58(),
name: 'My Token',
symbol: 'MTK',
uri: metadataUri,
buyAmountSol: 0.5,
slippage: 90,
jitoTip: 0.01 // Triggers bundle format response
})
});

const result = await response.json();
const mintKeypair = Keypair.fromSecretKey(bs58.decode(result.mintSecretKey));

// 2. Sign each transaction
const signedTxs = result.transactions.map((txInfo) => {
const tx = VersionedTransaction.deserialize(bs58.decode(txInfo.transaction));
const signers = txInfo.signers.includes('mint')
? [creator, mintKeypair]
: [creator];
tx.sign(signers);
return bs58.encode(tx.serialize());
});

// 3. Send as Jito bundle
const bundleRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});

const bundleResult = await bundleRes.json();
console.log('Bundle ID:', bundleResult.result);
console.log(`Token: https://pump.fun/${result.mint}`);
}
When to Use jitoTip

Only add jitoTip to /api/create if you plan to send via Jito. Without jitoTip, the API merges create + buy into a single transaction that you can send via any standard RPC — no bundle needed. See Token Creation for the single-transaction approach.


Multi-Buyer Bundle Launch​

Use /api/create-bundle to launch a token with multiple wallets buying atomically — creator + up to 3 additional buyers, all in the same block.

async function multiBuyerLaunch(metadataUri) {
const creator = Keypair.fromSecretKey(bs58.decode('CREATOR_KEY'));
const buyer1 = Keypair.fromSecretKey(bs58.decode('BUYER1_KEY'));
const buyer2 = Keypair.fromSecretKey(bs58.decode('BUYER2_KEY'));
const buyer3 = Keypair.fromSecretKey(bs58.decode('BUYER3_KEY'));

const wallets = { creator, buyer1, buyer2, buyer3 };

// 1. Request bundle from API
const response = await fetch(`${API_URL}/api/create-bundle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
publicKey: creator.publicKey.toBase58(),
name: 'Bundled Token',
symbol: 'BUND',
uri: metadataUri,
buyAmountSol: 1.0, // Creator buys 1 SOL
slippage: 90,
jitoTip: 0.03, // Tip split across transactions
additionalBuyers: [
{ publicKey: buyer1.publicKey.toBase58(), amountSol: 2.0 },
{ publicKey: buyer2.publicKey.toBase58(), amountSol: 1.5 },
{ publicKey: buyer3.publicKey.toBase58(), amountSol: 0.5 }
]
})
});

const result = await response.json();
const mintKeypair = Keypair.fromSecretKey(bs58.decode(result.mintSecretKey));

console.log('Mint:', result.mint);
console.log('Transactions:', result.transactions.length);

// 2. Sign each transaction with the correct signer
const signedTxs = result.transactions.map((txInfo) => {
const tx = VersionedTransaction.deserialize(bs58.decode(txInfo.transaction));
const signers = txInfo.signers
.map(s => s === 'mint' ? mintKeypair : wallets[s])
.filter(Boolean);
tx.sign(signers);
return bs58.encode(tx.serialize());
});

// 3. Send as Jito bundle
const bundleRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});

const bundleResult = await bundleRes.json();
console.log('Bundle sent:', bundleResult.result);
console.log(`Token: https://pump.fun/${result.mint}`);
}

Bundle Request Parameters​

ParameterTypeRequiredDescription
publicKeystringYesCreator wallet public key
namestringYesToken name (max 32 chars)
symbolstringYesToken symbol (max 10 chars)
uristringYesMetadata URI from Pinata or another IPFS/metadata host
buyAmountSolnumberNoCreator's buy amount for native-SOL pairs
buyAmountQuotenumberNoCreator's buy amount in quote-token units for non-SOL pairs
quoteMintstringNoQuote mint for the new coin. Omit for native SOL/WSOL pairs
slippagenumberNoSlippage % (default: 90)
jitoTipnumberNoJito tip in SOL, split across transactions (default: 0.03). Increase it when you want to pay more for bundle priority
priorityFeenumberNoPriority fee in SOL (default: 0.0005)
mintKeypairstringNoBase58 mint secret key (auto-generated if omitted)
additionalBuyersarrayNoUp to 3 additional buyers
cashbackEnabledbooleanNoDeprecated by pump.fun: new cashback coins can no longer be created, so true returns 400. Use holderReward
holderRewardbooleanNoCreate a pump.fun Holder Rewards coin: the creator fee of every trade goes to the coin's holders instead of the creator wallet, so there is nothing for the creator to claim. Permanent. Works on any quote and together with creatorFeeBps
creatorFeeBpsnumberNoCreator fee for custom pairs, in basis points: 1–300 (0.01–3%). Applies only when quoteMint is a custom pair (not SOL or USDC); SOL and USDC coins always use pump.fun's standard fee schedule, so it is ignored there. Fixed at launch

Provide one creator buy field: buyAmountSol for native-SOL pairs, or buyAmountQuote together with quoteMint for non-SOL quote pairs.

Additional Buyer Object​

{ "publicKey": "BuyerWalletPublicKey", "amountSol": 0.5 }

For non-SOL quote pairs, use amountQuote instead:

{ "publicKey": "BuyerWalletPublicKey", "amountQuote": 25 }

Bundle Transaction Structure​

TX #DescriptionSigners
1Create tokencreator, mint
2Creator buycreator
3Buyer 1 buybuyer1
4Buyer 2 buybuyer2
5Buyer 3 buybuyer3

All transactions execute atomically in the same Solana block.

Tip like a launch, not like a trade

A 5-transaction launch bundle competes with every other pump.fun launch in the same slot. Below the market tip Jito still returns a bundle id and then drops the bundle without any error — it simply never lands. Measured on 2026-08-24: 0.02 SOL never landed, 0.03 SOL landed on the first slot every time. Verify against the chain (does the mint account exist?) rather than trusting the sendBundle response.


Trade Bundles — Multi-Wallet Buy/Sell​

Use POST /api/trade-bundle to build multiple buy or sell transactions in a single API call. Each wallet gets its own transaction, and the last transaction receives the Jito tip.

async function tradeBundleBuy(mint) {
const creator = Keypair.fromSecretKey(bs58.decode('CREATOR_KEY'));
const wallet1 = Keypair.fromSecretKey(bs58.decode('WALLET1_KEY'));
const wallet2 = Keypair.fromSecretKey(bs58.decode('WALLET2_KEY'));

const accounts = [
{ publicKey: creator.publicKey.toBase58(), name: 'creator' },
{ publicKey: wallet1.publicKey.toBase58(), name: 'wallet1' },
{ publicKey: wallet2.publicKey.toBase58(), name: 'wallet2' }
];
const walletMap = { creator, wallet1, wallet2 };

// 1. Build all transactions in one API call
const response = await fetch(`${API_URL}/api/trade-bundle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
accounts,
action: 'buy',
mint,
amount: 0.5,
denominatedInSol: 'true',
slippage: 15,
jitoTip: 0.01 // Applied to last transaction only
})
});

const result = await response.json();

// 2. Sign each transaction with its wallet
const signedTxs = result.transactions
.filter(tx => tx.transaction !== null)
.map(tx => {
const decoded = VersionedTransaction.deserialize(bs58.decode(tx.transaction));
decoded.sign([walletMap[tx.name]]);
return bs58.encode(decoded.serialize());
});

// 3. Send as Jito bundle
await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});
}

Trade Bundle Request Parameters​

ParameterTypeRequiredDescription
accountsarrayYesArray of { publicKey, name } objects
actionstringYes"buy" or "sell"
mintstringYesToken mint address
amountnumber/stringYesTrade amount (SOL for buy, "100%" or tokens for sell)
denominatedInSolstringNoLegacy field name. Set "true" when a buy amount is in the pair's quote asset: SOL for SOL pairs, USDC for USDC pairs
slippagenumberNoSlippage % (default: 90)
priorityFeenumberNoPriority fee in SOL (default: 0.00005)
jitoTipnumberNoJito tip applied to last transaction (default: 0)
creatorstringNoCreator public key — skip bonding curve lookup for speed
closeTokenAccountbooleanNoClose token ATA after selling to reclaim ~0.002 SOL rent. Auto-enabled on "100%" sells. Set false to disable

Quote mint handling: trade-bundle resolves quote mint from the token on-chain. You do not pass quoteMint for ordinary buy/sell bundles. If a token is USDC-quoted, a buy with denominatedInSol: "true" expects the amount in USDC units.

Trade Bundle Response​

{
"transactions": [
{ "name": "creator", "transaction": "base58...", "error": null },
{ "name": "wallet1", "transaction": "base58...", "error": null },
{ "name": "wallet2", "transaction": "base58...", "error": null }
],
"stats": {
"total": 3,
"success": 3,
"failed": 0,
"durationMs": 45
}
}
Unique Wallets Required

Each account in the accounts array must use a unique wallet. Identical wallets produce identical transaction hashes, which Jito rejects with "Duplicate transaction message hash".


Jito Block Engine Endpoints​

Send your bundles to any Jito block engine. Send to multiple endpoints simultaneously for better landing rates:

const JITO_ENDPOINTS = [
'https://mainnet.block-engine.jito.wtf',
'https://amsterdam.mainnet.block-engine.jito.wtf',
'https://frankfurt.mainnet.block-engine.jito.wtf',
'https://ny.mainnet.block-engine.jito.wtf',
'https://tokyo.mainnet.block-engine.jito.wtf'
];

// Send to all endpoints for maximum landing rate
async function sendBundleToAll(signedTxs) {
const payload = JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
});

const results = await Promise.allSettled(
JITO_ENDPOINTS.map(endpoint =>
fetch(`${endpoint}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: payload
}).then(r => r.json())
)
);

const bundleId = results.find(r => r.status === 'fulfilled')?.value?.result;
console.log('Bundle ID:', bundleId);
return bundleId;
}

Jito Tip Recommendations​

The Jito tip incentivizes validators to include your bundle. Higher tips = faster landing.

ScenarioRecommended TipNotes
Token creation + dev buy0.01 SOLStandard priority
Multi-buyer launch0.02 - 0.05 SOLHigher tip for larger bundles
Trade bundle (2-3 wallets)0.01 SOLStandard priority
High-priority sniper0.05+ SOLCompetitive landing
Low urgency0.005 SOLMinimum viable tip
Tip Distribution

For /api/create-bundle, the Jito tip is automatically split across transactions to stay within Solana's per-transaction limits. For /api/trade-bundle, the tip is applied only to the last transaction in the bundle.


Bundle Pricing​

OperationFee
Token creation (in bundle)FREE
Buy transactions (in bundle)0.25% of buy amount
Jito tipPassed directly to validators

The Jito tip is separate from PumpDev fees. You pay the standard 0.25% commission on buy/sell amounts plus whatever Jito tip you choose.


Error Handling​

API Errors​

HTTP StatusCause
400Missing required fields, invalid parameters, duplicate wallets
402Insufficient SOL balance for transaction + fees
500Transaction build failed (invalid metadata URI, network issues)

Jito Bundle Errors​

ErrorCauseSolution
Duplicate transaction message hashSame wallet used twiceUse unique wallets per transaction
Bundle accepted but no on-chain txsBundle landed in failed slotRetry with new blockhash
Bundle simulation failedInsufficient funds or invalid stateCheck wallet balances and parameters
Monitoring Bundles

After sending a bundle, check its status using the bundle ID:

const statusRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'getBundleStatuses',
params: [[bundleId]]
})
});

Best Practices​

  1. Fund all wallets first — Every wallet in the bundle needs enough SOL for its transaction + fees
  2. Use unique wallets — Duplicate wallets produce duplicate tx hashes that Jito rejects
  3. Send to multiple Jito endpoints — Increases landing probability
  4. Set reasonable slippage — server defaults first; override slippage only when your strategy requires it
  5. Choose appropriate tips — Higher tips during congestion, lower during calm periods
  6. Check bundle status — Use getBundleStatuses to verify execution
  7. Test on devnet first — Validate your signing and bundle flow before mainnet

Frequently Asked Questions​

What is the maximum number of transactions in a Jito bundle?​

Jito supports up to 5 transactions per bundle. PumpDev's /api/create-bundle uses up to 5 (1 create + 1 creator buy + 3 additional buyers).

Can I mix buy and sell transactions in one bundle?​

The /api/trade-bundle endpoint processes either all buys or all sells in a single request, not mixed. For mixed operations, submit separate bundles.

What happens if one transaction in the bundle fails?​

The entire bundle fails. This is by design — atomic execution means all-or-nothing. No partial state changes occur.

Do I need a Jito staking account?​

No. You just need to pay a Jito tip in your transactions. The tip goes to the Jito validator that processes your bundle.

Can I use Jito bundles with the Lightning API?​

Yes! Two options:

  1. /api/bundle-lightning — server signs AND sends. One call, fully managed:
const response = await fetch('https://pumpdev.io/api/bundle-lightning', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
accounts: [
{ apiKey: 'YOUR_KEY', type: 'buy', amount: 0.1, denominatedInSol: 'true' }
],
mint: 'TokenMintAddress',
jitoTip: 0.01
})
});
  1. /api/bundle — returns unsigned txs. You sign locally and send to Jito. See the Local-Sign Bundle section above for full details and examples.

Next Steps​