create-message-kit 1.2.20 → 1.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +6 -1
- package/package.json +2 -2
- package/templates/toss/src/plugins/helpers.ts +1 -4
- package/templates/toss/src/skills/toss.ts +52 -103
- package/templates.json +58 -0
- package/templates/thegeneralstore/.cursorrules +0 -290
- package/templates/thegeneralstore/.env.example +0 -9
- package/templates/thegeneralstore/.yarnrc.yml +0 -9
- package/templates/thegeneralstore/package.json +0 -24
- package/templates/thegeneralstore/src/data/db.json +0 -812
- package/templates/thegeneralstore/src/index.ts +0 -37
- package/templates/thegeneralstore/src/plugins/learnweb3.ts +0 -96
- package/templates/thegeneralstore/src/plugins/lowdb.ts +0 -11
- package/templates/thegeneralstore/src/plugins/notion.ts +0 -89
- package/templates/thegeneralstore/src/plugins/redis.ts +0 -15
- package/templates/thegeneralstore/src/prompt.md +0 -51
- package/templates/thegeneralstore/src/prompt.ts +0 -3
- package/templates/thegeneralstore/src/skills/faucet.ts +0 -114
- package/templates/thegeneralstore/src/skills/notion.ts +0 -17
- package/templates/thegeneralstore/src/skills/poap.ts +0 -48
- package/templates/thegeneralstore/src/skills.ts +0 -37
package/index.js
CHANGED
@@ -7,7 +7,7 @@ import { default as fs } from "fs-extra";
|
|
7
7
|
import { isCancel } from "@clack/prompts";
|
8
8
|
import { detect } from "detect-package-manager";
|
9
9
|
import pc from "picocolors";
|
10
|
-
const defVersion = "1.2.
|
10
|
+
const defVersion = "1.2.22";
|
11
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
12
12
|
|
13
13
|
// Read package.json to get the version
|
@@ -140,6 +140,11 @@ async function gatherProjectInfo() {
|
|
140
140
|
const name = kebabcase(displayName);
|
141
141
|
const destDir = resolve(process.cwd(), name);
|
142
142
|
|
143
|
+
// Remove existing directory if it exists
|
144
|
+
if (fs.existsSync(destDir)) {
|
145
|
+
fs.removeSync(destDir);
|
146
|
+
}
|
147
|
+
|
143
148
|
// Copy template files
|
144
149
|
fs.copySync(templateDir, destDir);
|
145
150
|
|
package/package.json
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
{
|
2
2
|
"name": "create-message-kit",
|
3
|
-
"version": "1.2.
|
3
|
+
"version": "1.2.22",
|
4
4
|
"license": "MIT",
|
5
5
|
"type": "module",
|
6
6
|
"main": "index.js",
|
7
7
|
"module": "index.js",
|
8
8
|
"bin": "index.js",
|
9
9
|
"files": [
|
10
|
-
"
|
10
|
+
"templates.json",
|
11
11
|
"templates/**/*"
|
12
12
|
],
|
13
13
|
"scripts": {
|
@@ -5,7 +5,6 @@ interface Participant {
|
|
5
5
|
response: string;
|
6
6
|
name: string;
|
7
7
|
address: string;
|
8
|
-
agent_address: string;
|
9
8
|
}
|
10
9
|
export interface TossData {
|
11
10
|
group_id: string;
|
@@ -18,7 +17,6 @@ export interface TossData {
|
|
18
17
|
end_time: string;
|
19
18
|
description: string;
|
20
19
|
participants: Participant[];
|
21
|
-
toss_wallet_address: string;
|
22
20
|
}
|
23
21
|
export async function checkTossCorrect(
|
24
22
|
context: XMTPContext,
|
@@ -64,8 +62,7 @@ export async function checkTossCorrect(
|
|
64
62
|
return undefined;
|
65
63
|
}
|
66
64
|
|
67
|
-
|
68
|
-
return { ...tossData, toss_id, pool };
|
65
|
+
return { ...tossData, toss_id };
|
69
66
|
}
|
70
67
|
|
71
68
|
export function extractTossId(message: string): string | null {
|
@@ -139,9 +139,13 @@ export async function handleTossCreation(context: XMTPContext) {
|
|
139
139
|
if (params.description && params.options && !isNaN(Number(params.amount))) {
|
140
140
|
const keys = await tossDBClient.keys("*");
|
141
141
|
let tossId = keys.length + 1;
|
142
|
-
const
|
143
|
-
tossId.
|
142
|
+
const isCreated = await walletService.createWallet(
|
143
|
+
tossId + ":" + sender.address,
|
144
144
|
);
|
145
|
+
if (!isCreated) {
|
146
|
+
await context.reply("Failed to create toss wallet");
|
147
|
+
return;
|
148
|
+
}
|
145
149
|
|
146
150
|
let tossData: TossData = {
|
147
151
|
toss_id: tossId.toString(),
|
@@ -158,20 +162,13 @@ export async function handleTossCreation(context: XMTPContext) {
|
|
158
162
|
? new Date(params.endTime).toLocaleString()
|
159
163
|
: new Date(Date.now() + 24 * 60 * 60 * 1000).toLocaleString(),
|
160
164
|
participants: [],
|
161
|
-
toss_wallet_address: createdTossWallet?.address,
|
162
165
|
};
|
163
|
-
await tossDBClient.set(
|
164
|
-
"toss:" + tossId.toString(),
|
165
|
-
JSON.stringify(tossData),
|
166
|
-
);
|
167
|
-
console.log(tossData);
|
166
|
+
await tossDBClient.set("toss:" + tossId, JSON.stringify(tossData));
|
168
167
|
if (tossId !== undefined) {
|
169
|
-
|
170
|
-
console.log(msg);
|
171
|
-
await context.send(msg);
|
168
|
+
await context.send(generateTossMessage(tossData));
|
172
169
|
} else {
|
173
170
|
await context.reply(
|
174
|
-
`An error occurred while creating the toss. ${
|
171
|
+
`An error occurred while creating the toss. ${tossId}`,
|
175
172
|
);
|
176
173
|
}
|
177
174
|
}
|
@@ -183,7 +180,7 @@ export async function handleJoinToss(context: XMTPContext) {
|
|
183
180
|
return;
|
184
181
|
}
|
185
182
|
|
186
|
-
const { toss_id, participants, amount } = tossData;
|
183
|
+
const { toss_id, participants, amount, admin_address } = tossData;
|
187
184
|
|
188
185
|
const {
|
189
186
|
message: {
|
@@ -192,7 +189,6 @@ export async function handleJoinToss(context: XMTPContext) {
|
|
192
189
|
params: { response },
|
193
190
|
},
|
194
191
|
},
|
195
|
-
group,
|
196
192
|
walletService,
|
197
193
|
} = context;
|
198
194
|
|
@@ -201,35 +197,16 @@ export async function handleJoinToss(context: XMTPContext) {
|
|
201
197
|
await context.reply("You have already joined this toss.");
|
202
198
|
return;
|
203
199
|
}
|
204
|
-
|
205
|
-
|
206
|
-
if (!tossWallet) {
|
207
|
-
await context.reply("Toss wallet not found");
|
208
|
-
return;
|
209
|
-
}
|
200
|
+
//Create wallet for sender
|
201
|
+
await walletService.createWallet(sender.address);
|
210
202
|
const balance = await walletService.checkBalance(sender.address);
|
211
|
-
|
212
|
-
if (balance < amount) {
|
213
|
-
await context.send("You need to fund your account. Check your DMs:");
|
214
|
-
await walletService.requestFunds(context, amount);
|
215
|
-
return;
|
216
|
-
}
|
203
|
+
if (balance < amount) return walletService.requestFunds(amount);
|
217
204
|
|
218
205
|
try {
|
219
|
-
|
220
|
-
|
221
|
-
await context.reply("Sender wallet not found");
|
222
|
-
return;
|
223
|
-
}
|
224
|
-
const transfer = await walletService.transfer(
|
225
|
-
senderWallet,
|
226
|
-
tossWallet,
|
227
|
-
amount,
|
228
|
-
);
|
229
|
-
console.log("Transfer:", transfer.getTransactionHash());
|
206
|
+
let tempWalletID = toss_id + ":" + admin_address;
|
207
|
+
await walletService.transfer(sender.address, tempWalletID, amount);
|
230
208
|
const participant = {
|
231
209
|
address: sender.address,
|
232
|
-
agent_address: senderWallet.address,
|
233
210
|
response: response,
|
234
211
|
name:
|
235
212
|
(await context.getUserInfo(sender.address))?.preferredName ??
|
@@ -274,49 +251,30 @@ export async function handleEndToss(context: XMTPContext) {
|
|
274
251
|
await context.reply("No participants for this toss.");
|
275
252
|
return;
|
276
253
|
} else if (admin_address.toLowerCase() !== sender.address.toLowerCase()) {
|
277
|
-
await context.reply("Only the admin can
|
278
|
-
return;
|
279
|
-
} else if (
|
280
|
-
!options
|
281
|
-
.split(",")
|
282
|
-
.map((o) => o.toLowerCase())
|
283
|
-
.includes(option.toLowerCase())
|
284
|
-
) {
|
285
|
-
await context.reply("Invalid option selected.");
|
254
|
+
await context.reply("Only the admin can cancel the toss.");
|
286
255
|
return;
|
287
256
|
}
|
288
|
-
const { winners, losers } = await extractWinners(participants ?? [], option);
|
289
257
|
|
290
|
-
|
291
|
-
|
258
|
+
let tempWalletID = toss_id + ":" + admin_address;
|
259
|
+
const balance = await walletService.checkBalance(tempWalletID);
|
260
|
+
const fundsNeeded = tossData.amount * participants?.length;
|
261
|
+
if (balance < fundsNeeded) {
|
262
|
+
await context.reply(
|
263
|
+
`Toss wallet does not have enough funds ${fundsNeeded}, has ${balance}`,
|
264
|
+
);
|
292
265
|
return;
|
293
266
|
}
|
294
267
|
|
268
|
+
//Winners
|
269
|
+
|
270
|
+
const { winners, losers } = await extractWinners(participants, option);
|
271
|
+
|
295
272
|
const prize =
|
296
273
|
(tossData.amount * (participants?.length ?? 0)) / (winners.length ?? 1);
|
297
274
|
|
298
275
|
try {
|
299
276
|
for (const winner of winners) {
|
300
|
-
|
301
|
-
|
302
|
-
if (!tossWallet) {
|
303
|
-
await context.reply("Toss wallet not found");
|
304
|
-
return;
|
305
|
-
}
|
306
|
-
const winnerWallet = await walletService.getUserWallet(
|
307
|
-
winner.address,
|
308
|
-
winner.address,
|
309
|
-
);
|
310
|
-
if (!winnerWallet) {
|
311
|
-
await context.reply("Winner wallet not found");
|
312
|
-
return;
|
313
|
-
}
|
314
|
-
const transfer = await walletService.transfer(
|
315
|
-
tossWallet,
|
316
|
-
winnerWallet,
|
317
|
-
prize,
|
318
|
-
);
|
319
|
-
console.log("Transfer:", transfer.getTransactionHash());
|
277
|
+
await walletService.transfer(tempWalletID, winner.address, prize);
|
320
278
|
await tossDBClient.set(
|
321
279
|
`toss:${toss_id}`,
|
322
280
|
JSON.stringify({ ...tossData, status: "closed" }),
|
@@ -357,31 +315,26 @@ export async function handleCancelToss(context: XMTPContext) {
|
|
357
315
|
return;
|
358
316
|
}
|
359
317
|
|
360
|
-
|
318
|
+
let tempWalletID = toss_id + ":" + admin_address;
|
319
|
+
const balance = await walletService.checkBalance(tempWalletID);
|
320
|
+
const fundsNeeded = tossData.amount * participants?.length;
|
321
|
+
if (balance < fundsNeeded) {
|
322
|
+
await context.reply(
|
323
|
+
`Toss wallet does not have enough funds ${fundsNeeded}, has ${balance}`,
|
324
|
+
);
|
325
|
+
return;
|
326
|
+
}
|
327
|
+
for (const participant of participants) {
|
361
328
|
try {
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
}
|
368
|
-
|
369
|
-
const participantWallet = await walletService.getUserWallet(
|
370
|
-
participant.address,
|
329
|
+
await walletService.transfer(tempWalletID, participant.address, amount);
|
330
|
+
} catch (error) {
|
331
|
+
console.error(
|
332
|
+
`Failed to send prize to ${participant.address} agent wallet:`,
|
333
|
+
error,
|
371
334
|
);
|
372
|
-
|
373
|
-
|
374
|
-
return;
|
375
|
-
}
|
376
|
-
const transfer = await walletService.transfer(
|
377
|
-
tossWallet,
|
378
|
-
participantWallet,
|
379
|
-
amount,
|
335
|
+
await context.reply(
|
336
|
+
`Failed to send prize to ${participant.address} agent wallet`,
|
380
337
|
);
|
381
|
-
console.log("Transfer:", transfer.getTransactionHash());
|
382
|
-
} catch (error) {
|
383
|
-
console.error(`Failed to send prize to ${participant.address}:`, error);
|
384
|
-
await context.reply(`Failed to send prize to ${participant.address}`);
|
385
338
|
}
|
386
339
|
}
|
387
340
|
|
@@ -424,20 +377,17 @@ export async function handleDM(context: XMTPContext) {
|
|
424
377
|
if (skill === "help") {
|
425
378
|
await context.send(DM_HELP_MESSAGE);
|
426
379
|
} else if (skill === "create") {
|
427
|
-
const walletExist = await walletService.
|
380
|
+
const walletExist = await walletService.getWallet(sender.address);
|
428
381
|
if (walletExist) {
|
429
382
|
await context.reply("You already have an agent wallet.");
|
430
383
|
return;
|
431
384
|
}
|
432
|
-
|
433
|
-
await context.reply(
|
434
|
-
`Your agent wallet address is ${userWallet.address}\nBalance: $${await walletService.checkBalance(sender.address)}`,
|
435
|
-
);
|
385
|
+
await walletService.createWallet(sender.address);
|
436
386
|
} else if (skill === "balance") {
|
437
|
-
const userWallet = await walletService.
|
387
|
+
const userWallet = await walletService.getWallet(sender.address);
|
438
388
|
|
439
389
|
context.sendTo(
|
440
|
-
`Your agent wallet address is ${
|
390
|
+
`Your agent wallet for address is ${sender.address}\nBalance: $${await walletService.checkBalance(sender.address)}`,
|
441
391
|
[sender.address],
|
442
392
|
);
|
443
393
|
} else if (skill === "fund") {
|
@@ -447,8 +397,7 @@ export async function handleDM(context: XMTPContext) {
|
|
447
397
|
return;
|
448
398
|
} else if (amount) {
|
449
399
|
if (amount + balance <= 10) {
|
450
|
-
|
451
|
-
return;
|
400
|
+
return walletService.requestFunds(Number(amount));
|
452
401
|
} else {
|
453
402
|
await context.send("Wrong amount. Max 10 USDC.");
|
454
403
|
return;
|
@@ -464,7 +413,7 @@ export async function handleDM(context: XMTPContext) {
|
|
464
413
|
`Please specify the amount of USDC to prefund (1 to ${10 - balance}):`,
|
465
414
|
options,
|
466
415
|
);
|
467
|
-
|
416
|
+
return walletService.requestFunds(Number(response));
|
468
417
|
} else if (skill === "withdraw") {
|
469
418
|
const balance = await walletService.checkBalance(sender.address);
|
470
419
|
if (balance === 0) {
|
@@ -478,6 +427,6 @@ export async function handleDM(context: XMTPContext) {
|
|
478
427
|
`Please specify the amount of USDC to withdraw (1 to ${balance}):`,
|
479
428
|
options,
|
480
429
|
);
|
481
|
-
await walletService.withdrawFunds(
|
430
|
+
await walletService.withdrawFunds(Number(response));
|
482
431
|
}
|
483
432
|
}
|
package/templates.json
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"href": "/templates/ens",
|
4
|
+
"title": "ENS Agent",
|
5
|
+
"description": "A template for working with ENS domains.",
|
6
|
+
"icon": "🔗",
|
7
|
+
"author": "humanagent"
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"href": "/templates/simple",
|
11
|
+
"title": "Simple Template",
|
12
|
+
"description": "A simple template without skills.",
|
13
|
+
"icon": "🤖",
|
14
|
+
"author": "humanagent"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"href": "/templates/coinbase-agent",
|
18
|
+
"title": "Coinbase Agent",
|
19
|
+
"description": "A template for a Coinbase features.",
|
20
|
+
"icon": "💰",
|
21
|
+
"author": "humanagent"
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"href": "/templates/thegeneralstore",
|
25
|
+
"title": "The General Store",
|
26
|
+
"description": "All the goodies needed in a hackathon.",
|
27
|
+
"icon": "🏪",
|
28
|
+
"author": "humanagent"
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"href": "/templates/faucet",
|
32
|
+
"title": "Faucet Agent",
|
33
|
+
"description": "A template for requesting testnet funds.",
|
34
|
+
"icon": "💧",
|
35
|
+
"author": "humanagent"
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"href": "/templates/gated-group",
|
39
|
+
"title": "Gated Group",
|
40
|
+
"description": "A template for a gated group.",
|
41
|
+
"icon": "🔒",
|
42
|
+
"author": "humanagent"
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"href": "/templates/gm",
|
46
|
+
"title": "GM Bot",
|
47
|
+
"description": "A template for a GM bot.",
|
48
|
+
"icon": "👑",
|
49
|
+
"author": "humanagent"
|
50
|
+
},
|
51
|
+
{
|
52
|
+
"href": "/templates/toss",
|
53
|
+
"title": "Toss",
|
54
|
+
"description": "A friendly game for groups.",
|
55
|
+
"icon": "🪙",
|
56
|
+
"author": "humanagent"
|
57
|
+
}
|
58
|
+
]
|
@@ -1,290 +0,0 @@
|
|
1
|
-
# MessageKit Skill Template
|
2
|
-
|
3
|
-
## Examples
|
4
|
-
|
5
|
-
### Check if a Domain is Available
|
6
|
-
|
7
|
-
|
8
|
-
import { ensUrl } from "../index.js";
|
9
|
-
import { XMTPContext } from "@xmtp/message-kit";
|
10
|
-
import type { Skill } from "@xmtp/message-kit";
|
11
|
-
|
12
|
-
// Define Skill
|
13
|
-
export const checkDomain: Skill[] = [
|
14
|
-
{
|
15
|
-
skill: "check",
|
16
|
-
handler: handler,
|
17
|
-
examples: ["/check vitalik.eth", "/check fabri.base.eth"],
|
18
|
-
description: "Check if a domain is available.",
|
19
|
-
params: {
|
20
|
-
domain: {
|
21
|
-
type: "string",
|
22
|
-
},
|
23
|
-
},
|
24
|
-
},
|
25
|
-
];
|
26
|
-
|
27
|
-
// Handler Implementation
|
28
|
-
export async function handler(context: XMTPContext) {
|
29
|
-
const {
|
30
|
-
message: {
|
31
|
-
content: {
|
32
|
-
params: { domain },
|
33
|
-
},
|
34
|
-
},
|
35
|
-
} = context;
|
36
|
-
|
37
|
-
const data = await context.getUserInfo(domain);
|
38
|
-
|
39
|
-
if (!data?.address) {
|
40
|
-
let message = `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
|
41
|
-
return {
|
42
|
-
code: 200,
|
43
|
-
message,
|
44
|
-
};
|
45
|
-
} else {
|
46
|
-
let message = `Looks like ${domain} is already registered!`;
|
47
|
-
await context.executeSkill("/cool " + domain);
|
48
|
-
return {
|
49
|
-
code: 404,
|
50
|
-
message,
|
51
|
-
};
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
### Generate a payment request
|
56
|
-
|
57
|
-
|
58
|
-
import { XMTPContext } from "@xmtp/message-kit";
|
59
|
-
import type { Skill } from "@xmtp/message-kit";
|
60
|
-
|
61
|
-
// Define Skill
|
62
|
-
export const paymentRequest: Skill[] = [
|
63
|
-
{
|
64
|
-
skill: "pay",
|
65
|
-
examples: [
|
66
|
-
"/pay 10 vitalik.eth",
|
67
|
-
"/pay 1 usdc to 0xC60E6Bb79322392761BFe3081E302aEB79B30B03",
|
68
|
-
],
|
69
|
-
description:
|
70
|
-
"Send a specified amount of a cryptocurrency to a destination address. \nWhen tipping, you can assume it's 1 USDC.",
|
71
|
-
handler: handler,
|
72
|
-
params: {
|
73
|
-
amount: {
|
74
|
-
default: 10,
|
75
|
-
type: "number",
|
76
|
-
},
|
77
|
-
token: {
|
78
|
-
default: "usdc",
|
79
|
-
type: "string",
|
80
|
-
values: ["eth", "dai", "usdc", "degen"], // Accepted tokens
|
81
|
-
},
|
82
|
-
username: {
|
83
|
-
default: "",
|
84
|
-
type: "username",
|
85
|
-
},
|
86
|
-
address: {
|
87
|
-
default: "",
|
88
|
-
type: "address",
|
89
|
-
},
|
90
|
-
},
|
91
|
-
},
|
92
|
-
];
|
93
|
-
|
94
|
-
// Handler Implementation
|
95
|
-
export async function handler(context: XMTPContext) {
|
96
|
-
const {
|
97
|
-
message: {
|
98
|
-
content: {
|
99
|
-
params: { amount, token, username, address },
|
100
|
-
},
|
101
|
-
},
|
102
|
-
} = context;
|
103
|
-
let receiverAddress = address;
|
104
|
-
if (username) {
|
105
|
-
receiverAddress = (await context.getUserInfo(username))?.address;
|
106
|
-
}
|
107
|
-
if (address) {
|
108
|
-
// Prioritize address over username
|
109
|
-
receiverAddress = address;
|
110
|
-
}
|
111
|
-
|
112
|
-
await context.requestPayment(amount, token, receiverAddress);
|
113
|
-
}
|
114
|
-
|
115
|
-
|
116
|
-
## Types
|
117
|
-
|
118
|
-
import { XMTPContext } from "../plugins/xmtp.js";
|
119
|
-
import { ClientOptions, GroupMember } from "@xmtp/node-sdk";
|
120
|
-
import { ContentTypeId } from "@xmtp/content-type-primitives";
|
121
|
-
|
122
|
-
export type MessageAbstracted = {
|
123
|
-
id: string;
|
124
|
-
sent: Date;
|
125
|
-
content: {
|
126
|
-
text?: string | undefined;
|
127
|
-
reply?: string | undefined;
|
128
|
-
previousMsg?: string | undefined;
|
129
|
-
react?: string | undefined;
|
130
|
-
content?: any | undefined;
|
131
|
-
params?: any | undefined;
|
132
|
-
reference?: string | undefined;
|
133
|
-
skill?: string | undefined;
|
134
|
-
};
|
135
|
-
version: "v2" | "v3";
|
136
|
-
sender: AbstractedMember;
|
137
|
-
typeId: string;
|
138
|
-
};
|
139
|
-
export type GroupAbstracted = {
|
140
|
-
id: string;
|
141
|
-
sync: () => Promise<void>;
|
142
|
-
addMembers: (addresses: string[]) => Promise<void>;
|
143
|
-
addMembersByInboxId: (inboxIds: string[]) => Promise<void>;
|
144
|
-
send: (content: string, contentType?: ContentTypeId) => Promise<string>;
|
145
|
-
isAdmin: (inboxId: string) => boolean;
|
146
|
-
isSuperAdmin: (inboxId: string) => boolean;
|
147
|
-
admins: string[];
|
148
|
-
superAdmins: string[];
|
149
|
-
createdAt: Date;
|
150
|
-
members: GroupMember[];
|
151
|
-
};
|
152
|
-
export type SkillResponse = {
|
153
|
-
code: number;
|
154
|
-
message: string;
|
155
|
-
data?: any;
|
156
|
-
};
|
157
|
-
|
158
|
-
export type SkillHandler = (
|
159
|
-
context: XMTPContext,
|
160
|
-
) => Promise<SkillResponse | void>;
|
161
|
-
|
162
|
-
export type Handler = (context: XMTPContext) => Promise<void>;
|
163
|
-
|
164
|
-
export type RunConfig = {
|
165
|
-
// client options from XMTP client
|
166
|
-
client?: ClientOptions;
|
167
|
-
// private key to be used for the client, if not, default from env
|
168
|
-
privateKey?: string;
|
169
|
-
// if true, the init log message with messagekit logo and stuff will be hidden
|
170
|
-
experimental?: boolean;
|
171
|
-
// hide the init log message with messagekit logo and stuff
|
172
|
-
hideInitLogMessage?: boolean;
|
173
|
-
// if true, attachments will be enabled
|
174
|
-
attachments?: boolean;
|
175
|
-
// if true, member changes will be enabled, like adding members to the group
|
176
|
-
memberChange?: boolean;
|
177
|
-
// skills to be used
|
178
|
-
agent?: Agent;
|
179
|
-
// model to be used
|
180
|
-
gptModel?: string;
|
181
|
-
};
|
182
|
-
export interface SkillParamConfig {
|
183
|
-
default?: string | number | boolean;
|
184
|
-
type:
|
185
|
-
| "number"
|
186
|
-
| "string"
|
187
|
-
| "username"
|
188
|
-
| "quoted"
|
189
|
-
| "address"
|
190
|
-
| "prompt"
|
191
|
-
| "url";
|
192
|
-
plural?: boolean;
|
193
|
-
values?: string[]; // Accepted values for the parameter
|
194
|
-
}
|
195
|
-
|
196
|
-
export interface Frame {
|
197
|
-
title: string;
|
198
|
-
buttons: { content: string; action: string; target: string }[];
|
199
|
-
image: string;
|
200
|
-
}
|
201
|
-
export interface Agent {
|
202
|
-
name: string;
|
203
|
-
description: string;
|
204
|
-
tag: string;
|
205
|
-
skills: Skill[];
|
206
|
-
}
|
207
|
-
export interface Skill {
|
208
|
-
skill: string;
|
209
|
-
handler?: SkillHandler | undefined;
|
210
|
-
adminOnly?: boolean;
|
211
|
-
description: string;
|
212
|
-
examples: string[];
|
213
|
-
params: Record<string, SkillParamConfig>;
|
214
|
-
}
|
215
|
-
|
216
|
-
export interface AbstractedMember {
|
217
|
-
inboxId: string;
|
218
|
-
address: string;
|
219
|
-
accountAddresses: string[];
|
220
|
-
installationIds?: string[];
|
221
|
-
}
|
222
|
-
|
223
|
-
export type MetadataValue = string | number | boolean;
|
224
|
-
export type Metadata = Record<string, MetadataValue | MetadataValue[]>;
|
225
|
-
|
226
|
-
|
227
|
-
## Example final prompt
|
228
|
-
|
229
|
-
Your are a helpful and playful ens agent called @bot that lives inside a messaging app called Converse.
|
230
|
-
|
231
|
-
|
232
|
-
# Rules
|
233
|
-
- You can respond with multiple messages if needed. Each message should be separated by a newline character.
|
234
|
-
- You can trigger skills by only sending the command in a newline message.
|
235
|
-
- Each command starts with a slash (/).
|
236
|
-
- Never announce actions without using a command separated by a newline character.
|
237
|
-
- Never use markdown in your responses.
|
238
|
-
- Do not make guesses or assumptions
|
239
|
-
- Only answer if the verified information is in the prompt.
|
240
|
-
- Check that you are not missing a command
|
241
|
-
- Focus only on helping users with operations detailed below.
|
242
|
-
- Date: Fri, 06 Dec 2024 16:03:22 GMT
|
243
|
-
- When mentioning any action related to available skills, you MUST trigger the corresponding command in a new line
|
244
|
-
- If you suggest an action that has a command, you must trigger that command
|
245
|
-
|
246
|
-
|
247
|
-
## User context
|
248
|
-
- Start by fetch their domain from or Converse username
|
249
|
-
- Call the user by their name or domain, in case they have one
|
250
|
-
- Ask for a name (if they don't have one) so you can suggest domains.
|
251
|
-
- Message sent date: 2024-12-06T16:03:36.582Z
|
252
|
-
- Users address is: 0x40f08f0f853d1c42c61815652b7ccd5a50f0be09
|
253
|
-
- Users name is: ArizonaOregon
|
254
|
-
- Converse username is: ArizonaOregon
|
255
|
-
|
256
|
-
## Commands
|
257
|
-
/check [domain] - Check if a domain is available.
|
258
|
-
/cool [domain] - Get cool alternatives for a .eth domain.
|
259
|
-
/info [domain] - Get detailed information about an ENS domain including owner, expiry date, and resolver.
|
260
|
-
/register [domain] - Register a new ENS domain. Returns a URL to complete the registration process.
|
261
|
-
/renew [domain] - Extend the registration period of your ENS domain. Returns a URL to complete the renewal.
|
262
|
-
/reset - Reset the conversation clearing memory and usernames cache.
|
263
|
-
/pay [amount] [token] [username] [address] - Send a specified amount of a cryptocurrency to a destination address.
|
264
|
-
When tipping, you can asume its 1 usdc.
|
265
|
-
|
266
|
-
## Examples
|
267
|
-
/check vitalik.eth
|
268
|
-
/check fabri.base.eth
|
269
|
-
/cool vitalik.eth
|
270
|
-
/info nick.eth
|
271
|
-
/register vitalik.eth
|
272
|
-
/renew fabri.base.eth
|
273
|
-
/reset
|
274
|
-
/pay 10 vitalik.eth
|
275
|
-
/pay 1 usdc to 0xC60E6Bb79322392761BFe3081E302aEB79B30B03
|
276
|
-
|
277
|
-
## Scenarios
|
278
|
-
1. Missing commands in responses
|
279
|
-
**Issue**: Sometimes responses are sent without the required command.
|
280
|
-
**Example**:
|
281
|
-
Incorrect:
|
282
|
-
> "Looks like vitalik.eth is registered! What about these cool alternatives?"
|
283
|
-
Correct:
|
284
|
-
> "Looks like vitalik.eth is registered! What about these cool alternatives?
|
285
|
-
> /cool vitalik.eth"
|
286
|
-
|
287
|
-
Incorrect:
|
288
|
-
> Here is a summary of your TODOs. I will now send it via email.
|
289
|
-
Correct:
|
290
|
-
> /todo
|
@@ -1,9 +0,0 @@
|
|
1
|
-
KEY= # the private key of the agent wallet
|
2
|
-
TEST_ENCRYPTION_KEY= # a different private key for encryption
|
3
|
-
NOTION_API_KEY= # your Notion API key
|
4
|
-
NOTION_PAGE_ID= # the ID of the Notion page
|
5
|
-
NOTION_POAP_DB= # the ID of the Notion database
|
6
|
-
OPEN_AI_API_KEY= # your OpenAI API key
|
7
|
-
REDIS_CONNECTION_STRING= # your Redis connection string
|
8
|
-
LEARN_WEB3_API_KEY= # your Learn Web3 API key
|
9
|
-
FRAME_BASE_URL= # the URL of the Frame API
|