Index launches from chain
Program ids, the IDL, and the events that carry a buy, a sell, a completion and a migration.
What is live today
TREND runs on its own dev validator. The mainnet programs are not deployed: their ids are reserved and no launch exists there. Statement as of 2026-10-10.
You can read every launch from the chain without the API. The programs write their state changes as Anchor events in the transaction logs, and each event is built to be applied on its own.
Programs
| Program | Where | Id | Status |
|---|---|---|---|
trend_launch | Dev validator | G5VTggvWQRn9skJJ1YrDfPvpprVZYdhkUgCRxwpfcokz | Deployed on the dev validator |
trend_acquire | Dev validator | 6vNymM2JMoAS3VzXmmrEweRm3Ac5zkLs23NzDydemgEo | Deployed on the dev validator |
trend_launch | Mainnet | TREND9g3kaNTBfoQ98FVi4B2LVFAEmZVU5z6xxq9CLN | Reserved, not deployed yet |
trend_acquire | Mainnet | CARDSCV6h6VPBtz3k6QtWGWVnMhJZj2vfSyWpB4UsCcB | Reserved, not deployed yet |
| Program | Role |
|---|---|
trend_launch | Launches, the bonding curve, completion and migration |
trend_acquire | The collectible leg: acquisition and conversion |
Dev ids are the ids on the dev validator. Mainnet ids are reserved, not deployed: no event exists there yet.
The IDL
The IDL is published as a JSON file, refreshed from the build of the programs on every release of this site. Page: IDL downloads.
Events are self-sufficient
Every value-changing event carries launch, primaryMint, slot and seq, and the complete state after the
change, not a delta. You never fetch an account to understand an event. That is deliberate:
- an account read returns state as of now, not as of the event's slot, so replaying history against it writes the present into the past;
- an RPC round trip per event is what slows an indexer under the load it most needs to keep up with;
- an event that was complete when emitted stays complete, so a re-index is a pure function of the logs.
What is not in the events is off-chain metadata, a token's symbol and name. Read that from GET /v1/metadata/{mint}.
The four events an indexer needs
| What happened | Event |
|---|---|
| A buy on the curve | curveBuy |
| A sell on the curve | curveSell |
| The curve completed | graduationTriggered |
| The pools were created and the migration finished | migrationFinalized |
Also useful: launchCreated, launchActivated and migrationPoolCreated. Field tables for each are on
Events, generated from the IDL.
The IDL names events in camel case (curveBuy); that is the name Anchor's event coder returns.
Ordering and gaps
seq is a per-launch sequence number. Apply a launch's events in seq order. A missing number means an event was
dropped: the read model is desynced. Treat a gap as a fault, re-read the range of slots, and do not paper over it.
The uniqueness key of an event is the transaction signature, the instruction index and the event index.
Statuses
Events and statuses line up with the life of a launch: launchCreated and
launchActivated open a launch, graduationTriggered marks the curve as complete, and migrationFinalized marks the end
of the migration. Read status from GET /v1/launches/{id} when you need the exact value, not from the event name.
Do not price from reserves
The post-trade reserves in an event describe the launch's internal state. They are there so you can apply the event and
check your own state against it. The authoritative price of a trade is POST /v1/trades/quote: it accounts for fees,
routing and slippage that the reserves do not express.
A minimal decoder
The snippet is a real file, apps/docs/snippets/decode-events.mjs, and a test round-trips an encoded curveBuy through it with
the IDL this site publishes.
// Decode TREND events from the log lines of a transaction. Needs @coral-xyz/anchor and @solana/web3.js.
// `idl` is the parsed file you downloaded from /idl/trend_launch.json; `logs` is `meta.logMessages`
// of a confirmed transaction.
import { BorshCoder, EventParser } from '@coral-xyz/anchor';
import { PublicKey } from '@solana/web3.js';
export function eventsOf(idl, logs) {
const parser = new EventParser(new PublicKey(idl.address), new BorshCoder(idl));
return [...parser.parseLogs(logs)].map((e) => ({ name: e.name, data: e.data }));
}