import dotenv from "dotenv";
dotenv.config({ quiet: true });
import { BagsSDK } from "@bagsfm/bags-sdk";
import { Keypair, LAMPORTS_PER_SOL, PublicKey, Connection } from "@solana/web3.js";
import bs58 from "bs58";
// Initialize SDK
const BAGS_API_KEY = process.env.BAGS_API_KEY;
const SOLANA_RPC_URL = process.env.SOLANA_RPC_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
if (!BAGS_API_KEY || !SOLANA_RPC_URL || !PRIVATE_KEY) {
throw new Error("BAGS_API_KEY, SOLANA_RPC_URL, and PRIVATE_KEY are required");
}
const connection = new Connection(SOLANA_RPC_URL);
const sdk = new BagsSDK(BAGS_API_KEY, connection, "processed");
async function launchToken(launchParams: {
imageUrl: string;
name: string;
symbol: string;
description: string;
twitterUrl: string;
websiteUrl: string;
initialBuyAmountLamports: number;
}) {
try {
const PRIVATE_KEY = process.env.PRIVATE_KEY;
if (!PRIVATE_KEY) {
throw new Error("PRIVATE_KEY is not set");
}
const keypair = Keypair.fromSecretKey(bs58.decode(PRIVATE_KEY));
console.log(`🚀 Creating token $${launchParams.symbol} with wallet ${keypair.publicKey.toBase58()}`);
const connection = sdk.state.getConnection();
const commitment = sdk.state.getCommitment();
console.log("⚙️ Fetching configuration...");
// Get existing config or config creation TX
const configResponse = await sdk.config.getOrCreateConfig(keypair.publicKey);
// Config does not exist, create it
if (configResponse.transaction) {
console.log("🔧 Config does not exist, creating new configuration...");
configResponse.transaction.sign([keypair]);
const blockhash = await connection.getLatestBlockhash(commitment);
const txSignature = await connection.sendTransaction(configResponse.transaction, { maxRetries: 0, skipPreflight: true });
const confirmed = await connection.confirmTransaction({
blockhash: blockhash.blockhash,
lastValidBlockHeight: blockhash.lastValidBlockHeight,
signature: txSignature,
}, commitment);
if (confirmed.value.err) {
console.error("❌ Error creating config:", confirmed.value.err);
throw new Error("Error creating config");
}
else {
console.log("✅ Configuration successfully created!");
}
}
else {
console.log("♻️ Config already exists, reusing config key:", configResponse.configKey.toString());
}
console.log("📝 Creating token info and metadata...");
// Fetch image url to file like object
const imageBlob = await fetch(launchParams.imageUrl).then(res => res.blob());
// Create token info and metadata
const tokenInfoResponse = await sdk.tokenLaunch.createTokenInfoAndMetadata({
image: imageBlob,
name: launchParams.name,
description: launchParams.description,
symbol: launchParams.symbol?.toUpperCase()?.replace("$", ""),
twitter: launchParams.twitterUrl,
website: launchParams.websiteUrl,
});
console.log("✨ Successfully created token info and metadata!");
console.log("🪙 Token mint:", tokenInfoResponse.tokenMint);
console.log("🎯 Creating token launch transaction...");
// Create token launch
const tokenLaunchTransaction = await sdk.tokenLaunch.createLaunchTransaction({
metadataUrl: tokenInfoResponse.tokenMetadata,
tokenMint: new PublicKey(tokenInfoResponse.tokenMint),
launchWallet: keypair.publicKey,
initialBuyLamports: launchParams.initialBuyAmountLamports,
configKey: configResponse.configKey,
});
tokenLaunchTransaction.sign([keypair]);
const blockhash = await connection.getLatestBlockhash(commitment);
const txSignature = await connection.sendTransaction(tokenLaunchTransaction, { maxRetries: 0, skipPreflight: true });
console.log("🔑 Confirming transaction signature:", txSignature);
const confirmed = await connection.confirmTransaction({
blockhash: blockhash.blockhash,
lastValidBlockHeight: blockhash.lastValidBlockHeight,
signature: txSignature,
}, commitment);
if (confirmed.value.err) {
console.error("💥 Error creating token launch:", confirmed.value.err);
throw new Error("Error creating token launch");
}
console.log("🎉 Token launched successfully!");
console.log(`🌐 View your token at: https://bags.fm/${tokenInfoResponse.tokenMint}`);
}
catch (error) {
console.error("🚨 Unexpected error occurred:", error);
}
}
launchToken({
imageUrl: "https://img.freepik.com/premium-vector/white-abstract-vactor-background-design_665257-153.jpg",
name: "TEST",
symbol: "TEST",
description: "TEST",
twitterUrl: "https://x.com/test",
websiteUrl: "https://test.com",
initialBuyAmountLamports: 0.01 * LAMPORTS_PER_SOL, // 0.01 SOL
});