Summary
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.
Migration Guide to V2
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.
Contents
- Installation
- Importing the package and creating a Guild client
- SignerFunctions and Authentication
- Clients
- Modular / multi-platform architecture
- Examples
Installation
To install our SDK, open your terminal and run:
npm i @guildxyz/sdk
Importing the package and creating a Guild client
import { createGuildClient, createSigner } from "@guildxyz/sdk";
// The only parameter is the name of your project
const guildClient = createGuildClient("My project");
SignerFunctions and Authentication
Creating a signer from an ethers wallet
import { ethers } from "ethers";
const ethersWallet = new ethers.Wallet(...);
const signerFunction = createSigner.fromEthersWallet(ethersWallet);
Creating a custom signer for usage with web3-react
import { useWeb3React } from "@web3-react/core";
const { account: walletAddress, library } = useWeb3React();
const signerFunction = createSigner.custom(
(message) => library.getSigner(account).signMessage(signableMessage),
address
);
Creating a custom signer for usage with wagmi
import { useAccount, useSignMessage } from "wagmi";
const { signMessageAsync } = useSignMessage();
const { address } = useAccount();
const signerFunction = createSigner.custom(
(message) => signMessageAsync({ message }),
address
);
Support for EIP-1271 smart contract wallets
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
Clients
We have multiple clients for different entities. These clients are created from the guildClient
that we created above.
Guild client
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);
Guild reward client
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
);
Role client
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);
Requirement client
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
);
Role reward client
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);
User client
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);
User address client
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
);
User platform client
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);
Modular / multi-platform architecture
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
.
Examples
Example flow from Create Guild to Join
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);
Multiple telegram groups guild
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
);