Configuration

The public dashboard runs mainnet LIVE only. Every field below maps to project data stored in the cloud. Click Apply settings after bot changes, Save tiers when you only edit the tier table, and Save credentials for the dev wallet and RPC.

Identity

Dashboard labelFieldNotes
Project name (create bar)nameAny label you choose. Optional on create; default My Project.
Mint (CA) required (create bar)mintRequired when you click Create. Valid Solana base58 (32-byte pubkey). Stored on the project and in settings.mint.
Name (Bot settings)nameProject display name. Saved with Apply settings.
Mint (CA) (Bot settings)mintEditable. Must stay a valid CA; cannot be cleared. Changing it and saving refreshes the ticker from DexScreener.
Token symboltokenSymbolRead-only in the dashboard. Set by the server from DexScreener (max 16 chars). Updates when the mint changes. Used in logs (e.g. buyback lines).

On POST /api/projects, the API rejects a missing mint. Client PATCH cannot set tokenSymbol; only a mint change triggers a new lookup.

Cycle timing

Dashboard labelFieldDefaultRange
Cycle interval (s)cycleIntervalSec605 - 3600

After you press Start, the first on-chain cycle runs in about 3 seconds, then repeats every interval.

Claim, reserve, buyback

Dashboard labelFieldDefaultWhat it does
Min claim (SOL)minClaimSol0.005Skip claim until Pump.fun creator vault balance is at least this amount.
Min reserve (SOL)minReserveSol0.05SOL the bot tries to leave on the dev wallet for future fees. Also used by launch readiness balance checks.
Rewards to distribute %buybackPercent100Share of pooled creator fees (after tx fees) for holder rewards this cycle. Independent of burn %. Sum with burn % must be ≤ 100; remainder stays in the pool.
Burn %burnPercent0Extra share of the same pool for project-token buyback and SPL burn (not airdropped). Works with any reward asset. Sum with distribute % must be ≤ 100.
Slippage (bps)slippageBps500Basis points for buyback and Jupiter swaps. 500 = 5%. Max 5000.

For the project token (the default reward), the buyback route is chosen automatically: bonding curve before graduation, PumpSwap AMM after the curve completes. For SOL / USDC / custom-token rewards, see Airdrop reward below.

Airdrop reward (what holders receive)

Eligibility and holder snapshots are always computed against the project mint - holders must hold your token to qualify. Only the distributed asset is configurable. Choose it under Bot settings - Airdrop reward; it is stored as settings.rewardAsset.

Dashboard optionrewardAsset.kindHow it is acquired each cycle
Project token (buyback)SAME (default)Buy your token from claimed SOL (Pump.fun bonding curve or PumpSwap) and airdrop it. Legacy behaviour.
SOLSOLNo buyback. Claimed SOL is split directly to holders (native transfers, no ATA rent).
USDCUSDCSwap claimed SOL to USDC via Jupiter, then airdrop USDC.
Custom token (mint)CUSTOMSwap claimed SOL to any SPL mint via Jupiter, then airdrop it. Requires a tradable Jupiter route.

Reward mint (CA) (rewardAsset.mint) is required only for CUSTOM and must be a valid base58 SPL mint with a Jupiter swap route. It is independent from the project mint: holders still qualify on your token, but receive the reward mint. An invalid or routeless mint is rejected; an unrecognized rewardAsset safely degrades to SAME so existing projects keep working with no migration.

All reward types stay self-financing: gas, ATA rent, and (for USDC / custom) the Jupiter swap are paid from claimed creator fees before sizing the spend. Logs and overlay show the reward token's own ticker (e.g. $USDC or your custom symbol), not the project ticker.

Launch readiness adds a reward_asset check that probes a read-only Jupiter route for USDC / custom rewards (required to pass) and is informational for SOL / project-token rewards.

Public distribution transparency

When you change holder-facing policy in the dashboard and press Apply settings, Latrine Bot writes a permanent public audit line automatically. There is no toggle to disable this, no setting to change severity rules, and no way to hide a logged change from the token page or your dashboard Output after it is saved.

What triggers a public log line

Each successful PATCH /api/projects/:id that changes any of the following appends one or more POLICY events to project_events:

