How to Send Messages in a Token-Gated Video Call

Jennifer Tran
10 min readMay 21, 2023

--

This tutorial guides on creating a video call gated by an NFT or blockchain token using the Huddle01 SDK and sending messages to viewers using the Mailchain SDK.

Photo by Franck on Unsplash

Why Token-Gated Video Calls

Influencers and communities create live video calls to showcase products, meet with fans and members, and host conferences and events.

Photo by Malte Helmhold on Unsplash

Token gating is a secure way for hosts to distribute premium content. Unlike gating through usernames and passwords, users cannot easily share their tokens with others. Users must sign in with their wallet to prove token ownership, ensuring that only paying users can access the live stream.

Token gating is also a mechanism to maintain community. NFT communities and decentralized autonomous organizations (DAOs) can gate membership offerings using NFTs and tokens that symbolize membership. Ownership of these tokens grants automatic access to the associated community, eliminating the need for login credentials.

Many of these NFT communities and DAOs host regular community calls and live streams to update members about community activity or provide education and business insights. It is crucial to limit access to these events only to members and prevent scammers, bots, and Zoom “bombers.” By token-gating calls or live streams, hosts ensure that only verified members are participating.

Sending Messages During Video Calls

During calls and live streams, hosts often reward viewers with different perks such as discounts, freebies, and giveaway entries.

To prevent leaks and accurately track viewers during perk announcements, hosts require a method to identify current viewers and send messages exclusively to them.

Introducing a solution using Huddle01 and Mailchain.

Huddle01 is a composable and robust media infrastructure that enables cross-chain audio and video communication between users. Their SDK allows for the creation of token-gated video call rooms and tracking of the wallet addresses currently connected to the call room

Mailchain enables blockchain-based email-like messaging with plain or rich text and attachment capabilities. Their SDK allows for sending and receiving messages between wallets.

By combining these solutions, you can create a call or live stream gated by any NFT or token and send a message to all viewers currently joined on the call.

This specifically enables NFT communities and DAOs to:

  • Distribute Proof of Attendance (POAP), certificates of attendance, or other tokens of appreciation exclusively to members who attended the call, not just those who registered.
  • Send recording waivers and other necessary legal documents for attendees to review and sign.
  • Conduct feedback surveys.
  • Share meeting notes with members before making them public to the wider community.

I chose this solution because, as a participant in a DAO myself, I frequently receive an overwhelming number of emails and notifications about community calls that I have not attended. As a DAO event host, I have experienced instances where individuals have claimed POAPs for activities they signed up for but did not participate in.

Let’s check out how to implement this using code in the tutorial section below!

Tutorial

This tutorial assumes using NextJS.

Part 1: Create the live stream using Huddle01 SDK

  1. Go to https://www.huddle01.com/docs/api-keys to connect your wallet and generate your Huddle01 API key and project ID.
API Key page on Huddle01

2. Retrieve your wallet access token using https://auth-simulator.vercel.app/.

Your wallet access token is a JWT token that is needed for upcoming sections of the tutorial.

Connect your wallet. Click on the getMessage() button and then the signMessage() button, and sign the message with your wallet.

Click on the getAccessToken() button. Your access token will now show it.

Keep this tab open and/or copy and paste the access token into a digital document that you can save.

4. Set up your project using the Huddle01 starter app.

Huddle01 provides a start app to test and utilize their SDK. For simplicity, we will utilize the boilerplate to get started in this tutorial.

We suggest that you chose the NextJS framework and Typescript for your configuration as shown in an example command line here:

Example of setting up the Huddle01 boilerplate via command line

You can follow the tutorial in full at: https://www.huddle01.com/docs/sdk/reactjs/example

5. Create a token gated room.

Once you are done setting up the starter app, navigate to the project directory in the command line and run the application using the following commands.

cd your-app
pnpm i
pnpm run

You most likely ran the application on localhost port 3000 and navigate to the application in development on http://localhost:3000. Ensure which localhost port you ran the application.

The boilerplate consisted of the /pages/api/create-room component which generates the /create-room API. This API will allow you to generate your room.

