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

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 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,14 @@ 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 = `yarn@4.5.1`;
93
- }
69
+ const templateDir = resolve(__dirname, `./templates/${templateType}`);
70
+ const packageTemplate = fs.readJsonSync(`${templateDir}/package.json`);
94
71
 
95
- // Add .yarnrc.yml just in caseto disable PnP mode
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.packageManager = `yarn@4.5.1`;
100
75
 
101
76
  fs.writeJsonSync(resolve(destDir, "package.json"), packageTemplate, {
102
77
  spaces: 2,
@@ -106,8 +81,9 @@ async function addPackagejson(destDir, name, pkgManager) {
106
81
  async function gatherProjectInfo() {
107
82
  const templateOptions = [
108
83
  { value: "gpt", label: "Simple Gpt" },
109
- { value: "agent", label: "Agent" },
110
- { value: "group", label: "Group" },
84
+ { value: "agent", label: "ENS Agent" },
85
+ { value: "group", label: "Group bot" },
86
+ { value: "gated", label: "Gated Group" },
111
87
  ];
112
88
 
113
89
  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-beta.2",
3
+ "version": "1.1.9-beta.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -0,0 +1,4 @@
1
+ compressionLevel: mixed
2
+ enableGlobalCache: false
3
+ enableTelemetry: false
4
+ nodeLinker: node-modules
@@ -0,0 +1,21 @@
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
+ "postinstall": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@xmtp/message-kit": "workspace:*"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^20.14.2",
16
+ "typescript": "^5.4.5"
17
+ },
18
+ "engines": {
19
+ "node": ">=20"
20
+ }
21
+ }
@@ -1,4 +1,9 @@
1
- import { run, agentReply, replaceVariables } from "@xmtp/message-kit";
1
+ import {
2
+ run,
3
+ agentReply,
4
+ replaceVariables,
5
+ XMTPContext,
6
+ } from "@xmtp/message-kit";
2
7
  import { systemPrompt } from "./prompt.js";
3
8
  import { registerSkill as checkSkill } from "./handlers/check.js";
4
9
  import { registerSkill as coolSkill } from "./handlers/cool.js";
@@ -31,16 +36,16 @@ export const skills = [
31
36
  ];
32
37
 
33
38
  run(
34
- async (context) => {
39
+ async (context: XMTPContext) => {
35
40
  const {
36
41
  message: { sender },
37
- runConfig,
42
+ skills,
38
43
  } = context;
39
44
 
40
45
  let prompt = await replaceVariables(
41
46
  systemPrompt,
42
47
  sender.address,
43
- runConfig?.skills,
48
+ skills,
44
49
  "@ens",
45
50
  );
46
51
  fs.writeFileSync("example_prompt.md", prompt);
@@ -48,5 +48,5 @@ Your are helpful and playful agent called {agent_name} that lives inside a web3
48
48
  /cool [domain]
49
49
 
50
50
  ## Most common bugs
51
- 1. Sometimes 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.
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
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,24 @@
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
+ "postinstall": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@xmtp/message-kit": "workspace:*",
13
+ "alchemy-sdk": "^3.4.3",
14
+ "express": "^4.19.2"
15
+ },
16
+ "devDependencies": {
17
+ "@types/express": "^4",
18
+ "@types/node": "^20.14.2",
19
+ "typescript": "^5.4.5"
20
+ },
21
+ "engines": {
22
+ "node": ">=20"
23
+ }
24
+ }
@@ -0,0 +1,64 @@
1
+ import { run, xmtpClient, XMTPContext } from "@xmtp/message-kit";
2
+ import { Client } from "@xmtp/node-sdk";
3
+ import { startServer } from "./lib/gated.js";
4
+ import { verifiedRequest } from "./lib/nft.js";
5
+ const { client } = await xmtpClient({ hideInitLogMessage: true });
6
+ startServer(client, verifiedRequest);
7
+
8
+ run(async (context: XMTPContext) => {
9
+ const {
10
+ message: {
11
+ sender,
12
+ content: { skill },
13
+ },
14
+ client,
15
+ group,
16
+ } = context;
17
+
18
+ if (skill == "id") {
19
+ console.log(group?.id);
20
+ } else if (skill === "create") {
21
+ await context.send("Creating group...");
22
+ const group = await createGroup(
23
+ client,
24
+ sender.address,
25
+ client.accountAddress,
26
+ );
27
+
28
+ await context.send(
29
+ `Group created!\n- ID: ${group.id}\n- Group Frame URL: https://converse.xyz/group/${group.id}: \n- This url will deelink to the group inside Converse\n- Once in the other group you can share the invite with your friends.`,
30
+ );
31
+ return;
32
+ } else {
33
+ await context.send(
34
+ "👋 Welcome to the Gated Bot Group!\nTo get started, type /create to set up a new group. 🚀\nThis example will check if the user has a particular nft and add them to the group if they do.\nOnce your group is created, you'll receive a unique Group ID and URL.\nShare the URL with friends to invite them to join your group!",
35
+ );
36
+ }
37
+ });
38
+
39
+ async function createGroup(
40
+ client: Client,
41
+ senderAddress: string,
42
+ clientAddress: string,
43
+ ) {
44
+ let senderInboxId = "";
45
+ const group = await client?.conversations.newConversation([
46
+ senderAddress,
47
+ clientAddress,
48
+ ]);
49
+ const members = await group.members();
50
+ const senderMember = members.find((member) =>
51
+ member.accountAddresses.includes(senderAddress.toLowerCase()),
52
+ );
53
+ if (senderMember) {
54
+ const senderInboxId = senderMember.inboxId;
55
+ console.log("Sender's inboxId:", senderInboxId);
56
+ } else {
57
+ console.log("Sender not found in members list");
58
+ }
59
+ await group.addSuperAdmin(senderInboxId);
60
+ console.log("Sender is superAdmin", await group.isSuperAdmin(senderInboxId));
61
+ await group.send(`Welcome to the new group!`);
62
+ await group.send(`You are now the admin of this group as well as the bot`);
63
+ return group;
64
+ }
@@ -0,0 +1,51 @@
1
+ // Import necessary modules
2
+ import express from "express";
3
+ import { Client } from "@xmtp/node-sdk";
4
+
5
+ export function startServer(
6
+ client: Client,
7
+ verifiedRequest: (walletAddress: string, groupId: string) => Promise<boolean>,
8
+ ) {
9
+ async function addWalletToGroup(
10
+ walletAddress: string,
11
+ groupId: string,
12
+ ): Promise<string> {
13
+ const conversation =
14
+ await client.conversations.getConversationById(groupId);
15
+ const verified = await verifiedRequest(walletAddress, groupId);
16
+ if (!verified) {
17
+ console.log("User cant be added to the group");
18
+ return "not verified";
19
+ } else {
20
+ try {
21
+ await conversation?.addMembers([walletAddress]);
22
+ console.log(`Added wallet address: ${walletAddress} to the group`);
23
+ return "success";
24
+ } catch (error: any) {
25
+ console.log(error.message);
26
+ return "error";
27
+ }
28
+ }
29
+ }
30
+
31
+ // Endpoint to add wallet address to a group from an external source
32
+ const app = express();
33
+ app.use(express.json());
34
+ app.post("/add-wallet", async (req, res) => {
35
+ try {
36
+ const { walletAddress, groupId } = req.body;
37
+ const result = await addWalletToGroup(walletAddress, groupId);
38
+ res.status(200).send(result);
39
+ } catch (error: any) {
40
+ res.status(400).send(error.message);
41
+ }
42
+ });
43
+ // Start the server
44
+ const PORT = process.env.PORT || 3000;
45
+ const url = process.env.URL || `http://localhost:${PORT}`;
46
+ app.listen(PORT, () => {
47
+ console.warn(
48
+ `Use this endpoint to add a wallet to a group indicated by the groupId\n${url}/add-wallet <body: {walletAddress, groupId}>`,
49
+ );
50
+ });
51
+ }
@@ -0,0 +1,37 @@
1
+ import { Alchemy, Network } from "alchemy-sdk";
2
+
3
+ const settings = {
4
+ apiKey: process.env.ALCHEMY_API_KEY, // Replace with your Alchemy API key
5
+ network: Network.BASE_MAINNET, // Use the appropriate network
6
+ };
7
+
8
+ export async function verifiedRequest(
9
+ walletAddress: string,
10
+ groupId: string
11
+ ): Promise<boolean> {
12
+ console.log("new-request", {
13
+ groupId,
14
+ walletAddress,
15
+ });
16
+
17
+ const alchemy = new Alchemy(settings);
18
+ try {
19
+ const nfts = await alchemy.nft.getNftsForOwner(walletAddress);
20
+ const collectionSlug = "XMTPeople"; // The slug for the collection
21
+
22
+ const ownsNft = nfts.ownedNfts.some(
23
+ (nft: any) =>
24
+ nft.contract.name.toLowerCase() === collectionSlug.toLowerCase()
25
+ );
26
+ console.log(
27
+ `NFTs owned on ${Network.BASE_MAINNET}:`,
28
+ nfts.ownedNfts.length
29
+ );
30
+ console.log("is the nft owned: ", ownsNft);
31
+ return ownsNft as boolean;
32
+ } catch (error) {
33
+ console.error("Error fetching NFTs from Alchemy:", error);
34
+ }
35
+
36
+ return false;
37
+ }
@@ -0,0 +1,24 @@
1
+ import type { SkillGroup } from "@xmtp/message-kit";
2
+
3
+ export const skills: SkillGroup[] = [
4
+ {
5
+ name: "Group Id",
6
+ description: "Create and get group id.",
7
+ skills: [
8
+ {
9
+ skill: "/create",
10
+ examples: ["/create"],
11
+ adminOnly: true,
12
+ params: {},
13
+ description: "Create a new group.",
14
+ },
15
+ {
16
+ skill: "/id",
17
+ examples: ["/id"],
18
+ adminOnly: true,
19
+ params: {},
20
+ description: "Get group id.",
21
+ },
22
+ ],
23
+ },
24
+ ];
@@ -0,0 +1,4 @@
1
+ compressionLevel: mixed
2
+ enableGlobalCache: false
3
+ enableTelemetry: false
4
+ nodeLinker: node-modules
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "gpt",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "build": "tsc",
7
+ "dev": "tsc -w & sleep 1 && node --watch dist/index.js",
8
+ "postinstall": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@xmtp/message-kit": "workspace:*"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^20.14.2",
16
+ "typescript": "^5.4.5"
17
+ },
18
+ "engines": {
19
+ "node": ">=20"
20
+ }
21
+ }
@@ -1,18 +1,17 @@
1
- import { run, agentReply, replaceVariables } from "@xmtp/message-kit";
1
+ import {
2
+ run,
3
+ agentReply,
4
+ replaceVariables,
5
+ XMTPContext,
6
+ } from "@xmtp/message-kit";
2
7
 
3
8
  import { systemPrompt } from "./prompt.js";
4
9
 
5
- run(async (context) => {
10
+ run(async (context: XMTPContext) => {
6
11
  const {
7
12
  message: { sender },
8
- runConfig,
9
13
  } = context;
10
14
 
11
- let prompt = await replaceVariables(
12
- systemPrompt,
13
- sender.address,
14
- runConfig?.skills,
15
- "@bot",
16
- );
15
+ let prompt = await replaceVariables(systemPrompt, sender.address, [], "@bot");
17
16
  await agentReply(context, prompt);
18
17
  });
@@ -0,0 +1,4 @@
1
+ compressionLevel: mixed
2
+ enableGlobalCache: false
3
+ enableTelemetry: false
4
+ nodeLinker: node-modules
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "group",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "build": "tsc",
7
+ "dev": "tsc -w & sleep 1 && node --watch dist/index.js",
8
+ "postinstall": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@xmtp/message-kit": "workspace:*"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^20.14.2",
16
+ "typescript": "^5.4.5"
17
+ },
18
+ "engines": {
19
+ "node": ">=20"
20
+ }
21
+ }
@@ -25,13 +25,13 @@ export async function handleHelp(context: XMTPContext) {
25
25
  content: { skill },
26
26
  },
27
27
  group,
28
- runConfig,
28
+ skills,
29
29
  } = context;
