Skip to content

Create an XMTP client

Create an XMTP client that can use the signing capabilities provided by the signer. This signer links the client to the appropriate EOA or SCW.

Understand creating and building a client

This video provides a walkthrough of creating and building a client.

How it works

When you call Client.create(), the following steps happen under the hood:

  1. Extracts the signer and retrieves the wallet address from it.
  2. Checks the XMTP identity ledger to find an inbox ID associated with the signer address. The inbox ID serves as the user's identity on the XMTP network.
    1. If it doesn't find an existing inbox ID, it requests a wallet signature to register the identity and create an inbox ID.
    2. If it finds an existing inbox ID, it uses the existing inbox ID.
  3. Checks if a local SQLite database exists. This database contains the identity's installation state and message data.
    1. If it doesn't find an existing local database, it creates one and encrypts it with the provided dbEncryptionKey.
    2. If it finds an existing local database, it checks to see if the provided dbEncryptionKey is a match.
      • If the dbEncryptionKey matches, it uses the existing local database.
      • If the dbEncryptionKey doesn't match, it creates a new local database and encrypts it with the provided key.
  4. Returns the XMTP client, ready to send and receive messages.

Keep the database encryption key safe

The dbEncryptionKey is critical to the stability and continuity of an XMTP client. It encrypts the local SQLite database created when you call Client.create(), and must be provided every time you create or build a client.

As long as the local database and encryption key remain intact, you can use Client.build() to rehydrate the same client without re-signing.

This encryption key is not stored or persisted by the XMTP SDK, so it's your responsibility as the app developer to store it securely and consistently.

If the encryption key is lost, rotated, or passed incorrectly during a subsequent Client.create() or Client.build() call, the app will be unable to access the local database. Likewise, if you initially provided the dbPath option, you must always provide it with every subsequent call or the client may be unable to access the database. The client will assume that the database can't be decrypted or doesn't exist, and will fall back to creating a new installation.

Creating a new installation requires a new identity registration and signature—and most importantly, results in loss of access to all previously stored messages unless the user has done a history sync.

To ensure seamless app experiences, persist the dbEncryptionKey securely, and make sure it's available and correctly passed on each app launch.

To learn more about database operations, see the XMTP MLS protocol spec.

Create a client

To call Client.create(), you must pass in a required signer and can also pass in any of the optional parameters covered in Configure an XMTP client.

Browser
import { Client, type Signer } from "@xmtp/browser-sdk";
 
// create a signer
const signer: Signer = { /* ... */ };
 
/**
 * The database encryption key is optional but strongly recommended for
 * secure local storage of the database.
 *
 * This value must be consistent when creating a client with an existing
 * database.
 */
const dbEncryptionKey = window.crypto.getRandomValues(new Uint8Array(32));
 
const client = await Client.create(
  signer,
  // client options
  {
    dbEncryptionKey,
  },
);

Configure an XMTP client

You can configure an XMTP client with these options passed to Client.create:

Browser
import type { ContentCodec } from "@xmtp/content-type-primitives";
 
type ClientOptions = {
  /**
   * Specify which XMTP environment to connect to. (default: `dev`)
   */
  env?: "local" | "dev" | "production";
  /**
   * apiUrl can be used to override the `env` flag and connect to a
   * specific endpoint
   */
  apiUrl?: string;
  /**
   * historySyncUrl can be used to override the `env` flag and connect to a
   * specific endpoint for syncing history
   */
  historySyncUrl?: string;
  /**
   * Allow configuring codecs for additional content types
   */
  codecs?: ContentCodec[];
  /**
   * Path to the local DB
   */
  dbPath?: string;
  /**
   * Encryption key for the local DB
   */
  dbEncryptionKey?: Uint8Array;
  /**
   * Enable structured JSON logging
   */
  structuredLogging?: boolean;
  /**
   * Enable performance metrics
   */
  performanceLogging?: boolean;
  /**
   * Logging level
   */
  loggingLevel?: "off" | "error" | "warn" | "info" | "debug" | "trace";
  /**
   * Disable automatic registration when creating a client
   */
  disableAutoRegister?: boolean;
};
 

XMTP network environments

XMTP provides dev and production network environments. These networks are completely separate and not interchangeable.

For example, an XMTP identity on the dev network is completely distinct from the XMTP identity on the production network, as are the messages associated with these identities. In addition, XMTP identities and messages created on the dev network can't be accessed from or moved to the production network, and vice versa.

The production network is configured to store messages indefinitely. XMTP may occasionally delete messages and identities from the dev network, and will provide advance notice in the XMTP Community Forums.

You can also use a local network to have a client communicate with an XMTP node you are running locally. During development, it's highly recommended to use a local network environment for speed and reliability.

Build an existing client

Build, or resume, an existing client (created using Client.create()) that's logged in and has an existing local database.

Browser
import { Client, type Identifier } from "@xmtp/browser-sdk";
 
const identifier: Identifier = {
  identifier: "0x1234567890abcdef1234567890abcdef12345678",
  identifierKind: "Ethereum",
};
const client = await Client.build(identifier, options);

Log out a client

When you log a user out of your app, you can give them the option to delete their local database.

Browser
/**
 * The Browser SDK client does not currently support deleting the local database.
 */
 
// this method only terminates the client's associated web worker
client.close();