pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA。PumpSwap 使用的 AMM 程序与 Pump.fun 联合曲线程序相互独立。可以用本文识别该程序、解码交易,或根据 IDL 构造买入和卖出指令。
不想自己组装 AMM 账户?使用 Raptor Swap API,它会把已毕业的 Pump.fun 代币路由到 PumpSwap 和其他 DEX。
官方程序 ID
| 程序 | 地址 | 作用 |
|---|---|---|
| Pump.fun AMM(PumpSwap) | pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA | 买入/卖出、create_pool、deposit、withdraw |
| Pump.fun(联合曲线) | 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P | 毕业前的联合曲线,以及迁移到 AMM 的 migrate |
| Pump Fees | pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ | 买入/卖出的费用配置 |
常见账户
| 账户 | 说明 |
|---|---|
global_config | 种子为 ["global_config"] 的 PDA,通常是 ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw |
event_authority | AMM 程序上种子为 ["__event_authority"] 的 PDA |
pool | 每个市场各自的池账户(传入买入/卖出指令) |
| 计价 mint(通常) | So11111111111111111111111111111111111111112(WSOL) |
migrate 指令会创建 AMM 池。
Anchor IDL
使用文档附带的 IDL,或与 Pump.fun 上游仓库对比:- JSON IDL: /idl/pump_amm.json
- 上游:idl/pump_amm.json
import idl from "./idl/pump_amm.json" assert { type: "json" };
console.log(idl.address);
// pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA
指令鉴别器
| 指令 | 鉴别器(字节) | Hex |
|---|---|---|
buy | [102, 6, 61, 18, 1, 218, 235, 234] | 0x66063d1201daebea |
sell | [51, 230, 133, 164, 1, 127, 131, 173] | 0x33e685a4017f83ad |
buy_exact_quote_in | [198, 46, 21, 82, 180, 217, 232, 112] | 0xc62e1552b4d9e870 |
create_pool | [233, 146, 209, 142, 207, 104, 64, 188] | 0xe992d18ecf6840bc |
deposit | [242, 35, 198, 137, 82, 225, 242, 182] | 0xf223c68952e1f2b6 |
withdraw | [183, 18, 70, 156, 148, 109, 161, 34] | 0xb712469c946da122 |
AMM 的
buy / sell 使用与联合曲线 buy / sell 相同的 Anchor sighash。请按程序 ID 区分:pAMMBay…(AMM)和 6EF8rrecth…(曲线)。在 Rust 中判断 AMM 买入或卖出
const PUMP_AMM: &str = "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA";
const BUY: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234];
const SELL: [u8; 8] = [51, 230, 133, 164, 1, 127, 131, 173];
fn is_amm_buy(program_id: &str, data: &[u8]) -> bool {
program_id == PUMP_AMM && data.get(..8) == Some(&BUY)
}
buy 指令
参数
| 参数 | 类型 | 含义 |
|---|---|---|
base_amount_out | u64 | 要收到的代币数量 |
max_quote_amount_in | u64 | 最多花费的计价代币(例如 WSOL lamports) |
track_volume | OptionBool | { 0 } / { 1 } |
| # | 账户 | 可写 | 签名者 |
|---|---|---|---|
| 0 | pool | ✓ | |
| 1 | user | ✓ | ✓ |
| 2 | global_config | ||
| 3 | base_mint | ||
| 4 | quote_mint | ||
| 5 | user_base_token_account | ✓ | |
| 6 | user_quote_token_account | ✓ | |
| 7 | pool_base_token_account | ✓ | |
| 8 | pool_quote_token_account | ✓ | |
| 9 | protocol_fee_recipient | ||
| 10 | protocol_fee_recipient_token_account | ✓ | |
| 11 | base_token_program | ||
| 12 | quote_token_program | ||
| 13 | system_program | ||
| 14 | associated_token_program | ||
| 15 | event_authority | ||
| 16 | program | ||
| 17 | coin_creator_vault_ata | ✓ | |
| 18 | coin_creator_vault_authority | ||
| 19 | global_volume_accumulator | ||
| 20 | user_volume_accumulator | ✓ | |
| 21 | fee_config | ||
| 22 | fee_program |
sell 指令
参数
| 参数 | 类型 | 含义 |
|---|---|---|
base_amount_in | u64 | 要卖出的代币数量 |
min_quote_amount_out | u64 | 最少收到的计价代币(滑点保护) |
buy 相同,直到 coin_creator_vault_authority(索引 0–18),之后是 fee_config(19)和 fee_program(20)。卖出不传入成交量累加器账户。
使用 @solana/web3.js 买入和卖出
import {
PublicKey,
TransactionInstruction,
SystemProgram,
} from "@solana/web3.js";
import {
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID,
getAssociatedTokenAddressSync,
} from "@solana/spl-token";
export const PUMP_AMM_PROGRAM_ID = new PublicKey(
"pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
);
export const PUMP_FEE_PROGRAM_ID = new PublicKey(
"pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"
);
export const GLOBAL_CONFIG = new PublicKey(
"ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw"
);
const BUY_DISC = Buffer.from([102, 6, 61, 18, 1, 218, 235, 234]);
const SELL_DISC = Buffer.from([51, 230, 133, 164, 1, 127, 131, 173]);
function u64le(n) {
const b = Buffer.alloc(8);
b.writeBigUInt64LE(BigInt(n));
return b;
}
export function ammEventAuthority() {
return PublicKey.findProgramAddressSync(
[Buffer.from("__event_authority")],
PUMP_AMM_PROGRAM_ID
)[0];
}
export function ammFeeConfigPda() {
return PublicKey.findProgramAddressSync(
[Buffer.from("fee_config"), PUMP_AMM_PROGRAM_ID.toBuffer()],
PUMP_FEE_PROGRAM_ID
)[0];
}
export function coinCreatorVaultAuthority(coinCreator) {
return PublicKey.findProgramAddressSync(
[Buffer.from("creator_vault"), coinCreator.toBuffer()],
PUMP_AMM_PROGRAM_ID
)[0];
}
/**
* Minimal PumpSwap buy. Resolve pool vaults, fee recipient, and coin_creator
* from the pool account / a recent mainnet tx before production use.
*/
export function buildAmmBuyIx({
pool,
user,
baseMint,
quoteMint,
poolBaseTokenAccount,
poolQuoteTokenAccount,
protocolFeeRecipient,
coinCreator,
baseAmountOut,
maxQuoteAmountIn,
trackVolume = false,
baseTokenProgram = TOKEN_PROGRAM_ID,
quoteTokenProgram = TOKEN_PROGRAM_ID,
}) {
const userBase = getAssociatedTokenAddressSync(
baseMint,
user,
false,
baseTokenProgram
);
const userQuote = getAssociatedTokenAddressSync(
quoteMint,
user,
false,
quoteTokenProgram
);
const protocolFeeAta = getAssociatedTokenAddressSync(
quoteMint,
protocolFeeRecipient,
true,
quoteTokenProgram
);
const creatorAuthority = coinCreatorVaultAuthority(coinCreator);
const creatorAta = getAssociatedTokenAddressSync(
quoteMint,
creatorAuthority,
true,
quoteTokenProgram
);
const [globalVolume] = PublicKey.findProgramAddressSync(
[Buffer.from("global_volume_accumulator")],
PUMP_AMM_PROGRAM_ID
);
const [userVolume] = PublicKey.findProgramAddressSync(
[Buffer.from("user_volume_accumulator"), user.toBuffer()],
PUMP_AMM_PROGRAM_ID
);
const data = Buffer.concat([
BUY_DISC,
u64le(baseAmountOut),
u64le(maxQuoteAmountIn),
Buffer.from([trackVolume ? 1 : 0]),
]);
return new TransactionInstruction({
programId: PUMP_AMM_PROGRAM_ID,
keys: [
{ pubkey: pool, isSigner: false, isWritable: true },
{ pubkey: user, isSigner: true, isWritable: true },
{ pubkey: GLOBAL_CONFIG, isSigner: false, isWritable: false },
{ pubkey: baseMint, isSigner: false, isWritable: false },
{ pubkey: quoteMint, isSigner: false, isWritable: false },
{ pubkey: userBase, isSigner: false, isWritable: true },
{ pubkey: userQuote, isSigner: false, isWritable: true },
{ pubkey: poolBaseTokenAccount, isSigner: false, isWritable: true },
{ pubkey: poolQuoteTokenAccount, isSigner: false, isWritable: true },
{ pubkey: protocolFeeRecipient, isSigner: false, isWritable: false },
{ pubkey: protocolFeeAta, isSigner: false, isWritable: true },
{ pubkey: baseTokenProgram, isSigner: false, isWritable: false },
{ pubkey: quoteTokenProgram, isSigner: false, isWritable: false },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
{ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: ammEventAuthority(), isSigner: false, isWritable: false },
{ pubkey: PUMP_AMM_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: creatorAta, isSigner: false, isWritable: true },
{ pubkey: creatorAuthority, isSigner: false, isWritable: false },
{ pubkey: globalVolume, isSigner: false, isWritable: false },
{ pubkey: userVolume, isSigner: false, isWritable: true },
{ pubkey: ammFeeConfigPda(), isSigner: false, isWritable: false },
{ pubkey: PUMP_FEE_PROGRAM_ID, isSigner: false, isWritable: false },
],
data,
});
}
export function buildAmmSellIx({
pool,
user,
baseMint,
quoteMint,
poolBaseTokenAccount,
poolQuoteTokenAccount,
protocolFeeRecipient,
coinCreator,
baseAmountIn,
minQuoteAmountOut,
baseTokenProgram = TOKEN_PROGRAM_ID,
quoteTokenProgram = TOKEN_PROGRAM_ID,
}) {
const userBase = getAssociatedTokenAddressSync(
baseMint,
user,
false,
baseTokenProgram
);
const userQuote = getAssociatedTokenAddressSync(
quoteMint,
user,
false,
quoteTokenProgram
);
const protocolFeeAta = getAssociatedTokenAddressSync(
quoteMint,
protocolFeeRecipient,
true,
quoteTokenProgram
);
const creatorAuthority = coinCreatorVaultAuthority(coinCreator);
const creatorAta = getAssociatedTokenAddressSync(
quoteMint,
creatorAuthority,
true,
quoteTokenProgram
);
const data = Buffer.concat([
SELL_DISC,
u64le(baseAmountIn),
u64le(minQuoteAmountOut),
]);
return new TransactionInstruction({
programId: PUMP_AMM_PROGRAM_ID,
keys: [
{ pubkey: pool, isSigner: false, isWritable: true },
{ pubkey: user, isSigner: true, isWritable: true },
{ pubkey: GLOBAL_CONFIG, isSigner: false, isWritable: false },
{ pubkey: baseMint, isSigner: false, isWritable: false },
{ pubkey: quoteMint, isSigner: false, isWritable: false },
{ pubkey: userBase, isSigner: false, isWritable: true },
{ pubkey: userQuote, isSigner: false, isWritable: true },
{ pubkey: poolBaseTokenAccount, isSigner: false, isWritable: true },
{ pubkey: poolQuoteTokenAccount, isSigner: false, isWritable: true },
{ pubkey: protocolFeeRecipient, isSigner: false, isWritable: false },
{ pubkey: protocolFeeAta, isSigner: false, isWritable: true },
{ pubkey: baseTokenProgram, isSigner: false, isWritable: false },
{ pubkey: quoteTokenProgram, isSigner: false, isWritable: false },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
{ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: ammEventAuthority(), isSigner: false, isWritable: false },
{ pubkey: PUMP_AMM_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: creatorAta, isSigner: false, isWritable: true },
{ pubkey: creatorAuthority, isSigner: false, isWritable: false },
{ pubkey: ammFeeConfigPda(), isSigner: false, isWritable: false },
{ pubkey: PUMP_FEE_PROGRAM_ID, isSigner: false, isWritable: false },
],
data,
});
}
实际的 PumpSwap
buy 指令常在 23 个 IDL 账户之后追加剩余账户(在主网上观察到多 3 个)。sell 可能多 2 个。基础 mint 通常是 Token-2022(TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb),计价代币则是旧版 Token 程序上的 WSOL。在主网使用前,请用 /idl/pump_amm.json 解码池账户,或从近期成功的兑换中复制账户列表。更简单的方式:Raptor + Data API
# Find graduated Pump.fun / PumpSwap markets
curl "https://data.solanatracker.io/search?market=pumpfun-amm&limit=20" \
-H "x-api-key: YOUR_API_KEY"
// Swap a graduated token (Raptor picks PumpSwap / best route)
await fetch("https://swap-v2.solanatracker.io/swap", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
wallet: "YOUR_WALLET_ADDRESS",
from: "TOKEN_MINT_ADDRESS",
to: "So11111111111111111111111111111111111111112",
amount: 1000000,
slippage: 15,
}),
});
用 Solana Tracker 订阅和索引数据
| 产品 | 用途 |
|---|---|
| Pump.fun API | 已毕业代币的数据、交易、OHLCV |
| Data API | market=pumpfun-amm、/tokens/multi/graduated |
| Datastream | graduated 房间和单代币交易流 |
| Memescope | 实时信息流中的已迁移 / PumpSwap 栏目 |
| Raptor | 在 PumpSwap 池上执行买卖 |
| Yellowstone gRPC | 订阅 pAMMBay… 程序的交易 |
| Solana RPC | 获取池账户并确认兑换 |
- Pump.fun 联合曲线程序:
6EF8rrecth…的买入、卖出和创建 - Pump.fun 生命周期:发现 → 曲线 → 毕业 → 兑换
- 发现代币:毕业中和已毕业端点
- gRPC 买卖检测
联合曲线程序
联合曲线程序 ID、IDL,以及创建、买入、卖出的鉴别器。
发行与毕业
用 Solana Tracker API 追踪发行和毕业。
代币兑换
无需构建 AMM 指令即可买卖。
Memescope
已迁移 / PumpSwap 代币的实时信息流。