Skip to main content

Enable XMTP subscriptions using a wallet connection

This tutorial will show you how to create a simple Subscribe button with consent that enables users to subscribe to your messages or notifications.

📥 Need a quick reference? Check out this GitHub repo: xmtp-subscribe


Before diving into the code let's consider important aspects while integrating consent features. For example, before making an allow or block action you should synchronize the updated consent list in order to prevent overwriting network consent from another app. For more details head to these sections of our docs:

  • Understand user consent preferences: This section provides a comprehensive understanding of how user consent preferences are set, including but not limited to, direct actions within the app, settings adjustments, and responses to prompts.
  • Use consent preferences to respect user intent: Your app should aim to handle consent preferences appropriately because they are an expression of user intent.
  • Synchronize user consent preferences:All apps that use the user consent feature must adhere to the logic described in this section to keep the consent list on the network synchronized with local app user consent preferences, and vice versa.


Import libraries

Import the necessary XMTP and Ethereum packages. These libraries enable you to create an XMTP client and interact with the Ethereum blockchain.

import React, { useEffect, useState } from "react";
import { Client } from "@xmtp/xmtp-js";
import { ethers } from "ethers";

The receiver of the subscription is you. In this case, we'll make it a random wallet generated by ethers, but you could send your own wallet address as a prop.

Subscribe with your wallet

The connectWallet function facilitates the connection to the user's Ethereum wallet.

let wallet = await connectWallet();
let client = await Client.create(wallet, { env: env });

To ensure we're working with the most up-to-date information, refresh the consent list.

// Refresh the consent list to make sure your application is up-to-date with the
await client.contacts.refreshConsentList();

After refreshing, we get the current consent state of the subscriber. Valid values are allowed, blocked, or unknown.

// Get the consent state of the subscriber
let state = client.contacts.consentState(client.address);

Based on the current state, either allow or block the subscriber.

// If the state is unknown or denied, allow the subscriber
if (state == "unknown" || state == "denied") {
await client.contacts.allow([senderAddress]);
  • If the state is unknown or blocked, we change it to allowed using client.contacts.allow([address]) and call the onSubscribe function if it exists.
  • If the state is allowed, we don't change the consent and call the onUnsubscribe function if it exists.


The onSubscribe and onUnsubscribe functions are called when the consent state is updated. If you wrap your code around a component, you can use these functions to update your local state or to send a message to your subscribers.

// Define a SubscribeButton component that uses the onSubscribe and onUnsubscribe callbacks
function SubscribeButton({ onSubscribe, onUnsubscribe }) {
// ... other component logic

// Example usage of onSubscribe and onUnsubscribe within the component
const handleSubscribe = (address) => {
// Perform subscription logic...
onSubscribe(address); // Call the onSubscribe callback

const handleUnsubscribe = (address) => {
// Perform unsubscription logic...
onUnsubscribe(address); // Call the onUnsubscribe callback

return (
<button onClick={() => handleSubscribe("subscriberAddress")}>
<button onClick={() => handleUnsubscribe("subscriberAddress")}>

// Usage of SubscribeButton component with onSubscribe and onUnsubscribe callbacks
onSubscribe={(address) => {
// Update local db or send a message to the subscriber
onUnsubscribe={(address) => {
// Update local db or send a message to the subscriber

Always synchronize consent states: Before updating consent preferences on the network, ensure you refresh the consent list with refreshConsentList. Update the network's consent list only in these scenarios:

  • User Denies Contact: Set to denied if a user blocks or unsubscribes.
  • User Allows Contact: Set to allowed if a user subscribes or enables notifications.
  • Legacy Preferences: Align the network with any existing local preferences.
  • User Response: Set to allowed if the user has engaged in conversation.

Neglecting these guidelines can result in consent state conflicts and compromise user privacy.


Consent has really evolved through the years. It started with email, then email marketing, and was the wild west until laws like GPDR stepped in. This is new chapter in the history of consent in a new era for privacy, portability, and ownership.

Example repo

You can find a complete example of this tutorial in the xmtp-subscribe repo.

Was the information on this page helpful?
powered by XMTP