First, we must modify the API call parameters to create a token-gated room. In pages/api/create-room.ts, update the Huddle01 API to call to https://iriko.testing.huddle01.com/api/v1/create-room and add tokenType, chain, contractAddress, and hostWallets keys in the body.

  • tokenType: the kind of digital asset. Coins or tokens such as Ethereum or USDC are ERC20. Single-copy NFTs are usually ERC721 and NFTs with multiple copies of each are usually ERC1155.
  • chain: the complete name of the blockchain that the token was minted on. Currently, Huddle01 only supports wallet login on Ethereum.
  • contractAddress: an array list of all of the contract addresses or identifiers of the tokens.
  • hostWallets: an array list of all wallet addresses of users who are meeting hosts

Below is an example of an accepted body to generate a room gated by USDC on Ethereum.

{
title: 'Huddle01-Test', //title of the room call
"tokenType": "ERC20",
"chain": "ETHEREUM",
"contractAddress": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],
"hostWallets": ['0x5cf264fb15e275b14fba764e3d4d3e723b67b573', '0x16d7034610db82fd30ffc9667f4b4f55e2b8541f']
}

Here is a full example of the pages/api/create-room.ts component:

import axios from 'axios';

import type { NextApiRequest, NextApiResponse } from 'next';

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
try {
const { data } = await axios.post(
'https://iriko.testing.huddle01.com/api/v1/create-room',
{
title: 'Huddle01-Test',
"tokenType": "ERC20",
"chain": "ETHEREUM",
"contractAddress": ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"]
"hostWallets": ['0x5cf264fb15e275b14fba764e3d4d3e723b67b573', '0x16d7034610db82fd30ffc9667f4b4f55e2b8541f']
},
{
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.API_KEY,
},
}
);

res.status(200).json(data);
} catch (error) {
res.status(500).json(error);
}
};

export default handler;

You can now navigate to the API to get a token gated room returned to you.

// Navigate to [localhost server]/api/create-room
https://localhost:3000/api/create-room

You will be returned a JSON response such as this:

{"message":"Room Created Successfully","data":{"roomId":"wrm-pgsz-tgc"}}

Your room ID also serves as a prefix to the Huddle01 link that you can distribute.

The URL to the token gated room should be http://app.huddle01.com/[roomId].

6. Share the token gated room with your community.

Here’s what users should see when you share with them the link.

The page will note that the video call is “token-gated with [type of token”].

They’ll see a preview of them on camera. They’ll need to connect and sign using their wallet before they can enter a display name and join.

Example of accessing the token-gated video call. Users will need to sign in using their wallet.
The user is asked to sign using their wallet.
The user is confirmed to own the token and can proceed to adjust their display name and join the meeting.

They will see this error page if the wallet does not have the token.

Example of an error page if the wallet that the user connect does not have the token.

Part 2: Retrieve Current Attendee Addresses on the Call

You will return to the Huddle01 starter app that you created in Part 1 to track the current attendees in the call.

  1. Run the starter app. As a reminder, here are the commands to run it.
cd your-app
pnpm i
pnpm run

2. Navigate to the local application.

Note: You most likely ran the application on localhost port 3000 and navigate to the application in development on http://localhost:3000.

Your local application should look like this:

Example of local application of Huddle01 starter app

3. Under the project state section (labeled as Idle during start), add your Huddle01 project ID and click on the INIT button.

4. Under the Initialize section, add your room ID and the access token that you received in the first section. Click on Join_Lobby.

In your console, you will see a join_success log with an object. Open the object -> RoomMetaData -> PeerMetadata -> Open any of the “peers” or attendees listed and you will see their listed wallet address.

Example of console log return when a user has successfully joined a room

You can use this Typescript function to store all of the wallet addresses in an array:

interface Peer {
peerId: string;
role: string;
displayName: string;
walletAddress: string;
avatarUrl: string | null;
isHandRaised: boolean;
}

type PeersObject = {
[key: string]: Peer;
};

function extractWalletAddresses(peersObject: PeersObject): string[] {
const walletAddresses: string[] = [];

for (const peerId in peersObject) {
const peer = peersObject[peerId];
walletAddresses.push(peer.walletAddress);
}

return walletAddresses;
}

Use this function to return a CSV-formatted list.

interface Peer {
peerId: string;
role: string;
displayName: string;
walletAddress: string;
avatarUrl: string | null;
isHandRaised: boolean;
}

function generateWalletAddressCSV(peersList: Peer[]): string {
let csv = "Wallet Address";

for (const peer of peersList) {
csv += `"${peer.walletAddress}\n`;
}

return csv;
}

