Discord Roles from Chain-driven Application Data

What Is It?

The Tableland team is excited to introduce our new Discord<>Tableland bot integration—linking on/off-chain retribution back to Discord roles!

Namely, developers can create/deploy this bot as an extension to Vulcan using its native features. It allows the bot to read data from an application’s Tableland tables and use it in Discord user/role management—all with a decentralized cloud database!

Why Did We Do It?

Vulcan is great for checking Discord member NFT ownership and creating roles based on NFT traits—but what if you want other data to be part of that role attribution process, including conditional checks on that data? With a custom webhooks, you can dynamically update a member's role by reading application data from Tableland. For example, a smart contract can write user data (e.g., address & session data) to a set of tables, and you can then make queries to them using Vulcan.

This extension will automatically attach new roles to users predicated on on-chain data, enhancing your overall Discord role management & community experience!

What Does it Do?

The bot will give different Discord roles/badges to every member who has gone through the initial Vulcan authentication steps.

That is, only members who've verified will have roles associated with them, and the roles are based on data read from application-controlled Tableland tables. A role might even unlock additional Discord channels or capabilities for that subset of users!

How Does It Work?

This feature relies on Vulcan to provide user wallet information; it’s a great tool for web3 community management, as it provides the wallet-to-member attribution needed in our workflow. Although, the general approach could be used with other Discord bots, too! Recall that Tableland is EVM compatible with support for a number of L1/L2 chains and works in two parts:

  1. On-chain: table creation and writes go through a registry smart contract—i.e., these are signed transactions that correspond to a table ERC721 token, allowing for on-chain data like a user’s account address to be part of any written data context.

  2. Off-chain: table reads to validator nodes running the Tableland protocol—i.e., this enables open APIs for running read-only queries across any set of tables (including cross-chain), such as querying for the user’s address & other useful relational data.

Each developer’s Discord server will have their own Vulcan verification requirements and rules for the role attribution, but let’s assume you’ve developed a web3 application that stores your connected users’ EVM account addresses. With Vulcan’s custom webhooks, we’re creating an extension that queries dynamic, chain-driven table data. Developers can make SQL queries to the Tableland network and use this user data alongside Vulcan by controlling the webhook’s response. You can even compose data across one or multiple tables to determine what types of roles should be shown on each Discord member’s profile.

For example, a common application pattern is to store user data. Your app might capture user data upon logging in and write it to a Tableland table. Since Vulcan lets you associate each Discord member with their EVM account/address, you can combine Vulcan verification data with your own application’s user table data.

How Can You Use This?

Table Setup

There are endless ways to build this feature and add it to your Discord server! But, let’s walk through an example with user session data. First, you’ll want to create a table called sessions that tracks user data, perhaps with smart contracts or the Tableland SDK.

# Track user data in a `sessions` table CREATE TABLE sessions ( id INTEGER PRIMARY KEY, owner TEXT NOT NULL, start_block TEXT, end_block TEXT );

Let’s also assume our app only works if the user owns a specific NFT; a token-gated workflow. When users connect to your app, you’ll check for NFT ownership and then insert data into this table with the start_block (i.e., the time at which the session begins). Upon exiting the session, you’ll update the user’s session row with an end_block. So, you’ll execute various INSERT INTO and UPDATE statements that will change the user table’s data.

This provides us with a simple setup where we can check how long the user was using the app—Discord roles will be awarded to the most active community members!

Discord Setup

Our Discord bot will connect to Vulcan through their custom webhooks to retrieve the associated wallet address for verified community members. It’s a pretty simple implementation. Vulcan will post to an endpoint with the following:

{ "wallet": [wallet_address], }

If the user/address should be given a role, the endpoint needs to respond with a JSON object containing 'success': true and a 200 response code. Before returning a response, you will want to implement functionality to determine what the response should be. For example, you might use a query like the following with a Gateway API call or the Tableland SDK:

SELECT SUM(coalesce(end_time, BLOCK_NUM(1)) - start_time) FROM <sessions> # The full table name that stores all user sessions WHERE lower(owner) = lower('<wallet_address>') # Passed wallet address

If the query returns any session data for this wallet address, there could be a “basic” Discord role added for this member that indicates they’ve at least logged into the app. If a user has above some threshold of time spent on the app, this could help identify them as a “power user” and give them a more powerful role, such as accessing new channels. If no session data exists, then there is no role given to the user.

