FLOORLaunch app

Integration

Deriving the accounts

All addresses are PDAs. With @coral-xyz/anchor or @solana/web3.js:

import { PublicKey } from "@solana/web3.js"

const VENUE = new PublicKey("3vkpdUbzcQ7p5Ak36kjcfmWmgpuH3syswtwa5CGina8j")
const HALT = new PublicKey("hZWUysrRYBmuindfRrE78rKuwG7iqQwKm5c9ZpAqk7o")
const CAPS = new PublicKey("riN4V5uUokJ2GqBVtbfnHpwUKmvCQv3A2Ygt7kNYmxN")
const NOTICE = new PublicKey("4MLRiWbL48QgrZivaHp1RzZPTPGLNDU9zqNHnbFxBuKr")

const symbol = (s: string) => { const b = Buffer.alloc(12); b.write(s); return b }

const [venue] = PublicKey.findProgramAddressSync([Buffer.from("venue")], VENUE)
const [pool] = PublicKey.findProgramAddressSync([Buffer.from("pool"), stockMint.toBuffer(), quoteMint.toBuffer()], VENUE)
const [participant] = PublicKey.findProgramAddressSync([Buffer.from("participant"), wallet.toBuffer()], VENUE)
const [haltState] = PublicKey.findProgramAddressSync([Buffer.from("halt"), symbol("FWDI")], HALT)
const [symbolCap] = PublicKey.findProgramAddressSync([Buffer.from("cap"), symbol("FWDI")], CAPS)
const [capsConfig] = PublicKey.findProgramAddressSync([Buffer.from("config")], CAPS)
const [issuerNotice] = PublicKey.findProgramAddressSync([Buffer.from("notice"), stockMint.toBuffer()], NOTICE)

Quoting before you send

Read the pool's two vault balances, subtract venue_fee_stock and venue_fee_quote (the pool's reserves method does this on chain), then apply the same arithmetic as math::quote:

const BPS = 10_000n
function quote(reserveIn: bigint, reserveOut: bigint, amountIn: bigint, feeBps: bigint, venueShareBps: bigint) {
  const fee = (amountIn * feeBps + BPS - 1n) / BPS
  const venueFee = (fee * venueShareBps) / BPS
  const net = amountIn - fee
  const out = (reserveOut * net) / (reserveIn + net)
  return { fee, venueFee, out }
}

Set min_out from this quote with your own slippage allowance; the program refuses anything lower with Slippage.

Before a swap, check what the program will check

  1. Venue.paused == false and Pool.paused == false.
  2. HaltState.halted == false.
  3. IssuerNotice.issuer_sponsored || (!objected && now > notice_sent_at + 2_592_000).
  4. SymbolCap: executed + stockAmount <= cap_units, and if executed × 10_000 >= cap_units × 9_000 then stockAmount × 10_000 <= cap_units × 100. cap_units = adv_shares × cap_bps / 10_000 × 10^decimals with cap_bps 25 or 250 by tier. If cap.month != month_index(now) the counter is treated as zero.
  5. Participant.admitted == true for the signer.

Doing these reads first turns a failed transaction into a clear message in your UI.

Issuer gate and hook accounts

The real FWDI and GLXY mints carry no transfer hook: every token account is frozen by default and Superstate's freeze authority thaws allowlisted ones, so a transfer into an unthawed account fails inside Token-2022 itself. The harness's mock mints use a transfer hook instead; for them, pass the hook's extra account metas as remaining accounts; the program forwards ctx.remaining_accounts to both transfers. Resolve them with getExtraAccountMetaAddress and resolveExtraAccountMeta from @solana/spl-token.

Reading the tape

Subscribe to the venue program's logs and decode Fill events, or read the JSON the site publishes for the last 30 days. Each fill carries symbol, stock_mint, quote_mint, quote_kind, stock_to_quote, stock_amount, quote_amount, fee, venue_fee, stock_reserve_after, quote_reserve_after, slot and at. USD values come from the quote leg when the quote is a payment stablecoin.

Halt and ADV as a keeper

A keeper signs floor_halt::post(halted, seq) with seq equal to the applied sequence plus one, and floor_caps::post_adv(month, adv_shares) with month the index of a finished month (year × 12 + month0). Watch HaltChanged and AdvPosted to know when the threshold applied your vote.

Relay

Browser pages read mainnet through POST /api/rpc. Only these methods pass: getAccountInfo, getMultipleAccounts, getProgramAccounts, getBalance, getTokenAccountBalance, getTokenAccountsByOwner, getLatestBlockhash, getSlot, getBlockTime, getBlockHeight, getEpochInfo, getHealth, getSignatureStatuses, getSignaturesForAddress, getTransaction, getMinimumBalanceForRentExemption, getFeeForMessage, simulateTransaction, sendTransaction, getVersion, getGenesisHash, getTokenSupply. Batches of up to 20 calls are accepted.