Skip to main content

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",
});
FieldTypeDefaultDescription
limitnumbertotal message countMax messages to return
fromSeqnumberlastMsgSeqStarting 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 resolve the message body. Inline text stays local; URL/Irys/IPFS/Arweave content is fetched and returned as bytes with optional text.

const result = await message.loadContent();

if (result.kind === "inline") {
console.log(result.text); // Text message stored on-chain
} else {
console.log(result.url); // Gateway/source URL
console.log(result.contentType); // HTTP Content-Type when available
console.log(result.bytes); // Raw bytes
console.log(result.text); // Only set for textual MIME types
}
MessageTypeStorageBehaviour
Text (0)Inline, on-chainReads the buffer directly — no network call.
Url (1)External URLFetches the URL over HTTP.
Ipfs (2)IPFSFetches from the IPFS gateway URL in the message.
Irys (3)Irys / ArweaveFetches from the Irys URL.
Arweave (4)ArweaveSame as Irys.

Binary resources are not force-decoded into strings. For example, an unencrypted uploaded PNG returns bytes and contentType: "image/png", while text stays undefined.


Parsed content

Use loadParsedContent() when you want the normal Packet reader flow:

const parsed = await message.loadParsedContent({ decrypt: true });

console.log(parsed.encrypted);
console.log(parsed.subject);
console.log(parsed.message);
console.log(parsed.mediaKind); // "text" | "binary"

It loads inline/external content, decrypts textual encrypted JSON when requested, parses the Packet envelope, and returns display text plus raw bytes/text metadata.

For binary Packet envelope parts, parsed.message contains a preview such as [binary image/png, ~24 KB base64], and parsed.parts keeps the structured PacketContent values for download/resource rendering.


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

MethodDescription
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).
loadParsedContent({ decrypt?, force? })Load, optionally decrypt, parse Packet envelope, and classify text/binary media.

loadRetrying parameters (positional):

ParameterTypeDefaultDescription
retriesnumber3Max retry attempts
delaynumber250Delay between retries in milliseconds

Getters

GetterTypeDescription
LoadedbooleanWhether message data has been fetched
MessageMessageRaw on-chain data (throws if not loaded)
ContentMessageContentLoadResultResolved 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;
contentType?: string;
url?: string;
messageContentKind: "text" | "url" | "irys" | "ipfs" | "arweave";
};
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.