Docs menu: Architecture

Architecture

Components

  1. BrowserYour wallet signs every transaction
  2. build txsLatch webBuilds the transactions and reads chain state through an RPC
  3. sends txsLatch vault programHolds the position NFT, so only the vault can claim fees
    1. CPIMeteora DAMM v2The pool and its position
    2. CPISPL Token / MetaplexThe mint and its metadata
    1. permitClaim signerSite routes: check the X login, sign an ed25519 permit. Needs X credentials
    2. IndexerNot built. The pages read the chain directlyNot built

The claim signer and X login are routes on the Latch site (see X claims). There is no separate indexer: the token page reads the chain directly.

Accounts

All are program-derived addresses (PDAs) owned by the Latch vault program. This is the layout that is built and tested in vault/programs/ember-vault/src/state.rs.

// seeds: ["config"]
pub struct Config {
    pub admin: Pubkey,         // can change the treasury and the claim signer
    pub treasury: Pubkey,      // receives the protocol share
    pub pending_admin: Pubkey, // set by propose_admin, cleared by accept_admin
    pub claim_signer: Pubkey,  // key whose signatures authorise X claims (zero = off)
    pub bump: u8,
}

// seeds: ["launch", creator, position_nft_mint]
pub struct Launch {
    pub creator: Pubkey,
    pub recipient: Pubkey,        // the creator wallet, or the escrow PDA for an X-account launch
    pub pool: Pubkey,
    pub position: Pubkey,
    pub position_nft_mint: Pubkey,
    pub token_mint: Pubkey,       // the launched token
    pub creator_bps: u16,         // creator share, max 9500, can only go down
    pub creator_x_id: u64,        // numeric X user id, 0 = none
    pub metadata_delay_secs: i64, // 0 = the vault does not manage the name
    pub pending_executable_at: i64,
    pub pending_name: String,     // a queued rename
    pub pending_symbol: String,
    pub pending_uri: String,
    pub bump: u8,
}

// seeds: ["escrow", launch]
pub struct Escrow {
    pub launch: Pubkey,
    pub claim_nonce: u64,         // each successful claim adds one, so a permit works once
    pub bump: u8,
}

The launch account's address holds the position NFT. That is what lets the vault, and only the vault, claim fees. When the creator named an X account, the creator share is paid into token accounts owned by the escrow instead of a wallet.

Instructions

Instruction Who can call What it does
initialize_config the program's upgrade authority Sets the admin and the treasury. Only the upgrade authority can call it, so nobody can take the config by front-running deployment.
set_treasury admin Changes where the protocol share goes. Never touches a creator's share.
propose_admin, accept_admin admin, then the new admin Two-step handover of the admin role.
set_claim_signer admin Sets the key that authorises X-account claims. Zero turns them off.
register_launch creator Checks the position is fully locked and belongs to the pool, both mints are plain SPL Token mints, and the launch address holds the NFT. Records the creator share, the optional X account and the optional rename wait. If a wait is chosen, the vault must already hold the token's update authority.
crank_fees anyone Claims fees from Meteora (the launch address signs) and splits them: the creator share to the recipient or the escrow, the rest to the treasury.
lower_creator_bps creator Lowers the creator share. Raising it fails.
set_recipient creator Points the creator share at another wallet. Refused for X-account launches.
queue_metadata, cancel_metadata creator Queue a new name, symbol and link, or drop the queued change.
apply_metadata anyone After the launch's wait, writes the queued change into the token's metadata.
claim_creator_fees the claimant Pays an X-account launch's escrow to the claimant, only with a valid permit from the claim signer in the same transaction.

All of these are built and covered by the integration suite. See X claims for the permit and Upgradeability for the rename wait.

Launch transaction sequence

A single Solana transaction is limited to 1232 bytes, so a launch takes three. Sizes are checked offline by scripts/verify-launch.mts.

  1. Create the token (about 600 bytes). Create the mint, mint the full supply to the creator's wallet, write the metadata, and revoke the mint authority.
  2. Open and lock the pool (about 1050 bytes). The creator's wallet creates the DAMM v2 pool with a single-sided deposit over [Pa, Pb] and permanently locks the position in the same transaction. If the creator chose a first buy, the same transaction then wraps that SOL, swaps it for the token from the creator wallet and unwraps what is left (about 1,120 bytes in total), so nobody can trade between the pool opening and that buy.
  3. Hand the position to the vault (about 500 to 720 bytes). In one atomic transaction: create the launch account's Token-2022 account for the position NFT, move the NFT into it, optionally hand the token's update authority to the launch address, and call register_launch.

The vault cannot be the creator of the pool. The permanent lock instruction needs the creator to sign, and a PDA cannot sign outside a program. So the creator's wallet creates and locks the pool, and the NFT moves to the vault afterwards. The liquidity is already locked when it moves, so only the right to claim fees changes hands.

If step 2 or 3 fails, the supply stays in the creator's wallet (step 2) or the NFT stays in the creator's wallet (step 3), and the launch page retries from that step. Until step 3 lands, the creator can still claim fees directly, and nobody else can.

Why the vault owns the position

DAMM v2 positions are NFTs. Claiming fees needs the position owner's signature. If a person owned it, one wallet would control fees and could transfer the position away. If the launch account owns it, the vault is the only thing that can claim, and its code decides the split. Liquidity removal is impossible because of the permanent lock. This is also the reason the vault is the weakest link: see Security.

Off-chain pieces

  • Web. Next.js app that builds unsigned transactions. Users sign in their own wallet.
  • Indexer. Not built. The token page and the fees pages read accounts and program events straight from an RPC.
  • Claim signer. Built into the site as API routes. It checks the X login and signs a permit the vault verifies. See X claims.