create-message-kit 1.2.23 → 1.2.25
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 +14 -13
- package/package.json +1 -2
- package/templates/ens/.cursorrules +0 -112
- package/templates/ens/package.json +1 -2
- package/templates/ens/src/index.ts +2 -16
- package/templates/ens/src/prompt.ts +1 -1
- package/templates/simple/.cursorrules +0 -112
- package/templates/simple/src/index.ts +0 -1
- package/templates/coinbase-agent/.cursorrules +0 -290
- package/templates/coinbase-agent/.env.example +0 -4
- package/templates/coinbase-agent/.yarnrc.yml +0 -9
- package/templates/coinbase-agent/package.json +0 -22
- package/templates/coinbase-agent/src/index.ts +0 -29
- package/templates/coinbase-agent/src/plugins/learnweb3.ts +0 -96
- package/templates/coinbase-agent/src/plugins/redis.ts +0 -15
- package/templates/coinbase-agent/src/prompt.ts +0 -64
- package/templates/coinbase-agent/src/skills/drip.ts +0 -83
- package/templates/coinbase-agent/src/skills/mint.ts +0 -99
- package/templates/coinbase-agent/src/skills/pay.ts +0 -35
- package/templates/coinbase-agent/src/skills/swap.ts +0 -52
- package/templates/faucet/.cursorrules +0 -290
- package/templates/faucet/.env.example +0 -5
- package/templates/faucet/.yarnrc.yml +0 -9
- package/templates/faucet/package.json +0 -22
- package/templates/faucet/src/index.ts +0 -28
- package/templates/faucet/src/plugins/learnweb3.ts +0 -96
- package/templates/faucet/src/plugins/redis.ts +0 -15
- package/templates/faucet/src/prompt.ts +0 -11
- package/templates/faucet/src/skills/faucet.ts +0 -140
- package/templates/gated-group/.cursorrules +0 -290
- package/templates/gated-group/.env.example +0 -3
- package/templates/gated-group/.yarnrc.yml +0 -9
- package/templates/gated-group/package.json +0 -23
- package/templates/gated-group/src/index.ts +0 -17
- package/templates/gated-group/src/plugins/alchemy.ts +0 -27
- package/templates/gated-group/src/plugins/xmtp.ts +0 -137
- package/templates/gated-group/src/prompt.ts +0 -11
- package/templates/gated-group/src/skills/gated.ts +0 -88
- package/templates/gm/.cursorrules +0 -290
- package/templates/gm/.env.example +0 -2
- package/templates/gm/.yarnrc.yml +0 -9
- package/templates/gm/package.json +0 -20
- package/templates/gm/src/index.ts +0 -16
- package/templates/hackathon-store/.cursorrules +0 -290
- package/templates/hackathon-store/.env.example +0 -6
- package/templates/hackathon-store/.yarnrc.yml +0 -9
- package/templates/hackathon-store/package.json +0 -20
- package/templates/hackathon-store/src/index.ts +0 -47
- package/templates/hackathon-store/src/plugins/notion.ts +0 -60
- package/templates/hackathon-store/src/prompt.md +0 -27
- package/templates/playground/.cursorrules +0 -290
- package/templates/playground/.env.example +0 -6
- package/templates/playground/.yarnrc.yml +0 -9
- package/templates/playground/package.json +0 -26
- package/templates/playground/src/index.ts +0 -38
- package/templates/playground/src/plugins/alchemy.ts +0 -27
- package/templates/playground/src/plugins/minilog.ts +0 -26
- package/templates/playground/src/plugins/usdc.ts +0 -99
- package/templates/playground/src/plugins/xmtp.ts +0 -137
- package/templates/playground/src/prompt.ts +0 -11
- package/templates/playground/src/skills/broadcast.ts +0 -39
- package/templates/playground/src/skills/cash.ts +0 -122
- package/templates/playground/src/skills/cryptoPrice.ts +0 -63
- package/templates/playground/src/skills/dalle.ts +0 -61
- package/templates/playground/src/skills/gated.ts +0 -88
- package/templates/playground/src/skills/search.ts +0 -159
- package/templates/playground/src/skills/todo.ts +0 -79
- package/templates/playground/src/skills/token.ts +0 -57
- package/templates/playground/src/skills/web.ts +0 -83
- package/templates/playground/src/skills/wordle.ts +0 -96
- package/templates/playground/src/vibes/chill.ts +0 -9
- package/templates/playground/src/vibes/friendly.ts +0 -9
- package/templates/playground/src/vibes/inquisitive.ts +0 -10
- package/templates/playground/src/vibes/playful.ts +0 -10
- package/templates/playground/src/vibes/professional.ts +0 -9
- package/templates/toss/.cursorrules +0 -290
- package/templates/toss/.env.example +0 -7
- package/templates/toss/.yarnrc.yml +0 -9
- package/templates/toss/package.json +0 -21
- package/templates/toss/src/index.ts +0 -29
- package/templates/toss/src/plugins/helpers.ts +0 -174
- package/templates/toss/src/plugins/redis.ts +0 -15
- package/templates/toss/src/prompt.ts +0 -54
- package/templates/toss/src/skills/toss.ts +0 -318
- package/templates/toss/src/skills/waas.ts +0 -116
- package/templates.json +0 -58
@@ -1,79 +0,0 @@
|
|
1
|
-
import { Resend } from "resend";
|
2
|
-
import { XMTPContext } from "@xmtp/message-kit";
|
3
|
-
import type { Skill } from "@xmtp/message-kit";
|
4
|
-
|
5
|
-
const resend = new Resend(process.env.RESEND_API_KEY); // Replace with your Resend API key
|
6
|
-
|
7
|
-
export const todo: Skill[] = [
|
8
|
-
{
|
9
|
-
skill: "todo",
|
10
|
-
handler: handler,
|
11
|
-
examples: ["/todo"],
|
12
|
-
description:
|
13
|
-
"Summarize your TODOs and send an email with the summary. Receives no parameters.",
|
14
|
-
},
|
15
|
-
];
|
16
|
-
|
17
|
-
export async function handler(context: XMTPContext) {
|
18
|
-
const {
|
19
|
-
message: {
|
20
|
-
content: { previousMsg },
|
21
|
-
},
|
22
|
-
} = context;
|
23
|
-
|
24
|
-
let email = "";
|
25
|
-
if (!previousMsg) {
|
26
|
-
await context.send("You need to do it on a reply.");
|
27
|
-
return;
|
28
|
-
}
|
29
|
-
let intents = 2;
|
30
|
-
while (intents > 0) {
|
31
|
-
const emailResponse = await context.awaitResponse(
|
32
|
-
"Please provide your email address to receive the to-dos summary:",
|
33
|
-
);
|
34
|
-
email = emailResponse;
|
35
|
-
|
36
|
-
// Basic email validation
|
37
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
38
|
-
if (!emailRegex.test(email)) {
|
39
|
-
await context.send(
|
40
|
-
"Invalid email format. Please try again with a valid email address.",
|
41
|
-
);
|
42
|
-
intents--;
|
43
|
-
continue;
|
44
|
-
}
|
45
|
-
break;
|
46
|
-
}
|
47
|
-
if (intents == 0) {
|
48
|
-
await context.send(
|
49
|
-
"I couldn't get your email address. Please try again later.",
|
50
|
-
);
|
51
|
-
return;
|
52
|
-
}
|
53
|
-
try {
|
54
|
-
let { reply } = await context.textGeneration(
|
55
|
-
email,
|
56
|
-
"Make this summary concise and to the point to be sent in an email.\n msg: " +
|
57
|
-
previousMsg,
|
58
|
-
"You are an expert at summarizing to-dos. Return in format html and just the content inside the body tag. Dont return `html` or `body` tags",
|
59
|
-
);
|
60
|
-
if (typeof reply === "string") {
|
61
|
-
let content = {
|
62
|
-
from: "bot@mail.coin-toss.xyz",
|
63
|
-
to: email,
|
64
|
-
subject: "Your summary from Converse",
|
65
|
-
html: `
|
66
|
-
<h3>Your Converse Summary</h3>
|
67
|
-
<p>${reply}</p>
|
68
|
-
`,
|
69
|
-
};
|
70
|
-
await resend.emails.send(content);
|
71
|
-
await context.send(`✅ Summary sent successfully to ${email}`);
|
72
|
-
} else {
|
73
|
-
await context.send("❌ Message not found.");
|
74
|
-
}
|
75
|
-
} catch (error) {
|
76
|
-
await context.send("❌ Failed to send email. Please try again later.");
|
77
|
-
console.error("Error sending email:", error);
|
78
|
-
}
|
79
|
-
}
|
@@ -1,57 +0,0 @@
|
|
1
|
-
import { XMTPContext } from "@xmtp/message-kit";
|
2
|
-
import type { Skill } from "@xmtp/message-kit";
|
3
|
-
|
4
|
-
export const token: Skill[] = [
|
5
|
-
{
|
6
|
-
skill: "token",
|
7
|
-
handler: handler,
|
8
|
-
examples: ["/token bitcoin", "/token ethereum"],
|
9
|
-
description: "Get real time price of a any token.",
|
10
|
-
params: {
|
11
|
-
symbol: {
|
12
|
-
type: "string",
|
13
|
-
},
|
14
|
-
},
|
15
|
-
},
|
16
|
-
];
|
17
|
-
export async function handler(context: XMTPContext) {
|
18
|
-
const {
|
19
|
-
message: {
|
20
|
-
content: {
|
21
|
-
params: { symbol },
|
22
|
-
},
|
23
|
-
},
|
24
|
-
} = context;
|
25
|
-
const response = await fetch(
|
26
|
-
`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=${symbol}`,
|
27
|
-
);
|
28
|
-
if (!response.ok) {
|
29
|
-
context.send("Token not found");
|
30
|
-
context.send("try with its full name, instead of btc it would be bitcoin");
|
31
|
-
return;
|
32
|
-
}
|
33
|
-
const data = (await response.json()) as any;
|
34
|
-
const token = data[0];
|
35
|
-
|
36
|
-
const tokenInfo = {
|
37
|
-
name: token.name,
|
38
|
-
symbol: token.symbol.toUpperCase(),
|
39
|
-
price: token.current_price,
|
40
|
-
image: token.image,
|
41
|
-
link: `https://www.coingecko.com/en/coins/${token.id}`,
|
42
|
-
};
|
43
|
-
|
44
|
-
let frame = {
|
45
|
-
title: tokenInfo.name,
|
46
|
-
buttons: [
|
47
|
-
{ content: "Buy", action: "link", target: tokenInfo.link },
|
48
|
-
{
|
49
|
-
content: `Price (${tokenInfo.price})`,
|
50
|
-
action: "link",
|
51
|
-
target: tokenInfo.link,
|
52
|
-
},
|
53
|
-
],
|
54
|
-
image: tokenInfo.image,
|
55
|
-
};
|
56
|
-
await context.sendCustomFrame(frame);
|
57
|
-
}
|
@@ -1,83 +0,0 @@
|
|
1
|
-
import { XMTPContext } from "@xmtp/message-kit";
|
2
|
-
import type { Skill } from "@xmtp/message-kit";
|
3
|
-
import OpenAI from "openai";
|
4
|
-
|
5
|
-
const openai = new OpenAI({
|
6
|
-
apiKey: process.env.OPENAI_API_KEY,
|
7
|
-
});
|
8
|
-
|
9
|
-
export const web: Skill[] = [
|
10
|
-
{
|
11
|
-
skill: "web",
|
12
|
-
examples: ["/web https://message-kit.org"],
|
13
|
-
handler: handler,
|
14
|
-
description: "Get information about a website.",
|
15
|
-
params: {
|
16
|
-
url: {
|
17
|
-
type: "url",
|
18
|
-
},
|
19
|
-
},
|
20
|
-
},
|
21
|
-
];
|
22
|
-
|
23
|
-
export async function handler(context: XMTPContext) {
|
24
|
-
const {
|
25
|
-
message: {
|
26
|
-
content: {
|
27
|
-
params: { url },
|
28
|
-
},
|
29
|
-
},
|
30
|
-
} = context;
|
31
|
-
|
32
|
-
try {
|
33
|
-
const response = await fetch(url);
|
34
|
-
if (!response.ok) {
|
35
|
-
return {
|
36
|
-
code: response.status,
|
37
|
-
message: `Unable to access website: ${response.statusText}`,
|
38
|
-
};
|
39
|
-
}
|
40
|
-
|
41
|
-
const html = await response.text();
|
42
|
-
const content = extractContent(html);
|
43
|
-
const summary = await getAISummary(content, url);
|
44
|
-
|
45
|
-
return {
|
46
|
-
code: 200,
|
47
|
-
message: summary,
|
48
|
-
};
|
49
|
-
} catch (error: any) {
|
50
|
-
return {
|
51
|
-
code: 500,
|
52
|
-
message: `Could not analyze website: ${error.message}`,
|
53
|
-
};
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
function extractContent(html: string): string {
|
58
|
-
// Remove scripts and style elements
|
59
|
-
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
|
60
|
-
.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '');
|
61
|
-
|
62
|
-
// Get text content
|
63
|
-
const text = html.replace(/<[^>]+>/g, ' ')
|
64
|
-
.replace(/\s+/g, ' ')
|
65
|
-
.trim()
|
66
|
-
.slice(0, 1000);
|
67
|
-
|
68
|
-
return text;
|
69
|
-
}
|
70
|
-
|
71
|
-
async function getAISummary(content: string, url: string): Promise<string> {
|
72
|
-
const completion = await openai.chat.completions.create({
|
73
|
-
messages: [
|
74
|
-
{
|
75
|
-
role: "user",
|
76
|
-
content: `What is ${url} about? Summarize it in 2-3 sentences based on the following content: \n${content}\n\nDon't include any pretext but include the url in the summary.`
|
77
|
-
}
|
78
|
-
],
|
79
|
-
model: "gpt-4o-mini",
|
80
|
-
});
|
81
|
-
|
82
|
-
return completion.choices[0].message.content || "Could not generate summary. Please visit the website directly.";
|
83
|
-
}
|
@@ -1,96 +0,0 @@
|
|
1
|
-
import { XMTPContext } from "@xmtp/message-kit";
|
2
|
-
import type { Skill } from "@xmtp/message-kit";
|
3
|
-
|
4
|
-
export const wordle: Skill[] = [
|
5
|
-
{
|
6
|
-
skill: "wordle",
|
7
|
-
handler: handler,
|
8
|
-
examples: ["/wordle"],
|
9
|
-
description: "Play wordle.",
|
10
|
-
},
|
11
|
-
{
|
12
|
-
skill: "arena",
|
13
|
-
examples: ["/arena 3 15"],
|
14
|
-
handler: handler,
|
15
|
-
description: "Play arena.",
|
16
|
-
params: {
|
17
|
-
wordCount: {
|
18
|
-
default: 3,
|
19
|
-
type: "number",
|
20
|
-
},
|
21
|
-
audienceSize: {
|
22
|
-
default: 15,
|
23
|
-
type: "number",
|
24
|
-
},
|
25
|
-
},
|
26
|
-
},
|
27
|
-
];
|
28
|
-
|
29
|
-
async function handler(context: XMTPContext) {
|
30
|
-
const {
|
31
|
-
message: {
|
32
|
-
content: { skill },
|
33
|
-
},
|
34
|
-
} = context;
|
35
|
-
|
36
|
-
if (skill === "arena") {
|
37
|
-
await handleArenaMessage(context);
|
38
|
-
} else if (skill === "wordle") {
|
39
|
-
await context.send("https://framedl.xyz");
|
40
|
-
} else if (skill === "help") {
|
41
|
-
await context.send(
|
42
|
-
"For using this bot you can use the following commands:\n\n" +
|
43
|
-
"/wordle, @wordle, 🔍, 🔎 - To start the game\n" +
|
44
|
-
"/arena <word count> <audience size> - To start the arena game\n" +
|
45
|
-
"/help - To see commands",
|
46
|
-
);
|
47
|
-
}
|
48
|
-
}
|
49
|
-
async function handleArenaMessage(context: XMTPContext) {
|
50
|
-
const {
|
51
|
-
message: {
|
52
|
-
content: { text },
|
53
|
-
},
|
54
|
-
members,
|
55
|
-
} = context;
|
56
|
-
|
57
|
-
const apiKey = process.env.FRAMEDL_API_KEY;
|
58
|
-
if (!apiKey) {
|
59
|
-
console.log("FRAMEDL_API_KEY is not set");
|
60
|
-
await context.send("https://www.framedl.xyz/games/arena/create");
|
61
|
-
return;
|
62
|
-
}
|
63
|
-
const participantCount = members && members.length ? members.length - 1 : 0;
|
64
|
-
const args = text?.split(" ") ?? [];
|
65
|
-
const wordCountArg = args[1] ? parseInt(args[1], 10) : 3;
|
66
|
-
const audienceSizeArg = args[2] ? parseInt(args[2], 10) : participantCount;
|
67
|
-
if (isNaN(wordCountArg) || isNaN(audienceSizeArg)) {
|
68
|
-
await context.send(
|
69
|
-
"usage: /arena <word count> <audience size>\n\n" +
|
70
|
-
"word count: number of words in the arena (default: 3, min: 1, max: 9)\n" +
|
71
|
-
"audience size: number of audience members (default: number of participants excluding wordle bot, min: 1, max: 15)",
|
72
|
-
);
|
73
|
-
return;
|
74
|
-
}
|
75
|
-
|
76
|
-
const audienceSize = Math.max(1, Math.min(15, audienceSizeArg));
|
77
|
-
const wordCount = Math.max(1, Math.min(9, wordCountArg));
|
78
|
-
|
79
|
-
try {
|
80
|
-
const response = await fetch("https://www.framedl.xyz/api/arenas", {
|
81
|
-
method: "POST",
|
82
|
-
body: JSON.stringify({ wordCount, audienceSize }),
|
83
|
-
headers: {
|
84
|
-
"Content-Type": "application/json",
|
85
|
-
"x-framedl-api-key": apiKey,
|
86
|
-
},
|
87
|
-
});
|
88
|
-
|
89
|
-
const data = (await response.json()) as { arenaUrl: string };
|
90
|
-
|
91
|
-
await context.send(data.arenaUrl);
|
92
|
-
} catch (error) {
|
93
|
-
console.error(error);
|
94
|
-
await context.send("https://www.framedl.xyz/games/arena/create");
|
95
|
-
}
|
96
|
-
}
|
@@ -1,9 +0,0 @@
|
|
1
|
-
import { Vibe } from "@xmtp/message-kit";
|
2
|
-
|
3
|
-
export const chill: Vibe = {
|
4
|
-
name: "Chill",
|
5
|
-
description:
|
6
|
-
"A relaxed and easy-going personality, embodying the essence of tranquility and serenity. This vibe exudes a sense of calmness that soothes the soul and invites a peaceful atmosphere.",
|
7
|
-
tone: "calm and composed, like a gentle breeze on a warm summer day",
|
8
|
-
style: "laid-back, with an effortless grace that flows like a serene river",
|
9
|
-
};
|
@@ -1,9 +0,0 @@
|
|
1
|
-
import { Vibe } from "@xmtp/message-kit";
|
2
|
-
|
3
|
-
export const friendly: Vibe = {
|
4
|
-
name: "Friendly",
|
5
|
-
description:
|
6
|
-
"A warm and welcoming personality, radiating kindness and empathy. This vibe is like a comforting embrace, making everyone feel at home and valued.",
|
7
|
-
tone: "cheerful and uplifting, like the first rays of sunshine after a storm",
|
8
|
-
style: "approachable and open-hearted, with a smile that lights up the room",
|
9
|
-
};
|
@@ -1,10 +0,0 @@
|
|
1
|
-
import { Vibe } from "@xmtp/message-kit";
|
2
|
-
|
3
|
-
export const inquisitive: Vibe = {
|
4
|
-
name: "Inquisitive",
|
5
|
-
description:
|
6
|
-
"A curious and questioning nature, driven by an insatiable thirst for knowledge. This vibe is like a detective on a quest for truth, always seeking to uncover the mysteries of the world.",
|
7
|
-
tone: "curious and probing, like a cat exploring a new territory",
|
8
|
-
style:
|
9
|
-
"engaging and thought-provoking, with a knack for sparking lively discussions",
|
10
|
-
};
|
@@ -1,10 +0,0 @@
|
|
1
|
-
import { Vibe } from "@xmtp/message-kit";
|
2
|
-
|
3
|
-
export const playful: Vibe = {
|
4
|
-
name: "Playful",
|
5
|
-
description:
|
6
|
-
"A fun and light-hearted character, full of whimsy and joy. This vibe is like a child at play, bringing laughter and spontaneity to every moment.",
|
7
|
-
tone: "jovial and exuberant, like a carnival in full swing",
|
8
|
-
style:
|
9
|
-
"casual and carefree, with a dash of mischief and a twinkle in the eye",
|
10
|
-
};
|
@@ -1,9 +0,0 @@
|
|
1
|
-
import { Vibe } from "@xmtp/message-kit";
|
2
|
-
|
3
|
-
export const professional: Vibe = {
|
4
|
-
name: "Professional",
|
5
|
-
description:
|
6
|
-
"A formal and business-like demeanor, exuding confidence and competence. This vibe is like a seasoned diplomat, navigating complex situations with poise and precision.",
|
7
|
-
tone: "serious and authoritative, like a judge delivering a verdict",
|
8
|
-
style: "polished and refined, with an air of sophistication and elegance",
|
9
|
-
};
|
@@ -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,7 +0,0 @@
|
|
1
|
-
KEY= # the private key of the wallet
|
2
|
-
TEST_ENCRYPTION_KEY= # a different private key for encryption
|
3
|
-
OPENAI_API_KEY= # the API key for OpenAI
|
4
|
-
REDIS_CONNECTION_STRING= # the connection to the toss database in Redis
|
5
|
-
COINBASE_APP_ID= # the app id for Coinbase
|
6
|
-
COINBASE_API_KEY_NAME= # the API key name for Coinbase
|
7
|
-
COINBASE_API_KEY_PRIVATE_KEY= # the private key for Coinbase
|