create-message-kit 1.1.7-beta.8 → 1.1.8

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.
Files changed (33) hide show
  1. package/README.md +2 -2
  2. package/index.js +60 -50
  3. package/package.json +1 -1
  4. package/templates/agent/src/handler/ens.ts +14 -12
  5. package/templates/agent/src/index.ts +2 -10
  6. package/templates/agent/src/prompt.ts +28 -22
  7. package/templates/agent/src/skills.ts +8 -9
  8. package/templates/gm/.env.example +1 -1
  9. package/templates/gm/src/index.ts +1 -5
  10. package/templates/group/.env.example +2 -3
  11. package/templates/group/src/handler/game.ts +4 -5
  12. package/templates/group/src/handler/helpers.ts +10 -6
  13. package/templates/group/src/handler/payment.ts +29 -0
  14. package/templates/group/src/handler/tipping.ts +17 -35
  15. package/templates/group/src/index.ts +23 -26
  16. package/templates/group/src/prompt.ts +45 -0
  17. package/templates/group/src/skills.ts +17 -107
  18. package/templates/agent/package.json +0 -22
  19. package/templates/agent/src/lib/gpt.ts +0 -161
  20. package/templates/agent/src/lib/openai.ts +0 -174
  21. package/templates/agent/src/lib/resolver.ts +0 -151
  22. package/templates/gm/package.json +0 -21
  23. package/templates/group/package.json +0 -23
  24. package/templates/group/src/handler/agent.ts +0 -67
  25. package/templates/group/src/handler/group.ts +0 -24
  26. package/templates/group/src/handler/loyalty.ts +0 -46
  27. package/templates/group/src/handler/splitpayment.ts +0 -65
  28. package/templates/group/src/handler/transaction.ts +0 -50
  29. package/templates/group/src/lib/gpt.ts +0 -161
  30. package/templates/group/src/lib/openai.ts +0 -174
  31. package/templates/group/src/lib/resolver.ts +0 -151
  32. package/templates/group/src/lib/stack.ts +0 -18
  33. package/templates/group/src/lib/vision.ts +0 -42
package/README.md CHANGED
@@ -9,7 +9,7 @@ bun create message-kit
9
9
  ```
10
10
 
11
11
  ```bash
12
- npx create-message-kit@latest
12
+ npx create-message-kit
13
13
  ```
14
14
 
15
15
  ```bash
@@ -17,5 +17,5 @@ yarn create message-kit
17
17
  ```
18
18
 
19
19
  ```bash [npm]
20
- npm init message-kit@latest
20
+ npm init message-kit
21
21
  ```
package/index.js CHANGED
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
5
5
  import { log, outro, text, select } from "@clack/prompts";
6
6
  import { default as fs } from "fs-extra";
7
7
  import { isCancel } from "@clack/prompts";
8
+ import { detect } from "detect-package-manager";
8
9
  import pc from "picocolors";
9
10
 
10
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -15,9 +16,14 @@ const packageJson = JSON.parse(
15
16
  );
16
17
  const version = packageJson.version;
17
18
  program
18
- .name("byob")
19
+ .name("message-kit")
19
20
  .description("CLI to initialize projects")
20
21
  .action(async () => {
22
+ // Add Yarn 4 check at the start of the action
23
+ const pkgManager = await detectPackageManager();
24
+
25
+ log.info(pc.cyan(`pkgManager detected: ${pkgManager}`));
26
+
21
27
  log.info(pc.cyan(`Welcome to MessageKit CLI v${version}!`));
22
28
  const coolLogo = `
23
29
  ███╗ ███╗███████╗███████╗███████╗ █████╗ ██████╗ ███████╗██╗ ██╗██╗████████╗
@@ -32,9 +38,6 @@ Powered by XMTP`;
32
38
 
33
39
  const { templateType, displayName, destDir } = await gatherProjectInfo();
34
40
 
35
- // Replace dot files
36
- //replaceDotfiles(destDir);
37
-
38
41
  // Create .gitignore
39
42
  createGitignore(destDir);
40
43
 
@@ -44,13 +47,11 @@ Powered by XMTP`;
44
47
  // Create tsconfig.json file