ChangeExample log
Fee split (buybackPercent, burnPercent, hold %)Distribution changed. Holders 80% -> 100%. Burn 10% -> 0%. Hold 10% -> 0%.
Major holder cut (server rule)Major distribution cut. Holders 100% -> 61%. … with severity alert
Payout currency (rewardAsset)Payout currency changed: project token ($TICKER) -> SOL.
Holder reward choice on/offHolder reward choice enabled. / … disabled.
X post boost on/offX post boost enabled. / … disabled.
Hold fund transparency (holdFund)Creator hold fund: simple reserve (no public goal)., Creator hold fund: Dex Vault selected. …, Dex Vault active. Hold N% locked - …, or goal-mode Creator hold fund: Dex Paid. Target: 4 SOL. (only when hold % > 0)

Major distribution cut is decided by the platform, not by you: holder airdrop % drops by 20 points or more, or goes to 0%. You cannot change that threshold or suppress the alert styling.

Where holders and you see it

The token page refreshes about every 20 seconds. After Save, expect a short delay before the public page shows the new banner or history entry. The dashboard asks for confirmation before saving when a public policy change is detected.

API shapes: Distribution transparency API.

Hold fund transparency

When your Creator fee split keeps a non-zero hold slice, part of each cycle's pooled creator fees is reserved for your hold fund. In simple and goal modes the reserve stays on the dev wallet (stats.totalHeldSol). In Dex Vault mode hold fees transfer to a locked vault wallet each cycle - segregated from the dev wallet - until DexScreener is paid. The dashboard block Hold fund transparency lets you explain why you keep that slice and, optionally, show progress toward a SOL goal or Dex payment on your Stream Studio overlay and token page.

This is not holder hold cycles in the tier table. Hold cycles gate eligibility streaks; hold fund is the creator's fee-split reserve counter.

When the block appears

The hold fund panel is visible in Bot settings only when hold % (the remainder after distribute + burn) is greater than zero. If you set distribute + burn to 100%, hold fund settings reset to simple mode internally.

Modes

Dashboard modesettings.holdFundToken pageStream Studio (hold-vault layer)
Simple hold (amount only, no goal) { mode: "simple", template: null, customLabel: "", goalSol: 0 } No extra hold card (only the hold % in the fee split bar). Compact read-only card: Creator hold reserve, held SOL, hold %.
Hold with a goal { mode: "goal", template, customLabel?, goalSol } Hold fund transparency card: purpose line, held SOL, progress bar when goalSol > 0. Same data; card grows for long purpose text and goal row.
Dex Vault ($299 Dex Paid) { mode: "guaranteed", guaranteed: { … } } Dex Vault card: full purpose line, vault balance, progress toward ~$299. Same data; short purpose Reserved for Auto Dex Payment + status Accumulating.

Dex Vault (guaranteed mode)

Dex Vault is a locked vault for hands-free DexScreener Enhanced Token Info (~$299). After you complete Dex Prefill and click Activate Dex Vault, hold fees from your creator hold % slice transfer to a dedicated vault wallet each cycle - segregated from the dev wallet. The dev wallet cannot spend those funds. When the vault reaches the quoted target, Latrine pays Dex Paid automatically. Activation is irreversible. API field remains mode: "guaranteed".

Purpose templates (goal mode)

Pick one purpose under Purpose. Amounts are always in SOL, not USD.

Dashboard optiontemplatePublic label
Dex PaiddexHolding for Dex Paid
Dex Boost PaidboostHolding for Dex Boost Paid
Dex Ad PaidadHolding for Dex Ad Paid
Custom labelcustomHolding for <your text> (max 80 chars)

Goal (SOL) is optional but required for a progress bar. Without a positive goal, viewers still see the purpose and held SOL on the token page and stream. Changing hold fund settings triggers a POLICY audit line (see above) when hold % > 0.

Only you edit hold fund in the dashboard. Stream Studio and the token page are read-only. In Dex Vault mode public holdFund.heldSol is the vault balance, not stats.totalHeldSol. Enable the hold-vault layer in Studio to show the card on stream.

Holder reward choice (Holder perk)

Optional perk for eligible holders on your public token page (/realm/:projectId) and the homepage showcase when enabled. Holders pick what they receive each cycle: project token (buyback), SOL, or USDC. Eligibility and snapshot weight stay on your project mint - only the payout asset changes per wallet.

Dashboard labelFieldDefaultWhat it does
Holder reward choiceholderRewardChoiceEnabledfalseWhen on, the token page shows the Holder perk panel. Wallets connect Phantom once and sign a SIWS message to save a preference in D1 (holder_reward_prefs).

