Releases: xmtp/xmtp-js
@xmtp/[email protected]
This release focuses on delivering an SDK for a stable, performant, and hardened XMTP V3.
Important
Please upgrade your app to use @xmtp/node-sdk
≥ 1.0.0 by May 1, 2025 to enable your app to connect to the XMTP V3 network. If you do not upgrade your app, it will continue to connect to the XMTP V2 network, which will be deprecated and put in read-only mode on May 1. To learn more about XMTP V2 deprecation, see XIP-53: XMTP V2 deprecation plan.
Upgrade from 0.0.x to 1.0.0
Use the information in these release notes to upgrade from @xmtp/node-sdk
0.0.x to 1.0.0.
Breaking changes
Primary XMTP identifier is now an inbox ID, not an Ethereum address
In preparation for upcoming support for Passkeys, XMTP must evolve from using Ethereum account addresses (0x...) as the primary identifier to an inbox-based identity model.
This change allows for broader support of different authentication mechanisms, including the currently supported Externally Owned Accounts (EOAs) and Smart Contract Wallets (SCWs), as well as future support for Passkeys, Bitcoin, and Solana, for example.
The move to an inbox-based identity model means the following shift in approach when developing with XMTP:
-
Instead of assuming an Ethereum address as the unique identifier, developers should default to using an inbox ID where possible.
-
Where you previously used an Ethereum address, you must now use an inbox ID
addMembers(addresses)
→addMembers(inboxIds)
removeMember(addresses)
→removeMembers(inboxIds)
newGroup(addresses)
→newGroup(inboxIds)
newDm(address)
→newDm(inboxId)
Warning
These function changes (address → inbox ID) won't trigger errors since both parameters are strings. Your code will pass a type-check but may fail at runtime. Pay special attention to these changes when upgrading.
-
The previous methods that allowed the use of an inbox ID have been removed in favor of the above methods
addMembersByInboxIds(inboxIds)
removeMembersByInboxIds(inboxIds)
newGroupByInboxIds(inboxIds)
newDmByInboxId(inboxId)
-
New methods have been added to allow the use of addresses with the
Identifier
typeaddMembersByIdentifiers(Identifier[])
removeMembersByIdentifiers(Identifier[])
newGroupByIdentifiers(Identifier[])
newDmByIdentifier(Identifier)
-
We recommend moving away from using addresses in code completely. However, if you MUST use addresses, wrap them with the
Identifier
type.For example, the address
0x1234567890abcdef1234567890abcdef12345678
must now be wrapped like so:const identifier: Identifier = { identifier: "0x1234567890abcdef1234567890abcdef12345678", identifierKind: IdentifierKind.Ethereum, };
-
Because XMTP is interoperable, you may interact with inboxes that are not on your app. In these scenarios, you will need to find the appropriate inbox ID or address.
// get an inbox ID from an address const inboxId = await getInboxIdForIdentifier({ identifier: "0x1234567890abcdef1234567890abcdef12345678", identifierKind: IdentifierKind.Ethereum, }); // find the addresses associated with an inbox ID const inboxState = await client.inboxStateFromInboxIds([inboxId]); interface InboxState { inboxId: string recoveryIdentifier: Identifier installations: Installation[] identifiers: Identifier[] } const addresses = inboxState.identifiers .filter((i) => i.identifierKind === IdentifierKind.Ethereum) .map((i) => i.identifier);
Wallet and signer updates
The term “wallet” has been removed from the codebase. This is to align with future support for Passkeys and other non-wallet-based authentication methods.
This release includes breaking changes to the Signer
type.
- The
walletType
field is nowtype
. Thetype
field refers to the type of account that will sign messages, such as anEOA
orSCW
. - The
getAddress
field has been replaced bygetIdentifier
, which is a function that returns anIdentifier
type.
// old
const address = await signer.getAddress();
// new
const identifier = await signer.getIdentifier();
// identifier may not be an Ethereum address
const address = identifier.identifierKind === IdentifierKind.Ethereum ?
identifier.identifier :
undefined;
Other recent changes
Conversations are now instances of Group
or Dm
The new Group
and Dm
classes extend the Conversation
class and provide specific functionality based on the conversation type.
Note
client.conversations.list()
now returns an array of Group
or Dm
classes. When accessing specific functionality based on conversation type, you must check the type first so that the TypeScript compiler can narrow the type.
const conversations: (Group | Dm)[] = await client.conversations.list();
for (const conversation of conversations) {
// narrow the type to Group to access the group name
if (conversation instanceof Group) {
console.log(group.name);
}
// narrow the type to Dm to access the peer inboxId
if (conversation instanceof Dm) {
console.log(conversation.peerInboxId);
}
}
Recently added features
Disappearing messages
This release provides support for disappearing (ephemeral) messages. These are messages that are intended to be visible to users for only a short period of time. After the message expiration time passes, the messages are removed from the UI and deleted from local storage so the messages are no longer accessible to conversation participants.
To learn more, see Support disappearing messages with XMTP.
Future-proofing app interoperability
This release introduces error handling that will help support app interoperability across SDK versions, even when breaking changes are required in the future.
In the future, an SDK version may introduce a breaking change, such as a feature that works only for apps on the latest versions of the SDK. Instead of forcing immediate upgrades or causing apps on older versions to break, this update adds a safety net that gracefully handles breaking changes.
At this time, no features rely on this mechanism, and no action is needed. However, this ensures your app remains resilient to future SDK updates that introduce breaking changes.
@xmtp/[email protected]
Patch Changes
- dd1a33a:
- Fixed stream errors
- Fixed build for later node versions
@xmtp/[email protected]
Patch Changes
- dd1a33a: Fixed stream errors
@xmtp/[email protected]
Patch Changes
- 3cf6dd9:
- Exposed all client signature methods
- Refactored client signature methods to return
undefined
instead ofnull
- Added guard to
Client.addAccount
to prevent automatic reassignment of inboxes - Removed
allowedStates
,conversationType
, andincludeSyncGroups
fromListConversationsOptions
- Added
contentTypes
option toListMessagesOptions
- Added more exports from the bindings
- Added
Group
andDm
classes - Refactored some functions to use the new
Group
andDm
classes
@xmtp/[email protected]
Patch Changes
- 3cf6dd9:
- Exposed all client signature methods
- Added guard to
Client.addAccount
to prevent automatic reassignment of inboxes - Renamed
syncAdmins
tolistAdmins
andsyncSuperAdmins
tolistSuperAdmins
- Added consent and preference streaming
- Removed
allowedStates
,conversationType
, andincludeSyncGroups
fromListConversationsOptions
- Added
contentTypes
option toListMessagesOptions
- Changed OPFS VFS to SyncAccessHandle Pool
- Added more exports from the bindings
- Added
Group
andDm
classes - Refactored some functions to use the new
Group
andDm
classes
@xmtp/[email protected]
Patch Changes
- 5221111:
- Added new methods to create groups by inbox ID
- Added consent states option to
syncAllConversations
- Updated list conversations options to include
consentStates
andincludeDuplicateDms
- Removed automatic message filtering from DM groups
- Added disappearing messages methods to conversations
- Added optional
listMessage
property toConversation
- Added consent streaming
- Added preferences streaming
- Added
Client.version
static getter
@xmtp/[email protected]
Patch Changes
- c63d8af: Make
getBlockNumber
optional for SCW signers
@xmtp/[email protected]
Patch Changes
- 68b0200: Refactored
Signer
type
@xmtp/[email protected]
Patch Changes
- f53c967: Refactored
Signer
, madegetBlockNumber
optional for SCW signers
@xmtp/[email protected]
Patch Changes
- 74ce850: Fix signer for SCW