45
48
  createTsconfig(destDir);
46
49
 
47
- // Replace package.json properties
48
- updatePackageJson(destDir, displayName);
49
-
50
50
  // Wrap up
51
51
  log.success(`Project launched in ${pc.red(destDir)}!`);
52
52
 
53
- const pkgManager = detectPackageManager();
53
+ // Add package.json
54
+ addPackagejson(destDir, displayName, pkgManager);
54
55
 
55
56
  // Create README.md file
56
57
  createReadme(destDir, templateType, displayName, pkgManager);
@@ -63,6 +64,39 @@ Powered by XMTP`;
63
64
 
64
65
  program.parse(process.argv);
65
66
 
67
+ async function addPackagejson(destDir, name, pkgManager) {
68
+ // Create package.json based on the template
69
+ let packageTemplate = {
70
+ name: name,
71
+ private: true,
72
+ type: "module",
73
+ scripts: {
74
+ build: "tsc",
75
+ dev: "tsc -w & sleep 1 && node --watch dist/index.js",
76
+ start: "node dist/index.js",
77
+ postinstall: "tsc",
78
+ },
79
+ dependencies: {
80
+ "@xmtp/message-kit": "latest",
81
+ },
82
+ engines: {
83
+ node: ">=20",
84
+ },
85
+ };
86
+
87
+ if (pkgManager.startsWith("yarn")) {
88
+ packageTemplate.packageManager = `${pkgManager}`;
89
+ // Add .yarnrc.yml to disable PnP mode
90
+ fs.writeFileSync(
91
+ resolve(destDir, ".yarnrc.yml"),
92
+ "nodeLinker: node-modules\n",
93
+ );
94
+ }
95
+ fs.writeJsonSync(resolve(destDir, "package.json"), packageTemplate, {
96
+ spaces: 2,
97
+ });
98
+ }
99
+
66
100
  async function gatherProjectInfo() {
67
101
  const templateOptions = [
68
102
  { value: "gm", label: "GM" },
@@ -108,24 +142,6 @@ async function gatherProjectInfo() {
108
142
  return { templateType, displayName, destDir, templateDir };
109
143
  }
110
144
 
111
- function updateDependenciesToLatest(pkgJson) {
112
- const updateToLatest = (deps) => {
113
- for (const key in deps) {
114
- if (deps[key].startsWith("workspace:")) {
115
- deps[key] = "latest";
116
- }
117
- }
118
- };
119
-
120
- if (pkgJson.dependencies) {
121
- updateToLatest(pkgJson.dependencies);
122
- }
123
-
124
- if (pkgJson.devDependencies) {
125
- updateToLatest(pkgJson.devDependencies);
126
- }
127
- }
128
-
129
145
  function createTsconfig(destDir) {
130
146
  const tsconfigContent = {
131
147
  include: ["src/**/*"],
@@ -151,22 +167,6 @@ function createTsconfig(destDir) {
151
167
  spaces: 2,
152
168
  });
153
169
  }
154
- function replaceDotfiles(destDir) {
155
- for (const file of fs.readdirSync(destDir)) {
156
- if (!file.startsWith("_")) continue;
157
- fs.renameSync(
158
- resolve(destDir, file),
159
- resolve(destDir, `.${file.slice(1)}`),
160
- );
161
- }
162
- }
163
-
164
- function updatePackageJson(destDir, name) {
165
- const pkgJson = fs.readJsonSync(resolve(destDir, "package.json"));
166
- pkgJson.name = name;
167
- updateDependenciesToLatest(pkgJson);
168
- fs.writeJsonSync(resolve(destDir, "package.json"), pkgJson, { spaces: 2 });
169
- }
170
170
 
171
171
  function logNextSteps(name) {
172
172
  log.message("Next steps:");
@@ -202,14 +202,24 @@ yarn-error.log*
202
202
  fs.writeFileSync(resolve(destDir, ".gitignore"), gitignoreContent.trim());
203
203
  }
204
204
 
205
- function detectPackageManager() {
206
- const userAgent = process.env.npm_config_user_agent;
207
- if (!userAgent) return "npm";
208
- if (userAgent.includes("bun")) return "bun";
209
- if (userAgent.includes("yarn")) return "yarn";
210
- if (userAgent.includes("pnpm")) return "pnpm";
211
- if (userAgent.includes("npm")) return "npm";
212
- return "npm";
205
+ async function detectPackageManager() {
206
+ try {
207
+ const pkgManager = await detect();
208
+ const userAgent = process.env.npm_config_user_agent;
209
+ let version = "";
210
+
211
+ if (userAgent && pkgManager === "yarn") {
212
+ const parts = userAgent.split(" ")[0]?.split("/");
213
+ if (parts && parts.length > 1) {
214
+ version = `@${parts[1]}`;
215
+ }
216
+ }
217
+
218
+ return pkgManager + version;
219
+ } catch (error) {
220
+ // Fallback to npm if detection fails
221
+ return "npm";
222
+ }
213
223
  }
214
224
 
215
225
  function kebabcase(str) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-message-kit",
3
- "version": "1.1.7-beta.8",
3
+ "version": "1.1.8",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -9,17 +9,19 @@ export const baseTxUrl = "https://base-tx-frame.vercel.app";
9
9
 
10
10
  export async function handleEns(
11
11
  context: HandlerContext,
12
- ): Promise<SkillResponse> {
12
+ ): Promise<SkillResponse | undefined> {
13
13
  const {
14
14
  message: {
15
- content: { command, params, sender },
15
+ sender,
16
+ content: { skill, params },
16
17
  },
17
18
  } = context;
18
- if (command == "reset") {
19
+
20
+ if (skill == "reset") {
19
21
  clearMemory();
20
22
  return { code: 200, message: "Conversation reset." };
21
- } else if (command == "renew") {
22
- // Destructure and validate parameters for the ens command
23
+ } else if (skill == "renew") {
24
+ // Destructure and validate parameters for the ens
23
25
  const { domain } = params;
24
26
  // Check if the user holds the domain
25
27
  if (!domain) {
@@ -42,8 +44,8 @@ export async function handleEns(
42
44
  // Generate URL for the ens
43
45
  let url_ens = frameUrl + "frames/manage?name=" + domain;
44
46
  return { code: 200, message: `${url_ens}` };
45
- } else if (command == "register") {
46
- // Destructure and validate parameters for the ens command
47
+ } else if (skill == "register") {
48
+ // Destructure and validate parameters for the ens
47
49
  const { domain } = params;
48
50
 
49
51
  if (!domain) {
@@ -55,7 +57,7 @@ export async function handleEns(
55
57
  // Generate URL for the ens
56
58
  let url_ens = ensUrl + domain;
57
59
  return { code: 200, message: `${url_ens}` };
58
- } else if (command == "info") {
60
+ } else if (skill == "info") {
59
61
  const { domain } = params;
60
62
 
61
63
  const data = await getUserInfo(domain);
@@ -92,7 +94,7 @@ export async function handleEns(
92
94
  );
93
95
  }
94
96
  return { code: 200, message };
95
- } else if (command == "check") {
97
+ } else if (skill == "check") {
96
98
  const { domain } = params;
97
99
 
98
100
  if (!domain) {
@@ -117,7 +119,7 @@ export async function handleEns(
117
119
  message,
118
120
  };
119
121
  }
120
- } else if (command == "tip") {
122
+ } else if (skill == "tip") {
121
123
  const { address } = params;
122
124
  if (!address) {
123
125
  return {
@@ -134,7 +136,7 @@ export async function handleEns(
134
136
  code: 200,
135
137
  message: txUrl,
136
138
  };
137
- } else if (command == "cool") {
139
+ } else if (skill == "cool") {
138
140
  const { domain } = params;
139
141
  //What about these cool alternatives?\
140
142
  return {
@@ -142,7 +144,7 @@ export async function handleEns(
142
144
  message: `${generateCoolAlternatives(domain)}`,
143
145
  };
144
146
  } else {
145
- return { code: 400, message: "Command not found." };
147
+ return { code: 400, message: "Skill not found." };
146
148
  }
147
149
  }
148
150
 
@@ -4,23 +4,15 @@ import { agent_prompt } from "./prompt.js";
4
4
  import { getUserInfo } from "@xmtp/message-kit";
5
5
 
6
6
  run(async (context: HandlerContext) => {
7
- /*All the skills are handled through the skills file*/
8
- /* If its just text, it will be handled by the ensAgent*/
9
- /* If its a group message, it will be handled by the groupAgent*/
10
- if (!process?.env?.OPEN_AI_API_KEY) {
11
- console.warn("No OPEN_AI_API_KEY found in .env");
12
- return;
13
- }
14
-
15
7
  const {
16
8
  message: {
17
- content: { content, params },
9
+ content: { text, params },
18
10
  sender,
19
11
  },
20
12
  } = context;
21
13
 
22
14
  try {
23
- let userPrompt = params?.prompt ?? content;
15
+ let userPrompt = params?.prompt ?? text;
24
16
  const userInfo = await getUserInfo(sender.address);
25
17
  if (!userInfo) {
26
18
  console.log("User info not found");
@@ -1,57 +1,51 @@
1
1
  import { skills } from "./skills.js";
2
2
  import {
3
- getUserInfo,
4
3
  UserInfo,
5
4
  PROMPT_USER_CONTENT,
6
5
  PROMPT_RULES,
7
6
  PROMPT_SKILLS_AND_EXAMPLES,
7
+ PROMPT_REPLACE_VARIABLES,
8
8
  } from "@xmtp/message-kit";
9
9
 
10
10
  export async function agent_prompt(userInfo: UserInfo) {
11
- let { address, ensDomain, converseUsername, preferredName } = userInfo;
11
+ let systemPrompt =
12
+ PROMPT_RULES +
13
+ PROMPT_USER_CONTENT(userInfo) +
14
+ PROMPT_SKILLS_AND_EXAMPLES(skills, "@ens");
12
15
 
13
- //Update the name of the agent with predefined prompt
14
- let systemPrompt = PROMPT_RULES.replace("{NAME}", skills?.[0]?.tag ?? "@ens");
15
-
16
- //Add user context to the prompt
17
- systemPrompt += PROMPT_USER_CONTENT(userInfo);
18
-
19
- //Add skills and examples to the prompt
20
- systemPrompt += PROMPT_SKILLS_AND_EXAMPLES(skills, "@ens");
21
-
22
- systemPrompt += `
16
+ let fineTunning = `
23
17
 
24
18
  ## Example responses:
25
19
 
26
20
  1. Check if the user does not have a ENS domain
27
- Hey ${preferredName}! it looks like you don't have a ENS domain yet! \n\Let me start by checking your Converse username with the .eth suffix\n/check ${converseUsername}.eth
21
+ Hey {PREFERRED_NAME}! it looks like you don't have a ENS domain yet! \n\Let me start by checking your Converse username with the .eth suffix\n/check {CONVERSE_USERNAME}.eth
28
22
 
29
23
  2. If the user has a ENS domain
30
- Hello ${preferredName} ! I'll help you get your ENS domain.\n Let's start by checking your ENS domain ${ensDomain}. Give me a moment.\n/check ${ensDomain}
24
+ Hello {PREFERRED_NAME} ! I'll help you get your ENS domain.\n Let's start by checking your ENS domain {ENS_DOMAIN}. Give me a moment.\n/check {ENS_DOMAIN}
31
25
 
32
26
  3. Check if the ENS domain is available
33
- Hello! I'll help you get your domain.\n Let's start by checking your ENS domain ${ensDomain}. Give me a moment.\n/check ${ensDomain}
27
+ Hello! I'll help you get your domain.\n Let's start by checking your ENS domain {ENS_DOMAIN}. Give me a moment.\n/check {ENS_DOMAIN}
34
28
 
35
29
  4. If the ENS domain is available,
36
- Looks like ${ensDomain} is available! Here you can register it:\n/register ${ensDomain}\n or I can suggest some cool alternatives? Le me know!
30
+ Looks like {ENS_DOMAIN} is available! Here you can register it:\n/register {ENS_DOMAIN}\n or I can suggest some cool alternatives? Le me know!
37
31
 
38
32
  5. If the ENS domain is already registered, let me suggest 5 cool alternatives
39
- Looks like ${ensDomain} is already registered!\n What about these cool alternatives?\n/cool ${ensDomain}
33
+ Looks like {ENS_DOMAIN} is already registered!\n What about these cool alternatives?\n/cool {ENS_DOMAIN}
40
34
 
41
35
  6. If the user wants to register a ENS domain, use the command "/register [domain]"
42
- Looks like ${ensDomain} is available! Let me help you register it\n/register ${ensDomain}
36
+ Looks like {ENS_DOMAIN} is available! Let me help you register it\n/register {ENS_DOMAIN}
43
37
 
44
38
  7. If the user wants to directly to tip to the ENS domain owner, use directly the command "/tip [domain]", this will return a url but a button to send the tip
45
- Here is the url to send the tip:\n/tip ${ensDomain}
39
+ Here is the url to send the tip:\n/tip {ENS_DOMAIN}
46
40
 
47
41
  8. If the user wants to get information about the ENS domain, use the command "/info [domain]"
48
- Hello! I'll help you get info about ${ensDomain}.\n Give me a moment.\n/info ${ensDomain}
42
+ Hello! I'll help you get info about {ENS_DOMAIN}.\n Give me a moment.\n/info {ENS_DOMAIN}
49
43
 
50
44
  9. If the user wants to renew their domain, use the command "/renew [domain]"
51
- Hello! I'll help you get your ENS domain.\n Let's start by checking your ENS domain ${ensDomain}. Give me a moment.\n/renew ${ensDomain}
45
+ Hello! I'll help you get your ENS domain.\n Let's start by checking your ENS domain {ENS_DOMAIN}. Give me a moment.\n/renew {ENS_DOMAIN}
52
46
 
53
47
  10. If the user wants cool suggestions about a domain, use the command "/cool [domain]"
54
- Here are some cool suggestions for your domain.\n/cool ${ensDomain}
48
+ Here are some cool suggestions for your domain.\n/cool {ENS_DOMAIN}
55
49
 
56
50
  ## Most common bugs
57
51
 
@@ -59,5 +53,17 @@ export async function agent_prompt(userInfo: UserInfo) {
59
53
  But you forgot to add the command at the end of the message.
60
54
  You should have said something like: "Looks like vitalik.eth is registered! What about these cool alternatives?\n/cool vitalik.eth
61
55
  `;
