npm package: @star-factory/sdk-launchpad
Description: TypeScript SDK for Star Launchpad - Token launches with DAO integration
Author: Star Protocol
Latest version: 0.1.7

# @star-factory/sdk-launchpad

TypeScript SDK for the Star Launchpad program. Covers the full lifecycle:

1. **Launch Flow** — initialize, configure/update config, create token, execute launch (pool + DAO + authority transfer)
2. **Token Claims** — eligibility checks, vesting math, claim transaction building
3. **Launch Dry-Run + ALT Helpers** — simulation helpers, v0 compile, and execute ALT planning

## Install

```bash
yarn add @star-factory/sdk-launchpad
```

Runtime dependencies (including `@solana/web3.js`, `@coral-xyz/anchor`, `bn.js`) are bundled via this package's `dependencies`.
Peer dependency: `typescript@^5`.

## Quick Start

```typescript
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`.

```typescript
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]);
```

```typescript
const nowSec = Math.floor(Date.now() / 1000);
```

### 2. Configure Launch

Sets vanity mint configuration and token metadata. Transitions `FundraiseActive → ReadyToLaunch`.

```typescript
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`.

```typescript
const tx = await sdk.buildCreateLaunchTokenTx(launchpadProgram, {
  admin: admin.publicKey,
  baseKeypairPubkey: baseKeypair.publicKey,
  launchConfig: launchConfigPda,
  expectedMint: derivedMintAddress,
});
await sendTx(tx, [admin, baseKeypair]); // both must sign
```

### Optional: Update Launch Config (Recovery)

If the original base keypair is lost before token creation, replace vanity config in `ReadyToLaunch` state.

```typescript
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.

```typescript
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:

```typescript
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).

```typescript
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, send
```

### 6. Cancel Launch

Cancels from any pre-Launched state. Burns tokens if minted, enables refunds.

```typescript
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:
    - `configureOrUpdateTx`
    - `createLaunchTokenTx`
    - 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

```typescript
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):**

```typescript
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):**

```typescript
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:

```typescript
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 types
```

**Design principles:**

- **Pure math is separated from RPC** — `eligibility.ts` has 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 `Transaction` objects for the caller to sign however they want.
- **On-chain math parity** — `computeAllocatedAmount`, `computeUserTokens`, and `computeVestedAmount` mirror the Rust implementations exactly.
- **Full lifecycle coverage** — every launchpad program instruction has a corresponding TX builder.