Skip to content

https-github-com-okeamah/guild-sdk

 
 

Repository files navigation

Guild SDK for TypeScript | WIP


Application   •   Twitter   •   Github   •   Discord

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.

Demo app

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

Contents

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);
Points
// 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);

Guild admin client

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);

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 );

About

Typescript library for interacting with the Guild.xyz API

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 100.0%