Expand description
Self-CPI event emission primitives.
Log output is lossy. Transaction metadata is not. A program that needs events to arrive at indexers regardless of log truncation invokes itself with a distinctive CPI whose bytes carry the event payload. This module provides the building blocks: a reserved discriminator so the dispatcher can route the CPI to a no-op sentinel, a wire-format helper for the instruction data, and a one-line pattern programs can copy.
§Wire format
[0..2] CPI_EVENT_MARKER (0xE0, 0x1E)
[2] event tag (the byte from `#[hopper::event(tag = N)]`)
[3..] event payload (from `HopperEvent::as_bytes()`)The two-byte marker is the reserved Hopper discriminator for self-CPI events and is unlikely to collide with any sensibly chosen user discriminator. The user-facing instruction declaration for the sentinel is:
#[instruction(discriminator = [0xE0, 0x1E])]
fn __hopper_event_sink(_ctx: &mut Context<'_>) -> ProgramResult {
Ok(())
}§Why this pattern works
Anchor’s emit_cpi! uses the same trick: a self-CPI carrying
payload bytes guarantees the event appears in the transaction’s
inner-instruction list, which RPC nodes do not truncate. Indexers
scan for the reserved marker and decode the tail as the event.
Hopper’s version is leaner: a two-byte marker plus a one-byte event tag gives the indexer everything it needs to route without the Anchor eight-byte discriminator overhead.
Constants§
- CPI_
EVENT_ MARKER - The reserved self-CPI event discriminator.
- EVENT_
AUTHORITY_ SEED - Canonical PDA seed for the Hopper event-authority. Match this in the program’s sentinel handler setup so the CPI signer resolves.
Functions§
- encode_
event_ cpi - Fill an out buffer with the CPI wire format for an event.
- invoke_
event_ cpi - Invoke a self-CPI carrying the encoded event payload.