Reading Messages
Last message
The most common fetch — get the most recent message in a thread:
const message = await thread.loadLastMessage();
if (message) {
const content = await message.loadContent();
console.log(content.text);
}
Returns null if the thread has no messages yet.
Loading a range
loadMessages walks the sequence number range and returns an array of loaded MessageClient instances.
// Last 20 messages (newest first by default)
const messages = await thread.loadMessages({ limit: 20 });
// Paginate backward from a given seq
const older = await thread.loadMessages({
limit: 20,
fromSeq: 40,
direction: "backward",
});
| Field | Type | Default | Description |
|---|---|---|---|
limit | number | total message count | Max messages to return |
fromSeq | number | lastMsgSeq | Starting sequence number |
direction | "backward" | "forward" | "backward" | Walk direction |
All fetches in the range are parallelised internally.
Single message by sequence
const message = await thread.loadMessage(3);
Or build a handle without fetching and load it later:
const handle = thread.getMessage(3);
await handle.load();
Message content
Call loadContent() to read what the message says. This works the same regardless of where the content is stored:
const result = await message.loadContent();
if (result.kind === "inline") {
console.log(result.text); // Text message stored on-chain
} else {
console.log(result.text); // Fetched from external URL
console.log(result.bytes); // Raw bytes
}
MessageType | Storage | Behaviour |
|---|---|---|
Text (0) | Inline, on-chain | Reads the buffer directly — no network call. |
Url (1) | External URL | Fetches the URL over HTTP. |
Ipfs (2) | IPFS | Fetches from the IPFS gateway URL in the message. |
Irys (3) | Irys / Arweave | Fetches from the Irys URL. |
Arweave (4) | Arweave | Same as Irys. |
MessageClient reference
Static methods
MessageClient.Handle({ client, threadId, msgSeq })
Creates a handle without fetching. Load later with .load().
const handle = MessageClient.Handle({ client, threadId: 42, msgSeq: 3 });
await handle.load();
Returns MessageClient
Instance methods
| Method | Description |
|---|---|
load(force?) | Fetch from chain. Skips if already loaded unless force is true. |
loadRetrying(retries?, delay?) | Fetch with retries — useful right after sending when the tx may not yet be visible. |
refresh() | Force-reload and clear cached content. |
loadContent(force?) | Resolve content (inline read or external fetch). |
loadRetrying parameters (positional):
| Parameter | Type | Default | Description |
|---|---|---|---|
retries | number | 3 | Max retry attempts |
delay | number | 250 | Delay between retries in milliseconds |
Getters
| Getter | Type | Description |
|---|---|---|
Loaded | boolean | Whether message data has been fetched |
Message | Message | Raw on-chain data (throws if not loaded) |
Content | MessageContentLoadResult | Resolved content (throws if loadContent not called) |
Types
interface Message {
threadId: number;
msgSeq: number;
senderSide: MessageSenderSide; // 0 = from, 1 = to
timestamp: number;
payment: Payment | null;
messageType: MessageType;
content: Buffer; // raw bytes; URL string for non-Text types
}
type MessageContentLoadResult = {
kind: "inline" | "url";
bytes: Uint8Array;
text?: string;
};
enum MessageSenderSide {
From = 0, // the wallet that opened the thread
To = 1, // the wallet that received it
}
Message sequence numbers
Messages are numbered starting from 1. The thread tracks lastMsgSeq (the highest sent) and totalMsgs. For pagination, walk backward from lastMsgSeq in batches until you reach seq 1.