The dev default from rewardAsset is shown as DEV DEFAULT in the UI. Wallets without a saved preference receive the dev default cohort. Saved prefs are read each cycle and split the airdrop budget across SAME / SOL / USDC cohorts. API: Holder perks API.

X post boost (Boost)

Optional social perk: anyone can post on X about your token and paste the link + wallet on the token page. The boost is active for a fixed time window (default 1 hour) and affects every airdrop cycle that runs while the window is open. Payouts come from the same creator-fee pool as regular holder drops.

Core rules

RuleDetail
Active window1 hour by default (socialBoostDurationMin: 60). Dev can set 5-1440 minutes via PATCH. Timer starts when the claim is accepted.
One post URL per token, foreverEach X link (tweet_id) can be claimed once per project, globally. Any wallet - first valid claim wins. Re-submitting the same link returns 409, even after expiry or payout.
One active claim per wallet per tokenWhile boost_until is in the future, that wallet cannot claim a second post on this token. After the hour ends, claim again with a new post URL. Response 409 includes boostUntil.
Different wallets, same tokenEach wallet can claim its own post URL on the same token (each URL still once). Many wallets can have parallel active boosts on one token.
Same wallet, other tokensLimits are per token, not global. A wallet with an active boost on token A can still claim on token B.
Boost again laterAfter the window expires (or after a successful payout), publish a new X post and submit its new URL. Old URLs stay burned.
No wallet sign-inUnlike holder reward choice, boost claim does not require Phantom or SIWS - only a valid tweet URL and wallet address.
LIVE onlyFeature works only when the project is LIVE with a mint set and socialClaimEnabled: true.

Step-by-step (holder or non-holder)

  1. Dev enables Enable X post boost in Bot settings.
  2. On the token page, open the Boost panel. GET .../social-claim returns a suggested template (ticker, CA, Running on @Latrine_bot).
  3. User publishes a post on X that passes validation (see below).
  4. User pastes the full post link (x.com/... or twitter.com/...) and their wallet, then clicks Claim boost.
  5. Server fetches the tweet via X API, validates text, and stores a row with status: pending and boost_until (now + window).
  6. On each airdrop cycle while now < boost_until and status is still pending, the engine applies the boost (see outcomes below).
  7. After a cycle that actually pays that wallet, the claim moves to status: paid. The tweet URL remains unusable even if the hour has not ended.
  8. If the hour ends before any paying cycle, the boost simply stops applying. The tweet URL is still burned.

What happens in each cycle

Social boost runs after the normal hold-cycle gate. It does not change eligibility history or bypass hold streaks for full tier status.

Wallet situationActive boost effectReward cohort
Eligible holder (balance + hold streak passed) Proportional weight multiplied by socialHolderBoostMultiplier (default 1.15x) Same as normal (holder reward choice if enabled)
Not in the drop yet (no balance, below tier floor, anti-whale, or hold streak not met) Added as an intro recipient with virtual weight = socialNonHolderWeightRatio x active tier minTokens (default 8% of tier floor) Dev default reward only (socialOnly - not holder reward choice)

Intro share is a small discovery airdrop, not full holder eligibility. Holders who are still gated by hold cycles are treated like non-holders for boost purposes until they pass the streak.

Dashboard settings

Dashboard labelFieldDefaultWhat it does
Enable X post boostsocialClaimEnabledfalseShows the Boost panel on the token page. Wallets submit a tweet URL + address; the server fetches the post and validates it.
Boost window (minutes)socialBoostDurationMin60How long a claimed post stays active (5-1440). Not exposed in the dashboard UI yet; adjustable via PATCH.
Holder boost multipliersocialHolderBoostMultiplier1.15Multiplier on an eligible holder's proportional weight when they have an active boost (1-3).
Non-holder intro weightsocialNonHolderWeightRatio0.08Virtual weight for non-holders as a fraction of the active tier minTokens (0-0.5). They join the default reward cohort only (socialOnly).

Post requirements

Validated server-side when the claim is submitted (case-insensitive):

Common errors

HTTPWhen
400Missing or invalid tweet URL, wallet, or post text (no $TICKER, CA, or @handle)
403socialClaimEnabled is off
404Project not LIVE, or tweet deleted
409Tweet URL already used for this token, or this wallet already has an active boost on this token (see boostUntil)
429Rate limit (10 claim POSTs per IP per minute)
502X API could not return tweet text - retry shortly

API reference: Holder perks API. Eligibility interaction: X post boost.

Holder filters (fallback)

