Skip to main content

Build authentication with XMTP

The XMTP message API revolves around a network client that allows retrieving and sending messages to other network participants. A client must be connected to a wallet on startup. The client will request a wallet signature in two cases:

  1. To sign the newly generated key bundle. This happens only the very first time when key bundle is not found in storage.
  2. To sign a random salt used to encrypt the key bundle in storage. This happens every time the client is started (including the very first time).

Add the provider (React SDK only)

To use the hooks provided by the React SDK, you must wrap your app with an XMTPProvider. This gives the hooks access to the XMTP client instance.

info

There’s only one client instance per provider.

import { XMTPProvider } from "@xmtp/react-sdk";

createRoot(document.getElementById("root") as HTMLElement).render(
<StrictMode>
<XMTPProvider>
<App />
</XMTPProvider>
</StrictMode>,
);

Create a client

A client is created that requires passing in a connected wallet that implements the Signer interface. Use client configuration options to change parameters of a client's network connection.

import { Client } from "@xmtp/xmtp-js";
// Create the client with a `Signer` from your application
const xmtp = await Client.create(wallet, { env: "dev" });

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.

// Get the keys using a valid Signer. Save them somewhere secure.
import { loadKeys, storeKeys } from "./helpers";

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, { privateKeyOverride: keys });

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

// Create a client using keys returned from getKeys
const ENCODING = "binary";

export const buildLocalStorageKey = (walletAddress: string) =>
walletAddress ? `xmtp:${"dev"}: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));
};

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
appVersionundefinedAdd 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.
envdevConnect 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.
apiUrlundefinedManually 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.
persistConversationstrueMaintain a cache of previously seen V2 conversations in the storage provider (defaults to LocalStorage).
skipContactPublishingfalseDo 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.
preCreateIdentityCallbackundefinedpreCreateIdentityCallback is a function that will be called immediately before a Create Identity wallet signature is requested from the user.
preEnableIdentityCallbackundefinedpreEnableIdentityCallback is a function that will be called immediately before an Enable Identity wallet signature is requested from the user.

Environments

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

  • production: This network is used in production and is configured to store messages indefinitely.

    • Try the web inbox at https://xmtp.chat/.

    • Send a message to our gm bot to get started. gm.xmtp.eth

  • dev: XMTP may occasionally delete messages and keys from this network

    • Try the web dev inbox at https://dev.xmtp.chat/.

    • Send a message to our gm bot to get started. 0x8DC925338C1eE1fE62c0C43404371deb701BfB55

  • local: Use 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.

Was the information on this page helpful?
powered by XMTP