Start with Migrate to a self-hosted backend
for the backend, database, history, and push steps. This guide lists changes
from main at cc878025da
to self-hosted at 610175f3b3.
A call can keep its name and still have different parameters, results, or
behavior. The Before examples use the old SDK. The After examples use
the new SDK.
Keep the package name @xmtp/node-sdk. SDK 8 requires ESM and Node 22.12 or later.
Use import instead of require. Install the recommended version before checking
your app. The old @xmtp/node-bindings package is not the public SDK 8 API.
The previous examples below use
main at cc878025d.
They were checked against that source. The current examples use the local
SDK 8 declarations and are checked as complete TypeScript programs.
Previous value
Current value
Identifier with identifierKind: IdentifierKind.Ethereum
PublicIdentity with kind: "ethereum". Use "passkey" for a passkey. The identifier field remains a string.
Numeric enum imports such as ConsentState.Allowed, DeliveryStatus.Published, and SortDirection.Descending
String values such as "allowed", "published", and "descending". Import the type when you need a type annotation.
Types ConversationKind, MessageKind, MessageOrder, ConversationOrder. Values use lower camel case, such as "dm", "membershipChange", and "lastActivity".
Nanosecond fields ending in Ns, with a separate Date getter
Timestamp. Use .ns for a bigint, .date for a Date, and new Timestamp(ns) for an input. This applies to message, conversation, identity, archive, and action times.
Mutable records and binding classes
Read-only public records. IDs remain strings. Byte buffers are Uint8Array. Maps are Map, not plain JavaScript objects.
Generic Client<T>, Group<T>, Dm<T>, Conversation<T>, and DecodedMessage<T>
Classes Client, Group, Dm, and Message. Conversation is the type Group | Dm. Narrow a conversation with instanceof Group or instanceof Dm. Narrow received content with content.kind.
Direct new Client(...), client.init(...), or direct conversation/message constructors
Use Client.create, Client.build, and SDK lookup or creation methods. Public SDK objects have private constructors.
For a smart contract wallet, replace getChainId and getBlockNumber with
fields in the result of kind(). Return the signature bytes, address, chain ID,
and optional block number from sign(). Chain IDs and block numbers are
unsigned 64-bit bigint values.
Passkey signers are also supported. Their identity uses kind: "passkey";
kind() returns { kind: "passkey" }; sign() returns a "passkey" signature
with signature, publicKey, authenticatorData, and clientDataJson byte
buffers. Client.generateKeys() and LocalSigningKey.fromBytes(bytes) are new
helpers for local Ethereum signers.
Previous client setup:
Before (main cc878025da)
import { Client, type Signer } from "@xmtp/node-sdk";
export async function createClient(signer: Signer, key: Uint8Array) {
return Client.create(signer, {
env: "dev",
appVersion: "chat/7.0.0",
dbPath: "./chat.db3",
dbEncryptionKey: key,
minDbPoolSize: 5,
maxDbPoolSize: 25,
disableDeviceSync: false,
});
}
Current client setup:
const
constclient:Client
client=await
classClient
An XMTP client. Its inputs and results are public values; the binding
Client and the target transport stay private to the package.
await Backend.connect({ url, appVersion?, credentials? }). A connected Backend can be shared by clients and standalone queries. Environment helpers are removed.
Old Backend.env, v3Host, gatewayHost, appVersion getters and builder setApiUrl, setGatewayHost, setReadonly
Removed from the public Backend. Keep connection options in your app and use Backend.connect(options).
dbPath omitted
storage: { location: "default" }. SDK 8 has no implicit dev network label.
dbPath: null
storage: { location: "inMemory" }.
dbPath: "./chat.db3"
storage.location: { dbPath: "./chat.db3", attachmentsDir: "./chat-attachments" }. Both paths are required.
dbPath(inboxId) callback
Choose a directory with storage.location: { directory }, or compute explicit paths in your app before creation. No path callback is accepted.
dbEncryptionKey bytes or hex string
storage.encryptionKey: Uint8Array. Convert a hex key to bytes in the app. Keep the same 32-byte key when you reopen a database.
minDbPoolSize, maxDbPoolSize, useSingleConnection
storage.pool: { min, max } and storage.singleConnection.
Environment used in database filename
storage.label. Keep the label and storage location stable.
registration.nonce. It is an unsigned 64-bit bigint. New identity generation defaults to nonce 0, rather than the old 1. Keep an explicit nonce where the app requires it.
historySyncUrl, HistorySyncUrls
Removed. No history server is selected by the client.
waitForRegistrationVisible and VisibilityConfirmationOptions
Removed from the public client options. Registration waits for the self-hosted backend’s readable state.
workers.intervals: [{ kind, intervalNs?, jitterNs?, enabled? }]. Use enabled: false to disable that worker. Worker kinds use strings. New kinds include configurationRefresh, hmacEpoch, and attachmentCleanup.
unstableChangeCallbacks.appData, AppDataChange
Observe "conversation.metadata_changed" through client.events() or startListener(). Events report committed changes; they do not await an app merge before message processing continues.
Top-level logging and OTLP options
Configure logging with await initLogging(...); see the diagnostics section below.
Client.create(signer, options) and Client.build(identity, options, inboxId?)
require an options object. build reopens a client without storing a signer.
Its optional third argument selects the inbox explicitly. SDK 8 can use the
inbox stored in explicit storage. allowOffline: true permits startup from
stored state when the backend is unavailable. It does not supply the data needed
for a first registration.
const
constclient:Client
client=await
classClient
An XMTP client. Its inputs and results are public values; the binding
Client and the target transport stay private to the package.
The previous database is not an input to this migration. Create a new database
for the deployment. See the database migration rules
before choosing paths.
Configure backend credentials separately from the identity signer:
const
constclient:Client
client=await
classClient
An XMTP client. Its inputs and results are public values; the binding
Client and the target transport stay private to the package.
backend.credentials accepts a Credential or a source with asynchronous
credential(). A credential has value, signed 64-bit expiresAtSeconds in Unix
seconds, and optional header name. Use client.setCredential(credential) to
replace a supplied credential. handlers.preAuthenticate accepts a callback
with asynchronous run() for work that must precede authentication. forkRecovery
selects a policy ("none", "allowlistedGroups", or "all"), group IDs, whether
to disable responses, and an optional worker interval. attachments can set
maxDownloadBytes, maxPendingAgeSeconds, and allowPrivateNetwork. Client.fetchServerConfiguration(backend)
fetches configuration without a client. client.serverConfiguration is a
property; await client.refreshServerConfiguration() returns refreshed
configuration. Deployment limits and retention counts use bigint.
Previous standalone calls could omit a backend or pass an environment string.
Current calls require a BackendSource: { url, appVersion?, credentials? } or
a connected Backend.
Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
@returns ― Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
get(
`${
identity: PublicIdentity
identity.
kind: PublicIdentityKind
kind}:${
identity: PublicIdentity
identity.
identifier: string
identifier.
String.toLowerCase(): string
Converts all the alphabetic characters in a string to lowercase.
toLowerCase()}`,
);
const
conststates:InboxState[]
states=await
classClient
An XMTP client. Its inputs and results are public values; the binding
Client and the target transport stay private to the package.
Client.inboxIdFor(identity, backend): Promise<string>. This static method calculates a nonce-0 inbox ID when no network association exists. Use canMessage to test registration.
Same method names, with PublicIdentity[] and a required backend for the static method. Both return Map<string, boolean>. Keys are ethereum:<normalized address>, passkey:<lowercase key hex>, or handle:<lowercase handle>, rather than an address alone.
Free function latestInboxUpdatesCount(ids, backend): Promise<Map<string, bigint>>. There is no static method with the old name.
No old equivalent
Client.newestMessageMetadata(ids, backend): Promise<Map<string, MessageMetadataEntry>>. Each entry has sequenceId: bigint and createdAt: Timestamp.
client.fetchKeyPackageStatuses(ids)
client.keyPackageStatuses(ids): Promise<Map<string, KeyPackageStatus>>. The old binding result was a plain object. Client.keyPackageStatuses(ids, backend) is new.
client.removeAccount(identity)
client.removeAccount(recoverySigner, identity).
client.revokeInstallations(byteIds)
client.revokeInstallations(signer, stringIds). Installation IDs are hex strings.
Await each method. Signature and public-key inputs remain Uint8Array; verification returns Promise<boolean>.
generateInboxId(identifier, nonce?)
generateInboxId(identity, nonce?) remains synchronous. It now takes PublicIdentity, and an omitted nonce is 0.
client.close()
await client.end(). End the client before removing storage. client.storage.path() and client.storage.reconnect() are new. await client.storage.delete_() ends the client and removes its database file.
libxmtpVersion, appVersion, options, inboxId, installationId,
installationIdBytes, conversations, and preferences remain properties.
libxmtpVersion now always returns a string from a created client; appVersion
can be absent when connection options do not set it. The options result is
always present, has the new option shape, and omits backend credential
sources, static credentials, and the storage encryption key. isInMemory and
storagePath are new properties.
Handles are new. An inbox can claim a public name such as nick#2341, and a
PublicIdentity of kind handle finds that inbox. Static Client.inboxIdFor
never derives an inbox ID from a handle: it fails with IdentityNotFound for a
handle that no inbox claimed. See Handles.
unsafeAddAccount(newSigner, allowInboxReassign). Supply the boolean explicitly.
request.signatureText() remains asynchronous. For manual registration, create
with registration: { auto: false }, sign the returned request, then apply it:
Await listGroups(options | undefined) / listDms(options | undefined). The argument is required; pass undefined for defaults. list, listGroups, and listDms return public conversation objects. The raw ConversationListItem type is removed.
Await these methods. The snapshot also has admins and superAdmins arrays.
members(): Promise<GroupMember[]>
members(): Promise<Member[]>. accountIdentifiers becomes identities. installationIds is removed; use client.inboxStates for installation records. inboxId, permissionLevel, and consentState remain.
Synchronous updateConsentState(state) and hmacKeys()
Await both. Collection hmacKeys() returns Map<string, HmacKey[]>, rather than a plain object.
lastReadTimes() result with bigint values
Map<string, Timestamp>.
Cursor type and debugInfo().cursor with { originatorId, sequenceId } records
bigint[]. epoch stays bigint; the other debug fields remain.
Legacy string topics
conversation.topic is [group_message_v1/<hex-id>]. Collection .topic is removed. Wire topics use a kind byte followed by the identifier; push payloads encode those bytes as base64. See Topics.
processStreamedMessage(envelopeBytes)
Removed. A push contains a hint; use conversations.sync(), conversation.sync(), then local message queries.
sync, publishMessages, updateName, updateImageUrl, updateDescription,
addAdmin, removeAdmin, addSuperAdmin, removeSuperAdmin, and requestRemoval
keep their call forms. syncAll now requires a consent array or undefined:
await client.conversations.syncAll(undefined). updateAppData requires its
second argument: await group.updateAppData(value, undefined) for an unguarded
write. Use string consent and policy values. New methods include peerInboxIds(),
membershipCapabilities(), and lastActivityAt(contentTypes); pass undefined
to the last method for the default content types.
const
constsnapshot:GroupState
snapshot=await
group: Group
group.
Group.state(): Promise<GroupState>
state();
var console:Console
console.
Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
updatePermission(kind: PermissionUpdateKind, policy: PermissionPolicy, metadataField: MetadataFieldKind | undefined). Supply undefined when no field applies. Use "updateMetadata", for example, and a field such as "name", "description", "imageUrl", "disappearing", or "appData".
List conversationType
kind: "group" | "dm".
List createdAfterNs, createdBeforeNs
createdAfter, createdBefore with Timestamp. New bounds lastActivityAfter and lastActivityBefore also take Timestamp.
SDK 8 also exposes typed metadata fields. On a group or DM, use
metadataFields(), metadataField(name), metadataValue(field),
metadataValues(fields), mapValue(field, key), userData(fields, inboxIds),
updateUserData(values), and updateMetadataField(field, operation).
metadataFieldRef supplies well-known field IDs. This supports app fields and
per-inbox values without putting them all in the old opaque appData string.
Both userData arguments are required; pass undefined for all fields or inboxes.
Most standard send helpers retain their names. sendText, sendMarkdown,
sendReadReceipt, sendAttachment, sendRemoteAttachment,
sendMultiRemoteAttachment, sendTransactionReference, sendWalletSendCalls,
sendActions, and sendIntent still return a message ID. All use SendOptions.
Previous call or value
Current call or value
send(encoded, SendMessageOpts?)
send(encoded, SendOptions?), or send(codec, value, SendOptions?).
SendOpts and SendMessageOpts
One SendOptions type: shouldPush?, optimistic?, idempotencyKey?, and new compression?: "deflate" | "gzip".
send(encoded) defaults to shouldPush: false in the old Node wrapper
SDK 8 uses the standard content type’s push default. Set { shouldPush: false } explicitly when this is required. A custom codec’s shouldPush(value) can supply its default.
sendReaction(reference, referenceInboxId | undefined, { action, content, schema }, options?). Reaction values use strings such as "added" and "unicode".
sendReply(reference, referenceInboxId | undefined, encoded, options?). There is no public type named Reply; use ReplyContent when you need the standard codec payload record.
Removed. Use the current ClientOptions, Signer, and MessageContent types.
Client generics infer registered content types
Register codecs in ClientOptions.codecs for receive decoding. Send with send(codec, typedValue) for compile-time value checks. Received custom values remain unknown until the app checks them.
prepareMessage(encodedOrCodec, ...) stores an unpublished message, queues optimistic publication, and returns its ID. Background processing can publish it before an explicit publish call. Use publishMessage(id) or publishMessages() to drive pending publication. Keep private drafts outside the SDK until the app is ready to send. optimistic and idempotencyKey remain supported.
await client.decodeContent(encoded) is also available to decode an envelope
into the public content union.
A custom codec uses public records and needs no client parameter:
const
constcodec:ContentCodec<Point>
codec:
interfaceContentCodec<T>
A content codec over public values. The send helpers run its steps before
the send starts: encode, then fallback when the envelope has none, then
shouldPush when the send has no explicit shouldPush option. A step that
throws, rejects, or returns a value of the wrong type fails the send with
XmtpError.CodecEncodeFailed, and the SDK makes no publish attempt. Each
step is a function property, so the value type is checked in both
directions.
ContentCodec<Point>.decode: (encoded:EncodedContent) => Point
decode: ({
content: Uint8Array<ArrayBufferLike>
content }) => {
const
constparts:number[]
parts=new
var TextDecoder:new (label?:string, options?:TextDecoderOptions) =>TextDecoder
The TextDecoder interface represents a decoder for a specific text encoding, such as UTF-8, ISO-8859-2, or GBK. A decoder takes an array of bytes as input and returns a JavaScript string.
Split a string into substrings using the specified separator and return them as an array.
@param ― separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
@param ― limit A value used to limit the number of elements returned in the array.
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map(
var Number:NumberConstructor
An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.
Number);
if (
constparts:number[]
parts.
Array<number>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
Determines whether the specified callback function returns true for any element of an array.
@param ― predicate A function that accepts up to three arguments. The some method calls
the predicate function for each element in the array until the predicate returns a value
which is coercible to the Boolean value true, or until the end of the array.
@param ― thisArg An object to which the this keyword can refer in the predicate function.
If thisArg is omitted, undefined is used as the this value.
some((
value: number
value) =>!
var Number:NumberConstructor
An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.
Returns true if passed value is finite.
Unlike the global isFinite, Number.isFinite doesn't forcibly convert the parameter to a
number. Only finite values of the type number, result in true.
@param ― number A numeric value.
isFinite(
value: number
value))
) {
thrownew
var Error:ErrorConstructor
new (message?:string, options?:ErrorOptions) =>Error (+1 overload)
Reply with a value of a typed codec. The codec's fallback applies to the
nested envelope; the reply keeps the reply type's push default unless
options.shouldPush is set. A failed codec step is CodecEncodeFailed,
with no publish attempt.
The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.
Standard codecs are TextCodec, MarkdownCodec, ReadReceiptCodec,
ReactionV2Codec, ReplyCodec, DeleteMessageCodec, AttachmentCodec,
RemoteAttachmentCodec, MultiRemoteAttachmentCodec, TransactionReferenceCodec,
WalletSendCallsCodec, ActionsCodec, IntentCodec, GroupUpdatedCodec, and
LeaveRequestCodec. Text and markdown codecs take strings. Read receipts take
void. Reaction, reply, and delete-message codecs take only their matching
StandardContent variant. The other codecs take their payload record.
Do not install old codec packages to decode built-in content.
sentBefore, sentAfter, insertedBefore, insertedAfter, each a Timestamp.
Query enum ContentType[]
ContentTypeId[], for example [standardContentType("text")]. This also applies to exclusions. Unknown/custom types cannot be used as these message filters.
Query kind, deliveryStatus, direction, sortBy
Same names, with string values. excludeSenderInboxIds remains. limit is an unsigned 32-bit number.
message.content is a decoded value or undefined
MessageContent with a kind. Text and markdown use .value; payload records use .value; reactions have .reference, .referenceInboxId, and .reaction; replies have .referenceId and .body.
Reply content.body: MessageBody; message.inReplyTo: ReplyParent, inReplyToContent, and replyContent give the retained parent and bodies. Use await message.parent() for a current Message.
Undefined content after an unknown codec or decode error
"custom" content retains encoded, rawBytes, optional decoded value, and optional error. Malformed or undecodable standard content is "unknown" with rawBytes, optional encoded, and ErrorDetails.
Always present decoded contentType
Optional contentType, fallback, and encoded, plus always present rawBytes.
The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.
New message actions are refresh(), delete(), deleteLocally(), react(...),
reply(...), parent(), conversation(), and client(). Collection methods
deleteMessage, deleteMessageLocally, reactToMessage, and replyToMessage
also take message IDs. delete publishes a deletion and returns the deletion
message ID. deleteLocally only removes the local message. A message’s actions
need its originating client to remain open.
Some retained content records have new fields:
Previous payload
Current payload
Intent.metadata object with JSON values
metadataJson?: string. Serialize with JSON.stringify and parse after validation.
Actions.expiresAtNs, Action.expiresAtNs
Optional expiresAt: Timestamp. ActionStyle uses "primary", "secondary", or "danger".
WalletCall.metadata: Record<string, string>
WalletCallMetadata with description, transactionType, and extra: Map<string, string>. WalletSendCalls.capabilities is also a Map.
Group-update inbox arrays with { inboxId } objects
The added, removed, left, admin, and super-admin arrays contain inbox ID strings.
Deleted-message deletedBy enum and separate adminInboxId
One discriminated deletedBy value: { kind: "sender" } or { kind: "admin", inboxId }.
The old ReadReceipt record is replaced by the "readReceipt" content kind,
and the old group-update Inbox record is replaced by inbox ID strings.
Attachment, RemoteAttachment, MultiRemoteAttachment,
TransactionReference, TransactionMetadata, and LeaveRequest retain their
payload field names. Optional fields use undefined; record fields are read-only.
Use stream methods on client.conversations, a group, or a DM. Each method
returns a stream immediately. await stream.ready() waits for the local reader
to open. It does not prove that the backend is online or catch-up is complete.
Previous call
Current call
await conversation.stream(options?)
group.streamMessages(options?) or dm.streamMessages(options?).
await conversations.streamAllMessages(options?)
client.conversations.streamAllMessages(options?). Options use conversationKind, consentStates, and optional from.
Removed from the current public stream options. Core handles network recovery. After a terminal failure, repair the cause and explicitly open a replacement stream.
A non-generic StreamOptions and callbacks registered on each typed stream. The other helper types are removed.
AsyncStreamProxy, flush(), done()
Removed. Streams expose next, return, end, ready, and onValue. Await end() to close a stream.
preferences.streamConsent(options?)
client.events({ kinds: ["consent.changed"] }) or startListener with that filter. The result is a typed event, rather than an array of old consent records.
preferences.streamPreferences(options?)
Use specific events such as "hmac_keys.updated". There is no general UserPreferenceUpdate[] stream or record.
The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.
A next-item request acknowledges the previous message. Await all processing
before the next request. return(), end(), and cancellation do not acknowledge
the last item. Callback mode awaits the callback before it requests the next
message. Do not also iterate a callback stream.
Await each callback before the next read. For messages, that read acknowledges
the prior message. Await all processing in the callback. Work sent to an app
queue or an unawaited task can continue after acknowledgement.
onValue(async (
message: Message
message) => {
await
process: (message:Message) =>Promise<void>
process(
message: Message
message);
});
Only one default message reader owns delivery progress for a database. This
includes readers that select different conversations. A second default reader
fails with ConsumerOwned. Use options.from for independent replay.
message.deliveryCursor is a string or null; it is local to one database.
conversations.beginningDeliveryCursor() selects the first retained message.
Save a replay message’s cursor only after processing succeeds.
For history followed by live delivery, use one snapshot boundary:
The collection also has messageHistorySnapshot(limit, selection?). The snapshot
has messages and cursor. Replay does not change default delivery progress.
Current reader scope and filters stay fixed for the lifetime of the reader. There
are no groupIds, deliveredCursor, updateScope, updateFilter,
catchUpSnapshot, or catchUpChanged members on Node SDK 8’s public stream.
Use client.catchUpToLive(timeoutMs) with a millisecond bigint or undefined
for a CatchUpSummary with messages,
conversations, and failed as bigint, and completed as a boolean.
A live event subscription reports changes caused by sync, streams, workers, or
app calls. It does not fetch messages. Keep a message stream or explicit sync
where the app needs network updates. Event filters use exact event kind strings;
group_ids takes binary group IDs and content_types takes event content type
records. references_own_messages defaults to false.
A stream of the client events that filter selects.
events({
kinds: EventKind[]
kinds: [
"consent.changed",
"message.deleted",
"conversation.metadata_changed",
],
});
forawait (const
constevent:ClientEvent
eventof
constevents:EventStream
events) await
process: (event:ClientEvent) =>Promise<void>
process(
constevent:ClientEvent
event);
await client.startListener(filter, callback) returns a bigint listener ID.
await client.stopListener(id) ends it. Events use .kind and retain the
protocol’s snake_case payload field names. Handle "lagged" by reading current
state again; events are not durable message delivery.
Byte helpers exportToBytes(key, options), importFromBytes(data, key), metadataFromBytes(data, key) are also available on Node. The export options argument is required; pass undefined for defaults.
ArchiveOptions.startNs, endNs
start, end, each an optional Timestamp.
BackupElementSelectionOption values
ArchiveElement strings "messages" and "consent". Omitted elements selects both; [] selects neither. excludeDisappearingMessages remains.
ArchiveMetadata.exportedAtNs, startNs, endNs
exportedAt, start, end use Timestamp. backupVersion and elements remain.
Archive keys still require exactly 32 bytes. These APIs do not establish that a
pre-transition archive can restore active conversations on another backend.
Follow the history migration limits.
EncryptedEncodedContent { ciphertext, keys }. EncryptionKeys has secret, salt, nonce, digest, and length: bigint.
Construct the remote record manually
remoteAttachmentFromEncrypted(url, encrypted, filename). Supply undefined when there is no filename. This checks the URL and derives the ciphertext digest and length. Upload encrypted.ciphertext before sending the remote record.
decryptAttachment(bytes, remote): Attachment
Await decryptEncodedContent({ ciphertext: bytes, keys }), parse with decodeEncodedContent, then decode with AttachmentCodec. encryptBytes, decryptBytes, encryptFile, and decryptFile are also available.
When the deployment offers attachment storage, use client.attachments to stage,
upload, download, and keep local files. offered is a property. create(source)
accepts a "path" or "bytes" source and returns PendingAttachment.
Upload it before sending its remoteAttachment property. status() reports
waiting, uploading, complete, or failed. A failed upload or download needs an
explicit retry by the app. Other helpers are pending(remote), listPending(),
localPath(remote), listLocal(), and deleteLocal(remote).
if (!
client: Client
client.
ClientMembers.attachments: Attachments
attachments.
Attachments.offered: boolean
offered)
thrownew
var Error:ErrorConstructor
new (message?:string, options?:ErrorOptions) =>Error (+1 overload)
Node SDK 8 has new notification APIs. The previous Node SDK did not register
push channels through Client. Retire the old push service integration and
register with the self-hosted backend:
The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.
NotificationChannel selects { kind: "apns", token },
{ kind: "fcm", token }, or { kind: "http", url, signingKey }.
NotificationConfig also accepts consentStates, includeWelcomes,
includeSyncGroups, and includeCommits. enableNotifications returns a
NotificationState; notificationState() reads it synchronously.
setNotifications("enabled" | "disabled" | "default") sets a conversation
override. Read effective notificationsEnabled from group .common or DM state.
Call enableNotifications again when the provider token changes.
Push payloads carry a base64 binary topic and decimal-string sequence_id.
They contain no encrypted message bytes. Fetch from the backend, process welcomes,
sync the conversation, then read local messages. See
Push notifications.
A failure from the XMTP SDK. Its subclass names the failure variant. details.code keeps the Rust cause code.
XmtpError) {
var console:Console
console.
Console.error(...data: any[]): void
The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.
The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.
New configuration, storage, and delivery failures are subclasses such as
XmtpError.ConfigurationUnavailable, ConfigurationInvalid, BackendMismatch,
ClientVersionTooOld, AuthRequired, ChainNotAccepted, ClientClosed,
ConsumerOwned, and InvalidCursor. Stream failure details are in
error.details.streamFailure, not a getStreamFailureDetails helper.
A PublishedButUnconfirmed failure means the publish was accepted but local
confirmation did not complete. Sync and inspect the result before you decide to
send again.
New native helpers await suspendStreams() and await resumeStreams() act on
shared process streams and preserve their durable progress. sdkVersion()
returns the library version without a client. For local file logs,
enterDebugWriter(directory, rotation, maxFiles, level, processType) and
exitDebugWriter() are synchronous; rotation uses "minutely", "hourly",
"daily", or "never", and process type uses "main" or "extension".
End the client after its consumers stop:
await
client: Client
client.
Client.end(): Promise<void>
End the client. Messages from it then fail with ClientClosed. Ending a
closed client does nothing, also after its browser worker stopped.
end();
For the complete current signatures, use the Node reference.