Files
solana-agent-kit/src/actions/launchPumpfunToken.ts
2024-12-27 23:34:15 +01:00

203 lines
6.0 KiB
TypeScript

import { Action } from "../types/action";
import { SolanaAgentKit } from "../agent";
import { z } from "zod";
import { VersionedTransaction, Keypair } from "@solana/web3.js";
const launchPumpfunTokenAction: Action = {
name: "solana_launch_pumpfun_token",
similes: [
"create pumpfun token",
"launch token on pumpfun",
"deploy pumpfun token",
"create meme token",
"launch memecoin",
"create pump token"
],
description: "Launch a new token on Pump.fun with customizable metadata and initial liquidity",
examples: [
[
{
input: {
tokenName: "Sample Token",
tokenTicker: "SMPL",
description: "A sample token for demonstration",
imageUrl: "https://example.com/token.png",
twitter: "@sampletoken",
telegram: "t.me/sampletoken",
website: "https://sampletoken.com",
initialLiquiditySOL: 0.1,
slippageBps: 10,
priorityFee: 0.0001
},
output: {
status: "success",
signature: "2ZE7Rz...",
mint: "7nxQB...",
metadataUri: "https://arweave.net/...",
message: "Successfully launched token on Pump.fun"
},
explanation: "Launch a new token with custom metadata and 0.1 SOL initial liquidity"
}
]
],
schema: z.object({
tokenName: z.string()
.min(1)
.max(32)
.describe("Name of the token"),
tokenTicker: z.string()
.min(2)
.max(10)
.describe("Ticker symbol of the token"),
description: z.string()
.min(1)
.max(1000)
.describe("Description of the token"),
imageUrl: z.string()
.url()
.describe("URL of the token image"),
twitter: z.string()
.optional()
.describe("Twitter handle (optional)"),
telegram: z.string()
.optional()
.describe("Telegram group link (optional)"),
website: z.string()
.url()
.optional()
.describe("Website URL (optional)"),
initialLiquiditySOL: z.number()
.min(0.0001)
.default(0.0001)
.describe("Initial liquidity in SOL"),
slippageBps: z.number()
.min(1)
.max(1000)
.default(5)
.describe("Slippage tolerance in basis points"),
priorityFee: z.number()
.min(0.00001)
.default(0.00005)
.describe("Priority fee in SOL")
}),
handler: async (agent: SolanaAgentKit, input: Record<string, any>) => {
try {
const mintKeypair = Keypair.generate();
// Upload metadata
const formData = new URLSearchParams();
formData.append("name", input.tokenName);
formData.append("symbol", input.tokenTicker);
formData.append("description", input.description);
formData.append("showName", "true");
if (input.twitter) {
formData.append("twitter", input.twitter);
}
if (input.telegram) {
formData.append("telegram", input.telegram);
}
if (input.website) {
formData.append("website", input.website);
}
// Fetch and process image
const imageResponse = await fetch(input.imageUrl);
const imageBlob = await imageResponse.blob();
const imageFile = new File([imageBlob], "token_image.png", { type: "image/png" });
// Create final form data
const finalFormData = new FormData();
for (const [key, value] of formData.entries()) {
finalFormData.append(key, value);
}
finalFormData.append("file", imageFile);
// Upload metadata to IPFS
const metadataResponse = await fetch("https://pump.fun/api/ipfs", {
method: "POST",
body: finalFormData,
});
if (!metadataResponse.ok) {
throw new Error(`Metadata upload failed: ${metadataResponse.statusText}`);
}
const metadataResult = await metadataResponse.json();
// Create token transaction
const payload = {
publicKey: agent.wallet_address.toBase58(),
action: "create",
tokenMetadata: {
name: metadataResult.metadata.name,
symbol: metadataResult.metadata.symbol,
uri: metadataResult.metadataUri,
},
mint: mintKeypair.publicKey.toBase58(),
denominatedInSol: "true",
amount: input.initialLiquiditySOL || 0.0001,
slippage: input.slippageBps || 5,
priorityFee: input.priorityFee || 0.00005,
pool: "pump",
};
const txResponse = await fetch("https://pumpportal.fun/api/trade-local", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (!txResponse.ok) {
const errorText = await txResponse.text();
throw new Error(`Transaction creation failed: ${txResponse.status} - ${errorText}`);
}
// Process and sign transaction
const transactionData = await txResponse.arrayBuffer();
const tx = VersionedTransaction.deserialize(new Uint8Array(transactionData));
// Get latest blockhash
const { blockhash, lastValidBlockHeight } = await agent.connection.getLatestBlockhash();
tx.message.recentBlockhash = blockhash;
// Sign transaction
tx.sign([mintKeypair, agent.wallet]);
// Send transaction
const signature = await agent.connection.sendTransaction(tx, {
skipPreflight: false,
preflightCommitment: "confirmed",
maxRetries: 5,
});
// Wait for confirmation
const confirmation = await agent.connection.confirmTransaction({
signature,
blockhash,
lastValidBlockHeight,
});
if (confirmation.value.err) {
throw new Error(`Transaction failed: ${confirmation.value.err}`);
}
return {
status: "success",
signature,
mint: mintKeypair.publicKey.toBase58(),
metadataUri: metadataResult.metadataUri,
message: "Successfully launched token on Pump.fun"
};
} catch (error: any) {
return {
status: "error",
message: `Failed to launch token: ${error.message}`
};
}
}
};
export default launchPumpfunTokenAction;