@@ -2,11 +2,15 @@ import { Client, type XmtpEnv } from "@xmtp/node-sdk";
2
2
import { Alchemy , Network } from "alchemy-sdk" ;
3
3
import { createSigner , getEncryptionKeyFromHex } from "@/helpers" ;
4
4
5
+ /* Set the Alchemy API key and network */
5
6
const settings = {
6
- apiKey : process . env . ALCHEMY_API_KEY , // Replace with your Alchemy API key
7
- network : Network . BASE_MAINNET , // Use the appropriate network
7
+ apiKey : process . env . ALCHEMY_API_KEY ,
8
+ network : Network . BASE_MAINNET ,
8
9
} ;
9
10
11
+ /* Get the wallet key associated to the public key of
12
+ * the agent and the encryption key for the local db
13
+ * that stores your agent's messages */
10
14
const { WALLET_KEY , ENCRYPTION_KEY } = process . env ;
11
15
12
16
if ( ! WALLET_KEY ) {
@@ -17,28 +21,37 @@ if (!ENCRYPTION_KEY) {
17
21
throw new Error ( "ENCRYPTION_KEY must be set" ) ;
18
22
}
19
23
24
+ /* Create the signer using viem and parse the encryption key for the local db */
20
25
const signer = createSigner ( WALLET_KEY ) ;
21
26
const encryptionKey = getEncryptionKeyFromHex ( ENCRYPTION_KEY ) ;
22
27
28
+ /* Set the environment to dev or production */
23
29
const env : XmtpEnv = "dev" ;
24
30
31
+ /**
32
+ * Main function to run the agent
33
+ */
25
34
async function main ( ) {
26
35
console . log ( `Creating client on the '${ env } ' network...` ) ;
36
+ /* Initialize the xmtp client */
27
37
const client = await Client . create ( signer , encryptionKey , {
28
38
env,
29
39
} ) ;
30
40
31
41
console . log ( "Syncing conversations..." ) ;
42
+ /* Sync the conversations from the network to update the local db */
32
43
await client . conversations . sync ( ) ;
33
44
34
45
console . log (
35
46
`Agent initialized on ${ client . accountAddress } \nSend a message on http://xmtp.chat/dm/${ client . accountAddress } ` ,
36
47
) ;
37
48
38
49
console . log ( "Waiting for messages..." ) ;
50
+ /* Stream all messages from the network */
39
51
const stream = client . conversations . streamAllMessages ( ) ;
40
52
41
53
for await ( const message of await stream ) {
54
+ /* Ignore messages from the same agent or non-text messages */
42
55
if (
43
56
message ?. senderInboxId . toLowerCase ( ) === client . inboxId . toLowerCase ( ) ||
44
57
message ?. contentType ?. typeId !== "text"
@@ -50,6 +63,7 @@ async function main() {
50
63
`Received message: ${ message . content as string } by ${ message . senderInboxId } ` ,
51
64
) ;
52
65
66
+ /* Get the conversation from the local db */
53
67
const conversation = client . conversations . getConversationById (
54
68
message . conversationId ,
55
69
) ;
@@ -58,7 +72,10 @@ async function main() {
58
72
console . log ( "Unable to find conversation, skipping" ) ;
59
73
continue ;
60
74
}
75
+
76
+ /* If the message is to create a new group */
61
77
if ( message . content === "/create" ) {
78
+ /* Create a new group */
62
79
console . log ( "Creating group" ) ;
63
80
const group = await client . conversations . newGroup ( [ ] ) ;
64
81
console . log ( "Group created" , group . id ) ;
@@ -82,33 +99,38 @@ async function main() {
82
99
typeof message . content === "string" &&
83
100
message . content . startsWith ( "/add" )
84
101
) {
102
+ /* Extract the group id and wallet address from the message */
85
103
const groupId = message . content . split ( " " ) [ 1 ] ;
86
104
if ( ! groupId ) {
87
105
await conversation . send ( "Please provide a group id" ) ;
88
106
return ;
89
107
}
108
+ /* Get the group from the local db */
90
109
const group = client . conversations . getConversationById ( groupId ) ;
91
110
if ( ! group ) {
92
111
await conversation . send ( "Please provide a valid group id" ) ;
93
112
return ;
94
113
}
114
+ /* Extract the wallet address from the message */
95
115
const walletAddress = message . content . split ( " " ) [ 2 ] ;
96
116
if ( ! walletAddress ) {
97
117
await conversation . send ( "Please provide a wallet address" ) ;
98
118
return ;
99
119
}
100
-
120
+ /* Check if the user has the NFT */
101
121
const result = await checkNft ( walletAddress , "XMTPeople" ) ;
102
122
if ( ! result ) {
103
123
console . log ( "User can't be added to the group" ) ;
104
124
return ;
105
125
} else {
126
+ /* Add the user to the group */
106
127
await group . addMembers ( [ walletAddress ] ) ;
107
128
await conversation . send (
108
129
`User added to the group\n- Group ID: ${ groupId } \n- Wallet Address: ${ walletAddress } ` ,
109
130
) ;
110
131
}
111
132
} else {
133
+ /* Send a welcome message to the user */
112
134
await conversation . send (
113
135
"👋 Welcome to the Gated Bot Group!\nTo get started, type /create to set up a new group. 🚀\nThis example will check if the user has a particular nft and add them to the group if they do.\nOnce your group is created, you'll receive a unique Group ID and URL.\nShare the URL with friends to invite them to join your group!" ,
114
136
) ;
@@ -118,6 +140,12 @@ async function main() {
118
140
119
141
main ( ) . catch ( console . error ) ;
120
142
143
+ /**
144
+ * Check if the user has the NFT
145
+ * @param walletAddress - The wallet address of the user
146
+ * @param collectionSlug - The slug of the collection
147
+ * @returns true if the user has the NFT, false otherwise
148
+ */
121
149
async function checkNft (
122
150
walletAddress : string ,
123
151
collectionSlug : string ,
0 commit comments