Threads & Inboxes
Inboxes
An Inbox is an on-chain account a wallet creates to receive threads. It acts as a public directory: senders look up your inbox to find where to deliver threads and what rules to follow.
Creating an inbox opens on-chain account state and can cost around 1 USD depending on rent and network conditions. You do not need to create a custom inbox just to communicate; create inboxes when you need a named endpoint, metadata, payment rules, escrow rules, or separate routing.
Inbox Kinds
| Kind | Description |
|---|---|
Standard | Persists across uses and keeps a thread directory; the default for most applications |
Ephemeral | Lightweight, throwaway-style inbox that does not keep the same long-term directory history |
Inbox Metadata
An inbox can store a name and metadata uri on-chain. The URI can point to an off-chain JSON file describing the inbox further (icon, description, etc.).
Thread Directory
The inbox maintains a paginated list of all threads addressed to it. The inbox itself is an on-chain account, and each inbox body page is another on-chain account. As body pages fill, older pages are archived/compressed and new bodies continue the directory. Apps walk the pages to display a conversation list.
A wallet can have multiple inboxes (inbox 0, 1, 2, …), each with separate rules and thread lists.
Threads
A Thread is the conversation container between exactly two wallets. It is created by the sender in the same transaction as the first message.
Thread Lifecycle
1. Sender calls createThread(to, ...) → Thread account is created on-chain
2. Both parties can send messages (sendMessage)
3. Thread stays open indefinitely — there is no close operation
Thread Identity
Each thread has:
- A numeric thread ID (auto-assigned or caller-supplied)
- On-chain addresses for both
fromandtowallets - A
totalMsgscounter - An optional
escrowPaymentbalance (if the inbox required escrow)
Messages
Messages are appended to the thread by either party. Each message has:
- A sequential
msgSeqnumber - A
messageType:Text,Url,Ipfs,Irys, orArweave - A
contentfield: inline text or a canonical pointer/ID - Optional Packet envelope text that preserves MIME type and encoding for text or binary parts
- An optional attached
payment
Keep large bodies out of the compressed message account. Store URLs/pointers on-chain and upload the body to Irys, IPFS, Arweave, HTTPS, or custom storage. Inline payloads larger than about 128 bytes are not recommended because transactions can fail from size/compute limits.
Loading Threads
Threads are compressed accounts stored via Light Protocol. Reading them requires querying the Photon RPC indexer rather than the standard Solana RPC.
Messages and activity records also use compressed/indexed state. Inbox and inbox body accounts are normal on-chain accounts because they define receiving endpoints and browsable thread directories.
// Load a thread by numeric ID
const thread = await client.thread(42).load();
// Load all threads in an inbox
const threads = await inbox.loadThreadsAcrossBodies({ limit: 25 });
// Load all threads a wallet has sent or received
const activity = client.activity();
const threads = await activity.loadThreadsAcrossHistory({ limit: 50 });
Addressing
When creating a thread, the sender must specify which inbox to target:
await client.createThread({
to: recipientPublicKey,
// targetInbox is optional; defaults to the receiver's inbox 0
});
If the receiver has a payment rule on their inbox, the SDK automatically includes the required payment. You can also explicitly specify the inbox:
const targetInbox = await client.inbox(1); // inbox ID 1 of the connected wallet
await client.createThread({ to, targetInbox });
SDK Reference
- PacketClient — Inbox Methods —
client.inbox(),client.createInbox() - PacketClient — Thread Methods —
client.thread(),client.createThread() - InboxClient — payment rules, browsing threads
- ThreadClient — sending messages, loading history, escrow