@munsterberg/anselm-sdk
v0.3.3
Published
TypeScript SDK for the Anselm Solana launchpad program (PDAs, IDL, whitelist merkle tree, transaction builders).
Maintainers
Readme
@munsterberg/anselm-sdk
TypeScript SDK for the Anselm Solana launchpad program.
Ships the IDL, type definitions, PDA derivation helpers, whitelist merkle tree builder, transaction builders (remaining_accounts, ALT, WSOL pre-seed), math helpers (sqrt-price derivation, launch params), and fetchers.
Install
pnpm add @munsterberg/anselm-sdk @coral-xyz/anchor @solana/web3.js @solana/spl-token @meteora-ag/cp-amm-sdk bn.js
# or: npm i / yarn add — all are peer depsRequires Node.js >= 18.
Quick start
import {
getAnselmProgram,
ANSELM_PROGRAM_ID,
findConfigPda,
findFundraisePda,
buildWhitelistTree,
} from "@munsterberg/anselm-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
import { Wallet } from "@coral-xyz/anchor";
import BN from "bn.js";
const connection = new Connection("https://api.devnet.solana.com");
const program = getAnselmProgram(connection, wallet);
const configPda = findConfigPda(ANSELM_PROGRAM_ID);
const fundraisePda = findFundraisePda(nonce, ANSELM_PROGRAM_ID);
// Build a whitelist merkle tree:
const tree = buildWhitelistTree([
{ address: new PublicKey("..."), maxAmount: new BN(1_000_000_000) },
{ address: new PublicKey("..."), maxAmount: new BN(500_000_000) },
]);
const root = tree.root; // number[32] — pass as `whitelistRoot` to createFundraise
const { proof, maxAmount } = tree.proofFor(contributorPubkey); // for contribute txWhat's included
| Module | Exports |
|---|---|
| constants | ANSELM_PROGRAM_ID, DAMM_V2_PROGRAM_ID, WSOL_MINT, MPL_TOKEN_METADATA_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, MIN_SQRT_PRICE, MAX_SQRT_PRICE, ALLOWED_FEE_TIERS_BPS, MAX_TOTAL_SUPPLY, etc. |
| pda | findConfigPda, findLaunchPda, findFundraisePda, findVaultPda, findContributionPda, findFeeLockerPda, findClaimablePda, findTreasuryVaultPda, findCustomizablePoolPda, findTokenVaultPda, findPositionPda, findPositionNftAccountPda, findPoolAuthorityPda, findDammV2EventAuthority, sortMints, findMetadataPda |
| merkle | buildWhitelistTree, MerkleTree |
| program | getAnselmProgram, ANSELM_IDL, type AnselmProgram, type Anselm |
| math | deriveInitialSqrtPrice, deriveLaunchParams |
| alt | buildLaunchAltIxs |
| keypair | grindProjectMintKeypair, isProjectMintCanonical |
| wsol | buildWsolPreSeedIxs, DEFAULT_WSOL_PRESEED_LAMPORTS |
| fetchers | getAnselmConfig, getFundraise, getLaunch |
| whitelist-json | toWhitelistJson, parseWhitelistJson, findMyWhitelistEntry |
| tx-builders/finalize-launch | buildFinalizeAndLaunchRemainingAccounts |
| tx-builders/instant-launch | buildInstantLaunchRemainingAccounts |
New in 0.2.0
Transaction builders
import {
grindProjectMintKeypair,
buildFinalizeAndLaunchRemainingAccounts,
buildInstantLaunchRemainingAccounts,
buildWsolPreSeedIxs,
buildLaunchAltIxs,
} from "@munsterberg/anselm-sdk";
import { Keypair } from "@solana/web3.js";
// Grind a mint keypair that satisfies canonical ordering (projectMint > WSOL)
const projectMintKp = grindProjectMintKeypair();
// Build remaining_accounts for finalize_and_launch
const positionNftKp = Keypair.generate();
const remainingAccounts = buildFinalizeAndLaunchRemainingAccounts({
projectMint: projectMintKp.publicKey,
creator: wallet.publicKey,
launch: launchPda,
positionNftMint: positionNftKp.publicKey,
includeTreasury: true, // set true when treasury_allocation_bps > 0
});
// Build remaining_accounts for instant_launch (no treasury)
const instantRemaining = buildInstantLaunchRemainingAccounts({
projectMint: projectMintKp.publicKey,
creator: wallet.publicKey,
launch: launchPda,
positionNftMint: positionNftKp.publicKey,
});
// Pre-seed WSOL ATA before instant launch
const { ixs: wsolIxs, creatorWsolAta } = buildWsolPreSeedIxs({
payer: wallet.publicKey,
});
// Build ALT for address lookup table compression
const { createIx, extendIx, altAddress } = await buildLaunchAltIxs({
connection,
authority: wallet.publicKey,
});Math helpers
import { deriveLaunchParams, deriveInitialSqrtPrice } from "@munsterberg/anselm-sdk";
import BN from "bn.js";
// Derive token allocation math
const params = deriveLaunchParams({
hardcap: new BN(1_000_000_000), // 1 SOL in lamports
lpAllocationBps: 2000, // 20% to LP
});
// params.lpTokens, params.contributorTokens, params.treasuryTokens, params.treasuryBps
// Derive sqrt price at finalize time (use actual total_raised, not hardcap)
const sqrtPrice = deriveInitialSqrtPrice({
lpTokens: params.lpTokens,
totalRaised: new BN(actualTotalRaised),
});Fetchers
import { getAnselmConfig, getFundraise, getLaunch } from "@munsterberg/anselm-sdk";
const config = await getAnselmConfig(program);
const fundraise = await getFundraise(program, nonce);
const launch = await getLaunch(program, mintPublicKey);Whitelist JSON distribution
import { toWhitelistJson, parseWhitelistJson, findMyWhitelistEntry } from "@munsterberg/anselm-sdk";
import BN from "bn.js";
// Creator: build and distribute
const json = toWhitelistJson({
leaves: [
{ address: contributorPubkey1, maxAmount: new BN(1_000_000_000) },
{ address: contributorPubkey2, maxAmount: new BN(500_000_000) },
],
fundraise: fundraisePda,
nonce: 0n,
});
// Contributor: look up their entry
const parsed = parseWhitelistJson(json);
const entry = findMyWhitelistEntry(parsed, wallet.publicKey);
// entry.maxAmount, entry.proofIntegration gotchas
These bite integrators who skim. Read them.
Canonical mint ordering.
projectMintmust be>WSOL_MINTbyte-compare. Grind a mint keypair untilsortMints(...).projectIsA === true. Both launch paths rely on this.Instant launch WSOL pre-seed. The creator's WSOL ATA needs ~0.1 SOL pre-funded before instant launch to satisfy a DAMM V2
TransferCheckededge case. Not needed for fundraise-launch (vault drain covers it).Address Lookup Tables.
finalize_and_launchrequires an ALT. Create + extend the ALT in a setup tx, confirm it, then reference in the main tx.initial_sqrt_priceis a finalize-time arg. Compute it from actualtotal_raisedat finalize, nothardcapat create. The on-chain code validates it against[sqrt_min_price, sqrt_max_price]stored at create.Whitelist leaf shape.
keccak256(pubkey_32 || maxAmount_u64_BE_8). Diverges from Aquinas/Solidity which usesuint256— Anselm usesu64because lamports fit. The SDK'sbuildWhitelistTreehandles this; don't hand-roll trees.Permissionless finalize. Any wallet can call
finalizeAndLaunchonce softcap met + (hardcap hit OR time expired).launch.creatoris the original fundraise creator, not the tx signer — use that for authorization downstream.DAMM V2 position custody. The position NFT lands on the FeeLocker PDA. Use
collect_fees+claim_feesto extract LP rewards; never try to transfer the NFT.
Reference client
See the app/ directory in the anselm repo for a full reference Next.js client implementing:
- Fundraise create/contribute/finalize (with whitelist UI +
whitelist.jsondistribution) - Instant launch (with mint-keypair grinding + WSOL ATA pre-seed)
- Fee collection + recipient rotation
- Treasury vault withdrawals
Breaking changes in 0.2.0
findTreasuryVaultPdanow returnsPublicKeydirectly instead of[PublicKey, number]. Update any callers that destructured the bump:const [pda] = findTreasuryVaultPda(...)→const pda = findTreasuryVaultPda(...).- The
./idlsubpath export has been removed. Import the IDL via the main entry:import { ANSELM_IDL } from "@munsterberg/anselm-sdk".
Versioning
Pre-1.0: breaking changes may occur in minor versions. Lock to an exact version in production until we hit 1.0.
License
MIT
