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 +10 -34
- package/package.json +1 -1
- package/templates/agent/.yarnrc.yml +4 -0
- package/templates/agent/package.json +21 -0
- package/templates/agent/src/index.ts +9 -4
- package/templates/agent/src/prompt.ts +1 -1
- package/templates/gated/.env.example +3 -0
- package/templates/gated/.yarnrc.yml +4 -0
- package/templates/gated/package.json +24 -0
- package/templates/gated/src/index.ts +64 -0
- package/templates/gated/src/lib/gated.ts +51 -0
- package/templates/gated/src/lib/nft.ts +37 -0
- package/templates/gated/src/skills.ts +24 -0
- package/templates/gpt/.yarnrc.yml +4 -0
- package/templates/gpt/package.json +21 -0
- package/templates/gpt/src/index.ts +8 -9
- package/templates/group/.yarnrc.yml +4 -0
- package/templates/group/package.json +21 -0
- package/templates/group/src/handlers/helpers.ts +2 -2
- package/templates/group/src/handlers/tipping.ts +1 -2
- package/templates/group/src/index.ts +9 -4
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
|
-
|
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
|
67
|
+
async function updatePackagejson(destDir, templateType) {
|
68
68
|
// Create package.json based on the template
|
69
|
-
|
70
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
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
@@ -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 {
|
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
|
-
|
42
|
+
skills,
|
38
43
|
} = context;
|
39
44
|
|
40
45
|
let prompt = await replaceVariables(
|
41
46
|
systemPrompt,
|
42
47
|
sender.address,
|
43
|
-
|
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.
|
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,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,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 {
|
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,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
|
-
|
28
|
+
skills,
|
29
29
|
} = context;
|
30
30
|
|
31
31
|
if (skill == "help") {
|
32
32
|
const intro =
|
33
33
|
"Available experiences:\n" +
|
34
|
-
|
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 {
|
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 {
|
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
|
-
|
26
|
+
skills,
|
22
27
|
} = context;
|
23
28
|
|
24
29
|
let prompt = await replaceVariables(
|
25
30
|
systemPrompt,
|
26
31
|
sender.address,
|
27
|
-
|
32
|
+
skills,
|
28
33
|
"@bot",
|
29
34
|
);
|
30
35
|
await agentReply(context, prompt);
|