Skip to content

Commit

Permalink
example: custom point distribution (#28)
Browse files Browse the repository at this point in the history
* bump @guildxyz/types

* add example script

* fix tests
  • Loading branch information
cs-balazs authored Jul 23, 2024
1 parent c92f224 commit adca922
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 5 deletions.
28 changes: 28 additions & 0 deletions examples/custom-point-distribution/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Custom point distribution

This example script shows how you can distribute points on Guild based on custom data / logic

## Setup

- Install the dependencies: `npm i`
- Set the `PRIVATE_KEY` environment variable: `export PRIVATE_KEY=0x...`
- If you already have a Guild, in which you intend to create the point reward, the account of the private key has to be an admin in that Guild, so it has the necessary permissions to create and update the points

## Creating a Guild

This example app can create a Guild by executing `npx ts-node index.js create-guild`
It will print the Guild's URL, and the relevant ID-s for the point updates

It sets the following things in the Guild:

- Basic data (its name, urlName, ...)
- A role with a GUILD_SNAPSHOT requirement. This requirement will be the source of the point distribution
- A POINTS reward, which taks it's input from the requirement

## Editing the points

The script shows how you can edit the points by running `npx ts-node index.js edit {guildId} {roleId} {requirementId}`

The `snapshot` represents the point distribution. It maps addresses to point values

> When a snapshot is updated this way, the whole previous `data` field fill be overwritten, so you'll have to call this update with the whole list every time it changes
160 changes: 160 additions & 0 deletions examples/custom-point-distribution/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { createGuildClient, createSigner } from "@guildxyz/sdk";
import { randomBytes } from "crypto";
import { privateKeyToAccount } from "viem/accounts";

const YOUR_PROJECT_NAME = "snapshot-test-snippet";

const client = createGuildClient(YOUR_PROJECT_NAME);

if (!process.env.PRIVATE_KEY) {
throw new Error("Please set the PRIVATE_KEY env var");
}

// Load an account here (viem is just an example, any library works by implementing the singer function in createSigner.custom())
const viemAccount = privateKeyToAccount(
process.env.PRIVATE_KEY as `0x${string}`
);
// Pass a function which signs a message with the admin account, and the address of this account
const signer = createSigner.custom(
(message) => viemAccount.signMessage({ message }),
viemAccount.address
);

// If you don't have a guild yet, you can create one by calling this function
async function createGuildWithSnapshot() {
try {
const createdGuild = await client.guild.create(
{
name: "For snapshot testing",
urlName: "snapshot-testing",
contacts: [],
roles: [
{
name: "Test role",
requirements: [
{
type: "GUILD_SNAPSHOT",
data: {
snapshot: [
{
key: "0x0000000000000000000000000000000000000000",
value: 10,
},
],
},
},
],
},
],
},
signer
);

console.log("Guild created!");

const guildId = createdGuild.id;
const roleId = createdGuild.roles[0].id;
const requirementId = createdGuild.roles[0].requirements[0].id;

console.log(createdGuild.guildPlatforms);

// Created the reward on the guild
await client.guild.role.reward.create(
guildId,
roleId,
{
guildPlatform: {
platformName: "POINTS",
platformGuildId: `unique-name-${randomBytes(4).toString("hex")}`,
platformGuildData: {
name: "Tokens",
},
},
platformRoleData: { score: "0" },
dynamicAmount: {
operation: {
type: "LINEAR",
input: [
{
type: "REQUIREMENT_AMOUNT",
roleId,
requirementId,
},
],
},
},
},
signer
);
console.log(`https://guild.xyz/${createdGuild.urlName}`);
console.log(
`You can now edit the snapshot with:\nnpx ts-node index.ts edit ${guildId} ${roleId} ${requirementId}`
);
return createdGuild;
} catch (error) {
console.error(error);
throw error;
}
}

// This function edits an existing snapshot
async function editSnapshot(
guildId: number,
roleId: number,
requirementId: number
) {
try {
const editedRequirement = await client.guild.role.requirement.update(
guildId,
roleId,
requirementId,
{
data: {
// The provided snapshot overwrites the previous array
snapshot: [
{ key: "0x0000000000000000000000000000000000000000", value: 12 },
{ key: "0x0000000000000000000000000000000000000001", value: 10 },
],
},
},
signer
);
console.log("Snapshot edited!");
return editedRequirement;
} catch (error) {
console.error(error);
throw error;
}
}

/**
* Set the `PRIVATE_KEY` env var. It should be an admin in the snapshot's guild,
* so it has access to edit the snapshot
*
* Create a guild with `npx ts-node index.ts create-guild`
*
* Edit the snapshot with `npx ts-node index.ts edit {guildId} {roleId} {requirementId}`
*
* The three ID-s for editing can be retrieved by the
* https://api.guild.xyz/v2/guilds/guild-page/{urlName} endpoint.
* The creation command also outputs them for the freshly created guild
*
* If the guild is created externally, make sure that the `PRIVATE_KEY`'s account is
* added to the guild as an admin
*/
async function main() {
const [, , command, ...params] = process.argv;
switch (command) {
case "create-guild": {
await createGuildWithSnapshot();
break;
}
case "edit": {
const [guildIdStr, roleIdStr, requirementIdStr] = params;
await editSnapshot(+guildIdStr, +roleIdStr, +requirementIdStr);
break;
}
}
}

main();
16 changes: 16 additions & 0 deletions examples/custom-point-distribution/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "custom-point-distribution",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"author": "",
"license": "ISC",
"dependencies": {
"@guildxyz/sdk": "^2.5.0",
"viem": "^2.17.10"
},
"devDependencies": {
"ts-node": "^10.9.2"
}
}
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"testWithPrivileged": "npx dotenv-cli -e .test.privileged.env -- npm run test"
},
"dependencies": {
"@guildxyz/types": "^1.7.31",
"@guildxyz/types": "^1.9.27",
"ethers": "^6.7.1",
"randombytes": "^2.1.0"
},
Expand Down
1 change: 1 addition & 0 deletions tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export async function createTestGuild() {
{
name: "SDK Test Guild",
urlName: `sdk-test-guild-${random}`,
contacts: [],
roles: [{ name: "SDK Test Role", requirements: [{ type: "FREE" }] }],
},
TEST_SIGNER
Expand Down

0 comments on commit adca922

Please sign in to comment.