56
+
57
+ // Add the fine tuning to the system prompt
58
+ systemPrompt += fineTunning;
59
+
60
+ // Replace the variables in the system prompt
61
+ systemPrompt = PROMPT_REPLACE_VARIABLES(
62
+ systemPrompt,
63
+ userInfo?.address ?? "",
64
+ userInfo,
65
+ "@ens",
66
+ );
67
+ // console.log(systemPrompt);
62
68
  return systemPrompt;
63
69
  }
@@ -8,7 +8,7 @@ export const skills: SkillGroup[] = [
8
8
  description: "Register ENS domains.",
9
9
  skills: [
10
10
  {
11
- command: "/register [domain]",
11
+ skill: "/register [domain]",
12
12
  triggers: ["/register"],
13
13
  handler: handleEns,
14
14
  description:
@@ -21,8 +21,7 @@ export const skills: SkillGroup[] = [
21
21
  },
22
22
  },
23
23
  {
24
- command: "/exists",
25
- adminOnly: true,
24
+ skill: "/exists",
26
25
  examples: ["/exists"],
27
26
  handler: handleEns,
28
27
  triggers: ["/exists"],
@@ -34,7 +33,7 @@ export const skills: SkillGroup[] = [
34
33
  },
35
34
  },
36
35
  {
37
- command: "/info [domain]",
36
+ skill: "/info [domain]",
38
37
  triggers: ["/info"],
39
38
  handler: handleEns,
40
39
  description:
@@ -47,7 +46,7 @@ export const skills: SkillGroup[] = [
47
46
  },
48
47
  },
49
48
  {
50
- command: "/renew [domain]",
49
+ skill: "/renew [domain]",
51
50
  triggers: ["/renew"],
52
51
  handler: handleEns,
53
52
  description:
@@ -60,7 +59,7 @@ export const skills: SkillGroup[] = [
60
59
  },
61
60
  },
62
61
  {
63
- command: "/check [domain]",
62
+ skill: "/check [domain]",
64
63
  triggers: ["/check"],
65
64
  handler: handleEns,
66
65
  examples: ["/check vitalik.eth", "/check fabri.base.eth"],
@@ -72,7 +71,7 @@ export const skills: SkillGroup[] = [
72
71
  },
73
72
  },
74
73
  {
75
- command: "/cool [domain]",
74
+ skill: "/cool [domain]",
76
75
  triggers: ["/cool"],
77
76
  examples: ["/cool vitalik.eth"],
78
77
  handler: handleEns,
@@ -84,7 +83,7 @@ export const skills: SkillGroup[] = [
84
83
  },
85
84
  },
86
85
  {
87
- command: "/reset",
86
+ skill: "/reset",
88
87
  triggers: ["/reset"],
89
88
  examples: ["/reset"],
90
89
  handler: handleEns,
@@ -92,7 +91,7 @@ export const skills: SkillGroup[] = [
92
91
  params: {},
93
92
  },
94
93
  {
95
- command: "/tip [address]",
94
+ skill: "/tip [address]",
96
95
  description: "Show a URL for tipping a domain owner.",
97
96
  triggers: ["/tip"],
98
97
  handler: handleEns,
@@ -1 +1 @@
1
- KEY= # the private key of the bot wallet
1
+ KEY= # the private key of the agent wallet
@@ -1,9 +1,5 @@
1
1
  import { run, HandlerContext } from "@xmtp/message-kit";
2
2
 
3
3
  run(async (context: HandlerContext) => {
4
- // Get the message and the address from the sender
5
- const { content, sender } = context.message;
6
-
7
- // To reply, just call `reply` on the HandlerContext
8
- await context.send(`gm`);
4
+ context.send("gm");
9
5
  });
@@ -1,3 +1,2 @@
1
- KEY= # the private key of the bot wallet
2
- OPEN_AI_API_KEY= # openai api key
3
- STACK_API_KEY= # stack api key
1
+ KEY= # the private key of the agent wallet
2
+ OPEN_AI_API_KEY= # openai api key
@@ -1,14 +1,13 @@
1
1
  import { HandlerContext } from "@xmtp/message-kit";
2
2
 
3
- // Handler function to process game-related commands
3
+ // Handler function to process game-related
4
4
  export async function handler(context: HandlerContext) {
5
5
  const {
6
6
  message: {
7
- content: { command, params },
7
+ content: { skill, params, text },
8
8
  },
9
9
  } = context;
10
- if (!command) {
11
- const { content: text } = context?.message?.content;
10
+ if (!skill) {
12
11
  if (text === "🔎" || text === "🔍") {
13
12
  // Send the URL for the requested game
14
13
  context.reply("https://framedl.xyz/");
@@ -36,7 +35,7 @@ export async function handler(context: HandlerContext) {
36
35
  default:
37
36
  // Inform the user about unrecognized skills and provide available options
38
37
  context.send(
39
- "Command not recognized. Available games: wordle, slot, or help.",
38
+ "Skill not recognized. Available games: wordle, slot, or help.",
40
39
  );
41
40
  }
42
41
  }
@@ -3,22 +3,26 @@ import { HandlerContext } from "@xmtp/message-kit";
3
3
  export async function handler(context: HandlerContext) {
4
4
  const {
5
5
  skills,
6
- group,
7
6
  message: {
8
- content: { command },
7
+ content: { skill },
9
8
  },
9
+ group,
10
10
  } = context;
11
11
 
12
- if (command == "help") {
12
+ if (skill == "help") {
13
13
  const intro =
14
14
  "Available experiences:\n" +
15
15
  skills
16
16
  ?.flatMap((app) => app.skills)
17
- .map((skill) => `${skill.command} - ${skill.description}`)
17
+ .map((skill) => `${skill.skill} - ${skill.description}`)
18
18
  .join("\n") +
19
19
  "\nUse these skills to interact with specific apps.";
20
20
  context.send(intro);
21
- } else if (command == "id") {
22
- context.send(context.group?.id);
21
+ } else if (skill == "id") {
22
+ if (!group?.id) {
23
+ context.send("This skill only works in group chats.");
24
+ return;
25
+ }
26
+ context.send(group?.id);
23
27
  }
24
28
  }
@@ -0,0 +1,29 @@
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 baseUrl = "https://txpay.vercel.app";
10
+
11
+ if (skill === "pay") {
12
+ const { amount: amountSend, token: tokenSend, username } = params; // [!code hl] // [!code focus]
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 = `${baseUrl}/?&amount=${amountSend}&token=${tokenSend}&receiver=${senderInfo.address}`;
27
+ await context.send(`${sendUrl}`);
28
+ }
29
+ }
@@ -1,49 +1,31 @@
1
- import { HandlerContext, AbstractedMember } from "@xmtp/message-kit";
1
+ import {
2
+ HandlerContext,
3
+ AbstractedMember,
4
+ SkillResponse,
5
+ } from "@xmtp/message-kit";
2
6
  import { getUserInfo } from "@xmtp/message-kit";
3
7
 
4
8
  export async function handler(context: HandlerContext) {
5
9
  const {
6
- members,
7
- getMessageById,
8
- message: { content, sender, typeId },
10
+ message: {
11
+ content: {
12
+ skill,
13
+ params: { amount, username },
14
+ },
15
+ sender,
16
+ },
9
17
  } = context;
10
- const msg = await getMessageById(content.reference);
11
- const replyReceiver = members?.find(
12
- (member) => member.inboxId === msg?.senderInboxId,
13
- );
14
- let amount: number = 0,
15
- receivers: AbstractedMember[] = [];
16
- // Handle different types of messages
17
- if (typeId === "reply" && replyReceiver) {
18
- const { content: reply } = content;
19
-
20
- if (reply.includes("degen")) {
21
- receivers = [replyReceiver];
22
- const match = reply.match(/(\d+)/);
23
- if (match)
24
- amount = parseInt(match[0]); // Extract amount from reply
25
- else amount = 10;
26
- }
27
- } else if (typeId === "text") {
28
- const { content: text, params } = content;
29
- if (text.startsWith("/tip") && params) {
30
- // Process text skills starting with "/tip"
31
- const {
32
- params: { amount: extractedAmount, username },
33
- } = content;
34
- amount = extractedAmount || 10; // Default amount if not specified
18
+ let receivers: AbstractedMember[] = [];
35
19
 
36
- receivers = await Promise.all(
37
- username.map((username: string) => getUserInfo(username)),
38
- );
39
- }
20
+ if (skill === "tip") {
21
+ receivers = await Promise.all(
22
+ username.map((username: string) => getUserInfo(username)),
23
+ );
40
24
  }
41
25
  if (!sender || receivers.length === 0 || amount === 0) {
42
26
  context.reply("Sender or receiver or amount not found.");
43
- return;
44
27
  }
45
28
  const receiverAddresses = receivers.map((receiver) => receiver.address);
46
- // Process sending tokens to each receiver
47
29
 
48
30
  context.sendTo(
49
31
  `You received ${amount} tokens from ${sender.address}.`,