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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. package/index.js +12 -36
  2. package/package.json +2 -2
  3. package/templates/agent/.yarnrc.yml +4 -0
  4. package/templates/agent/package.json +20 -0
  5. package/templates/agent/src/handlers/check.ts +42 -0
  6. package/templates/agent/src/handlers/cool.ts +52 -0
  7. package/templates/agent/src/handlers/info.ts +65 -0
  8. package/templates/agent/src/handlers/register.ts +40 -0
  9. package/templates/agent/src/handlers/renew.ts +52 -0
  10. package/templates/agent/src/handlers/reset.ts +19 -0
  11. package/templates/agent/src/handlers/tip.ts +29 -0
  12. package/templates/agent/src/index.ts +55 -55
  13. package/templates/agent/src/prompt.ts +52 -0
  14. package/templates/gated/.env.example +3 -0
  15. package/templates/gated/.yarnrc.yml +4 -0
  16. package/templates/gated/package.json +23 -0
  17. package/templates/gated/src/index.ts +64 -0
  18. package/templates/gated/src/lib/gated.ts +51 -0
  19. package/templates/gated/src/lib/nft.ts +37 -0
  20. package/templates/gated/src/skills.ts +24 -0
  21. package/templates/gpt/.yarnrc.yml +4 -0
  22. package/templates/gpt/package.json +20 -0
  23. package/templates/gpt/src/index.ts +8 -29
  24. package/templates/gpt/src/prompt.ts +8 -18
  25. package/templates/group/.yarnrc.yml +4 -0
  26. package/templates/group/package.json +20 -0
  27. package/templates/group/src/{handler → handlers}/game.ts +19 -3
  28. package/templates/group/src/{handler → handlers}/helpers.ts +22 -3
  29. package/templates/group/src/handlers/payment.ts +51 -0
  30. package/templates/group/src/handlers/tipping.ts +60 -0
  31. package/templates/group/src/index.ts +34 -21
  32. package/templates/group/src/prompt.ts +21 -16
  33. package/templates/agent/src/handler.ts +0 -174
  34. package/templates/agent/src/skills.ts +0 -88
  35. package/templates/ens-agent-pro/.env.example +0 -2
  36. package/templates/ens-agent-pro/src/index.ts +0 -90
  37. package/templates/ens-agent-pro/src/prompt.ts +0 -19
  38. package/templates/ens-agent-pro/src/skills.ts +0 -233
  39. package/templates/group/src/handler/payment.ts +0 -29
  40. package/templates/group/src/handler/tipping.ts +0 -40
  41. package/templates/group/src/skills.ts +0 -87
package/index.js CHANGED
@@ -51,7 +51,7 @@ Powered by XMTP`;
51
51
  log.success(`Project launched in ${pc.red(destDir)}!`);
52
52
 
53
53
  // Add package.json
54
- addPackagejson(destDir, displayName, pkgManager);
54
+ updatePackagejson(destDir, templateType);
55
55
 
56
56
  // Create README.md file
57
57
  createReadme(destDir, templateType, displayName, pkgManager);
@@ -64,39 +64,15 @@ Powered by XMTP`;
64
64
 
65
65
  program.parse(process.argv);
66
66
 
