Skip to content
FeeRelaydevnet

Documentation

Everything FeeRelay does is in one small Anchor program. The website and API are conveniences on top of it.

Overview

A project stores 1–8 recipient wallets and their shares in basis points (total exactly 10,000). Each project has a vault: a data-less, system-owned address derived from the project. Fees sent to the vault are swept into the project account by distribute and credited to recipients. Each recipient withdraws with their own signature.

Accounts & PDAs

AccountSeedsPurpose
Config["config"]Admin, pending admin, pause flags, project count.
Project["project", creator, project_id]Recipients, shares, claimable balances, totals, dust, config nonce, lock.
Vault["vault", project]Fee address. Pre-funded to its rent floor so small payouts land.

Including the creator in the project seed prevents another wallet from squatting a project ID seen in the mempool.

Instructions

InstructionWhoEffect
initializeUpgrade authorityCreates Config. Can only run once.
create_projectAny walletValidates recipients, creates Project, funds vault rent floor.
distributeAnyoneSweeps vault balance above rent floor and credits recipients.
withdraw(index, amount)That recipientMoves up to the recipient’s claimable lamports to their wallet.
update_recipients(nonce, …)Project authorityDistributes pending fees under the old split, carries balances, replaces the list. Rejects removing a recipient with a balance, and stale nonces.
lock_recipientsProject authorityPermanently freezes the list.
set_authorityCurrent + new authorityBoth must sign.
set_paused, propose_admin, accept_adminAdminPause config/distribution and, separately, withdrawals; two-step admin rotation. Admin cannot move funds.

Routing fees into a vault

The vault address is shown after you create a project and on the dashboard. Options:

  • Manual (works now): send SOL to the vault from any wallet or program, then call distribute.
  • pump.fun fee sharing (unvalidated): pump.fun's official fee-sharing config lets a coin creator split fees among shareholders by basis points. Adding the vault as a shareholder would route that share into FeeRelay.
  • pump.fun creator address (unvalidated): launching a coin with the vault as creator.

The pump.fun routes have not been reproduced on devnet by this project, so live launch is disabled. See docs/PUMPFUN_INTEGRATION.md in the repository for the validation plan. FeeRelay never hard-codes pump.fun fee percentages.

Split math & dust

For each distribution, pool = swept + dust; each recipient gets floor(pool × bps / 10000) using 128-bit intermediates; the remainder (always fewer lamports than recipients) becomes the new dust. Invariant: project lamports = rent + Σ claimable + dust.

HTTP API

All state-changing endpoints require a wallet session (Sign-In With Solana message, single-use nonce, 5-minute expiry) and same-origin requests. Create endpoints require an Idempotency-Key header. Full reference: docs/API.md.

GET  /api/health
POST /api/auth/nonce        { wallet }
POST /api/auth/verify       { wallet, nonce, signature }
GET  /api/projects          (mine)
POST /api/projects          { name, recipients[], launchConfig }  + Idempotency-Key
GET  /api/projects/:id
POST /api/projects/:id/onchain  { signature }   (server re-verifies on-chain)
POST /api/withdrawals       { projectId, signature } + Idempotency-Key
GET  /api/tx/:signature

Keeper & indexer

Long-running jobs do not run on Vercel. An external worker (worker/keeper.ts) calls /api/indexer/sync with a bearer secret to cache events, and can optionally call distribute for projects with pending fees. The dashboard always reads balances directly from the chain, so the cache is never the source of truth.

Security model →