@star-factory/sdk-launchpad
v0.1.7
Published
TypeScript SDK for Star Launchpad - Token launches with DAO integration
Downloads
708
Maintainers
Readme
@star-factory/sdk-launchpad
TypeScript SDK for the Star Launchpad program. Covers the full lifecycle:
- Launch Flow — initialize, configure/update config, create token, execute launch (pool + DAO + authority transfer)
- Token Claims — eligibility checks, vesting math, claim transaction building
- Launch Dry-Run + ALT Helpers — simulation helpers, v0 compile, and execute ALT planning
Install
yarn add @star-factory/sdk-launchpadRuntime dependencies (including @solana/web3.js, @coral-xyz/anchor, bn.js) are bundled via this package's dependencies.
Peer dependency: typescript@^5.
Quick Start
import {
getLaunchpadProgram,
LAUNCHPAD_PROGRAM_ID,
LaunchpadSDK,
} from '@star-factory/sdk-launchpad';
const sdk = new LaunchpadSDK({
connection,
cluster: 'devnet',
zcApiKey: process.env.ZC_API_KEY!,
});
const launchpadProgram = getLaunchpadProgram(connection, LAUNCHPAD_PROGRAM_ID);Launch Flow
1. Initialize Launch
Creates a LaunchConfig PDA + underlying fundraise vault via CPI to vault::make.
const tx = await sdk.buildInitializeLaunchTx(launchpadProgram, {
creator: wallet.publicKey,
seed: new BN(Date.now()),
vaultSeed: new BN(Date.now() + 1),
totalSupply: new BN('1000000000000000'), // 1M tokens @ 9 decimals
tokensToParticipants: new BN('500000000000000'), // 500K to participants
quoteMint: NATIVE_MINT,
minRaise: new BN('100000000'),
targetRaise: new BN('100000000'),
// IMPORTANT: unix seconds (not milliseconds)
startTime: new BN(nowSec + 60), // starts in 1 minute
endTime: new BN(nowSec + 4 * 24 * 60 * 60), // 4-day raise window
vaultProgramId: VAULT_PROGRAM_ID,
});
await sendTx(tx, [creator]);const nowSec = Math.floor(Date.now() / 1000);2. Configure Launch
Sets vanity mint configuration and token metadata. Transitions FundraiseActive → ReadyToLaunch.
const tx = await sdk.buildConfigureLaunchTx(launchpadProgram, {
admin: admin.publicKey,
launchConfig: launchConfigPda,
fundraiseState: vaultPda,
basePubkey: baseKeypair.publicKey,
vanitySeed: 'my-token-seed',
expectedMint: derivedMintAddress,
name: 'My Token',
symbol: 'MTK',
uri: 'https://arweave.net/metadata.json',
});
await sendTx(tx, [admin]);3. Create Launch Token
Creates the vanity mint, Metaplex metadata, and mints total supply. Transitions ReadyToLaunch → TokenCreated.
const tx = await sdk.buildCreateLaunchTokenTx(launchpadProgram, {
admin: admin.publicKey,
baseKeypairPubkey: baseKeypair.publicKey,
launchConfig: launchConfigPda,
expectedMint: derivedMintAddress,
});
await sendTx(tx, [admin, baseKeypair]); // both must signOptional: Update Launch Config (Recovery)
If the original base keypair is lost before token creation, replace vanity config in ReadyToLaunch state.
const tx = await sdk.buildUpdateLaunchConfigTx(launchpadProgram, {
admin: admin.publicKey,
launchConfig: launchConfigPda,
basePubkey: newBaseKeypair.publicKey,
vanitySeed: 'new-seed',
expectedMint: newExpectedMint,
});
await sendTx(tx, [admin]);4. Reserve Admin (off-chain)
Calls the zCombinator API to allocate a managed admin wallet for the DAO.
const poolAddress = sdk.derivePoolAddress(baseMint, quoteMint);
const reservation = await sdk.reserveAdmin({
name: 'ProjectDAO',
tokenMint: baseMint,
poolAddress,
poolType: 'damm',
quoteMint,
treasuryCosigner: teamMultisig,
ownerWallet: projectOwner,
});Or use the one-call helper:
const result = await sdk.prepareLaunchExecution({
daoName: 'ProjectDAO',
tokenMint: baseMint,
quoteMint,
treasuryCosigner: teamMultisig,
ownerWallet: projectOwner,
});5. Execute Launch
Atomically finalizes the vault, creates DAMM pool, creates DAO, transfers authorities, and routes funds. Transitions TokenCreated → Launched.
Returns both the TX and all resolved accounts (for ALT creation).
const { tx, accounts } = await sdk.buildExecuteLaunchTx(launchpadProgram, {
admin: admin.publicKey,
launchConfig: launchConfigPda,
launchConfigData,
poolActivationTime: new BN(now + 120),
daoName: 'ProjectDAO',
treasuryCosigner: teamMultisig,
newDaoAdmin: reservation.adminWallet,
dammPool: poolAddress,
vaultProgramId: VAULT_PROGRAM_ID,
computeUnits: 1_400_000,
});
// Create ALT from `accounts`, compile to VersionedTransaction, send6. Cancel Launch
Cancels from any pre-Launched state. Burns tokens if minted, enables refunds.
const tx = await sdk.buildCancelLaunchTx(launchpadProgram, {
admin: admin.publicKey,
launchConfig: launchConfigPda,
launchConfigData,
vaultProgramId: VAULT_PROGRAM_ID,
});
await sendTx(tx, [admin]);Post-Raise Dry Run and ALT Helpers
For dashboard/backend orchestration after request_tge:
- Build mint setup in one call:
sdk.buildAdminMintSetupTxs(...)returns:configureOrUpdateTxcreateLaunchTokenTx- normalized
metadataArgs
- Simulate launch steps:
sdk.simulateConfigureLaunch(tx)sdk.simulateCreateLaunchToken(tx)sdk.simulateExecuteLaunch(tx, { lookupTables })sdk.simulatePostRaiseLaunchFlow(...)(stateless wrapper)sdk.simulateVersionedLaunchTx(v0Tx)for precompiled v0 messages
- Execute-launch ALT/v0 support:
sdk.buildExecuteLaunchAltPlan(accounts)sdk.compileToV0Transaction(tx, { lookupTables })
- Stateful dry run hook:
sdk.dryRunPostRaiseLaunchStateful(input, executor)- caller provides backend executor (LiteSVM/local-validator/fork runner)
Token Claims
After a launch executes, depositors claim vested tokens through the claim_tokens instruction.
Check Eligibility
const eligibility = await sdk.getClaimEligibility(
launchpadProgram,
vaultProgram,
launchConfigPda,
wallet.publicKey,
);
if (eligibility.canClaim) {
console.log(`Claimable: ${eligibility.claimableNow.toString()}`);
} else {
console.log(`Reason: ${eligibility.reason}`);
}The ClaimEligibility result contains everything a UI needs:
| Field | Type | Description |
|-------------------|-------------------|------------------------------------------------|
| canClaim | boolean | Whether the user can claim right now |
| reason | string \| null | Why they can't (null when canClaim is true) |
| claimableNow | BN | Tokens claimable at this moment |
| totalTokens | BN | User's total token entitlement |
| totalClaimed | BN | Already claimed |
| totalVested | BN | Total vested as of now |
| tier | number \| null | Vesting tier (0–6) |
| vestingSchedule | VestingSchedule | Start/end timestamps, percent vested, etc. |
Build Claim Transaction
Client-side (wallet adapter):
const tx = await sdk.buildClaimTx(launchpadProgram, {
user: wallet.publicKey,
launchConfig: launchConfigPda,
launchConfigData,
vaultProgramId: VAULT_PROGRAM_ID,
});
const sig = await wallet.sendTransaction(tx, connection);Server-side (sponsored/relay):
const tx = await sdk.buildClaimTx(launchpadProgram, {
user: userPubkey,
launchConfig: launchConfigPda,
launchConfigData,
vaultProgramId: VAULT_PROGRAM_ID,
feePayer: relayPubkey,
priorityFee: 10_000,
computeUnits: 200_000,
});Vesting Model
Tokens vest linearly from pool activation time based on the depositor's tier:
| Tier | Vesting Duration | Unlock | |------|------------------|------------------------------| | 0 | Immediate | 100% at pool activation | | 1 | 2 weeks | Linear over 1,209,600s | | 2 | 4 weeks | Linear over 2,419,200s | | 3 | 6 weeks | Linear over 3,628,800s | | 4 | 8 weeks | Linear over 4,838,400s | | 5 | 10 weeks | Linear over 6,048,000s | | 6 | 12 weeks | Linear over 7,257,600s |
Users can claim multiple times — each claim transfers vested - already_claimed.
Low-Level Exports
Every building block is exported individually:
import {
// Instruction TX builders
getLaunchpadProgram,
buildInitializeLaunchTx,
buildConfigureLaunchTx,
buildUpdateLaunchConfigTx,
buildCreateLaunchTokenTx,
buildExecuteLaunchTx,
buildCancelLaunchTx,
// Claim TX builders
buildClaimTransaction,
buildBatchClaimTransactions,
// Launchpad PDAs
deriveLaunchConfigPda,
deriveLaunchpadSignerPda,
deriveClaimRecordPda,
derivePositionNftMintPda,
// External program PDAs
deriveVaultPda,
deriveTgeConfigPda,
deriveDammPoolAuthority,
deriveDammTokenVault,
deriveDammPosition,
deriveDammPositionNftAccount,
deriveDammEventAuthority,
deriveSquadsMultisig,
deriveSquadsVault,
deriveSquadsProgramConfig,
deriveDaoPda,
deriveModeratorPda,
deriveMintCreateKeyPda,
deriveMetadataPda,
// Pool derivation
derivePoolAddress,
sortMints,
// Account fetching + resolution
fetchLaunchConfig,
fetchClaimRecord,
fetchDepositorRecord,
resolveClaimAccounts,
deriveDepositorRecordPda,
// Eligibility (pure computation)
computeAllocatedAmount,
computeClaimEligibility,
computeUserTokens,
computeVestedAmount,
// Constants
LAUNCHPAD_PROGRAM_ID,
LAUNCHPAD_IDL,
NUM_TIERS,
TIER_VESTING_SECONDS,
TIER_VESTING_WEEKS,
DAMM_PROGRAM_ID,
DAMM_CONFIG_PDA,
SQUADS_PROGRAM_ID,
METAPLEX_PROGRAM_ID,
// ZC client
ZCClient,
} from '@star-factory/sdk-launchpad';Architecture
sdk-launchpad/src/
├── index.ts Barrel exports
├── program.ts getLaunchpadProgram() helper + typed program client
├── sdk.ts LaunchpadSDK class (high-level API)
├── types.ts All TypeScript interfaces and types
├── idl/
│ └── launchpad.json Bundled launchpad IDL (copied to dist on build)
├── pdas.ts DAMM pool PDA derivation
├── instructions/
│ ├── pdas.ts External program PDAs (DAMM, Squads, Futarchy, Metaplex, Vault)
│ ├── constants.ts External program IDs
│ ├── initialize-launch.ts
│ ├── configure-launch.ts
│ ├── update-launch-config.ts
│ ├── create-launch-token.ts
│ ├── execute-launch.ts Account resolution (~35 accounts) + TX builder
│ └── cancel-launch.ts
├── claims/
│ ├── pdas.ts Launchpad PDA derivation (launch config, signer, claim record)
│ ├── accounts.ts Account fetching + resolution
│ ├── eligibility.ts Pure vesting math + eligibility computation
│ └── tx.ts claim_tokens TX builder
└── zc/
├── client.ts zCombinator REST API client
├── constants.ts Program IDs, API endpoints, rate limits
└── types.ts ZC-specific typesDesign principles:
- Pure math is separated from RPC —
eligibility.tshas zero network calls; it takes pre-fetched data and returns a deterministic result. - All PDAs are deterministic — every account for every instruction is derived from known inputs. No guessing, no fetching account lists.
- Transactions are unsigned — the SDK never touches private keys. It returns
Transactionobjects for the caller to sign however they want. - On-chain math parity —
computeAllocatedAmount,computeUserTokens, andcomputeVestedAmountmirror the Rust implementations exactly. - Full lifecycle coverage — every launchpad program instruction has a corresponding TX builder.
