initialize_pool
Creates a new launchpad pool, mints the sale token (PDA mint), assigns authorities, creates vaults, and sets on-chain metadata via the Metaplex Token Metadata program.
Program: Tradersdex Curve (Launchpad) Instruction:
initialize_pool
What it does
Creates pool PDA:
["pool", mint]
Creates PDA mint for the sale token (authority =
["token_authority"]
)Creates vaults:
Token vault =
ATA(mint, pool)
Quote vault =
ATA(quote_mint, pool)
(if quote != native SOL)
Creates MPL metadata with
name
,symbol
, anduri
Stores curve parameters and sale targets
Emits
PoolCreatedEvent
for indexers
URI enforcement: If a non-empty
uri
is provided, it must begin with with a valid ipfs gateway:"https://ipfs.io/ipfs/" "https://gateway.pinata.cloud/ipfs/" "https://cloudflare-ipfs.com/ipfs/"
otherwise the transaction fails. Name and symbol must each be at least 1 characters long.
Accounts (in order)
0
pool_signer
["token_authority"]
Program authority for mint & vaults
1
payer
✅
Funds rent & creates accounts
2
mint
✅
Created in handler
PDA mint for sale token
3
quote_mint
Native SOL or SPL quote asset
4
pool
✅
["pool", mint]
(PDA), space = Pool::size_for_type(args.curve_type)
Pool state
5
token_vault
✅
ATA(mint, pool)
Base token vault
6
quote_vault
✅
ATA(quote_mint, pool) or WSOL vault
Quote token vault
7
metadata
✅
MPL PDA: ["metadata", mpl_token_metadata::ID, mint]
Token metadata
8
metadata_program
= mpl_token_metadata::ID
MPL Token Metadata program
9
token_program
= anchor_spl::token::ID
SPL Token
10
associated_token_program
For ATA creation
11
system_program
12
tradersdex_curve
= crate::ID
Self-check
13
event_authority
["event_authority"]
Event signer for Anchor events
Arguments
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct InitializePoolArgs {
/// Curve type
/// 0: SOL / NO creator fee | 1: SOL /creator fee | 2: WSOL / no cf | 3: WSOL / cf
pub curve_type: PoolType,
/// Total quote tokens to raise before finalize/migrate
/// must be between 60 and 100, will round to 0 decimals
pub target_raised: u64,
/// PDA salt for mint derivation
pub salt: u128,
/// Fixed 80 for now
pub bonding_token_share: u8,
/// must be between 20 and 255
pub slope_multiplier: u8,
/// Currently only 6 supported
pub decimals: u8,
/// MPL metadata
pub name: String, // >= 1 chars
pub symbol: String, // >= 1 chars
pub uri: String, // must start with valid ipfs gateway
}
Events
#[event]
pub struct PoolCreatedEvent {
pub pool: Pubkey,
pub mint: Pubkey,
pub creator: Pubkey,
pub quote_mint: Pubkey,
pub target_raised: u64,
pub total_supply: u64,
pub virtual_token_reserves: u64,
pub virtual_sol_reserves: u64,
pub curve_type: PoolType,
pub timestamp: i64,
}
PDA Derivation
Pool =
PDA(["pool", mint])
Program signer =
PDA(["token_authority"])
Mint =
PDA(["mint", le_u128(salt)])
Vaults:
Token vault =
ATA(mint, pool)
Quote vault =
ATA(quote_mint, pool)
or pool for SOL
Metadata =
PDA(["metadata", MPL_ID, mint], program = MPL_ID)
Validation rules
decimals
must equal 6name.len() >= 1
andsymbol.len() >= 1
quote_mint
must be either wrapped SOL mint or the native SOL mintPDA derivations must match
Adequate lamports for rent-exempt accounts
Client example (TypeScript)
import { AnchorProvider, Program, BN } from "@coral-xyz/anchor";
import { PublicKey, SystemProgram } from "@solana/web3.js";
import { NATIVE_MINT } from "@solana/spl-token";
import crypto from "crypto";
const TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
const ATOKEN_PROGRAM_ID = new PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
const LAUNCHPAD_ID = new PublicKey("TDEXxqqkyJ4Jh8UtLB5BzYoxbJKHwo3FFGKc5GeS1H6");
const MPL_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
/** random u128 as bigint */
function randomU128(): bigint {
return BigInt("0x" + crypto.randomBytes(16).toString("hex"));
}
function le128(n: bigint): Buffer {
const b = Buffer.alloc(16);
let x = n;
for (let i = 0; i < 16; i++) { b[i] = Number(x & 0xffn); x >>= 8n; }
return b;
}
/** derive mint PDA from salt: seeds ["mint", le_u128(salt)] */
function deriveMintPda(programId: PublicKey, salt: bigint): PublicKey {
const [mint] = PublicKey.findProgramAddressSync(
[Buffer.from("mint"), le128(salt)],
programId
);
return mint;
}
function deriveEventAuthority(programId: PublicKey): PublicKey {
return PublicKey.findProgramAddressSync([Buffer.from("event_authority")], programId)[0];
}
export async function initializePoolInstruction(program: Program, args: {
payer: PublicKey;
quoteMint: PublicKey;
creatorFeeEnabled: bool;
targetRaised: bigint;
salt?: bigint;
bondingTokenShare: number;
slopeMultiplier: number;
decimals: number;
name: string;
symbol: string;
uri: string;
}) {
const isWSOL = args.quoteMint.equals(NATIVE_MINT);
const curveType = (isWSOL ? 2 : 0) + (args.creatorFeeEnabled ? 1 : 0);
const [poolSigner] = PublicKey.findProgramAddressSync(
[Buffer.from("token_authority")],
program.programId
);
const [metadata] = PublicKey.findProgramAddressSync(
[Buffer.from("metadata"), MPL_ID.toBuffer(), args.mint.toBuffer()],
MPL_ID
);
let salt = args.salt ?? randomU128();
const derivedMint = deriveMintPda(program.programId, salt);
const [pool] = PublicKey.findProgramAddressSync(
[Buffer.from("pool"), derivedMint.toBuffer()],
program.programId
);
// Off-curve owner (PDA), so allowOwnerOffCurve=true
const tokenVault = getAssociatedTokenAddressSync(mint, pool, true); // ATA(mint, pool)
// For WSOL we also use the NATIVE_MINT ATA; program will wrap/unwrap as needed
const quoteVault = isWSOL
? getAssociatedTokenAddressSync(NATIVE_MINT, pool, true)
: pool;
const ix = await program.methods
.initializePool({
curveType,
targetRaised: new BN(args.targetRaised.toString()),
salt: new BN(salt.toString()),
bondingTokenShare: args.bondingTokenShare,
slopeMultiplier: args.slopeMultiplier,
decimals: args.decimals,
name: args.name,
symbol: args.symbol,
uri: args.uri,
})
.accounts({
poolSigner,
payer: args.payer,
mint: derivedMint,
quoteMint: args.quoteMint,
pool,
tokenVault,
quoteVault,
metadata,
metadataProgram: MPL_ID,
tokenProgram: TOKEN_PROGRAM_ID,
associatedTokenProgram: ATOKEN_PROGRAM_ID,
systemProgram: SystemProgram.programId,
tradersdex_curve: program.programId,
eventAuthority: deriveEventAuthority(program.programId),
})
.instruction();
return {
ix,
mint: derivedMint,
saltLeHex: le128(salt).toString("hex"),
curveType,
accounts: { poolSigner, pool, tokenVault, quoteVault, metadata },
};
}
Vanity mint grinder (TypeScript)
Finds one salt that produces a mint PDA (seed: ["mint", le_u128(salt)]
) ending with a desired Base58 suffix.
grinder_one.ts
import { PublicKey } from "@solana/web3.js";
import crypto from "crypto";
// --- configuration ---
const PROGRAM_ID = new PublicKey("TDEXxqqkyJ4Jh8UtLB5BzYoxbJKHwo3FFGKc5GeS1H6");
const SUFFIX = "TDEX";
// --- helpers ---
function le128(n: bigint): Buffer {
const buf = Buffer.alloc(16);
let x = n;
for (let i = 0; i < 16; i++) {
buf[i] = Number(x & 0xffn);
x >>= 8n;
}
return buf;
}
function randomU128(): bigint {
return BigInt("0x" + crypto.randomBytes(16).toString("hex"));
}
// --- main ---
async function main() {
console.log(`Searching for mint PDA ending with '${SUFFIX}'`);
console.log(`Program ID: ${PROGRAM_ID.toBase58()}`);
console.log("====================================");
let salt = randomU128();
let attempts = 0n;
const startTime = Date.now();
while (true) {
const saltLe = le128(salt);
const [pda] = PublicKey.findProgramAddressSync(
[Buffer.from("mint"), saltLe],
PROGRAM_ID
);
const base58 = pda.toBase58();
attempts++;
if (base58.endsWith(SUFFIX)) {
const elapsed = (Date.now() - startTime) / 1000;
console.log("\n✅ Found vanity mint!");
console.log(`Mint PDA: ${base58}`);
console.log(`Salt (LE u128 hex): ${saltLe.toString("hex")}`);
console.log(`Attempts: ${attempts}`);
console.log(`Elapsed: ${elapsed.toFixed(2)}s`);
break;
}
if (attempts % 100000n === 0n) {
const elapsed = (Date.now() - startTime) / 1000;
process.stdout.write(
`Attempts: ${attempts.toString()} | ${(Number(attempts) / Math.max(elapsed, 1)).toFixed(0)}/s | last: ${base58}\r`
);
}
salt = (salt + 1n) & ((1n << 128n) - 1n);
}
}
main().catch((e) => console.error("Error:", e));
Usage:
ts-node grinder_one.ts
Output:
Searching for mint PDA ending with 'TDEX'
Program ID: TDEXxqq...
====================================
✅ Found vanity mint!
Mint PDA: 3Myg7TDEX
Salt (LE u128 hex): e4f7c0000021f0f4a9c3...
Attempts: 693452
Elapsed: 10.21s
Use the found salt (in LE hex) as your InitializePoolArgs.salt
.
Last updated