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

Sign up to get free protection for your applications and to get access to all the features.
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.9",
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}.`,