From fd7ffa01418558c2034d4c9939d6a94999702fec Mon Sep 17 00:00:00 2001 From: cs-balazs <44908417+cs-balazs@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:05:53 +0100 Subject: [PATCH] [GUILD-2017] - Requirement types (#25) * test improvements * update @guildxyz/types * fix some tests * use randomly generated wallets * use proper update type * upgrade @guildxyz/types * 2.3.0 --- package-lock.json | 14 +- package.json | 4 +- src/clients/requirement.ts | 10 +- tests/callGuildAPI.test.ts | 2 +- tests/clients/actions/accessCheck.test.ts | 2 +- tests/clients/actions/join.test.ts | 2 +- tests/clients/guild.test.ts | 154 +++++-------------- tests/clients/guildAdmin.test.ts | 34 ++--- tests/clients/guildPlatform.test.ts | 90 +++++------ tests/clients/platform.test.ts | 2 +- tests/clients/platformUser.test.ts | 2 +- tests/clients/requirement.test.ts | 172 +++++++++++++--------- tests/clients/role.test.ts | 32 ++-- tests/clients/rolePlatform.test.ts | 132 ++++++++--------- tests/clients/user.test.ts | 73 +++++---- tests/clients/userAddress.test.ts | 52 +++---- tests/common.ts | 12 ++ tests/points.test.ts | 118 ++++++++------- tests/utils.ts | 40 +++++ 19 files changed, 464 insertions(+), 483 deletions(-) create mode 100644 tests/common.ts create mode 100644 tests/utils.ts diff --git a/package-lock.json b/package-lock.json index 0204e2d..4458529 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@guildxyz/sdk", - "version": "2.1.1", + "version": "2.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@guildxyz/sdk", - "version": "2.1.1", + "version": "2.3.0", "license": "MIT", "dependencies": { - "@guildxyz/types": "^1.3.2", + "@guildxyz/types": "^1.3.9", "ethers": "^6.7.1", "randombytes": "^2.1.0" }, @@ -130,11 +130,11 @@ } }, "node_modules/@guildxyz/types": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@guildxyz/types/-/types-1.3.2.tgz", - "integrity": "sha512-xGppntesdfgalDVqT7Mt0crMBobpSpTFx94/Q8x7lqiGSLv/U2BhISFJmI9iQ5JilmQxvsiSmTtx0783adIosQ==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@guildxyz/types/-/types-1.3.9.tgz", + "integrity": "sha512-7AfySX6RWSCzEkVoj+x0i7z705QwE77g7f7P7VL4fK2/yq3GgyzDX2Qr/xz1IdFPEr2b7gdozS+3oYhJwdFDjw==", "dependencies": { - "zod": "^3.22.2" + "zod": "^3.22.4" } }, "node_modules/@humanwhocodes/config-array": { diff --git a/package.json b/package.json index f43ddf0..ce89fcf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@guildxyz/sdk", - "version": "2.2.0", + "version": "2.3.0", "description": "SDK for Guild.xyz Public API ", "main": "./dist/index.js", "module": "./dist/index.mjs", @@ -43,7 +43,7 @@ "testWithPrivileged": "npx dotenv-cli -e .test.privileged.env -- npm run test" }, "dependencies": { - "@guildxyz/types": "^1.3.2", + "@guildxyz/types": "^1.3.9", "ethers": "^6.7.1", "randombytes": "^2.1.0" }, diff --git a/src/clients/requirement.ts b/src/clients/requirement.ts index dd4ddc9..1f0e8e4 100644 --- a/src/clients/requirement.ts +++ b/src/clients/requirement.ts @@ -1,4 +1,8 @@ -import { Requirement, Schemas } from "@guildxyz/types"; +import { + Requirement, + RequirementUpdatePayload, + Schemas, +} from "@guildxyz/types"; import { SignerFunction, callGuildAPI } from "../utils"; const requirement = { @@ -31,7 +35,7 @@ const requirement = { requirementCreationParams: Schemas["RequirementCreationPayload"], signer: SignerFunction ) => - callGuildAPI({ + callGuildAPI({ url: `/guilds/${guildIdOrUrlName}/roles/${roleId}/requirements`, method: "POST", body: { @@ -45,7 +49,7 @@ const requirement = { guildIdOrUrlName: string | number, roleId: number, requirementId: number, - requirementUpdateParams: Schemas["RequirementUpdatePayload"], + requirementUpdateParams: RequirementUpdatePayload, signer: SignerFunction ) => callGuildAPI({ diff --git a/tests/callGuildAPI.test.ts b/tests/callGuildAPI.test.ts index 8c01414..930b0ce 100644 --- a/tests/callGuildAPI.test.ts +++ b/tests/callGuildAPI.test.ts @@ -36,7 +36,7 @@ describe.concurrent("callGuildAPI", () => { method: "POST", body: { schema: "RequirementCreationPayloadSchema", - data: { type: "ALLOWLIST" }, + data: { type: "ALLOWLIST", data: { addresses: [] } }, }, signer, }); diff --git a/tests/clients/actions/accessCheck.test.ts b/tests/clients/actions/accessCheck.test.ts index 3246d01..8110587 100644 --- a/tests/clients/actions/accessCheck.test.ts +++ b/tests/clients/actions/accessCheck.test.ts @@ -9,7 +9,7 @@ const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( const { guild } = createGuildClient("vitest"); -describe("Access check action", () => { +describe.skip("Access check action", () => { it("can check access", async () => { // const onPoll = vi.fn(); diff --git a/tests/clients/actions/join.test.ts b/tests/clients/actions/join.test.ts index fe8f14a..0046e27 100644 --- a/tests/clients/actions/join.test.ts +++ b/tests/clients/actions/join.test.ts @@ -9,7 +9,7 @@ const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( const { guild } = createGuildClient("vitest"); -describe("Join action", () => { +describe.skip("Join action", () => { it("can join", async () => { // const onPoll = vi.fn(); const result = await guild.join( diff --git a/tests/clients/guild.test.ts b/tests/clients/guild.test.ts index ec79539..2f284d0 100644 --- a/tests/clients/guild.test.ts +++ b/tests/clients/guild.test.ts @@ -1,140 +1,64 @@ -import { Guild } from "@guildxyz/types"; -import { Wallet } from "ethers"; import { assert, describe, expect, it } from "vitest"; -import { createGuildClient } from "../../src"; import { GuildSDKValidationError } from "../../src/error"; -import { createSigner } from "../../src/utils"; +import { CLIENT, TEST_SIGNER, TEST_USER } from "../common"; +import { createTestGuild, pick } from "../utils"; -// TODO Create test guilds for these instead of using data like our-guild +const createdGuild = await createTestGuild(); +const createdGuild2 = await createTestGuild(); -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); - -const { guild } = createGuildClient("vitest"); - -describe.concurrent("Guild client", () => { +describe("Guild client", () => { it("Can get a guild by id", async () => { - const response = await guild.get(1985); + const response = await CLIENT.guild.get(createdGuild.id); - expect(response).toMatchObject({ - urlName: "our-guild", - name: "Our Guild", - } satisfies Partial); + expect(response).toMatchObject(pick(createdGuild, ["id", "urlName"])); }); it("Can get multiple guilds by ids", async () => { - const response = await guild.getMany([1985, 20111]); - - expect(response).toMatchObject([ - { - urlName: "our-guild", - name: "Our Guild", - } satisfies Partial, - { - urlName: "buildonbase", - name: "Base Guild", - } satisfies Partial, + const response = await CLIENT.guild.getMany([ + createdGuild.id, + createdGuild2.id, ]); - }); - it("Can get multiple guilds with pagination", async () => { - const [ - [firstGuild, , , , fifthGuild], - [fifthGuildWithPagination], - [firstGuildWithPagination], - ] = await Promise.all([ - guild.search({ limit: 5, offset: 0 }), - guild.search({ - limit: 1, - offset: 4, - }), - guild.search({ - limit: 1, - offset: 0, - }), + expect(response).toMatchObject([ + pick(createdGuild, ["id", "urlName"]), + pick(createdGuild2, ["id", "urlName"]), ]); - - expect(fifthGuildWithPagination.id).toEqual(fifthGuild.id); - expect(firstGuildWithPagination.id).toEqual(firstGuild.id); }); it("Can get guild members", async () => { - const numberOfPublicRoles = await guild.role - .getAll(1985) - .then((res) => res.length); + const response = await CLIENT.guild.getMembers(createdGuild.id); - const response = await guild.getMembers(1985); - - expect(response).toHaveLength(numberOfPublicRoles); + expect(response).toHaveLength(1); }); it("Can get user membership for guild", async () => { - const numberOfPublicRoles = await guild.role - .getAll(1985) - .then((res) => res.length); - - const response = await guild.getUserMemberships(1985, 4226297); + const response = await CLIENT.guild.getUserMemberships( + createdGuild.id, + TEST_USER.id + ); - expect(response).toHaveLength(numberOfPublicRoles); + expect(response).toHaveLength(1); }); - describe("guild create - update - delete", () => { - let createdGuildId: number; - - it("Can create guild", async () => { - const response = await guild.create( - { - name: "SDK Test Guild", - urlName: "sdk-test-guild", - roles: [ - { - name: "SDK Test Role", - requirements: [{ type: "FREE" }], - }, - ], - }, - TEST_WALLET_SIGNER - ); - - createdGuildId = response.id; - - expect(response).toMatchObject({ - name: "SDK Test Guild", - roles: [ - { - name: "SDK Test Role", - requirements: [{ type: "FREE" }], - }, - ], - }); - expect(response.urlName.startsWith("sdk-test-guild")).toBeTruthy(); - }); - - it("Can update guild", async () => { - try { - await guild.update(createdGuildId, {}, TEST_WALLET_SIGNER); - assert(false); - } catch (error) { - expect(error).toBeInstanceOf(GuildSDKValidationError); - } - - const updated = await guild.update( - createdGuildId, - { description: "EDITED" }, - TEST_WALLET_SIGNER - ); - - expect(updated.description).toMatchObject("EDITED"); - }); - - it("Subsequent GET returns updated data", async () => { - const fetchedGuild = await guild.get(createdGuildId); - expect(fetchedGuild.description).toEqual("EDITED"); - }); + it("Can update guild", async () => { + try { + await CLIENT.guild.update(createdGuild.id, {}, TEST_SIGNER); + assert(false); + } catch (error) { + expect(error).toBeInstanceOf(GuildSDKValidationError); + } + + const updated = await CLIENT.guild.update( + createdGuild.id, + { description: "EDITED" }, + TEST_SIGNER + ); + + expect(updated.description).toMatchObject("EDITED"); + }); - it("Can delete guild", async () => { - await guild.delete(createdGuildId, TEST_WALLET_SIGNER); - }); + it("Subsequent GET returns updated data", async () => { + const fetchedGuild = await CLIENT.guild.get(createdGuild.id); + expect(fetchedGuild.description).toEqual("EDITED"); }); }); diff --git a/tests/clients/guildAdmin.test.ts b/tests/clients/guildAdmin.test.ts index b810b2b..9fd5563 100644 --- a/tests/clients/guildAdmin.test.ts +++ b/tests/clients/guildAdmin.test.ts @@ -1,36 +1,34 @@ import { Wallet } from "ethers"; import { describe, expect, it } from "vitest"; -import { GuildAPICallFailed, createGuildClient, createSigner } from "../../src"; +import { GuildAPICallFailed } from "../../src"; +import { CLIENT, TEST_SIGNER, TEST_USER } from "../common"; +import { createTestGuild } from "../utils"; -const client = createGuildClient("vitest"); - -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); -const GUILD_ID = "sdk-test-guild-62011a"; const adminAddress = Wallet.createRandom().address.toLowerCase(); +const guild = await createTestGuild(); + describe("Guild admins", () => { it("get all", async () => { - const admins = await client.guild.admin.getAll(1985); + const admins = await CLIENT.guild.admin.getAll(guild.id); expect(admins.length).toBeGreaterThan(0); }); it("get", async () => { - const admin = await client.guild.admin.get(1985, 45); - expect(admin).toMatchObject({ userId: 45 }); + const admin = await CLIENT.guild.admin.get(guild.id, TEST_USER.id); + expect(admin).toMatchObject({ userId: TEST_USER.id }); }); let adminUserId: number; it("create", async () => { - const newAdmin = await client.guild.admin.create( - GUILD_ID, + const newAdmin = await CLIENT.guild.admin.create( + guild.id, { address: adminAddress, isOwner: false, }, - TEST_WALLET_SIGNER + TEST_SIGNER ); adminUserId = newAdmin.userId; @@ -39,22 +37,22 @@ describe("Guild admins", () => { }); it("get created admin", async () => { - const admin = await client.guild.admin.get(GUILD_ID, adminUserId); + const admin = await CLIENT.guild.admin.get(guild.id, adminUserId); expect(admin).toMatchObject({ userId: adminUserId, isOwner: false }); }); it("delete", async () => { - await client.guild.admin.delete( - GUILD_ID, + await CLIENT.guild.admin.delete( + guild.id, adminUserId, - TEST_WALLET_SIGNER + TEST_SIGNER ); }); it("can't get created admin", async () => { try { - await client.guild.admin.get(GUILD_ID, adminUserId); + await CLIENT.guild.admin.get(guild.id, adminUserId); } catch (error) { expect(error).toBeInstanceOf(GuildAPICallFailed); expect(error.statusCode).toEqual(404); diff --git a/tests/clients/guildPlatform.test.ts b/tests/clients/guildPlatform.test.ts index 1080bc5..2598fd6 100644 --- a/tests/clients/guildPlatform.test.ts +++ b/tests/clients/guildPlatform.test.ts @@ -1,89 +1,89 @@ -import { Wallet } from "ethers"; +import { GuildReward } from "@guildxyz/types"; import { describe } from "node:test"; import { assert, expect, it } from "vitest"; -import { createGuildClient } from "../../src"; import { GuildAPICallFailed } from "../../src/error"; -import { createSigner } from "../../src/utils"; +import { CLIENT, TEST_SIGNER } from "../common"; +import { createTestGuild, omit } from "../utils"; -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); -const GUILD_ID = "sdk-test-guild-62011a"; -const PLATFORM_GUILD_ID = "TEST_PLATFORM_GUILD_ID"; +const guildPlatformToCreate = { + platformGuildId: "my-point-system", + platformName: "POINTS", + platformGuildData: { name: "xp" }, +} as const; -let createdGuildPlatformId: number; +const guildPlatformUpdate = { + platformGuildData: { name: "coins" }, +} as const; -const { guild } = createGuildClient("vitest"); +let createdGuildPlatform: GuildReward; + +const guild = await createTestGuild(); describe("guildPlatform client", () => { it("Can create guildPlatform", async () => { - const created = await guild.reward.create( - GUILD_ID, - { - platformGuildId: PLATFORM_GUILD_ID, - platformName: "TELEGRAM", - }, - TEST_WALLET_SIGNER + createdGuildPlatform = await CLIENT.guild.reward.create( + guild.id, + guildPlatformToCreate, + TEST_SIGNER ); - createdGuildPlatformId = created.id; - - expect(created).toMatchObject({ - platformGuildId: PLATFORM_GUILD_ID, - }); + expect(createdGuildPlatform).toMatchObject( + omit(guildPlatformToCreate, ["platformName"]) + ); }); it("Can update guildPlatform", async () => { - const updated = await guild.reward.update( - GUILD_ID, - createdGuildPlatformId, - { platformGuildData: { invite: "testInvite" } }, - TEST_WALLET_SIGNER + const updated = await CLIENT.guild.reward.update( + guild.id, + createdGuildPlatform.id, + guildPlatformUpdate, + TEST_SIGNER ); expect(updated).toMatchObject({ - platformGuildId: PLATFORM_GUILD_ID, - platformGuildData: { invite: "testInvite" }, + ...omit(guildPlatformToCreate, ["platformName"]), + ...guildPlatformUpdate, }); }); it("Can fetch updated guildPlatform", async () => { - const fetched = await guild.reward.get( - GUILD_ID, - createdGuildPlatformId, - TEST_WALLET_SIGNER + const fetched = await CLIENT.guild.reward.get( + guild.id, + createdGuildPlatform.id, + TEST_SIGNER ); expect(fetched).toMatchObject({ - platformGuildId: PLATFORM_GUILD_ID, - platformGuildData: { invite: "testInvite" }, + ...omit(guildPlatformToCreate, ["platformName"]), + ...guildPlatformUpdate, }); }); it("Can fetch updated guildPlatform by guildId", async () => { - const fetched = await guild.reward.getAll(GUILD_ID, TEST_WALLET_SIGNER); + const fetched = await CLIENT.guild.reward.getAll(guild.id, TEST_SIGNER); expect( fetched.some( - ({ platformGuildData }) => platformGuildData.invite === "testInvite" + ({ platformGuildData }) => + platformGuildData.name === guildPlatformUpdate.platformGuildData.name ) ).toBeTruthy(); }); it("Can delete guildPlatform", async () => { - await guild.reward.delete( - GUILD_ID, - createdGuildPlatformId, - TEST_WALLET_SIGNER + await CLIENT.guild.reward.delete( + guild.id, + createdGuildPlatform.id, + TEST_SIGNER ); }); it("Returns 404 after delete", async () => { try { - await guild.reward.get( - GUILD_ID, - createdGuildPlatformId, - TEST_WALLET_SIGNER + await CLIENT.guild.reward.get( + guild.id, + createdGuildPlatform.id, + TEST_SIGNER ); assert(false); } catch (error) { diff --git a/tests/clients/platform.test.ts b/tests/clients/platform.test.ts index eea6878..7e14afb 100644 --- a/tests/clients/platform.test.ts +++ b/tests/clients/platform.test.ts @@ -5,7 +5,7 @@ const OUR_GUILD_DC_SERVER_ID = "886314998131982336"; const { platform } = createGuildClient("vitest"); -describe("platform client", () => { +describe.skip("platform client", () => { it("Can get guild by platform data", async () => { const ourGuild = await platform.getGuildByPlatform( "DISCORD", diff --git a/tests/clients/platformUser.test.ts b/tests/clients/platformUser.test.ts index 7b8f0de..8987879 100644 --- a/tests/clients/platformUser.test.ts +++ b/tests/clients/platformUser.test.ts @@ -10,7 +10,7 @@ const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( const { user } = createGuildClient("vitest"); -describe.concurrent("platformUser client", () => { +describe.skip.concurrent("platformUser client", () => { it("can get a platformUser", async () => { const result = await user.platform.get( TEST_WALLET_ADDRESS, diff --git a/tests/clients/requirement.test.ts b/tests/clients/requirement.test.ts index caaedab..9478b49 100644 --- a/tests/clients/requirement.test.ts +++ b/tests/clients/requirement.test.ts @@ -1,94 +1,120 @@ +import { Schemas } from "@guildxyz/types"; import { Wallet } from "ethers"; import { assert, describe, expect, it } from "vitest"; -import { createGuildClient } from "../../src"; -import { GuildAPICallFailed } from "../../src/error"; -import { createSigner } from "../../src/utils"; +import { GuildAPICallFailed, GuildSDKValidationError } from "../../src/error"; +import { CLIENT, TEST_SIGNER } from "../common"; +import { createTestGuild, omit } from "../utils"; -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); -const GUILD_ID = "sdk-test-guild-62011a"; -const ROLE_ID = 88123; -const PRE_EXISTING_REQUIREMENT_ID = 284075; +const ALLOWLIST_ADDRESS = Wallet.createRandom().address; -const { guild } = createGuildClient("vitest"); +const guild = await createTestGuild(); +let createdRequirement: Schemas["RequirementCreateResponse"]; + +describe("Requirement client", () => { + const requirementToCreate: Schemas["RequirementCreationPayload"] = { + type: "ALLOWLIST", + data: { addresses: [] }, + }; + + it("Can create requirement", async () => { + createdRequirement = await CLIENT.guild.role.requirement.create( + guild.id, + guild.roles[0].id, + requirementToCreate, + TEST_SIGNER + ); + + expect(createdRequirement).toMatchObject(requirementToCreate); + }); -describe.concurrent("Requirement client", () => { it("Can get a requirement", async () => { - const role = await guild.role.requirement.get( - GUILD_ID, - ROLE_ID, - PRE_EXISTING_REQUIREMENT_ID + const role = await CLIENT.guild.role.requirement.get( + guild.id, + guild.roles[0].id, + createdRequirement.id + ); + expect(role).toMatchObject( + omit(createdRequirement, ["deletedRequirements"]) ); - expect(role.type).toEqual("ALLOWLIST"); }); - it("Can get requirements of role", async () => { - const roles = await guild.role.requirement.getAll(GUILD_ID, ROLE_ID); + it("Can get all requirements of role", async () => { + const roles = await CLIENT.guild.role.requirement.getAll( + guild.id, + guild.roles[0].id + ); - expect(roles).toMatchObject([{ type: "ALLOWLIST" }]); + expect(roles).toMatchObject([ + omit(createdRequirement, ["deletedRequirements"]), + ]); }); - describe("requirement create - update - delete", () => { - let createdRequirementId: number; + it("Can update requirement", async () => { + const created = await CLIENT.guild.role.requirement.update( + guild.id, + guild.roles[0].id, + createdRequirement.id, + { data: { addresses: [ALLOWLIST_ADDRESS] } }, + TEST_SIGNER + ); + expect(created.data.addresses).toEqual([ALLOWLIST_ADDRESS.toLowerCase()]); + }); - it("Can create requirement", async () => { - const created = await guild.role.requirement.create( - GUILD_ID, - ROLE_ID, - { type: "ALLOWLIST", data: { addresses: [] } }, - TEST_WALLET_SIGNER + it("Can't change requirement type", async () => { + try { + await CLIENT.guild.role.requirement.update( + guild.id, + guild.roles[0].id, + createdRequirement.id, + { type: "FREE" } as any, + TEST_SIGNER ); + assert(false); + } catch (error) { + expect(error).toBeInstanceOf(GuildSDKValidationError); + } + }); - createdRequirementId = created.id; - expect(created).toMatchObject({ - type: "ALLOWLIST", - data: { addresses: [] }, - isNegated: false, - }); - }); + it("Returns edited requirement", async () => { + const role = await CLIENT.guild.role.requirement.get( + guild.id, + guild.roles[0].id, + createdRequirement.id + ); - it("Can update requirement", async () => { - const created = await guild.role.requirement.update( - GUILD_ID, - ROLE_ID, - createdRequirementId, - { isNegated: true }, - TEST_WALLET_SIGNER - ); - expect(created.isNegated).toEqual(true); - }); + expect(role.data.addresses).toEqual([ALLOWLIST_ADDRESS.toLowerCase()]); + }); - it("Returns edited requirement", async () => { - const role = await guild.role.requirement.get( - GUILD_ID, - ROLE_ID, - createdRequirementId - ); - expect(role.isNegated).toEqual(true); - }); + // This is needed, so we can test deletion + it("Create one more requirement", async () => { + await CLIENT.guild.role.requirement.create( + guild.id, + guild.roles[0].id, + { type: "ALLOWLIST", data: { addresses: [] } }, + TEST_SIGNER + ); + }); - it("Can delete requirement", async () => { - await guild.role.requirement.delete( - GUILD_ID, - ROLE_ID, - createdRequirementId, - TEST_WALLET_SIGNER - ); - }); + it("Can delete requirement", async () => { + await CLIENT.guild.role.requirement.delete( + guild.id, + guild.roles[0].id, + createdRequirement.id, + TEST_SIGNER + ); + }); - it("Doesn't return after delete", async () => { - try { - await guild.role.requirement.get( - GUILD_ID, - ROLE_ID, - createdRequirementId - ); - assert(false); - } catch (error) { - expect(error).toBeInstanceOf(GuildAPICallFailed); - expect(error.statusCode).toEqual(404); - } - }); + it("Doesn't return after delete", async () => { + try { + await CLIENT.guild.role.requirement.get( + guild.id, + guild.roles[0].id, + createdRequirement.id + ); + assert(false); + } catch (error) { + expect(error).toBeInstanceOf(GuildAPICallFailed); + expect(error.statusCode).toEqual(404); + } }); }); diff --git a/tests/clients/role.test.ts b/tests/clients/role.test.ts index 1b58e64..895637c 100644 --- a/tests/clients/role.test.ts +++ b/tests/clients/role.test.ts @@ -1,24 +1,18 @@ -import { Wallet } from "ethers"; import { assert, describe, expect, it } from "vitest"; -import { createGuildClient } from "../../src"; import { GuildAPICallFailed } from "../../src/error"; -import { createSigner } from "../../src/utils"; +import { CLIENT, TEST_SIGNER } from "../common"; +import { createTestGuild } from "../utils"; -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); -const GUILD_ID = "sdk-test-guild-62011a"; - -const { guild } = createGuildClient("vitest"); +const guild = await createTestGuild(); describe("role create - update - delete", () => { let createdRoleId: number; it("Can create role", async () => { - const created = await guild.role.create( - GUILD_ID, + const created = await CLIENT.guild.role.create( + guild.id, { name: "SDK Role Creation test", requirements: [{ type: "FREE" }] }, - TEST_WALLET_SIGNER + TEST_SIGNER ); createdRoleId = created.id; @@ -29,32 +23,32 @@ describe("role create - update - delete", () => { }); it("Can get created role", async () => { - const role = await guild.role.get(GUILD_ID, createdRoleId); + const role = await CLIENT.guild.role.get(guild.id, createdRoleId); expect(role.name).toEqual("SDK Role Creation test"); }); it("Can update role", async () => { - const created = await guild.role.update( - GUILD_ID, + const created = await CLIENT.guild.role.update( + guild.id, createdRoleId, { description: "EDITED" }, - TEST_WALLET_SIGNER + TEST_SIGNER ); expect(created.description).toEqual("EDITED"); }); it("Returns edited role", async () => { - const role = await guild.role.get(GUILD_ID, createdRoleId); + const role = await CLIENT.guild.role.get(guild.id, createdRoleId); expect(role.description).toEqual("EDITED"); }); it("Can delete role", async () => { - await guild.role.delete(GUILD_ID, createdRoleId, TEST_WALLET_SIGNER); + await CLIENT.guild.role.delete(guild.id, createdRoleId, TEST_SIGNER); }); it("Doesn't return after delete", async () => { try { - await guild.role.get(GUILD_ID, createdRoleId); + await CLIENT.guild.role.get(guild.id, createdRoleId); assert(false); } catch (error) { expect(error).toBeInstanceOf(GuildAPICallFailed); diff --git a/tests/clients/rolePlatform.test.ts b/tests/clients/rolePlatform.test.ts index 296d8df..3d71bde 100644 --- a/tests/clients/rolePlatform.test.ts +++ b/tests/clients/rolePlatform.test.ts @@ -1,108 +1,98 @@ -import { Wallet } from "ethers"; -import { afterAll, assert, beforeAll, describe, expect, it } from "vitest"; -import { createGuildClient } from "../../src"; +import { GuildReward, RoleReward } from "@guildxyz/types"; +import { randomBytes } from "crypto"; +import { assert, describe, expect, it } from "vitest"; import { GuildAPICallFailed } from "../../src/error"; -import { createSigner } from "../../src/utils"; +import { CLIENT, TEST_SIGNER } from "../common"; +import { createTestGuild } from "../utils"; -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); -const GUILD_ID = "sdk-test-guild-62011a"; -const ROLE_ID = 88123; +const guild = await createTestGuild(); -let guildPlatformId: number; -let createdRolePlatformId: number; +const guildPlatformToCreate = { + platformGuildId: `my-point-system-${randomBytes(4).toString("hex")}`, + platformName: "POINTS", + platformGuildData: { name: "xp" }, +} as const; -const { guild } = createGuildClient("vitest"); +let createdGuildPlatform: GuildReward; +let createdRolePlatform: RoleReward; -beforeAll(async () => { - const guildPlatforms = await guild.reward.getAll( - GUILD_ID, - TEST_WALLET_SIGNER - ); - - const tgPlatform = guildPlatforms.find(({ platformId }) => platformId === 2); - - if (tgPlatform) { - guildPlatformId = tgPlatform.id; - return; - } - - const created = await guild.reward.create( - GUILD_ID, - { - platformGuildId: "FOR_ROLE_PLATFORM_TEST", - platformName: "TELEGRAM", - }, - TEST_WALLET_SIGNER - ); - - guildPlatformId = created.id; -}); +describe("rolePlatform client", () => { + it("Can create guildPlatform", async () => { + createdGuildPlatform = await CLIENT.guild.reward.create( + guild.id, + guildPlatformToCreate, + TEST_SIGNER + ); -afterAll(async () => { - await guild.reward.delete(GUILD_ID, guildPlatformId, TEST_WALLET_SIGNER); -}); + expect(createdGuildPlatform.platformGuildId).toEqual( + guildPlatformToCreate.platformGuildId + ); + }); -describe("rolePlatform client", () => { it("Can create rolePlatform", async () => { - const created = await guild.role.reward.create( - GUILD_ID, - ROLE_ID, + createdRolePlatform = await CLIENT.guild.role.reward.create( + guild.id, + guild.roles[0].id, { - guildPlatformId, - visibility: "HIDDEN", + guildPlatformId: createdGuildPlatform.id, + platformRoleData: { score: "5" }, }, - TEST_WALLET_SIGNER + TEST_SIGNER ); - createdRolePlatformId = created.id; - - expect(created.visibility).toEqual("HIDDEN"); + expect(createdRolePlatform).toMatchObject({ + guildPlatformId: createdGuildPlatform.id, + platformRoleData: { score: "5" }, + }); }); it("Can update rolePlatform", async () => { - const created = await guild.role.reward.update( - GUILD_ID, - ROLE_ID, - createdRolePlatformId, - { - visibility: "PUBLIC", - }, - TEST_WALLET_SIGNER + const updated = await CLIENT.guild.role.reward.update( + guild.id, + guild.roles[0].id, + createdRolePlatform.id, + { platformRoleData: { score: "15" } }, + TEST_SIGNER ); - expect(created.visibility).toEqual("PUBLIC"); + expect(updated.platformRoleData!.score).toEqual("15"); }); it("Returns updated data", async () => { - const created = await guild.role.reward.get( - GUILD_ID, - ROLE_ID, - createdRolePlatformId + const created = await CLIENT.guild.role.reward.get( + guild.id, + guild.roles[0].id, + createdRolePlatform.id ); - expect(created.visibility).toEqual("PUBLIC"); + expect(created.platformRoleData!.score).toEqual("15"); }); it("Returns updated data by role", async () => { - const created = await guild.role.reward.getAll(GUILD_ID, ROLE_ID); + const created = await CLIENT.guild.role.reward.getAll( + guild.id, + guild.roles[0].id + ); - expect(created).toMatchObject([{ visibility: "PUBLIC" }]); + expect(created).toMatchObject([{ platformRoleData: { score: "15" } }]); }); it("Can delete rolePlatform", async () => { - await guild.role.reward.delete( - GUILD_ID, - ROLE_ID, - createdRolePlatformId, - TEST_WALLET_SIGNER + await CLIENT.guild.role.reward.delete( + guild.id, + guild.roles[0].id, + createdRolePlatform.id, + TEST_SIGNER ); }); it("404 after delete", async () => { try { - await guild.role.reward.get(GUILD_ID, ROLE_ID, createdRolePlatformId); + await CLIENT.guild.role.reward.get( + guild.id, + guild.roles[0].id, + createdRolePlatform.id + ); assert(false); } catch (error) { expect(error).toBeInstanceOf(GuildAPICallFailed); diff --git a/tests/clients/user.test.ts b/tests/clients/user.test.ts index cc38cfd..3a221cd 100644 --- a/tests/clients/user.test.ts +++ b/tests/clients/user.test.ts @@ -1,62 +1,61 @@ import { randomBytes } from "crypto"; import { Wallet } from "ethers"; -import { describe, expect, it } from "vitest"; -import { createGuildClient } from "../../src"; +import { assert, describe, expect, it } from "vitest"; +import { GuildAPICallFailed } from "../../src"; import { createSigner } from "../../src/utils"; +import { CLIENT } from "../common"; + +const NEW_WALLET = new Wallet(randomBytes(32).toString("hex")); +const NEW_ADDRESS = NEW_WALLET.address.toLowerCase(); +const NEW_SIGNER = createSigner.fromEthersWallet(NEW_WALLET); + +describe("User client", () => { + it("user initially doesn't exist", async () => { + try { + await CLIENT.user.get(NEW_ADDRESS); + assert(false); + } catch (error) { + expect(error).toBeInstanceOf(GuildAPICallFailed); + expect((error as GuildAPICallFailed).statusCode).toEqual(404); + } + }); -const { user } = createGuildClient("vitest"); - -const TEST_WALLET_ADDRESS = new Wallet(process.env.PRIVATE_KEY!).address; -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); + it("created user with a signed request", async () => { + const profile = await CLIENT.user.getProfile(NEW_ADDRESS, NEW_SIGNER); -const WALLET_OF_CREATED_USER = new Wallet(randomBytes(32).toString("hex")); -const SIGNER_OF_CREATED_USER = createSigner.fromEthersWallet( - WALLET_OF_CREATED_USER -); + expect(profile.addresses).toMatchObject([{ address: NEW_ADDRESS }]); + }); -describe.concurrent("User client", () => { - it("Can fetch user", async () => { - const fetchedUser = await user.get(TEST_WALLET_ADDRESS); + it("can fetch user", async () => { + const fetchedUser = await CLIENT.user.get(NEW_ADDRESS); expect(fetchedUser.id).toBeGreaterThan(0); }); - it("Can fetch user public user profile", async () => { - const fetchedUserProfile = await user.getProfile(TEST_WALLET_ADDRESS); + it("can fetch user public user profile", async () => { + const fetchedUserProfile = await CLIENT.user.getProfile(NEW_ADDRESS); expect(fetchedUserProfile.id).toBeGreaterThan(0); - expect("publicKey" in fetchedUserProfile).toBeTruthy(); }); it("Can fetch user private user profile", async () => { - const fetchedUserProfile = await user.getProfile( - TEST_WALLET_ADDRESS, - TEST_WALLET_SIGNER + const fetchedUserProfile = await CLIENT.user.getProfile( + NEW_ADDRESS, + NEW_SIGNER ); expect(fetchedUserProfile.id).toBeGreaterThan(0); - expect(fetchedUserProfile.addresses).toHaveLength(1); - expect("publicKey" in fetchedUserProfile).toBeTruthy(); + expect(fetchedUserProfile.addresses).toMatchObject([ + { address: NEW_ADDRESS }, + ]); }); it("Can fetch memberships", async () => { - const memberships = await user.getMemberships(TEST_WALLET_ADDRESS); - expect(memberships.length).toBeGreaterThan(0); + const memberships = await CLIENT.user.getMemberships(NEW_ADDRESS); + expect(memberships.length).toBe(0); }); - describe("user crete - delete", () => { - it("can create a user", async () => { - const profile = await user.getProfile( - WALLET_OF_CREATED_USER.address, - SIGNER_OF_CREATED_USER - ); - expect(profile.addresses.length).toBeGreaterThan(0); - }); - - it("can delete user", async () => { - await user.delete(WALLET_OF_CREATED_USER.address, SIGNER_OF_CREATED_USER); - }); + it("can delete user", async () => { + await CLIENT.user.delete(NEW_ADDRESS, NEW_SIGNER); }); }); diff --git a/tests/clients/userAddress.test.ts b/tests/clients/userAddress.test.ts index 513bc7a..44240a7 100644 --- a/tests/clients/userAddress.test.ts +++ b/tests/clients/userAddress.test.ts @@ -1,61 +1,47 @@ +import { randomBytes } from "crypto"; import { Wallet } from "ethers"; import { describe, expect, it } from "vitest"; -import { createGuildClient } from "../../src"; import { createSigner } from "../../src/utils"; +import { CLIENT, TEST_ADDRESS, TEST_SIGNER } from "../common"; -const { user } = createGuildClient("vitest"); - -const TEST_WALLET_ADDRESS = new Wallet(process.env.PRIVATE_KEY!).address; -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY!) -); - -const ADDRESS_TO_LINK = new Wallet( - process.env.PRIVATE_KEY_FOR_ADDRESS_LINK! -).address.toLowerCase(); - -const WALLET_TO_LINK_SIGNER = createSigner.fromEthersWallet( - new Wallet(process.env.PRIVATE_KEY_FOR_ADDRESS_LINK!) -); +const NEW_WALLET = new Wallet(randomBytes(32).toString("hex")); +const NEW_ADDRESS = NEW_WALLET.address.toLowerCase(); +const NEW_SIGNER = createSigner.fromEthersWallet(NEW_WALLET); describe("userAddress client", () => { it("Can create userAddress", async () => { - const created = await user.address.create( - TEST_WALLET_ADDRESS, - WALLET_TO_LINK_SIGNER, - TEST_WALLET_SIGNER + const created = await CLIENT.user.address.create( + TEST_ADDRESS, + NEW_SIGNER, + TEST_SIGNER ); expect(created).toMatchObject({ - address: ADDRESS_TO_LINK, + address: NEW_ADDRESS, isPrimary: false, }); }); it("Can get linked address", async () => { - const address = await user.address.get( - TEST_WALLET_ADDRESS, - ADDRESS_TO_LINK, - TEST_WALLET_SIGNER + const address = await CLIENT.user.address.get( + TEST_ADDRESS, + NEW_ADDRESS, + TEST_SIGNER ); - expect(address.address).toEqual(ADDRESS_TO_LINK); + expect(address.address).toEqual(NEW_ADDRESS); }); it("Can get linked addresses", async () => { - const addresses = await user.address.getAll( - TEST_WALLET_ADDRESS, - TEST_WALLET_SIGNER + const addresses = await CLIENT.user.address.getAll( + TEST_ADDRESS, + TEST_SIGNER ); expect(addresses.length).toEqual(2); }); it("Can delete userAddress", async () => { - await user.address.delete( - TEST_WALLET_ADDRESS, - ADDRESS_TO_LINK, - TEST_WALLET_SIGNER - ); + await CLIENT.user.address.delete(TEST_ADDRESS, NEW_ADDRESS, TEST_SIGNER); }); }); diff --git a/tests/common.ts b/tests/common.ts new file mode 100644 index 0000000..3b463c2 --- /dev/null +++ b/tests/common.ts @@ -0,0 +1,12 @@ +import { randomBytes } from "crypto"; +import { Wallet } from "ethers"; +import { createGuildClient, createSigner } from "../src"; + +export const CLIENT = createGuildClient("vitest"); +export const TEST_WALLET = new Wallet(randomBytes(32).toString("hex")); +export const TEST_ADDRESS = TEST_WALLET.address.toLowerCase(); +export const TEST_SIGNER = createSigner.fromEthersWallet(TEST_WALLET); +export const TEST_USER = await CLIENT.user.getProfile( + TEST_ADDRESS, + TEST_SIGNER +); diff --git a/tests/points.test.ts b/tests/points.test.ts index f1d88d6..6be7b21 100644 --- a/tests/points.test.ts +++ b/tests/points.test.ts @@ -1,69 +1,77 @@ -import { LeaderboardItem, RoleReward, UserPointsItem } from "@guildxyz/types"; -import { Wallet } from "ethers"; -import { describe, expect, test } from "vitest"; -import { createGuildClient, createSigner } from "../src"; +import { + LeaderboardItem, + RoleCreationResponse, + RoleReward, + UserPointsItem, +} from "@guildxyz/types"; +import { describe, expect, it, test } from "vitest"; +import { CLIENT, TEST_ADDRESS, TEST_SIGNER, TEST_USER } from "./common"; +import { createTestGuild } from "./utils"; + +const guild = await createTestGuild(); +const role1 = guild.roles[0]; + +let createdRolePlatform: RoleReward; +let role2: RoleCreationResponse; -const TEST_WALLET = new Wallet(process.env.PRIVATE_KEY!); -const TEST_WALLET_SIGNER = createSigner.fromEthersWallet(TEST_WALLET); -const TEST_USER_ID = 4069666; - -// https://guild.xyz/guild-for-sdk-points-test -const TEST_GUILD_DATA = { - urlName: "guild-for-sdk-points-test", - guildId: 58167, - roleId1: 98849, - roleId2: 98850, -}; +describe("points", () => { + it("created second role", async () => { + role2 = await CLIENT.guild.role.create( + guild.id, + { + name: "Role 2", + requirements: [{ type: "FREE" }], + }, + TEST_SIGNER + ); -const { guild, user } = createGuildClient("vitest"); + expect(role2.id).toBeGreaterThan(0); + }); -describe("points", () => { test("initially has no guildPlatform", async () => { - const guildPlatforms = await guild.reward.getAll( - TEST_GUILD_DATA.guildId, - TEST_WALLET_SIGNER + const guildPlatforms = await CLIENT.guild.reward.getAll( + guild.id, + TEST_SIGNER ); expect(guildPlatforms).toHaveLength(0); }); - let createdRolePlatform: RoleReward; - test("can create a points reward", async () => { - createdRolePlatform = await guild.role.reward.create( - TEST_GUILD_DATA.guildId, - TEST_GUILD_DATA.roleId1, + createdRolePlatform = await CLIENT.guild.role.reward.create( + guild.id, + role1.id, { guildPlatform: { platformGuildId: "my-points", platformName: "POINTS", platformGuildData: { name: "coins" }, }, - platformRoleData: { score: 5 }, + platformRoleData: { score: "5" }, }, - TEST_WALLET_SIGNER + TEST_SIGNER ); expect(createdRolePlatform.platformRoleData).toEqual({ score: "5" }); }); test("can create a points reward for other role", async () => { - createdRolePlatform = await guild.role.reward.create( - TEST_GUILD_DATA.guildId, - TEST_GUILD_DATA.roleId2, + createdRolePlatform = await CLIENT.guild.role.reward.create( + guild.id, + role2.id, { guildPlatformId: createdRolePlatform.guildPlatformId, - platformRoleData: { score: 10 }, + platformRoleData: { score: "10" }, }, - TEST_WALLET_SIGNER + TEST_SIGNER ); expect(createdRolePlatform.platformRoleData).toEqual({ score: "10" }); }); test("get leaderboard - not signed", async () => { - const { leaderboard, aroundUser } = await guild.getLeaderboard( - TEST_GUILD_DATA.guildId, + const { leaderboard, aroundUser } = await CLIENT.guild.getLeaderboard( + guild.id, createdRolePlatform.guildPlatformId ); @@ -71,18 +79,18 @@ describe("points", () => { expect(aroundUser).toBeFalsy(); expect(leaderboard).toHaveLength(1); expect(leaderboard[0]).toMatchObject({ - roleIds: [TEST_GUILD_DATA.roleId1, TEST_GUILD_DATA.roleId2], - userId: TEST_USER_ID, + roleIds: [role1.id, role2.id], + userId: TEST_USER.id, totalPoints: 15, // rank: 1, }); }); test("get leaderboard - signed", async () => { - const { leaderboard, aroundUser } = await guild.getLeaderboard( - TEST_GUILD_DATA.guildId, + const { leaderboard, aroundUser } = await CLIENT.guild.getLeaderboard( + guild.id, createdRolePlatform.guildPlatformId, - TEST_WALLET_SIGNER + TEST_SIGNER ); expect(leaderboard).toBeTruthy(); @@ -90,52 +98,52 @@ describe("points", () => { expect(aroundUser).toHaveLength(1); expect(leaderboard).toHaveLength(1); expect(leaderboard[0]).toMatchObject({ - roleIds: [TEST_GUILD_DATA.roleId1, TEST_GUILD_DATA.roleId2], - userId: TEST_USER_ID, + roleIds: [role1.id, role2.id], + userId: TEST_USER.id, totalPoints: 15, // rank: 1, }); expect(aroundUser![0]).toMatchObject({ - roleIds: [TEST_GUILD_DATA.roleId1, TEST_GUILD_DATA.roleId2], - userId: TEST_USER_ID, + roleIds: [role1.id, role2.id], + userId: TEST_USER.id, totalPoints: 15, // rank: 1, }); }); test("get user points", async () => { - const response = await user.getPoints(TEST_USER_ID, TEST_WALLET_SIGNER); + const response = await CLIENT.user.getPoints(TEST_USER.id, TEST_SIGNER); expect(response).toHaveLength(1); expect(response[0]).toEqual({ - guildId: TEST_GUILD_DATA.guildId, + guildId: guild.id, guildPlatformId: createdRolePlatform.guildPlatformId, - roleIds: [TEST_GUILD_DATA.roleId1, TEST_GUILD_DATA.roleId2], + roleIds: [role1.id, role2.id], totalPoints: 15, }); }); test("get user rank", async () => { - const response = await user.getRankInGuild( - TEST_USER_ID, - TEST_GUILD_DATA.guildId, + const response = await CLIENT.user.getRankInGuild( + TEST_USER.id, + guild.id, createdRolePlatform.guildPlatformId ); expect(response).toMatchObject({ - userId: TEST_USER_ID, - roleIds: [TEST_GUILD_DATA.roleId1, TEST_GUILD_DATA.roleId2], + userId: TEST_USER.id, + roleIds: [role1.id, role2.id], totalPoints: 15, rank: 1, - address: TEST_WALLET.address.toLowerCase(), + address: TEST_ADDRESS, }); }); test("can delete guildPlatform", async () => { - await guild.reward.delete( - TEST_GUILD_DATA.guildId, + await CLIENT.guild.reward.delete( + guild.id, createdRolePlatform.guildPlatformId, - TEST_WALLET_SIGNER + TEST_SIGNER ); }); }); diff --git a/tests/utils.ts b/tests/utils.ts new file mode 100644 index 0000000..6c0592a --- /dev/null +++ b/tests/utils.ts @@ -0,0 +1,40 @@ +import { randomBytes } from "crypto"; +import { afterAll } from "vitest"; +import { CLIENT, TEST_SIGNER } from "./common"; + +export function omit, K extends keyof T>( + obj: T, + keys: K[] +): Omit { + return Object.fromEntries( + Object.keys(obj) + .filter((key: keyof T) => !keys.includes(key as K)) + .map((key) => [key, obj[key]]) + ) as Omit; +} + +export function pick, K extends keyof T>( + obj: T, + keys: K[] +): Pick { + return Object.fromEntries(keys.map((key) => [key, obj[key]])) as Pick; +} + +export async function createTestGuild() { + const random = randomBytes(4).toString("hex"); + + const guild = await CLIENT.guild.create( + { + name: "SDK Test Guild", + urlName: `sdk-test-guild-${random}`, + roles: [{ name: "SDK Test Role", requirements: [{ type: "FREE" }] }], + }, + TEST_SIGNER + ); + + afterAll(async () => { + await CLIENT.guild.delete(guild.id, TEST_SIGNER); + }); + + return guild; +}