Launching Tokens
Overview
Authenticate ──> Launch ──> Poll status ──> Token live on SolanaPrerequisites
Full TypeScript example
import { Keypair } from "@solana/web3.js";
import nacl from "tweetnacl";
import bs58 from "bs58";
const API_BASE = "https://api-blowfish.neuko.ai";
// --- Authentication ---
async function authenticate(keypair: Keypair): Promise<string> {
const wallet = keypair.publicKey.toBase58();
const challengeRes = await fetch(`${API_BASE}/api/auth/challenge`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ wallet }),
});
const { nonce } = await challengeRes.json();
const message = `Sign this message to authenticate: ${nonce}`;
const sig = nacl.sign.detached(new TextEncoder().encode(message), keypair.secretKey);
const verifyRes = await fetch(`${API_BASE}/api/auth/verify`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ wallet, nonce, signature: bs58.encode(sig) }),
});
const { token } = await verifyRes.json();
return token;
}
// --- Launch ---
async function launchToken(
token: string,
params: { name: string; ticker: string; description?: string; imageUrl?: string }
): Promise<string> {
const response = await fetch(`${API_BASE}/api/v1/tokens/launch`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Launch failed (${response.status}): ${error.error}`);
}
const { eventId } = await response.json();
return eventId;
}
// --- Poll for status ---
async function waitForDeployment(eventId: string, token: string): Promise<string> {
const url = `${API_BASE}/api/v1/tokens/launch/status/${eventId}`;
for (let i = 0; i < 60; i++) {
const response = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
const data = await response.json();
if (data.status === "success") {
return "success";
}
if (data.status === "failed" || data.status === "rate_limited") {
throw new Error(`Launch ${data.status}`);
}
await new Promise((resolve) => setTimeout(resolve, 5000));
}
throw new Error("Launch timed out");
}
// --- Main ---
async function main() {
// Load your keypair (replace with your key loading logic)
const secretKey = Uint8Array.from(JSON.parse(process.env.WALLET_SECRET_KEY!));
const keypair = Keypair.fromSecretKey(secretKey);
const token = await authenticate(keypair);
const eventId = await launchToken(token, {
name: "My Agent Token",
ticker: "MAT",
description: "Launched programmatically via the Blowfish Agent API",
});
console.log(`Launch submitted. Event ID: ${eventId}`);
const status = await waitForDeployment(eventId, token);
console.log(`Launch complete: ${status}`);
}
main().catch(console.error);Token naming guidelines
Field
Constraints
Tips
Handling errors
Ticker collision (409)
Rate limited
JWT expiry
What happens after launch
Last updated