TRENDDocs
Guides

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

ProgramWhereIdStatus
trend_launchDev validatorG5VTggvWQRn9skJJ1YrDfPvpprVZYdhkUgCRxwpfcokzDeployed on the dev validator
trend_acquireDev validator6vNymM2JMoAS3VzXmmrEweRm3Ac5zkLs23NzDydemgEoDeployed on the dev validator
trend_launchMainnetTREND9g3kaNTBfoQ98FVi4B2LVFAEmZVU5z6xxq9CLNReserved, not deployed yet
trend_acquireMainnetCARDSCV6h6VPBtz3k6QtWGWVnMhJZj2vfSyWpB4UsCcBReserved, not deployed yet
ProgramRole
trend_launchLaunches, the bonding curve, completion and migration
trend_acquireThe 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 happenedEvent
A buy on the curvecurveBuy
A sell on the curvecurveSell
The curve completedgraduationTriggered
The pools were created and the migration finishedmigrationFinalized

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.

snippets/decode-events.mjs
// 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 }));
}

On this page