Velocity ProtocolDevelopers
Velocity SDK

Events

The program emits its events into transaction logs. EventSubscriber tails those logs, deserializes each event into a typed object, emits it in real time, and keeps a bounded buffer of recent ones that can be read without waiting for the next arrival.

Event types

Every name below is a key of EventMap, which is what eventTypes accepts and what event.eventType returns.

Event TypeDescription
DepositRecordA user depositing or withdrawing funds from the protocol
FundingPaymentRecordA user paying or receiving funding payments
LiquidationRecordA user being liquidated
OrderRecordA user placing an order (includes all order parameters)
OrderActionRecordA user action on an order: place, cancel, or fill
FundingRateRecordThe funding rate changing for a market
NewUserRecordA new user account being created
DeleteUserRecordA user account being deleted
SettlePnlRecordA user settling their perp PnL
InsuranceFundRecordThe insurance fund balance changing
SpotInterestRecordSpot interest accruing
InsuranceFundStakeRecordA user staking or unstaking from the insurance fund
AmmCurveChangedThe AMM curve parameters updating
SwapRecordA Jupiter or Titan swap executed through a Velocity account
SpotMarketVaultDepositRecordAn external deposit landing directly in a spot market vault
SignedMsgOrderRecordA signed (Swift) order being placed
LPMintRedeemRecordA user minting or redeeming Velocity liquidity pool tokens
LPSettleRecordA Velocity liquidity pool settling PnL against its constituents
LPSwapRecordA swap between constituents inside a Velocity liquidity pool
LPBorrowLendDepositRecordA Velocity liquidity pool borrow/lend deposit or withdrawal against a constituent
PerpMarketFeeSweepRecordA streaming sweep of a perp market's fee ledger into the insurance, protocol, and AMM fee pools
ProtocolFeeWithdrawRecordAn admin withdrawal from a perp or spot market's protocol fee pool
RevenueShareSettleRecordA builder or referrer revenue-share settlement for a market
TransferFeeAndPnlPoolRecordAn admin transfer between a perp market's fee pool and PnL pool
AcceleratedReferralStatusChangedRecordAn authority's Accelerated referral status changing, by automatic enrollment or an admin grant or revoke

CurveRecord was renamed to AmmCurveChanged, and its fields changed with it. LPRecord (vAMM and BAMM LP shares) no longer exists: passive liquidity now flows through the Velocity liquidity pool module, whose activity is split across LPMintRedeemRecord, LPSettleRecord, LPSwapRecord, and LPBorrowLendDepositRecord.

PerpMarketFeeSweepRecord, ProtocolFeeWithdrawRecord, RevenueShareSettleRecord, and TransferFeeAndPnlPoolRecord have long been emitted onchain but were only recently registered in the SDK's event map. Older SDK versions dropped them from EventSubscriber silently.

Subscribing to events

Construct an EventSubscriber with the connection, the client's Anchor program, and the options. newEvent is the only real-time emitter: it fires once for every incoming event that matches the eventTypes filter, and handlers branch on event.eventType from there.

import { EventSubscriber, EventSubscriptionOptions } from "@velocity-exchange/sdk";

const options: EventSubscriptionOptions = {
  eventTypes: ["OrderActionRecord", "DepositRecord", "LiquidationRecord"],
  maxTx: 4096,           // transactions retained for getEventsByTx
  maxEventsPerType: 4096, // per-type buffer size
  orderBy: "blockchain",
  orderDir: "asc",
  commitment: "confirmed",
  logProviderConfig: { type: "websocket" },
};

const eventSubscriber = new EventSubscriber(connection, velocityClient.program, options);
await eventSubscriber.subscribe();

eventSubscriber.eventEmitter.on("newEvent", (event) => {
  console.log(event.eventType, event);
});

await eventSubscriber.unsubscribe();

Options left unset are merged over DefaultEventSubscriptionOptions, so omitting eventTypes entirely subscribes to every type in the table above. Narrow it deliberately: each extra type costs buffer memory and deserialization work on every matching transaction.

Filtering events

Enum-valued fields on an event, such as marketType and action, are Anchor enums rather than strings, so compare them with isVariant instead of ===. Plain fields like marketIndex and eventType compare directly.

import { isVariant } from "@velocity-exchange/sdk";

const marketIndex = 0;

// Perp fills on one market: eventType and marketIndex compare directly,
// marketType and action are enums and need isVariant.
const isPerpFill = (event) =>
  event.eventType === "OrderActionRecord" &&
  event.marketIndex === marketIndex &&
  isVariant(event.marketType, "perp") &&
  isVariant(event.action, "fill");

eventSubscriber.eventEmitter.on("newEvent", (event) => {
  if (isPerpFill(event)) console.log("perp fill on market", marketIndex, event);
});

In TypeScript, checking event.eventType does not narrow event. WrappedEvent is generic over EventType, so the compiler cannot correlate the discriminant with the rest of the shape. Cast explicitly after the check: const orderEvent = event as WrappedEvent<"OrderActionRecord">.

Querying stored events

The subscriber keeps a rolling, size-bounded buffer per event type, plus a per-transaction index. Both are readable at any time without waiting for a new event.

// A snapshot copy of every buffered event of one type.
const events = eventSubscriber.getEventsArray("OrderActionRecord");

// The live, size-bounded EventList the subscriber inserts into.
// Prefer this when iterating: it does not copy.
const eventList = eventSubscriber.getEventList("OrderActionRecord");

// Everything emitted by one transaction, in emission order.
const txSig = "3dq5PtQ3VnNTkQRrHhQ1nRACWZaFVvSBKs1RLXM8WvCqLHTzTuVGc7XER5awoLFLTdJ4kqZiNmo7e8b3pXaEGaoo";
const txEvents = eventSubscriber.getEventsByTx(txSig);

All three return undefined or an empty result rather than throwing when nothing matches, and the buffer only holds what arrived since subscribe(): it is not a historical backfill.