Note: Huddle01 currently does not expose the wallet addresses connected to a room through an API. Huddle01 plans to expose the wallet addresses in their Iframe SDK in their next update and is working with them to expose the data in their other SDKs and APIs.

Part 3: Send a Message to Current Attendees

You can utilize the Mailchain app or create an API to programmatically send a message.

  1. Get the Mailchain email addresses of the attendees.

A user’s Mailchain email address on Ethereum is formatted as [address]@ethereum.mailchain.com. For example, if the user’s address is 0x5CF264FB15e275B14fba764E3d4D3E723B67B573, their Mailchain email address is 0x5CF264FB15e275B14fba764E3d4D3E723B67B573@ethereum.mailchain.com.

You can utilize this Google Sheets: https://docs.google.com/spreadsheets/d/1pcvQR6liC7bIyOaNa0N929YqrfAVC47D2PMaUePi-mI/edit?usp=sharing to get a list of Mailchain email addresses from a list of wallet addresses.

2. Send a message to the attendees.

You can choose to either use the Mailchain app or create an API.

Using the Mailchain app

a. Go to the Mailchain app at https://app.mailchain.com/.

b. Sign up for a Mailchain account if you do not already have one. You can get a free email handle!

By the way, I’m jennifer@mailchain.com.

c. Once you have logged in or signed up, Mailchain will redirect you to your mailbox.

d. Register your wallet address by connecting your wallet. This will now allow anyone to email you using your [address]@ethereum.mailchain.com.

Example of a Mailchain inbox

e. Click on the Compose Button. It will open a message box.

f. Enter the email addresses from step 1 of this section in the recipient (To:) part of the box.

e. Compose your message and send it when you’re ready!

Creating an API

You can also create an API that accepts an array of wallet addresses in the body, programmatically appends @ethereum.mailchain.com to each address, and sends a message.

Here is an example of an API:

import { NextApiRequest, NextApiResponse } from 'next';
import { Mailchain } from '@mailchain/sdk';

const secretRecoveryPhrase = process.env.SECRET_RECOVERY_PHRASE!; /

const mailchain = Mailchain.fromSecretRecoveryPhrase(secretRecoveryPhrase);

export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { walletAddresses } = req.body;

const toAddresses = walletAddresses.map(
(walletAddress: string) => `${walletAddress}@ethereum.mailchain.com`
);

const { data, error } = await mailchain.sendMail({
from: `yoursername@mailchain.com`,
to: toAddresses,
subject: 'My first message',
content: {
text: 'Hello Mailchain 👋',
html: '<p>Hello Mailchain 👋</p>',
},
});

if (error) {
console.warn('Mailchain error', error);
return res.status(500).json({ message: 'Mailchain error. Mail not sent.' });
}
console.log(data);
return res.status(200).json({ message: 'Mail sent successfully.' });
}

Voila! You have sent a message to attendees while they were on the call. Token gating provides a secure way for hosts to distribute premium content and maintain community membership for NFT communities and DAOs. By requiring users to sign in with their wallet to prove token ownership, token gating ensures that only paying users can access live streams, while also granting automatic access to associated communities for NFT owners.

Combining Huddle01 and Mailchain provides a solution for hosts to identify current viewers during calls and live streams and send messages exclusively to them. This solution enables NFT communities and DAOs to distribute POAPs and other tokens of appreciation exclusively to members who attended the call, send legal documents and feedback surveys, and share meeting notes with members before making them public.

How can Huddle01 and Mailchain Work Better Together?

  • As mentioned, Huddle01 aims to expose the wallet addresses in their Iframe SDK in their next release, and other SDKs and APIs in future releases. This will facilitate a more seamless integration process and potentially allow for the integration of Mailchain into the Huddle01 native application and host dashboard in the future.

Other ideas include:

  • A Mailchain login in the Huddle01 native application and their wallet SDK.
  • Mailchain integration in the Huddle01 host dashboard at https://dashboard.huddle01.com The Huddle01 host dashboard shows video call data and allows hosts to schedule upcoming video calls. A Mailchain integration would allow hosts to send emails and notifications (i.e. when a call recording to ready) to attendees post-call.
  • Mailchain email resolution in peer or attendee metadata in Huddle01 APIs and SDKs.
  • Mailchain plugin that enables hosts to send a message to attendees, request attendees without Mailchain account to register, and once the user registers, they will get sent the message that they missed.

--

--