pumpdotfun-sdk-sp
Version:
A simple SDK for interacting with pumpdotfun
228 lines (224 loc) • 11.2 kB
JavaScript
;
var web3_js = require('@solana/web3.js');
var anchor = require('@coral-xyz/anchor');
var globalAccount = require('./globalAccount.cjs');
var events = require('./events.cjs');
var splToken = require('@solana/spl-token');
var bondingCurveAccount = require('./bondingCurveAccount.cjs');
var bn_js = require('bn.js');
var util = require('./util.cjs');
var pumpFun = require('./IDL/pump-fun.json.cjs');
const PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
const MPL_TOKEN_METADATA_PROGRAM_ID = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
const GLOBAL_ACCOUNT_SEED = "global";
const MINT_AUTHORITY_SEED = "mint-authority";
const BONDING_CURVE_SEED = "bonding-curve";
const METADATA_SEED = "metadata";
const DEFAULT_DECIMALS = 6;
class PumpFunSDK {
program;
connection;
constructor(provider) {
this.program = new anchor.Program(pumpFun.default, provider);
this.connection = this.program.provider.connection;
}
async createAndBuy(creator, mint, createTokenMetadata, buyAmountSol, slippageBasisPoints = 500n, priorityFees, commitment = util.DEFAULT_COMMITMENT, finality = util.DEFAULT_FINALITY) {
let tokenMetadata = await this.createTokenMetadata(createTokenMetadata);
let createTx = await this.getCreateInstructions(creator.publicKey, createTokenMetadata.name, createTokenMetadata.symbol, tokenMetadata.metadataUri, mint);
let newTx = new web3_js.Transaction().add(createTx);
if (buyAmountSol > 0) {
const globalAccount = await this.getGlobalAccount(commitment);
const buyAmount = globalAccount.getInitialBuyPrice(buyAmountSol);
const buyAmountWithSlippage = util.calculateWithSlippageBuy(buyAmountSol, slippageBasisPoints);
const buyTx = await this.getBuyInstructions(creator.publicKey, mint.publicKey, globalAccount.feeRecipient, buyAmount, buyAmountWithSlippage);
newTx.add(buyTx);
}
let createResults = await util.sendTx(this.connection, newTx, creator.publicKey, [creator, mint], priorityFees, commitment, finality);
return createResults;
}
async buy(buyer, mint, buyAmountSol, slippageBasisPoints = 500n, priorityFees, commitment = util.DEFAULT_COMMITMENT, finality = util.DEFAULT_FINALITY) {
let buyTx = await this.getBuyInstructionsBySolAmount(buyer.publicKey, mint, buyAmountSol, slippageBasisPoints, commitment);
let buyResults = await util.sendTx(this.connection, buyTx, buyer.publicKey, [buyer], priorityFees, commitment, finality);
return buyResults;
}
async sell(seller, mint, sellTokenAmount, slippageBasisPoints = 500n, priorityFees, commitment = util.DEFAULT_COMMITMENT, finality = util.DEFAULT_FINALITY) {
let sellTx = await this.getSellInstructionsByTokenAmount(seller.publicKey, mint, sellTokenAmount, slippageBasisPoints, commitment);
let sellResults = await util.sendTx(this.connection, sellTx, seller.publicKey, [seller], priorityFees, commitment, finality);
return sellResults;
}
//create token instructions
async getCreateInstructions(creator, name, symbol, uri, mint) {
const mplTokenMetadata = new web3_js.PublicKey(MPL_TOKEN_METADATA_PROGRAM_ID);
const [metadataPDA] = web3_js.PublicKey.findProgramAddressSync([
Buffer.from(METADATA_SEED),
mplTokenMetadata.toBuffer(),
mint.publicKey.toBuffer(),
], mplTokenMetadata);
return this.program.methods
.create(name, symbol, uri, creator)
.accounts({
mint: mint.publicKey,
user: creator,
program: this.program.programId,
})
.signers([mint])
.transaction();
}
async getBuyInstructionsBySolAmount(buyer, mint, buyAmountSol, slippageBasisPoints = 500n, commitment = util.DEFAULT_COMMITMENT) {
let bondingCurveAccount = await this.getBondingCurveAccount(mint, commitment);
if (!bondingCurveAccount) {
throw new Error(`Bonding curve account not found: ${mint.toBase58()}`);
}
let buyAmount = bondingCurveAccount.getBuyPrice(buyAmountSol);
let buyAmountWithSlippage = util.calculateWithSlippageBuy(buyAmountSol, slippageBasisPoints);
let globalAccount = await this.getGlobalAccount(commitment);
return await this.getBuyInstructions(buyer, mint, globalAccount.feeRecipient, buyAmount, buyAmountWithSlippage);
}
//buy
async getBuyInstructions(buyer, mint, feeRecipient, amount, solAmount, commitment = util.DEFAULT_COMMITMENT) {
await splToken.getAssociatedTokenAddress(mint, this.getBondingCurvePDA(mint), true);
const associatedUser = await splToken.getAssociatedTokenAddress(mint, buyer, false);
let transaction = new web3_js.Transaction();
try {
await splToken.getAccount(this.connection, associatedUser, commitment);
}
catch (e) {
transaction.add(splToken.createAssociatedTokenAccountInstruction(buyer, associatedUser, buyer, mint));
}
transaction.add(await this.program.methods
.buy(new bn_js.BN(amount.toString()), new bn_js.BN(solAmount.toString()), false)
.accounts({
feeRecipient: feeRecipient,
mint: mint,
associatedUser: associatedUser,
user: buyer,
program: this.program.programId,
})
.transaction());
return transaction;
}
//sell
async getSellInstructionsByTokenAmount(seller, mint, sellTokenAmount, slippageBasisPoints = 500n, commitment = util.DEFAULT_COMMITMENT) {
let bondingCurveAccount = await this.getBondingCurveAccount(mint, commitment);
if (!bondingCurveAccount) {
throw new Error(`Bonding curve account not found: ${mint.toBase58()}`);
}
let globalAccount = await this.getGlobalAccount(commitment);
let minSolOutput = bondingCurveAccount.getSellPrice(sellTokenAmount, globalAccount.feeBasisPoints);
let sellAmountWithSlippage = util.calculateWithSlippageSell(minSolOutput, slippageBasisPoints);
return await this.getSellInstructions(seller, mint, globalAccount.feeRecipient, sellTokenAmount, sellAmountWithSlippage);
}
async getSellInstructions(seller, mint, feeRecipient, amount, minSolOutput) {
const associatedUser = await splToken.getAssociatedTokenAddress(mint, seller, false);
let transaction = new web3_js.Transaction();
transaction.add(await this.program.methods
.sell(new bn_js.BN(amount.toString()), new bn_js.BN(minSolOutput.toString()))
.accounts({
feeRecipient: feeRecipient,
mint: mint,
associatedUser: associatedUser,
user: seller,
program: this.program.programId,
})
.transaction());
return transaction;
}
async getBondingCurveAccount(mint, commitment = util.DEFAULT_COMMITMENT) {
const tokenAccount = await this.connection.getAccountInfo(this.getBondingCurvePDA(mint), commitment);
if (!tokenAccount) {
return null;
}
return bondingCurveAccount.BondingCurveAccount.fromBuffer(tokenAccount.data);
}
async getGlobalAccount(commitment = util.DEFAULT_COMMITMENT) {
const [globalAccountPDA] = web3_js.PublicKey.findProgramAddressSync([Buffer.from(GLOBAL_ACCOUNT_SEED)], new web3_js.PublicKey(PROGRAM_ID));
const tokenAccount = await this.connection.getAccountInfo(globalAccountPDA, commitment);
return globalAccount.GlobalAccount.fromBuffer(tokenAccount.data);
}
getBondingCurvePDA(mint) {
return web3_js.PublicKey.findProgramAddressSync([Buffer.from(BONDING_CURVE_SEED), mint.toBuffer()], this.program.programId)[0];
}
async createTokenMetadata(create) {
// Validate file
if (!(create.file instanceof Blob)) {
throw new Error("File must be a Blob or File object");
}
let formData = new FormData();
formData.append("file", create.file, "image.png"); // Add filename
formData.append("name", create.name);
formData.append("symbol", create.symbol);
formData.append("description", create.description);
formData.append("twitter", create.twitter || "");
formData.append("telegram", create.telegram || "");
formData.append("website", create.website || "");
formData.append("showName", "true");
try {
const request = await fetch("https://pump.fun/api/ipfs", {
method: "POST",
headers: {
Accept: "application/json",
},
body: formData,
credentials: "same-origin",
});
if (request.status === 500) {
// Try to get more error details
const errorText = await request.text();
throw new Error(`Server error (500): ${errorText || "No error details available"}`);
}
if (!request.ok) {
throw new Error(`HTTP error! status: ${request.status}`);
}
const responseText = await request.text();
if (!responseText) {
throw new Error("Empty response received from server");
}
try {
return JSON.parse(responseText);
}
catch (e) {
throw new Error(`Invalid JSON response: ${responseText}`);
}
}
catch (error) {
console.error("Error in createTokenMetadata:", error);
throw error;
}
}
//EVENTS
addEventListener(eventType, callback) {
return this.program.addEventListener(eventType, (event, slot, signature) => {
let processedEvent;
switch (eventType) {
case "createEvent":
processedEvent = events.toCreateEvent(event);
callback(processedEvent, slot, signature);
break;
case "tradeEvent":
processedEvent = events.toTradeEvent(event);
callback(processedEvent, slot, signature);
break;
case "completeEvent":
processedEvent = events.toCompleteEvent(event);
callback(processedEvent, slot, signature);
break;
case "setParamsEvent":
processedEvent = events.toSetParamsEvent(event);
callback(processedEvent, slot, signature);
break;
default:
console.error("Unhandled event type:", eventType);
}
});
}
removeEventListener(eventId) {
this.program.removeEventListener(eventId);
}
}
exports.BONDING_CURVE_SEED = BONDING_CURVE_SEED;
exports.DEFAULT_DECIMALS = DEFAULT_DECIMALS;
exports.GLOBAL_ACCOUNT_SEED = GLOBAL_ACCOUNT_SEED;
exports.METADATA_SEED = METADATA_SEED;
exports.MINT_AUTHORITY_SEED = MINT_AUTHORITY_SEED;
exports.PumpFunSDK = PumpFunSDK;
//# sourceMappingURL=pumpfun.cjs.map