67
- async function addPackagejson(destDir, name, pkgManager) {
67
+ async function updatePackagejson(destDir, templateType) {
68
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
- devDependencies: {
83
- "@types/node": "latest",
84
- typescript: "latest",
85
- },
86
- engines: {
87
- node: ">=20",
88
- },
89
- };
90
-
91
- if (pkgManager.includes("yarn")) {
92
- //packageTemplate.packageManager = `${pkgManager}`;
93
- // Add .yarnrc.yml to disable PnP mode
94
- }
69
+ const templateDir = resolve(__dirname, `./templates/${templateType}`);
70
+ const packageTemplate = fs.readJsonSync(`${templateDir}/package.json`);
95
71
 
96
- fs.writeFileSync(
97
- resolve(destDir, ".yarnrc.yml"),
98
- "nodeLinker: node-modules\n",
99
- );
72
+ packageTemplate.dependencies["@xmtp/message-kit"] = "latest";
73
+ //Add for yarn in general
74
+ packageTemplate.scripts.postinstall = "tsc";
75
+ packageTemplate.packageManager = `yarn@4.5.1`;
100
76
 
101
77
  fs.writeJsonSync(resolve(destDir, "package.json"), packageTemplate, {
102
78
  spaces: 2,
@@ -105,10 +81,10 @@ async function addPackagejson(destDir, name, pkgManager) {
105
81
 
106
82
  async function gatherProjectInfo() {
107
83
  const templateOptions = [
108
- { value: "gpt", label: "GPT" },
109
- { value: "agent", label: "Agent" },
110
- { value: "group", label: "Group" },
111
- { value: "ens", label: "Ens Agent Pro" },
84
+ { value: "gpt", label: "Simple Gpt" },
85
+ { value: "agent", label: "ENS Agent" },
86
+ { value: "group", label: "Group bot" },
87
+ { value: "gated", label: "Gated Group" },
112
88
  ];
113
89
 
114
90
  const templateType = await select({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-message-kit",
3
- "version": "1.1.9",
3
+ "version": "1.1.10-beta.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -30,7 +30,7 @@
30
30
  "@types/node": "^20.14.2",
31
31
  "prettier": "^3.3.1"
32
32
  },
33
- "packageManager": "yarn@4.2.2",
33
+ "packageManager": "yarn@4.5.1",
34
34
  "engines": {
35
35
  "node": ">=20"
36
36
  },
@@ -0,0 +1,4 @@
1
+ compressionLevel: mixed
2
+ enableGlobalCache: false
3
+ enableTelemetry: false
4
+ nodeLinker: node-modules
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "agent",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "build": "tsc",
7
+ "dev": "tsc -w & sleep 1 && node --watch dist/index.js",
8
+ "start": "node dist/index.js"
9
+ },
10
+ "dependencies": {
11
+ "@xmtp/message-kit": "workspace:*"
12
+ },
13
+ "devDependencies": {
14
+ "@types/node": "^20.14.2",
15
+ "typescript": "^5.4.5"
16
+ },
17
+ "engines": {
18
+ "node": ">=20"
19
+ }
20
+ }
@@ -0,0 +1,42 @@
1
+ import { ensUrl } from "../index.js";
2
+ import { XMTPContext, getUserInfo } from "@xmtp/message-kit";
3
+ import type { skillAction } from "@xmtp/message-kit";
4
+
5
+ export const registerSkill: skillAction[] = [
6
+ {
7
+ skill: "/check [domain]",
8
+ handler: handleCheck,
9
+ examples: ["/check vitalik.eth", "/check fabri.base.eth"],
10
+ description: "Check if a domain is available.",
11
+ params: {
12
+ domain: {
13
+ type: "string",
14
+ },
15
+ },
16
+ },
17
+ ];
18
+ export async function handleCheck(context: XMTPContext) {
19
+ const {
20
+ message: {
21
+ content: {
22
+ params: { domain },
23
+ },
24
+ },
25
+ } = context;
26
+
27
+ const data = await getUserInfo(domain);
28
+ if (!data?.address) {
29
+ let message = `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
30
+ return {
31
+ code: 200,
32
+ message,
33
+ };
34
+ } else {
35
+ let message = `Looks like ${domain} is already registered!`;
36
+ await context.executeSkill("/cool " + domain);
37
+ return {
38
+ code: 404,
39
+ message,
40
+ };
41
+ }
42
+ }
@@ -0,0 +1,52 @@
1
+ import { XMTPContext } from "@xmtp/message-kit";
2
+
3
+ import type { skillAction } from "@xmtp/message-kit";
4
+
5
+ export const registerSkill: skillAction[] = [
6
+ {
7
+ skill: "/cool [domain]",
8
+ examples: ["/cool vitalik.eth"],
9
+ handler: handleCool,
10
+ description: "Get cool alternatives for a .eth domain.",
11
+ params: {
12
+ domain: {
13
+ type: "string",
14
+ },
15
+ },
16
+ },
17
+ ];
18
+ export async function handleCool(context: XMTPContext) {
19
+ const {
20
+ message: {
21
+ content: {
22
+ params: { domain },
23
+ },
24
+ },
25
+ } = context;
26
+ //What about these cool alternatives?\
27
+ return {
28
+ code: 200,
29
+ message: `${generateCoolAlternatives(domain)}`,
30
+ };
31
+ }
32
+
33
+ export const generateCoolAlternatives = (domain: string) => {
34
+ const suffixes = ["lfg", "cool", "degen", "moon", "base", "gm"];
35
+ const alternatives = [];
36
+ for (let i = 0; i < 5; i++) {
37
+ const randomPosition = Math.random() < 0.5;
38
+ const baseDomain = domain.replace(/\.eth$/, ""); // Remove any existing .eth suffix
39
+ alternatives.push(
40
+ randomPosition
41
+ ? `${suffixes[i]}${baseDomain}.eth`
42
+ : `${baseDomain}${suffixes[i]}.eth`,
43
+ );
44
+ }
45
+
46
+ const cool_alternativesFormat = alternatives
47
+ .map(
48
+ (alternative: string, index: number) => `${index + 1}. ${alternative} ✨`,
49
+ )
50
+ .join("\n");
51
+ return cool_alternativesFormat;
52
+ };
@@ -0,0 +1,65 @@
1
+ import { ensUrl } from "../index.js";
2
+ import { XMTPContext, getUserInfo, isOnXMTP } from "@xmtp/message-kit";
3
+
4
+ import type { skillAction } from "@xmtp/message-kit";
5
+
6
+ export const registerSkill: skillAction[] = [
7
+ {
8
+ skill: "/info [domain]",
9
+ handler: handleInfo,
10
+ description:
11
+ "Get detailed information about an ENS domain including owner, expiry date, and resolver.",
12
+ examples: ["/info nick.eth"],
13
+ params: {
14
+ domain: {
15
+ type: "string",
16
+ },
17
+ },
18
+ },
19
+ ];
20
+
21
+ export async function handleInfo(context: XMTPContext) {
22
+ const {
23
+ message: {
24
+ sender,
25
+ content: {
26
+ params: { domain },
27
+ },
28
+ },
29
+ } = context;
30
+
31
+ const data = await getUserInfo(domain);
32
+ if (!data?.ensDomain) {
33
+ return {
34
+ code: 404,
35
+ message: "Domain not found.",
36
+ };
37
+ }
38
+
39
+ const formattedData = {
40
+ Address: data?.address,
41
+ "Avatar URL": data?.ensInfo?.avatar,
42
+ Description: data?.ensInfo?.description,
43
+ ENS: data?.ensDomain,
44
+ "Primary ENS": data?.ensInfo?.ens_primary,
45
+ GitHub: data?.ensInfo?.github,
46
+ Resolver: data?.ensInfo?.resolverAddress,
47
+ Twitter: data?.ensInfo?.twitter,
48
+ URL: `${ensUrl}${domain}`,
49
+ };
50
+
51
+ let message = "Domain information:\n\n";
52
+ for (const [key, value] of Object.entries(formattedData)) {
53
+ if (value) {
54
+ message += `${key}: ${value}\n`;
55
+ }
56
+ }
57
+ message += `\n\nWould you like to tip the domain owner for getting there first 🤣?`;
58
+ message = message.trim();
59
+ if (await isOnXMTP(context.client, context.v2client, sender?.address)) {
60
+ await context.send(
61
+ `Ah, this domains is in XMTP, you can message it directly: https://converse.xyz/dm/${domain}`,
62
+ );
63
+ }
64
+ return { code: 200, message };
65
+ }
@@ -0,0 +1,40 @@
1
+ import { ensUrl } from "../index.js";
2
+ import { XMTPContext } from "@xmtp/message-kit";
3
+
4
+ import type { skillAction } from "@xmtp/message-kit";
5
+
6
+ export const registerSkill: skillAction[] = [
7
+ {
8
+ skill: "/register [domain]",
9
+ handler: handleRegister,
10
+ description:
11
+ "Register a new ENS domain. Returns a URL to complete the registration process.",
12
+ examples: ["/register vitalik.eth"],
13
+ params: {
14
+ domain: {
15
+ type: "string",
16
+ },
17
+ },
18
+ },
19
+ ];
20
+
21
+ export async function handleRegister(context: XMTPContext) {
22
+ const {
23
+ message: {
24
+ content: {
25
+ params: { domain },
26
+ },
27
+ },
28
+ } = context;
29
+
30
+ if (!domain) {
31
+ return {
32
+ code: 400,
33
+ message: "Missing required parameters. Please provide domain.",
34
+ };
35
+ }
36
+ // Generate URL for the ens
37
+ let url_ens = ensUrl + domain;
38
+ context.send(`${url_ens}`);
39
+ return { code: 200, message: `${url_ens}` };
40
+ }
@@ -0,0 +1,52 @@
1
+ import { frameUrl } from "../index.js";
2
+ import { getUserInfo, XMTPContext } from "@xmtp/message-kit";
3
+
4
+ import type { skillAction } from "@xmtp/message-kit";
5
+
6
+ export const registerSkill: skillAction[] = [
7
+ {
8
+ skill: "/renew [domain]",
9
+ handler: handleRenew,
10
+ description:
11
+ "Extend the registration period of your ENS domain. Returns a URL to complete the renewal.",
12
+ examples: ["/renew fabri.base.eth"],
13
+ params: {
14
+ domain: {
15
+ type: "string",
16
+ },
17
+ },
18
+ },
19
+ ];
20
+
21
+ export async function handleRenew(context: XMTPContext) {
22
+ const {
23
+ message: {
24
+ sender,
25
+ content: {
26
+ params: { domain },
27
+ },
28
+ },
29
+ } = context;
30
+
31
+ // Check if the user holds the domain
32
+ if (!domain) {
33
+ return {
34
+ code: 400,
35
+ message: "Missing required parameters. Please provide domain.",
36
+ };
37
+ }
38
+
39
+ const data = await getUserInfo(domain);
40
+
41
+ if (!data?.address || data?.address !== sender?.address) {
42
+ return {
43
+ code: 403,
44
+ message:
45
+ "Looks like this domain is not registered to you. Only the owner can renew it.",
46
+ };
47
+ }
48
+
49
+ // Generate URL for the ens
50
+ let url_ens = frameUrl + "frames/manage?name=" + domain;
51
+ return { code: 200, message: `${url_ens}` };
52
+ }
@@ -0,0 +1,19 @@
1
+ import { clearInfoCache, clearMemory } from "@xmtp/message-kit";
2
+ import { XMTPContext } from "@xmtp/message-kit";
3
+
4
+ import type { skillAction } from "@xmtp/message-kit";
5
+
6
+ export const registerSkill: skillAction[] = [
7
+ {
8
+ skill: "/reset",
9
+ examples: ["/reset"],
10
+ handler: handleReset,
11
+ description: "Reset the conversation.",
12
+ params: {},
13
+ },
14
+ ];
15
+ export async function handleReset(context: XMTPContext) {
16
+ clearMemory();
17
+ clearInfoCache();
18
+ return { code: 200, message: "Conversation reset." };
19
+ }
@@ -0,0 +1,29 @@
1
+ import { txpayUrl } from "../index.js";
2
+ import { XMTPContext, getUserInfo } from "@xmtp/message-kit";
3
+
4
+ import type { skillAction } from "@xmtp/message-kit";
5
+
6
+ export const registerSkill: skillAction[] = [
7
+ {
8
+ skill: "/tip [address]",
9
+ description: "Show a URL for tipping a domain owner.",
10
+ handler: handleTip,
11
+ examples: ["/tip 0x1234567890123456789012345678901234567890"],
12
+ params: {
13
+ address: {
14
+ type: "string",
15
+ },
16
+ },
17
+ },
18
+ ];
19
+ export async function handleTip(context: XMTPContext) {
20
+ const {
21
+ message: {
22
+ content: {
23
+ params: { address },
24
+ },
25
+ },
26
+ } = context;
27
+ console.log("tip", address);
28
+ await context.sendPay(1, "USDC", address);
29
+ }
@@ -1,55 +1,55 @@
1
- import { run, HandlerContext } from "@xmtp/message-kit";
2
- import { agentRun } from "@xmtp/message-kit";
3
- import { skills } from "./skills.js";
4
- import { defaultPromptTemplate } from "@xmtp/message-kit";
5
-
6
- export async function agent_prompt(senderAddress: string) {
7
- let fineTuning = `
8
- ## Example responses:
9
-
10
- 1. Check if the user does not have a ENS domain
11
- 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
12
-
13
- 2. If the user has a ENS domain
14
- 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}
15
-
16
- 3. Check if the ENS domain is available
17
- 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}
18
-
19
- 4. If the ENS domain is available,
20
- 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!
21
-
22
- 5. If the ENS domain is already registered, let me suggest 5 cool alternatives
23
- Looks like {ENS_DOMAIN} is already registered!\n What about these cool alternatives?\n/cool {ENS_DOMAIN}
24
-
25
- 6. If the user wants to register a ENS domain, use the command "/register [domain]"
26
- Looks like {ENS_DOMAIN} is available! Let me help you register it\n/register {ENS_DOMAIN}
27
-
28
- 7. If the user wants to directly to tip to the ENS domain owner, use directly the command "/tip [address]", this will return a url but a button to send the tip
29
- Here is the url to send the tip:\n/tip 0x...
30
-
31
- 8. If the user wants to get information about the ENS domain, use the command "/info [domain]"
32
- Hello! I'll help you get info about {ENS_DOMAIN}.\n Give me a moment.\n/info {ENS_DOMAIN}
33
-
34
- 9. If the user wants to renew their domain, use the command "/renew [domain]"
35
- 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}
36
-
37
- 10. If the user wants cool suggestions about a domain, use the command "/cool [domain]"
38
- Here are some cool suggestions for your domain.\n/cool {ENS_DOMAIN}
39
-
40
- ## Most common bugs
41
-
42
- 1. Some times you will say something like: "Looks like vitalik.eth is registered! What about these cool alternatives?"
43
- But you forgot to add the command at the end of the message.
44
- You should have said something like: "Looks like vitalik.eth is registered! What about these cool alternatives?\n/cool vitalik.eth
45
- `;
46
-
47
- return defaultPromptTemplate(fineTuning, senderAddress, skills, "@ens");
48
- }
49
-
50
- run(async (context: HandlerContext) => {
51
- agentRun(context, async (address: string) => {
52
- const result = (await agent_prompt(address)) ?? "No response available";
53
- return result;
54
- });
55
- });
1
+ import {
2
+ run,
3
+ agentReply,
4
+ replaceVariables,
5
+ XMTPContext,
6
+ } from "@xmtp/message-kit";
7
+ import { systemPrompt } from "./prompt.js";
8
+ import { registerSkill as checkSkill } from "./handlers/check.js";
9
+ import { registerSkill as coolSkill } from "./handlers/cool.js";
10
+ import { registerSkill as infoSkill } from "./handlers/info.js";
11
+ import { registerSkill as registerSkill } from "./handlers/register.js";
12
+ import { registerSkill as renewSkill } from "./handlers/renew.js";
13
+ import { registerSkill as resetSkill } from "./handlers/reset.js";
14
+ import { registerSkill as tipSkill } from "./handlers/tip.js";
15
+ import fs from "fs";
16
+
17
+ export const frameUrl = "https://ens.steer.fun/";
18
+ export const ensUrl = "https://app.ens.domains/";
19
+ export const txpayUrl = "https://txpay.vercel.app";
20
+
21
+ export const skills = [
22
+ {
23
+ name: "Ens Domain Bot",
24
+ tag: "@ens",
25
+ description: "Register ENS domains.",
26
+ skills: [
27
+ ...checkSkill,
28
+ ...coolSkill,
29
+ ...infoSkill,
30
+ ...registerSkill,
31
+ ...renewSkill,
32
+ ...resetSkill,
33
+ ...tipSkill,
34
+ ],
35
+ },
36
+ ];
37
+
38
+ run(
39
+ async (context: XMTPContext) => {
40
+ const {
41
+ message: { sender },
42
+ skills,
43
+ } = context;
44
+
45
+ let prompt = await replaceVariables(
46
+ systemPrompt,
47
+ sender.address,
48
+ skills,
49
+ "@ens",
50
+ );
51
+ fs.writeFileSync("example_prompt.md", prompt);
52
+ await agentReply(context, prompt);
53
+ },
54
+ { skills },
55
+ );
@@ -0,0 +1,52 @@
1
+ export const systemPrompt = `
2
+ Your are helpful and playful agent called {agent_name} that lives inside a web3 messaging app called Converse.
3
+
4
+ {rules}
5
+
6
+ {user_context}
7
+
8
+ {skills}
9
+
10
+ ## Response Scenarios:
11
+
12
+ 1. When greeting or when the user asks for an ENS domain, check if the user does not have an ENS domain:
13
+ Hey {name}! It looks like you don't have an ENS domain yet!
14
+ Let me start by checking your Converse username with the .eth suffix
15
+ /check localdev6.eth
16
+ 2. If the user has an ENS domain:
17
+ I'll help you get your ENS domain.
18
+ Let's start by checking your ENS domain. Give me a moment.
19
+ /check [domain]
20
+ 3. Check if the ENS domain is available:
21
+ Hello! I'll help you get your domain.
22
+ Let's start by checking your ENS domain. Give me a moment.
23
+ /check [domain]
24
+ 4. If the ENS domain is available:
25
+ Looks like [domain] is available! Here you can register it:
26
+ /register [domain]
27
+ Or I can suggest some cool alternatives? Let me know!
28
+ 5. If the ENS domain is already registered, suggest 5 cool alternatives:
29
+ Looks like [domain] is already registered!
30
+ What about these cool alternatives?
31
+ /cool [domain]
32
+ 6. If the user wants to register an ENS domain:
33
+ Looks like [domain] is available! Let me help you register it.
34
+ /register [domain]
35
+ 7. If the user wants to directly tip the ENS domain owner:
36
+ Here is the URL to send the tip:
37
+ /tip [address]
38
+ 8. If the user wants to get information about the ENS domain:
39
+ Hello! I'll help you get info about [domain].
40
+ Give me a moment.
41
+ /info [domain]
42
+ 9. If the user wants to renew their domain:
43
+ Hello! I'll help you get your ENS domain.
44
+ Let's start by checking your ENS domain. Give me a moment.
45
+ /renew [domain]
46
+ 10. If the user wants cool suggestions about a domain:
47
+ Here are some cool suggestions for your domain.
48
+ /cool [domain]
49
+
50
+ ## Most common bugs
51
+ 1. Some times you will say something like: "Looks like vitalik.eth is registered! What about these cool alternatives?" But you forgot to add the command at the end of the message.
52
+ `;
@@ -0,0 +1,3 @@
1
+ KEY= # the private key of the bot wallet
2
+ PORT= # the port of the server
3
+ ALCHEMY_API_KEY= # the alchemy api key
@@ -0,0 +1,4 @@
1
+ compressionLevel: mixed
2
+ enableGlobalCache: false
3
+ enableTelemetry: false
4
+ nodeLinker: node-modules
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "gated",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "build": "tsc",
7
+ "dev": "tsc -w & sleep 1 && node --watch dist/index.js",
8
+ "start": "node dist/index.js"
9
+ },
10
+ "dependencies": {
11
+ "@xmtp/message-kit": "workspace:*",
12
+ "alchemy-sdk": "^3.4.3",
13
+ "express": "^4.19.2"
14
+ },
15
+ "devDependencies": {
16
+ "@types/express": "^4",
17
+ "@types/node": "^20.14.2",
18
+ "typescript": "^5.4.5"
19
+ },
20
+ "engines": {
21
+ "node": ">=20"
22
+ }
23
+ }