Dashboard labelFieldDefaultWhat it does
Min holder (fallback)minHolderBalance500,000Fallback minimum balance (whole tokens) if no tier matches the current market cap or MC is unknown.
Max holder (anti-whale)maxHolderBalance20,000,000Anti-whale cap in whole tokens. Wallets holding more than this are excluded. Set 0 to disable.

All token amounts in the dashboard are whole tokens (the number you would see on Pump.fun or in a wallet). The bot converts to base units internally when comparing on-chain balances.

Once DexScreener reports market cap, the active tier floor from eligibilityTiers replaces the fallback min holder for that cycle.

Eligibility tiers

Stored as eligibilityTiers: an array of { mcUsd, minTokens, holdCycles } rows. Use Save tiers to PATCH only tiers, or Apply settings to save tiers together with other bot fields. See Eligibility.

MC ≥ (USD)Min tokensHold cycles
0500,0005
50,000450,0006
100,000400,0008
250,000300,00010
500,000220,00012
1,000,000150,00015
2,500,000110,00022
5,000,00075,00030
10,000,00055,00040
15,000,00040,00050
25,000,00030,00060
50,000,00022,00080
100,000,00015,000100

Reset to default calls POST /api/projects/:id/tiers/reset-default and restores the platform default table above.

Launch readiness (preflight)

Before Start or Run now, open Launch readiness in the Controls panel (or call GET /api/projects/:id/preflight from your integration). The dashboard blocks Start and Run now until every required check passes.

  1. Select your project. Preflight runs automatically after load and after you save credentials or bot settings (debounced).
  2. Click Check again to refresh without starting a cycle.
  3. When the summary says Ready to launch, you may Start or Run now. If it says Not ready yet, fix failed required lines first.

What preflight checks

Dashboard labelCheck idRequiredWhat it verifies
Mint (CA)mint_setyesProject has a mint address
Mint formatmint_formatyesValid base58 Solana pubkey
CredentialscredentialsyesDev wallet secret and Helius RPC URL saved
RPC connectionrpcyesgetHealth / slot ping against your RPC URL
Mint on mainnetmint_onchainyesMint account exists (SPL Token or Token-2022)
Market datamint_marketnoDexScreener ticker found (informational; bot can still run)
Airdrop rewardreward_assetconditionalFor USDC / custom rewards: required Jupiter swap-route probe. For SOL / project-token rewards: informational.
Dev wallet is creatordev_is_creatoryesSaved dev pubkey can claim Pump.fun creator fees for this mint
Dev wallet balancebalance_reserveyesOn-chain SOL ≥ minReserveSol
Recommended balancebalance_recommendednoCovers minReserveSol + minClaimSol (launch buffer)
On-chain enginerunneryesCloud engine available (may show warming up on cold start)

Response field ready is true only when every check with required: true has ok: true. Optional checks (market data, recommended balance) help you tune settings but do not block launch.

Full API shape and curl examples: API reference - Launch readiness.

PATCH /api/projects/:id (client fields)

Client PATCH accepts name, mint, and settings. It cannot change mode (always mainnet LIVE for end users).

Inside settings, the API merges and clamps these keys (via server sanitizeSettings):

tokenSymbol is server-owned: any tokenSymbol in the PATCH body is ignored. Operator-only keys (legacy simulation tuning and other internal knobs) are not documented here and are omitted from public API responses.

PATCH /api/projects/:id
{
  "name": "My token",
  "mint": "YOUR_CA_BASE58",
  "settings": {
    "cycleIntervalSec": 90,
    "minClaimSol": 0.01,
    "buybackPercent": 80,
    "rewardAsset": { "kind": "CUSTOM", "mint": "REWARD_MINT_BASE58" },
    "holderRewardChoiceEnabled": true,
    "socialClaimEnabled": true,
    "holdFund": {
      "mode": "goal",
      "template": "dex",
      "customLabel": "",
      "goalSol": 4
    },
    "eligibilityTiers": [
      { "mcUsd": 0, "minTokens": 500000, "holdCycles": 5 }
    ]
  }
}

Use { "kind": "SOL" }, { "kind": "USDC" }, or { "kind": "SAME" } for the other reward types (mint is ignored unless kind is CUSTOM).

Credentials (separate save)

Not part of Apply settings - use Save credentials (POST /api/projects/:id/secrets):

Click Test RPC after save to verify connectivity. Credentials metadata (pubkey, masked RPC host) is available at GET /api/projects/:id/credentials.

Full setup guideModesPreflight API