30
30
 
31
31
  if (skill == "help") {
32
32
  const intro =
33
33
  "Available experiences:\n" +
34
- runConfig?.skills
34
+ skills
35
35
  ?.flatMap((app) => app.skills)
36
36
  .map((skill) => `${skill.skill} - ${skill.description}`)
37
37
  .join("\n") +
@@ -1,5 +1,4 @@
1
- import { XMTPContext, AbstractedMember } from "@xmtp/message-kit";
2
- import { getUserInfo } from "@xmtp/message-kit";
1
+ import { getUserInfo, AbstractedMember, XMTPContext } from "@xmtp/message-kit";
3
2
  import type { skillAction } from "@xmtp/message-kit";
4
3
 
5
4
  export const registerSkill: skillAction[] = [
@@ -1,4 +1,9 @@
1
- import { run, agentReply, replaceVariables } from "@xmtp/message-kit";
1
+ import {
2
+ run,
3
+ agentReply,
4
+ XMTPContext,
5
+ replaceVariables,
6
+ } from "@xmtp/message-kit";
2
7
  import { registerSkill as tippingSkill } from "./handlers/tipping.js";
3
8
  import { registerSkill as paymentSkill } from "./handlers/payment.js";
4
9
  import { registerSkill as gameSkill } from "./handlers/game.js";
@@ -15,16 +20,16 @@ export const skills = [
15
20
  ];
16
21
 
17
22
  run(
18
- async (context) => {
23
+ async (context: XMTPContext) => {
19
24
  const {
20
25
  message: { sender },
21
- runConfig,
26
+ skills,
22
27
  } = context;
23
28
 
24
29
  let prompt = await replaceVariables(
25
30
  systemPrompt,
26
31
  sender.address,
27
- runConfig?.skills,
32
+ skills,
28
33
  "@bot",
29
34
  );
30
35
  await agentReply(context, prompt);