Events
Packet exposes live event helpers for UI refreshes and agents that are already running.
These APIs are live subscriptions, not historical indexers. They do not replay missed messages. Use thread/inbox/activity loading APIs when you need past messages.
Message events
client.messageEvents listens to MessageSent Anchor emit_cpi! events through client.cpiEvents.
const sub = client.messageEvents.listenIncoming({
onMessage: async (message, event) => {
console.log("new message", event.threadId, event.msgSeq);
// The event gives you a MessageClient handle.
// Load the account if you need raw message data.
await message.loadRetrying(5, 500);
},
onError: console.error,
});
await sub.stop();
This listener subscribes to program logs, fetches the transaction, decodes CPI-emitted Anchor events, and then applies SDK-level filters.
Methods
| Method | Description |
|---|---|
client.messageEvents.listen(params) | Listen to all live message events with optional filters. |
client.messageEvents.listenIncoming(params) | Shorthand for messages where receiver is client.walletPublicKey. |
client.messageEvents.listenOutgoing(params) | Shorthand for messages where sender is client.walletPublicKey. |
client.messageEvents.listenThread(threadId, params) | Listen to live events in one thread. |
ListenMessagesParams
| Field | Type | Description |
|---|---|---|
onMessage | (message: MessageClient, event: PacketMessageSentEvent) => void | Promise<void> | Called for each matching live event. |
onError | (error: unknown) => void | Called when decoding/loading/callback processing throws. |
threadId | number | Filter to a specific thread. |
sender | PublicKey | Filter by sender. |
receiver | PublicKey | Filter by receiver. |
incomingFor | PublicKey | Receiver must equal this key. |
outgoingFrom | PublicKey | Sender must equal this key. |
eventName | "messageSent" | string | Event name compatibility override. |
commitment | Finality | WebSocket/getTransaction commitment. |
maxRetries | number | Retry count while waiting for the transaction to become fetchable. |
PacketMessageSentEvent
type PacketMessageSentEvent = {
threadId: number;
msgSeq: number;
sender: PublicKey;
receiver: PublicKey;
slot: number;
signature?: string;
};
Inbox account events
InboxClient.listenEvents listens to live account changes for one inbox. It is cheaper than listening to every message event when you only need to know that one inbox changed.
const inbox = await client.inbox(0);
const sub = inbox.listenEvents({
clearPages: true,
onChange: async (inboxClient, event) => {
console.log("inbox changed at slot", event.slot);
console.log("new len", inboxClient.Inbox.len.toString());
},
onError: console.error,
});
await sub.stop();
ListenInboxEventsParams
| Field | Type | Description |
|---|---|---|
commitment | Finality | Account-change subscription commitment. Defaults to confirmed. |
clearPages | boolean | Clear cached inbox body/archive pages when the inbox account changes. |
filter | (event: InboxChangedEvent) => boolean | Promise<boolean> | Suppress changes by returning false. |
onChange | (client: InboxClient, event: InboxChangedEvent) => void | Promise<void> | Called for each matching account change. |
onError | (error: unknown) => void | Called if decoding/filter/callback processing throws. |
InboxChangedEvent
type InboxChangedEvent = {
address: PublicKey;
previous: Inbox;
inbox: Inbox;
slot: number;
accountInfo: AccountInfo<Buffer>;
};
Low-level CPI event client
client.cpiEvents is available for advanced callers who need to decode other Anchor CPI events.
const sub = client.cpiEvents.listen({
eventName: ["messageSent", "MessageSent"],
parse: (raw, ctx) => ({ raw, signature: ctx.signature }),
filter: (event) => Boolean(event.raw),
onEvent: async (event) => {
console.log(event.signature);
},
});
Most apps should use client.messageEvents or inbox.listenEvents instead.
Subscription lifecycle
All event methods return:
type PacketEventSubscription = {
id: number;
stop: () => Promise<void>;
};
Call stop() when a component unmounts, an agent loop exits, or a CLI process is shutting down.