Skip to content

Create and configure an XMTP client

The XMTP message API revolves around a network client that allows retrieving and sending messages to other network participants.

Create a client

To create an XMTP client, it must be connected to a wallet on startup. You must pass in a connected wallet that implements the Signer interface. This wallet is required for authentication and encryption purposes.

For more information about wallet signature requests, see Account signatures.

Clients created by XMTP v3 SDKs also support XMTP v2 messages. At a high-level, XMTP v3 is used to support group chat and XMTP v2 is used to support 1:1 chat.

In the near future, XMTP v3 will support both group and 1:1 chat with Messaging Layer Security (MLS). Have questions or feedback, post to the XMTP Community Forums.

Group chat is currently supported for mobile apps in Kotlin, Swift, React Native, and Node.js.

In the near future, XMTP v3 will also support group chat for the web.

For more information about the work being done to support group chat for the web, see this SQLite, WebAssembly, and Diesel talk in the XMTP Developer Community Call.

If your mobile app provides group chat, you must explicitly configure your client to enable this functionality by setting the enableV3 client option to true.

For more information about client options, including how to set your client's network environment, see client configuration options.

JavaScript
import { Client } from "@xmtp/xmtp-js";
 
// Create the client with a `Signer` from your application
const xmtp = await Client.create(signer, {
  env: "production",
  enableV3: true, // Enable group chat support
});

Saving keys

You can export the unencrypted key bundle using the static method getKeys, save it somewhere secure, and then provide those keys at a later time to initialize a new client using the exported XMTP identity.

JavaScript
// Get the keys using a valid Signer. Save them somewhere secure.
import { loadKeys, storeKeys } from "./helpers";
const clientOptions = {
  env: "production",
};
 
let keys = loadKeys(address);
if (!keys) {
keys = await Client.getKeys(signer, {
...clientOptions,
// we don't need to publish the contact here since it
// will happen when we create the client later
skipContactPublishing: true,
// we can skip persistence on the keystore for this short-lived
// instance
persistConversations: false,
});
storeKeys(address, keys);
}
const client = await Client.create(null, {
...clientOptions,
privateKeyOverride: keys,
});
 

We are using the following helper functions to store and retrieve the keys

TypeScript
// Create a client using keys returned from getKeys
const ENCODING = "binary";
 
export const getEnv = (): "dev" | "production" | "local" => {
  return "production";
};
 
export const buildLocalStorageKey = (walletAddress: string) =>
  walletAddress ? `xmtp:${getEnv()}:keys:${walletAddress}` : "";
 
export const loadKeys = (walletAddress: string): Uint8Array | null => {
  const val = localStorage.getItem(buildLocalStorageKey(walletAddress));
  return val ? Buffer.from(val, ENCODING) : null;
};
 
export const storeKeys = (walletAddress: string, keys: Uint8Array) => {
  localStorage.setItem(
    buildLocalStorageKey(walletAddress),
    Buffer.from(keys).toString(ENCODING),
  );
};
 
export const wipeKeys = (walletAddress: string) => {
  // This will clear the conversation cache + the private keys
  localStorage.removeItem(buildLocalStorageKey(walletAddress));
};

Create a client with a private key

You can create a client with a private key using a compatible client library.

TypeScript
import { Client } from "@xmtp/xmtp-js";
 
const privateKey = "your_private_key";
 
//ethers
import { Wallet } from "ethers";
const signer = new Wallet();
 
//viem
import { privateKeyToAccount } from "viem/accounts";
const hexPrivateKey = `0x${privateKey}`;
let account = privateKeyToAccount(privateKey);
let signer = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});
 
// Create the client with a `Signer` from your application
const xmtp = await Client.create(signer, { env: "dev" });

Configure the client

Configure a client's network connection and other options using these client creation parameters:

Set the env client option to dev while developing. Set it to production before you launch.

ParameterDefaultDescription
envdev

Connect to the specified XMTP network environment. Valid values include dev, production, or local. For important details about working with these environments, see XMTP production and dev network environments.

enableV3false

As a best practice, set enableV3 to true to benefit from the upgraded XMTP v3 protocol.

appVersionundefined

Add a client app version identifier that's included with API requests. Production apps are strongly encouraged to set this value.


For example, you can use the following format: appVersion: APP_NAME + '/' + APP_VERSION.


Setting this value provides telemetry that shows which apps are using the XMTP client SDK. This information can help XMTP developers provide app support, especially around communicating important SDK updates, including deprecations and required upgrades.

apiUrlundefined

Manually specify an API URL to use. If specified, value of env will be ignored.

keystoreProviders

[StaticKeystoreProvider, NetworkKeystoreProvider, KeyGeneratorKeystoreProvider]

Override the default behavior of how the Client creates a Keystore with a custom provider. This can be used to get the user's private keys from a different storage mechanism.

persistConversationstrue

Maintain a cache of previously seen V2 conversations in the storage provider (defaults to LocalStorage).

skipContactPublishingfalse

Do not publish the user's contact bundle to the network on Client creation. Designed to be used in cases where the Client session is short-lived (for example, decrypting a push notification), and where it is known that a Client instance has been instantiated with this flag set to false at some point in the past.

codecs[TextCodec]Add codecs to support additional content types.
maxContentSize100MMaximum message content size in bytes.
preCreateIdentityCallbackundefined

preCreateIdentityCallback is a function that will be called immediately before a Create Identity wallet signature is requested from the user.

preEnableIdentityCallbackundefined

preEnableIdentityCallback is a function that will be called immediately before an Enable Identity wallet signature is requested from the user.

useSnapsfalse

Enabling the useSnaps flag will allow the client to attempt to connect to the "Sign in with XMTP" MetaMask Snap as part of client creation. It is safe to enable this flag even if you do not know whether the user has an appropriate MetaMask version enabled. If no compatible version of MetaMask is found, client creation will proceed as if this flag was set to false. To learn more, see Build with the Snap.

basePersistence

InMemoryPersistence (Node.js) or LocalStoragePersistence (browser)

A persistence provider used by the Keystore to persist its cache of conversations and metadata. Ignored in cases where the useSnaps is enabled and the user has a Snaps-compatible browser. To learn more, see Keystore and Pluggable persistence.

apiClientFactoryHttpApiClient

Override the function used to create an API client for the XMTP network. If you are running xmtp-js on a server, you will want to import @xmtp/grpc-api-client and set this option to GrpcApiClient.fromOptions for better performance and reliability. To learn more, see Pluggable gRPC API client.

XMTP network environments

An XMTP identity on the dev network is completely distinct from its XMTP identity on the production network, as are the messages associated with these identities.

  • production: Use this network for production messages.

    • To send and receive messages on the production network, you can use the open source Converse web app connected to the production network: https://app.converse.xyz.
  • dev: Use this network for development.

  • local: Use this network to have a client communicate with an XMTP node you are running locally. For example, an XMTP node developer can set env to local to generate client traffic to test a node running locally.