Skip to content

Commit 9bacb0f

Browse files
authored
Updated comments and readme (#35)
* updated comments and readme * fix the example run * removed obvious comments
1 parent b118256 commit 9bacb0f

File tree

7 files changed

+111
-11
lines changed

7 files changed

+111
-11
lines changed

examples/gated-group/README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,17 @@ async function checkNft(
9797
3. Once you have the group ID, you can add members using `/add <group_id> <wallet_address>`
9898
4. The bot will verify NFT ownership and add the wallet if they own the required NFT
9999

100-
The bot will automatically make the group creator a super admin and can optionally make new members admins as well.
100+
## Run the agent
101+
102+
```bash
103+
# git clone repo
104+
git clone https://github.com/ephemeraHQ/xmtp-agent-examples.git
105+
# go to the folder
106+
cd xmtp-agent-examples
107+
# install packages
108+
yarn
109+
# generate random keys (optional)
110+
yarn gen:keys
111+
# run the example
112+
yarn examples:gated
113+
```

examples/gated-group/index.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ import { Alchemy, Network } from "alchemy-sdk";
33
import { createSigner, getEncryptionKeyFromHex } from "@/helpers";
44

55
const settings = {
6-
apiKey: process.env.ALCHEMY_API_KEY, // Replace with your Alchemy API key
7-
network: Network.BASE_MAINNET, // Use the appropriate network
6+
apiKey: process.env.ALCHEMY_API_KEY,
7+
network: Network.BASE_MAINNET,
88
};
99

10+
/* Get the wallet key associated to the public key of
11+
* the agent and the encryption key for the local db
12+
* that stores your agent's messages */
1013
const { WALLET_KEY, ENCRYPTION_KEY } = process.env;
1114

1215
if (!WALLET_KEY) {
@@ -17,9 +20,11 @@ if (!ENCRYPTION_KEY) {
1720
throw new Error("ENCRYPTION_KEY must be set");
1821
}
1922

23+
/* Create the signer using viem and parse the encryption key for the local db */
2024
const signer = createSigner(WALLET_KEY);
2125
const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY);
2226

27+
/* Set the environment to dev or production */
2328
const env: XmtpEnv = "dev";
2429

2530
async function main() {
@@ -39,6 +44,7 @@ async function main() {
3944
const stream = client.conversations.streamAllMessages();
4045

4146
for await (const message of await stream) {
47+
/* Ignore messages from the same agent or non-text messages */
4248
if (
4349
message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() ||
4450
message?.contentType?.typeId !== "text"
@@ -58,6 +64,11 @@ async function main() {
5864
console.log("Unable to find conversation, skipping");
5965
continue;
6066
}
67+
68+
/* This example works by parsing slash commands to create a new group or add a member to a group
69+
* /create - create a new group
70+
* /add <group_id> <wallet_address> - add a member to a group */
71+
6172
if (message.content === "/create") {
6273
console.log("Creating group");
6374
const group = await client.conversations.newGroup([]);
@@ -97,7 +108,6 @@ async function main() {
97108
await conversation.send("Please provide a wallet address");
98109
return;
99110
}
100-
101111
const result = await checkNft(walletAddress, "XMTPeople");
102112
if (!result) {
103113
console.log("User can't be added to the group");
@@ -118,6 +128,12 @@ async function main() {
118128

119129
main().catch(console.error);
120130

131+
/**
132+
* Check if the user has the NFT
133+
* @param walletAddress - The wallet address of the user
134+
* @param collectionSlug - The slug of the collection
135+
* @returns true if the user has the NFT, false otherwise
136+
*/
121137
async function checkNft(
122138
walletAddress: string,
123139
collectionSlug: string,

examples/gm/README.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ if (!ENCRYPTION_KEY) {
2222
throw new Error("ENCRYPTION_KEY must be set");
2323
}
2424

25-
/* Create the signer using viem and parse the encryption key for the local db */
2625
const signer = createSigner(WALLET_KEY);
2726
const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY);
2827

@@ -31,7 +30,6 @@ const env: XmtpEnv = "dev";
3130

3231
async function main() {
3332
console.log(`Creating client on the '${env}' network...`);
34-
/* Initialize the xmtp client */
3533
const client = await Client.create(signer, encryptionKey, { env });
3634

3735
console.log("Syncing conversations...");
@@ -43,7 +41,6 @@ async function main() {
4341
);
4442

4543
console.log("Waiting for messages...");
46-
/* Stream all messages from the network */
4744
const stream = client.conversations.streamAllMessages();
4845

4946
for await (const message of await stream) {
@@ -59,7 +56,6 @@ async function main() {
5956
`Received message: ${message.content as string} by ${message.senderInboxId}`,
6057
);
6158

62-
/* Get the conversation by id */
6359
const conversation = client.conversations.getConversationById(
6460
message.conversationId,
6561
);
@@ -70,7 +66,6 @@ async function main() {
7066
}
7167

7268
console.log(`Sending "gm" response...`);
73-
/* Send a message to the conversation */
7469
await conversation.send("gm");
7570

7671
console.log("Waiting for messages...");
@@ -79,3 +74,18 @@ async function main() {
7974

8075
main().catch(console.error);
8176
```
77+
78+
## Run the agent
79+
80+
```bash
81+
# git clone repo
82+
git clone https://github.com/ephemeraHQ/xmtp-agent-examples.git
83+
# go to the folder
84+
cd xmtp-agent-examples
85+
# install packages
86+
yarn
87+
# generate random keys (optional)
88+
yarn gen:keys
89+
# run the example
90+
yarn examples:gm
91+
```

examples/gm/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { Client, type XmtpEnv } from "@xmtp/node-sdk";
22
import { createSigner, getEncryptionKeyFromHex } from "@/helpers";
33

4+
/* Get the wallet key associated to the public key of
5+
* the agent and the encryption key for the local db
6+
* that stores your agent's messages */
47
const { WALLET_KEY, ENCRYPTION_KEY } = process.env;
58

69
if (!WALLET_KEY) {

examples/gpt/README.md

+18-2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const signer = createSigner(WALLET_KEY);
4646
const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY);
4747
const openai = new OpenAI({ apiKey: OPENAI_API_KEY });
4848

49+
/* Set the environment to dev or production */
4950
const env: XmtpEnv = "dev";
5051

5152
async function main() {
@@ -55,6 +56,7 @@ async function main() {
5556
});
5657

5758
console.log("Syncing conversations...");
59+
/* Sync the conversations from the network to update the local db */
5860
await client.conversations.sync();
5961

6062
console.log(
@@ -65,6 +67,7 @@ async function main() {
6567
const stream = client.conversations.streamAllMessages();
6668

6769
for await (const message of await stream) {
70+
/* Ignore messages from the same agent or non-text messages */
6871
if (
6972
message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() ||
7073
message?.contentType?.typeId !== "text"
@@ -91,9 +94,11 @@ async function main() {
9194
model: "gpt-3.5-turbo",
9295
});
9396

97+
/* Get the AI response */
9498
const response =
9599
completion.choices[0]?.message?.content ||
96100
"I'm not sure how to respond to that.";
101+
97102
console.log(`Sending AI response: ${response}`);
98103
await conversation.send(response);
99104
} catch (error) {
@@ -110,6 +115,17 @@ async function main() {
110115
main().catch(console.error);
111116
```
112117

113-
Run the agent and send a test message from [xmtp.chat](https://xmtp.chat).
118+
## Run the agent
114119

115-
Enjoy your GPT-powered XMTP agent!
120+
```bash
121+
# git clone repo
122+
git clone https://github.com/ephemeraHQ/xmtp-agent-examples.git
123+
# go to the folder
124+
cd xmtp-agent-examples
125+
# install packages
126+
yarn
127+
# generate random keys (optional)
128+
yarn gen:keys
129+
# run the example
130+
yarn examples:gpt
131+
```

examples/gpt/index.ts

+23
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,60 @@ import { Client, type XmtpEnv } from "@xmtp/node-sdk";
22
import OpenAI from "openai";
33
import { createSigner, getEncryptionKeyFromHex } from "@/helpers";
44

5+
/* Get the wallet key associated to the public key of
6+
* the agent and the encryption key for the local db
7+
* that stores your agent's messages */
58
const { WALLET_KEY, ENCRYPTION_KEY, OPENAI_API_KEY } = process.env;
69

10+
/* Check if the environment variables are set */
711
if (!WALLET_KEY) {
812
throw new Error("WALLET_KEY must be set");
913
}
1014

15+
/* Check if the encryption key is set */
1116
if (!ENCRYPTION_KEY) {
1217
throw new Error("ENCRYPTION_KEY must be set");
1318
}
1419

20+
/* Check if the OpenAI API key is set */
1521
if (!OPENAI_API_KEY) {
1622
throw new Error("OPENAI_API_KEY must be set");
1723
}
1824

25+
/* Create the signer using viem and parse the encryption key for the local db */
1926
const signer = createSigner(WALLET_KEY);
2027
const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY);
28+
29+
/* Initialize the OpenAI client */
2130
const openai = new OpenAI({ apiKey: OPENAI_API_KEY });
2231

32+
/* Set the environment to dev or production */
2333
const env: XmtpEnv = "dev";
2434

35+
/**
36+
* Main function to run the agent
37+
*/
2538
async function main() {
2639
console.log(`Creating client on the '${env}' network...`);
40+
/* Initialize the xmtp client */
2741
const client = await Client.create(signer, encryptionKey, {
2842
env,
2943
});
3044

3145
console.log("Syncing conversations...");
46+
/* Sync the conversations from the network to update the local db */
3247
await client.conversations.sync();
3348

3449
console.log(
3550
`Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}`,
3651
);
3752

3853
console.log("Waiting for messages...");
54+
/* Stream all messages from the network */
3955
const stream = client.conversations.streamAllMessages();
4056

4157
for await (const message of await stream) {
58+
/* Ignore messages from the same agent or non-text messages */
4259
if (
4360
message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() ||
4461
message?.contentType?.typeId !== "text"
@@ -50,25 +67,31 @@ async function main() {
5067
`Received message: ${message.content as string} by ${message.senderInboxId}`,
5168
);
5269

70+
/* Get the conversation from the local db */
5371
const conversation = client.conversations.getConversationById(
5472
message.conversationId,
5573
);
5674

75+
/* If the conversation is not found, skip the message */
5776
if (!conversation) {
5877
console.log("Unable to find conversation, skipping");
5978
continue;
6079
}
6180

6281
try {
82+
/* Get the AI response */
6383
const completion = await openai.chat.completions.create({
6484
messages: [{ role: "user", content: message.content as string }],
6585
model: "gpt-3.5-turbo",
6686
});
6787

88+
/* Get the AI response */
6889
const response =
6990
completion.choices[0]?.message?.content ||
7091
"I'm not sure how to respond to that.";
92+
7193
console.log(`Sending AI response: ${response}`);
94+
/* Send the AI response to the conversation */
7295
await conversation.send(response);
7396
} catch (error) {
7497
console.error("Error getting AI response:", error);

helpers/index.ts

+19
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ import { fromString, toString } from "uint8arrays";
33
import { toBytes } from "viem";
44
import { privateKeyToAccount } from "viem/accounts";
55

6+
/**
7+
* Create a signer from a private key
8+
* @param privateKey - The private key of the account
9+
* @returns The signer
10+
*/
611
export const createSigner = (privateKey: `0x${string}`) => {
12+
/* Convert the private key to an account */
713
const account = privateKeyToAccount(privateKey);
14+
/* Return the signer */
815
return {
916
getAddress: () => account.address,
1017
signMessage: async (message: string) => {
@@ -16,11 +23,23 @@ export const createSigner = (privateKey: `0x${string}`) => {
1623
};
1724
};
1825

26+
/**
27+
* Generate a random encryption key
28+
* @returns The encryption key
29+
*/
1930
export const generateEncryptionKeyHex = () => {
31+
/* Generate a random encryption key */
2032
const uint8Array = getRandomValues(new Uint8Array(32));
33+
/* Convert the encryption key to a hex string */
2134
return toString(uint8Array, "hex");
2235
};
2336

37+
/**
38+
* Get the encryption key from a hex string
39+
* @param hex - The hex string
40+
* @returns The encryption key
41+
*/
2442
export const getEncryptionKeyFromHex = (hex: string) => {
43+
/* Convert the hex string to an encryption key */
2544
return fromString(hex, "hex");
2645
};

0 commit comments

Comments
 (0)