The Guild SDK library is a Typescript library for interacting with the Guild API. This document explains how to authenticate, manage your Guilds easily and automate token-gated access in any application with this SDK.
Guild.xyz is the membership layer protocol for web3 communities, making community management easy and interoperable between platforms.
1.x.x versions
of the SDK are deprecated, these versions won't work after 2024-01-31. Please migrate to the latest version. You can find the migration guide HERE.
A demo app is available here, it shows how to:
- Connect wallet (with wagmi)
- Sign a message
- Get user profile with signature
- Fetch data (with SWR)
- Guild roles
- User memberships
- Leaderboard
- Installation
- Importing the package and creating a Guild client
- SignerFunctions and Authentication
- Clients
- Modular / multi-platform architecture
- Examples
To install our SDK, open your terminal and run:
npm i @guildxyz/sdk
import { createGuildClient, createSigner } from "@guildxyz/sdk";
// The only parameter is the name of your project
const guildClient = createGuildClient("My project");
import { ethers } from "ethers";
const ethersWallet = new ethers.Wallet(...);
const signerFunction = createSigner.fromEthersWallet(ethersWallet);
import { useWeb3React } from "@web3-react/core";
const { account: walletAddress, library } = useWeb3React();
const signerFunction = createSigner.custom(
(message) => library.getSigner(account).signMessage(signableMessage),
address
);
import { useAccount, useSignMessage } from "wagmi";
const { signMessageAsync } = useSignMessage();
const { address } = useAccount();
const signerFunction = createSigner.custom(
(message) => signMessageAsync({ message }),
address
);
For signatures produced by EIP-1272 wallets, pass { chainIdOfSmartContractWallet: chainId }
as the third parameter of createSigner.custom
, where chainId
is the chain where the wallet operates. The Guild backend will try to call isValidSignature
on the specified chain.
We have an example app under examples
, which covers this parameter
We have multiple clients for different entities. These clients are created from the guildClient
that we created above.
const { guild: client } = guildClient;
// Get Guild by its numeric ID
const guild = await client.get(guildId);
// Get Guild by its urlName (slug)
const guild = await client.get(urlName);
// Get multiple guilds by their IDs
const guilds = await client.getMany([guildId1, guildId2]);
// Search guilds with pagination
const guilds = await client.search({ limit: 10, offset: 0, search: "our" });
// Get the members of a guild
const members = await client.getMembers(
guildId,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Join into a guild
const joinResult = await client.join(guildId, signerFunction);
// Check access to a guild, signerFuncion is required
await client.accessCheck(guildId, signerFunction);
// Create a new guild, check the possible creation parameters according to the typing
await client.create(
{
// In this example we are creating a guild with one FREE role
name: "My Guild",
urlName: "my-guild",
roles: [{ name: "My Role", requirements: [{ type: "FREE" }] }],
},
signerFunction
);
// Update an existing guild, check the possible update parameters according to the typing
await client.update(guildId, { description: "Edited" }, signerFunction);
// Delete a guild
await client.delete(guildId, signerFunction);
// For a given role, create a new point system, and assign some points as reward
const created = await guild.role.reward.create(
guildId,
roleId, // This role will have the 5 points reward
{
guildPlatform: {
platformGuildId: "my-points", // Some unique name for your point system
platformName: "POINTS",
platformGuildData: { name: "coins" }, // Assign a custom name for the points
},
platformRoleData: { score: 5 }, // Members will get this many points
},
signerFunction
);
// Use an existing point system for a role
const created = await guild.role.reward.create(
guildId,
roleId, // This role will have the 10 points reward
{
guildPlatformId, // The ID of the existing guildPlatform (reward) object
platformRoleData: { score: 10 },
},
signerFunction
);
// Get leaderboard for a specific point guild reward
const { leaderboard, aroundUser } = await guild.getLeaderboard(
guildId,
guildPlatformId,
signerFunction // Optional. If provided, the response will include an "aroundUser" field, which contains leaderboard items from around the user's position, otherwise it will be undefined
);
// Get user's rank in a specific reward
const response = await user.getRankInGuild(userId, guildId, guildPlatformId); // Returns the leaderboard position of a user for the given reward
// Get all the points of a user across all relevant rewards
const response = await user.getPoints(userId, signerFunction);
const {
guild: { admin: adminClient },
} = guildClient;
// Get all admins of a guild
const admins = await adminClient.getAll(guildIdOrUrlName);
// Get a specific admin of a guild
const admin = await adminClient.get(guildIdOrUrlName, userIdOfAdmin);
const {
guild: { reward: guildRewardClient },
} = guildClient;
// Get a guild reward (like a Discord server)
const guildReward = await guildRewardClient.get(
guildIdOrUrlName,
guildPlatformId,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Get all rewards of a guild
const guildRewards = await guildRewardClient.getAll(
guildIdOrUrlName,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Add a new reward to a guild
const createdGuildReward = await guildRewardClient.create(guildIdOrUrlName, {
platformName: "DISCORD", // In this example we are adding a Discord server
platformGuildId: "<SERVER_ID>",
});
// Delete a reward from a guild
await guildRewardClient.delete(
guildIdOrUrlName,
guildPlatformId,
signerFunction
);
const {
guild: { role: roleClient },
} = guildClient;
// Get a role
await roleClient.get(
guildIdOrUrlName,
roleId,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Get all roles of a guild
await roleClient.getAll(
guildIdOrUrlName,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Create a new role. Refer to the typing for other possible input parameters, like description, logic, or visibility
const createdRole = await roleClient.create(
guildIdOrUrlName,
{
name: "My new role",
requirements: [{ type: "FREE" }],
},
signerFunction
);
// Update an existing role
const updatedRole = await roleClient.update(
guildIdOrUrlName,
roleId,
{ description: "Edited" },
signerFunction
);
// Delete a role
await roleClient.delete(guildIdOrUrlName, roleId, signerFunction);
const {
guild: {
role: { requirement: requirementClient },
},
} = guildClient;
// Get a requirement
const requirement = await requirementClient.get(
guildIdOrUrlName,
roleId,
requirementId,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Get all requirements of a role
const requirements = await requirementClient.getAll(
guildIdOrUrlName,
roleId,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Create a new requirement
const createdRequirement = await requirementClient.create(
guildIdOrUrlName,
roleId,
{ type: "FREE" },
signerFunction
);
// Update an existing requirement (for example addresses in an ALLOWLIST requirement)
const updatedRequirement = await requirementClient.update(
guildIdOrUrlName,
roleId,
requirementId,
{ data: { addresses: ["0x..."] } }, // Lowercased addresses
signerFunction
);
// Delete a requirement
await requirementClient.delete(
guildIdOrUrlName,
roleId,
requirementId,
signerFunction
);
const {
guild: {
role: { reward: rewardClient },
},
} = guildClient;
// Get a role reward
const reward = rewardClient.get(
guildIdOrUrlName,
roleId,
rolePlatformId,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Get all rewards of a role
const roleReward = rewardClient.getAll(
guildIdOrUrlName,
roleId,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Create a role reward (for example a Discord role) with a guild reward (Discord server)
const createdReward = rewardClient.create(
guildIdOrUrlName,
roleId,
{
guildPlatform: {
// Here we are also creating a guild reward (the Discord server)
platformName: "DISCORD",
platformGuildId: "<DC_SERVER_ID>",
},
platformRoleId: "<DC_ROLE_ID>",
},
signerFunction
);
// Or create a role reward using an existing guild reward
const createdReward = rewardClient.create(
guildIdOrUrlName,
roleId,
{
guildPlatformId, // Here we are passing the id of an existing guild role (in this case a Discord server)
platformRoleId: "<DC_ROLE_ID>",
},
signerFunction
);
// Update an existing role reward
const updatedRoleReward = rewardClient.update(
guildIdOrUrlName,
roleId,
rolePlatformId,
{ visibility: "HIDDEN" }, // In this example we update a reward's visibility to HIDDEN
signerFunction
);
// Delete a role reward
rewardClient.delete(guildIdOrUrlName, roleId, rolePlatformId, signerFunction);
const { user: userClient } = guildClient;
// Get a user by numeric ID, or an address
const user = await userClient.get(userIdOrAddress);
// Get current memberships of a user
const userMemberships = await userClient.getMemberships(
userIdOrAddress,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Get a user's profile
const profile = await userClient.getProfile(
userIdOrAddress,
signerFunction // Optional, if a valid signer is provided, the result will contain private data
);
// Delete a user
await userClient.delete(userIdOrAddress, signerFunction);
const {
user: { address: userAddressClient },
} = guildClient;
// Get a user address
const userAddress = await userAddressClient.get(
userIdOrAddress, // Used for identifying the guild user
address, // The userAddress with this address will be returned
signerFunction
);
// Get all addresses of a user
const userAddresses = await userAddressClient.getAll(
userIdOrAddress,
signerFunction
);
// Create (connect / link) a new user address
const linkedAddress = await userAddressClient.create(
userIdOrAddress,
signerFunctionOfAddressToLink, // Should be a SignerFunction that is derived from the wallet that is being linked to the user. Can be obtained as described above
signerFunction
);
// Update a user address
const updatedUserAddress = await userAddressClient.update(
userIdOrAddress,
addressToUpdate,
{ isPrimary: true }, // In this example we update an address to be primary
signerFunction
);
// Delete (disconnect / unlink) a user address
await userAddressClient.delete(
userIdOrAddress,
addressToUpdate,
signerFunction
);
const {
user: { platform: userPlatformClient },
} = guildClient;
// Get a user platform connection
const userPlatform = await userPlatformClient.get(
userIdOrAddress,
platformId,
signerFunction
);
// Get all platform connections of a user
const userPlatforms = await userPlatformClient.getAll(
userIdOrAddress,
signerFunction
);
// Delete (disconnect / unlink) a platform connection
await userPlatformClient.delete(userIdOrAddress, platformId, signerFunction);
Guild.xyz no longer limits its platform gating functionalities to a single gateable Discord server or Telegram group. In the new multi-platform architecture you can gate more platforms in a single guild/role.
The guildPlatform
entity refers to a platform gated by the guild. It contains information about the gate platform, e.g.: a Discord server's id (platformGuildId
which is a uniqu identifier of this platform) and optionally some additional data like the inviteChannel
in the platformRoleData
property in this case.
The rolePlatform
entity connects a guildPlatform
to a role indicating that this role gives access to that platform. It can also contain some additional information about the platform (platformRoleId
and platformRoleData
), in Discord's case it's the Discord-role's id.
Note that for example in Telegram's case platformRoleId
is not required; only platformGuild
(which refers to a telegram group's id) needs to be provided in guildPlatform
.
import { createGuildClient, createSigner } from "@guildxyz/sdk";
import { Wallet } from "ethers";
import { randomBytes } from "crypto";
// Creating a guild client
const guildClient = createGuildClient("sdk-readme-example");
// Creating a random wallet for the example
const wallet = new Wallet(randomBytes(32).toString("hex"));
// Creating a signer function
const signerFunction = createSigner.fromEthersWallet(wallet);
// Creating a Guild
await guildClient.guild.create(
{
name: "My New Guild",
urlName: "my-new-guild-123", // Optinal
description: "Cool stuff", // Optional
admins: ["0x916b1aBC3C38852B338a22B08aF19DEe14113627"], // Optional
showMembers: true, // Optional
hideFromExplorer: false, // Optional
theme: [{ color: "#000000" }], // Optional
guildPlatforms: [
// Optional (declaring the gated platforms)
{
platformName: "DISCORD",
platformGuildId: "717317894983225012",
platformGuildData: { inviteChannel: "832195274127999019" },
},
],
roles: [
{
name: "My First Role",
logic: "AND",
requirements: [
{
type: "ALLOWLIST",
data: {
addresses: [
"0xedd9C1954c77beDD8A2a524981e1ea08C7E484Be",
"0x1b64230Ad5092A4ABeecE1a50Dc7e9e0F0280304",
],
},
},
],
rolePlatforms: [
// Optional (connecting gated platforms to the role)
{
guildPlatformIndex: 0,
platformRoleId: "947846353822178118",
},
],
},
{
name: "My Second Role",
logic: "OR",
requirements: [
{
type: "ERC20",
chain: "ETHEREUM",
address: "0xf76d80200226ac250665139b9e435617e4ba55f9",
data: {
amount: 1,
},
},
{
type: "ERC721",
chain: "ETHEREUM",
address: "0x734AA2dac868218D2A5F9757f16f6f881265441C",
data: {
amount: 1,
},
},
],
rolePlatforms: [
// Optional (connecting gated platforms to the role)
{
guildPlatformIndex: 0,
platformRoleId: "283446353822178118",
},
],
},
],
},
signerFunction
);
// Joining to a Guild if any role is accessible by the given address
await guildClient.guild.join(myGuild.id, signerFunction);
const myGuild = await guildClient.guild.create(
{
name: "My Telegram Guild",
guildPlatforms: [
{
platformName: "TELEGRAM", // Telegram group 0
platformGuildId: "-1001190870894",
},
{
platformName: "TELEGRAM", // Telegram group 1
platformGuildId: "-1003847238493",
},
{
platformName: "TELEGRAM", // Telegram group 2
platformGuildId: "-1008347384212",
},
],
roles: [
{
name: "My First Role",
logic: "AND",
requirements: [
{
type: "ALLOWLIST",
data: {
addresses: [
"0xedd9C1954c77beDD8A2a524981e1ea08C7E484Be",
"0x1b64230Ad5092A4ABeecE1a50Dc7e9e0F0280304",
],
},
},
],
rolePlatforms: [
{
guildPlatformIndex: 0, // Telegram group 0
},
{
guildPlatformIndex: 2, // Telegram group 2
},
],
},
{
name: "My Second Role",
logic: "OR",
requirements: [
{
type: "ERC20",
chain: "ETHEREUM",
address: "0xf76d80200226ac250665139b9e435617e4ba55f9",
data: {
amount: 1,
},
},
],
rolePlatforms: [
{
guildPlatformIndex: 1, // Telegram group 1
},
],
},
],
},
signerFunction
);