Skip to main content

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

KindDescription
StandardPersists across uses and keeps a thread directory; the default for most applications
EphemeralLightweight, 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 from and to wallets
  • A totalMsgs counter
  • An optional escrowPayment balance (if the inbox required escrow)

Messages

Messages are appended to the thread by either party. Each message has:

  • A sequential msgSeq number
  • A messageType: Text, Url, Ipfs, Irys, or Arweave
  • A content field: 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