As for creating your webhook, again, there are many different to do this. Let’s say you have a web app built with Vite + NextJS, deployed with Vercel. You could use Vercel Edge Functions and create a custom API route to return the required data to determine the Vulcan response we outlined above!

Example: Tableland Rigs Community

In general, we’ve been thinking a lot about what Flight Time (”FT”) can do for Rigs owners—if you’ve haven’t checked out our deep dive on token reputation, this will give you some additional insight. Recall that if you own a Rig, you can actively “use” it via actions like piloting and parking. When you pilot your Rig, you start earning FT (which disables marketplace trades), and upon parking you stop accruing FT (but it re-enables trading).

Important: You must re-verify with Vulcan in order to access this feature in the Tableland Discord.

The Tableland server’s Discord bot uses FT as a way to attach roles to community members, based on their total FT. A quick reminder on what the Tableland Rigs and FT encompass:

In other words, building up a bunch of FT shows your commitment to the Rigs project by displaying a Discord badge and reflects your dedication as a community member!

Implementation

You can see this logic in our Rigs repo under the garage/api/ft/[from]/[to] directory. There, a simple query is made to Tableland tables:

SELECT SUM(ft) as "ft" FROM ( SELECT (coalesce(end_time, BLOCK_NUM(1)) - start_time) as "ft" FROM <pilot_sessions> # The table that stores all piloting/parking sessions WHERE lower(owner) = lower('<wallet_address>') # Passed wallet address UNION ALL SELECT amount as "ft" FROM <ft_rewards> # The table that stores *additional* FT rewards for addresses WHERE lower(recipient) = lower('<wallet_address>') # Passed wallet address )

This makes queries to two tables:

  • One that stores all of the piloting/parking session data, which is what gets displayed in The Garage and holds the majority of FT data. This comes from the Rigs/Pilots contract itself.

  • Another that stores FT rewards—additional FT that can be rewarded to holders, outside of the piloting/parking actions (e.g., off-chain rewards).

The query is made using Vercel Edge Functions. Then, our API allows a custom from and to FT amount range to be specified, which is used in determining the different roles for each user. For example, you can make a query in The Garage to check if a wallet has earned between 1M to 5M FT:

https://garage.tableland.xyz/api/ft/1000000/5000000

Community Usage

Let’s review the steps you need to use this feature. If you’re already a community member and own a Rig, it’s likely you’ve already done this but will need to verify again:

  1. Join/enter the Tableland Discord server.

  2. Verify your account using Vulcan in the #rigs-verfiy channel.

  3. That’s it!

Once you’re (re-)verified, the logic described above will make the proper queries and add roles/badges to your Discord account. That is, as your Rigs continue to earn FT, you’ll automatically have the roles added/upgraded—no additional actions are required!

How Can Someone Use It?

Above, we walked through how developers can build this functionality into their Discord servers. We used Vulcan to attribute Discord members with their on-chain accounts/addresses. Then, we combined that information with user application data stored in Tableland tables, and custom webhooks return a boolean that attaches a user’s Discord role.

Developers can also reference the Rigs GitHub repo and the API we’ve built in garage directory; the ethereum directory is where the tables are created. In general, this concept could be recreated with the same FT-related tables we’ve noted above, or you could create a similar setup but with your own reputation-related data.

In the Rigs setup, the Discord bot uses an existing pilot_sessions table that stores core reputation data from user-initiated smart contract piloting and parking methods. The secondary ft_rewards table gives you the ability to add one-off FT that rewards users for something they’ve done, such as an on-chain action for voting on a proposal or an off-chain action like contributing to open source code. Depending on your needs, you might have a smart contract writing data on-chain to the ft_rewards table, or you might have an off-chain-only use case where you can simply use the Tableland SDK to mutate the table after a community member completes some task.

Get in Touch!

Be sure to give us a follow on Twitter and hop into our Discord if you’d like to discuss this design or the protocol in more detail—and give the rigs repo a star on GitHub if you found this useful.

And if you’re not familiar with Tableland Rigs, check out the collection on OpenSea, and The Garage app is open for anyone to view!

Textile Blog & Newsletter logo
Subscribe to Textile Blog & Newsletter and never miss a post.
  • Loading comments...