create-message-kit 1.1.9-beta.1 → 1.1.9-beta.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,233 +0,0 @@
1
- import { DynamicStructuredTool } from "langchain/tools";
2
- import { getUserInfo } from "@xmtp/message-kit";
3
- import { clearMemory } from "@xmtp/message-kit";
4
- import { isAddress } from "viem";
5
- import { z } from "zod";
6
-
7
- const frameUrl = "https://ens.steer.fun/";
8
- const ensUrl = "https://app.ens.domains/";
9
- const txpayUrl = "https://txpay.vercel.app";
10
- const converseUrl = "https://converse.xyz/profile/";
11
-
12
- // Add interface for Converse API response
13
- interface ConverseProfile {
14
- address: string;
15
- avatar?: string;
16
- formattedName?: string;
17
- name?: string;
18
- onXmtp: boolean;
19
- }
20
-
21
- // Add function to check XMTP status
22
- async function checkXMTPStatus(address: string): Promise<boolean> {
23
- try {
24
- const response = await fetch(converseUrl + address, {
25
- method: "POST",
26
- headers: {
27
- "Content-Type": "application/json",
28
- Accept: "application/json",
29
- },
30
- body: JSON.stringify({ address }),
31
- });
32
-
33
- if (!response.ok) {
34
- console.error(`Failed to check XMTP status: ${response.status}`);
35
- return false;
36
- }
37
-
38
- const data = (await response.json()) as ConverseProfile;
39
- return data.onXmtp;
40
- } catch (error) {
41
- console.error("Error checking XMTP status:", error);
42
- return false;
43
- }
44
- }
45
-
46
- const generateCoolAlternatives = (domain: string) => {
47
- const suffixes = ["lfg", "cool", "degen", "moon", "base", "gm"];
48
- const alternatives = [];
49
- for (let i = 0; i < 5; i++) {
50
- const randomPosition = Math.random() < 0.5;
51
- const baseDomain = domain.replace(/\.eth$/, ""); // Remove any existing .eth suffix
52
- alternatives.push(
53
- randomPosition
54
- ? `${suffixes[i]}${baseDomain}.eth`
55
- : `${baseDomain}${suffixes[i]}.eth`,
56
- );
57
- }
58
-
59
- return alternatives
60
- .map(
61
- (alternative: string, index: number) => `${index + 1}. ${alternative} ✨`,
62
- )
63
- .join("\n");
64
- };
65
-
66
- // Export tools array with all tools
67
- export const tools = [
68
- new DynamicStructuredTool({
69
- name: "reset_ens_conversation",
70
- description: "Reset the ENS conversation and clear memory",
71
- schema: z.object({}),
72
- func: async () => {
73
- clearMemory();
74
- return "Conversation reset successfully.";
75
- },
76
- }),
77
-
78
- new DynamicStructuredTool({
79
- name: "renew_ens_domain",
80
- description:
81
- "Generate renewal URL for an ENS domain. Only works if sender owns the domain",
82
- schema: z.object({
83
- domain: z.string().describe("The ENS domain to renew"),
84
- }),
85
- func: async ({ domain }) => {
86
- const data = await getUserInfo(domain);
87
- if (!data?.address) {
88
- return "Domain not found or not registered.";
89
- }
90
- return `${frameUrl}frames/manage?name=${domain}`;
91
- },
92
- }),
93
-
94
- new DynamicStructuredTool({
95
- name: "register_ens_domain",
96
- description: "Get URL to register a new ENS domain",
97
- schema: z.object({
98
- domain: z.string().describe("The ENS domain to register"),
99
- }),
100
- func: async ({ domain }) => {
101
- if (!domain) return "Please provide a domain name";
102
- return `${ensUrl}${domain}`;
103
- },
104
- }),
105
-
106
- new DynamicStructuredTool({
107
- name: "get_ens_info",
108
- description:
109
- "Get detailed information about an ENS domain including owner, avatar, description, etc",
110
- schema: z.object({
111
- domain: z.string().describe("The ENS domain to get information about"),
112
- }),
113
- func: async ({ domain }) => {
114
- const data = await getUserInfo(domain);
115
- if (!data?.ensDomain) {
116
- return "Domain not found.";
117
- }
118
-
119
- const formattedData = {
120
- Address: data?.address,
121
- "Avatar URL": data?.ensInfo?.avatar,
122
- Description: data?.ensInfo?.description,
123
- ENS: data?.ensDomain,
124
- "Primary ENS": data?.ensInfo?.ens_primary,
125
- GitHub: data?.ensInfo?.github,
126
- Resolver: data?.ensInfo?.resolverAddress,
127
- Twitter: data?.ensInfo?.twitter,
128
- URL: `${ensUrl}${domain}`,
129
- };
130
-
131
- let message = "Domain information:\n\n";
132
- for (const [key, value] of Object.entries(formattedData)) {
133
- if (value) {
134
- message += `${key}: ${value}\n`;
135
- }
136
- }
137
- message +=
138
- "\nWould you like to tip the domain owner for getting there first? 🤣";
139
-
140
- // Check XMTP status if we have an address
141
- if (data.address) {
142
- const isOnXMTP = await checkXMTPStatus(data.address);
143
- if (isOnXMTP) {
144
- message += `\n\nAh, this domain is on XMTP! You can message it directly: https://converse.xyz/dm/${domain}`;
145
- }
146
- }
147
-
148
- return message;
149
- },
150
- }),
151
-
152
- new DynamicStructuredTool({
153
- name: "check_ens_availability",
154
- description: "Check if an ENS domain is available for registration",
155
- schema: z.object({
156
- domain: z
157
- .string()
158
- .transform((str) => str.replace(/^["'](.+)["']$/, "$1")) // Remove quotes if present
159
- .transform((str) => str.toLowerCase())
160
- .describe("The ENS domain to check availability for"),
161
- }),
162
- func: async ({ domain }) => {
163
- if (!domain) return "Please provide a domain name to check.";
164
-
165
- if (domain.includes(".") && !domain.endsWith(".eth")) {
166
- return "Invalid ENS domain. Only .eth domains are supported.";
167
- }
168
-
169
- if (!domain.includes(".")) {
170
- domain = `${domain}.eth`;
171
- }
172
-
173
- const data = await getUserInfo(domain);
174
- if (!data?.address) {
175
- return `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
176
- } else {
177
- const alternatives = generateCoolAlternatives(domain);
178
- return `Looks like ${domain} is already registered!\n\nHere are some cool alternatives:\n${alternatives}`;
179
- }
180
- },
181
- }),
182
-
183
- new DynamicStructuredTool({
184
- name: "get_ens_alternatives",
185
- description: "Generate cool alternative names for an ENS domain",
186
- schema: z.object({
187
- domain: z
188
- .string()
189
- .describe("The ENS domain to generate alternatives for"),
190
- }),
191
- func: async ({ domain }) => {
192
- if (!domain) return "Please provide a domain name.";
193
- return `What about these cool alternatives?\n\n${generateCoolAlternatives(domain)}`;
194
- },
195
- }),
196
-
197
- new DynamicStructuredTool({
198
- name: "get_ens_tip_url",
199
- description:
200
- "Generate a URL to tip an ENS domain owner in USDC. Works with both ENS domains and Ethereum addresses.",
201
- schema: z.object({
202
- addressOrDomain: z
203
- .string()
204
- .describe("The ENS domain or Ethereum address to tip"),
205
- amount: z
206
- .number()
207
- .optional()
208
- .default(1)
209
- .describe("The amount of USDC to tip"),
210
- }),
211
- func: async ({ addressOrDomain, amount }) => {
212
- if (!addressOrDomain) {
213
- return "Please provide an address or ENS domain to tip.";
214
- }
215
-
216
- let address: string | undefined;
217
-
218
- if (isAddress(addressOrDomain)) {
219
- address = addressOrDomain;
220
- } else {
221
- const data = await getUserInfo(addressOrDomain);
222
- address = data?.address;
223
- }
224
-
225
- if (!address) {
226
- return "Could not resolve address for tipping. Please provide a valid ENS domain or Ethereum address.";
227
- }
228
-
229
- let sendUrl = `${txpayUrl}/?&amount=${amount}&token=USDC&receiver=${address}`;
230
- return sendUrl;
231
- },
232
- }),
233
- ];
@@ -1,29 +0,0 @@
1
- import { getUserInfo, HandlerContext } from "@xmtp/message-kit";
2
-
3
- export async function handler(context: HandlerContext) {
4
- const {
5
- message: {
6
- content: { skill, params },
7
- },
8
- } = context;
9
- const txpayUrl = "https://txpay.vercel.app";
10
-
11
- if (skill === "pay") {
12
- const { amount: amountSend, token: tokenSend, username } = params;
13
- console.log("username", username);
14
- let senderInfo = await getUserInfo(username);
15
- if (!amountSend || !tokenSend || !senderInfo) {
16
- context.reply(
17
- "Missing required parameters. Please provide amount, token, and username.",
18
- );
19
- return {
20
- code: 400,
21
- message:
22
- "Missing required parameters. Please provide amount, token, and username.",
23
- };
24
- }
25
-
26
- let sendUrl = `${txpayUrl}/?&amount=${amountSend}&token=${tokenSend}&receiver=${senderInfo.address}`;
27
- await context.send(`${sendUrl}`);
28
- }
29
- }
@@ -1,40 +0,0 @@
1
- import {
2
- HandlerContext,
3
- AbstractedMember,
4
- SkillResponse,
5
- } from "@xmtp/message-kit";
6
- import { getUserInfo } from "@xmtp/message-kit";
7
-
8
- export async function handler(context: HandlerContext) {
9
- const {
10
- message: {
11
- content: {
12
- skill,
13
- params: { amount, username },
14
- },
15
- sender,
16
- },
17
- } = context;
18
- let receivers: AbstractedMember[] = [];
19
-
20
- if (skill === "tip") {
21
- receivers = await Promise.all(
22
- username.map((username: string) => getUserInfo(username)),
23
- );
24
- }
25
- if (!sender || receivers.length === 0 || amount === 0) {
26
- context.reply("Sender or receiver or amount not found.");
27
- }
28
- const receiverAddresses = receivers.map((receiver) => receiver.address);
29
-
30
- context.sendTo(
31
- `You received ${amount} tokens from ${sender.address}.`,
32
- receiverAddresses,
33
- );
34
-
35
- // Notify sender of the transaction details
36
- context.sendTo(
37
- `You sent ${amount * receiverAddresses.length} tokens in total.`,
38
- [sender.address],
39
- );
40
- }
@@ -1,87 +0,0 @@
1
- import { handler as tipping } from "./handler/tipping.js";
2
- import { handler as payment } from "./handler/payment.js";
3
- import { handler as games } from "./handler/game.js";
4
- import { handler as help } from "./handler/helpers.js";
5
- import type { SkillGroup } from "@xmtp/message-kit";
6
-
7
- export const skills: SkillGroup[] = [
8
- {
9
- name: "Group bot",
10
- tag: "@bot",
11
- description: "Group agent for tipping and transactions.",
12
- skills: [
13
- {
14
- skill: "/tip [usernames] [amount] [token]",
15
- examples: ["/tip @vitalik 10 usdc"],
16
- description: "Tip users in a specified token.",
17
- handler: tipping,
18
- params: {
19
- username: {
20
- default: "",
21
- plural: true,
22
- type: "username",
23
- },
24
- amount: {
25
- default: 10,
26
- type: "number",
27
- },
28
- token: {
29
- default: "usdc",
30
- type: "string",
31
- values: ["eth", "dai", "usdc", "degen"],
32
- },
33
- },
34
- },
35
- {
36
- skill: "/pay [amount] [token] [username]",
37
- examples: ["/pay 10 usdc vitalik.eth", "/pay 1 @alix"],
38
- description:
39
- "Send a specified amount of a cryptocurrency to a destination address.",
40
- handler: payment,
41
- params: {
42
- amount: {
43
- default: 10,
44
- type: "number",
45
- },
46
- token: {
47
- default: "usdc",
48
- type: "string",
49
- values: ["eth", "dai", "usdc", "degen"], // Accepted tokens
50
- },
51
- username: {
52
- default: "",
53
- type: "username",
54
- },
55
- },
56
- },
57
- {
58
- skill: "/game [game]",
59
- handler: games,
60
- description: "Play a game.",
61
- examples: ["/game wordle", "/game slot", "/game help"],
62
- params: {
63
- game: {
64
- default: "",
65
- type: "string",
66
- values: ["wordle", "slot", "help"],
67
- },
68
- },
69
- },
70
- {
71
- skill: "/help",
72
- examples: ["/help"],
73
- handler: help,
74
- description: "Get help with the bot.",
75
- params: {},
76
- },
77
- {
78
- skill: "/id",
79
- adminOnly: true,
80
- examples: ["/id"],
81
- handler: help,
82
- description: "Get the group ID.",
83
- params: {},
84
- },
85
- ],
86
- },
87
- ];