create-message-kit 1.1.8 → 1.1.9-beta.2
Sign up to get free protection for your applications and to get access to all the features.
- package/index.js +32 -12
- package/package.json +2 -2
- package/templates/agent/src/handlers/check.ts +43 -0
- package/templates/agent/src/handlers/cool.ts +52 -0
- package/templates/agent/src/handlers/info.ts +65 -0
- package/templates/agent/src/handlers/register.ts +40 -0
- package/templates/agent/src/handlers/renew.ts +52 -0
- package/templates/agent/src/handlers/reset.ts +19 -0
- package/templates/agent/src/handlers/tip.ts +42 -0
- package/templates/agent/src/index.ts +46 -27
- package/templates/agent/src/prompt.ts +49 -66
- package/templates/gpt/.env.example +2 -0
- package/templates/gpt/src/index.ts +18 -0
- package/templates/gpt/src/prompt.ts +10 -0
- package/templates/group/src/{handler → handlers}/game.ts +19 -3
- package/templates/group/src/{handler → handlers}/helpers.ts +23 -4
- package/templates/group/src/handlers/payment.ts +51 -0
- package/templates/group/src/handlers/tipping.ts +61 -0
- package/templates/group/src/index.ts +29 -27
- package/templates/group/src/prompt.ts +24 -36
- package/templates/agent/src/handler/ens.ts +0 -175
- package/templates/agent/src/skills.ts +0 -107
- package/templates/gm/.env.example +0 -1
- package/templates/gm/src/index.ts +0 -5
- package/templates/group/src/handler/payment.ts +0 -29
- package/templates/group/src/handler/tipping.ts +0 -40
- package/templates/group/src/skills.ts +0 -87
@@ -1,18 +1,37 @@
|
|
1
|
-
import {
|
1
|
+
import { XMTPContext } from "@xmtp/message-kit";
|
2
2
|
|
3
|
-
|
3
|
+
import type { skillAction } from "@xmtp/message-kit";
|
4
|
+
|
5
|
+
export const registerSkill: skillAction[] = [
|
6
|
+
{
|
7
|
+
skill: "/help",
|
8
|
+
examples: ["/help"],
|
9
|
+
handler: handleHelp,
|
10
|
+
description: "Get help with the bot.",
|
11
|
+
params: {},
|
12
|
+
},
|
13
|
+
{
|
14
|
+
skill: "/id",
|
15
|
+
examples: ["/id"],
|
16
|
+
handler: handleHelp,
|
17
|
+
description: "Get the group ID.",
|
18
|
+
params: {},
|
19
|
+
},
|
20
|
+
];
|
21
|
+
|
22
|
+
export async function handleHelp(context: XMTPContext) {
|
4
23
|
const {
|
5
|
-
skills,
|
6
24
|
message: {
|
7
25
|
content: { skill },
|
8
26
|
},
|
9
27
|
group,
|
28
|
+
runConfig,
|
10
29
|
} = context;
|
11
30
|
|
12
31
|
if (skill == "help") {
|
13
32
|
const intro =
|
14
33
|
"Available experiences:\n" +
|
15
|
-
skills
|
34
|
+
runConfig?.skills
|
16
35
|
?.flatMap((app) => app.skills)
|
17
36
|
.map((skill) => `${skill.skill} - ${skill.description}`)
|
18
37
|
.join("\n") +
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import { getUserInfo, XMTPContext } from "@xmtp/message-kit";
|
2
|
+
import type { skillAction } from "@xmtp/message-kit";
|
3
|
+
export const registerSkill: skillAction[] = [
|
4
|
+
{
|
5
|
+
skill: "/pay [amount] [token] [username]",
|
6
|
+
examples: ["/pay 10 usdc vitalik.eth", "/pay 1 @alix"],
|
7
|
+
description:
|
8
|
+
"Send a specified amount of a cryptocurrency to a destination address.",
|
9
|
+
handler: handlePay,
|
10
|
+
params: {
|
11
|
+
amount: {
|
12
|
+
default: 10,
|
13
|
+
type: "number",
|
14
|
+
},
|
15
|
+
token: {
|
16
|
+
default: "usdc",
|
17
|
+
type: "string",
|
18
|
+
values: ["eth", "dai", "usdc", "degen"], // Accepted tokens
|
19
|
+
},
|
20
|
+
username: {
|
21
|
+
default: "",
|
22
|
+
type: "username",
|
23
|
+
},
|
24
|
+
},
|
25
|
+
},
|
26
|
+
];
|
27
|
+
|
28
|
+
export async function handlePay(context: XMTPContext) {
|
29
|
+
const {
|
30
|
+
message: {
|
31
|
+
content: { params },
|
32
|
+
},
|
33
|
+
} = context;
|
34
|
+
const txpayUrl = "https://txpay.vercel.app";
|
35
|
+
|
36
|
+
const { amount: amountSend, token: tokenSend, username } = params;
|
37
|
+
let senderInfo = await getUserInfo(username);
|
38
|
+
if (!amountSend || !tokenSend || !senderInfo) {
|
39
|
+
context.reply(
|
40
|
+
"Missing required parameters. Please provide amount, token, and username.",
|
41
|
+
);
|
42
|
+
return {
|
43
|
+
code: 400,
|
44
|
+
message:
|
45
|
+
"Missing required parameters. Please provide amount, token, and username.",
|
46
|
+
};
|
47
|
+
}
|
48
|
+
|
49
|
+
let sendUrl = `${txpayUrl}/?&amount=${amountSend}&token=${tokenSend}&receiver=${senderInfo.address}`;
|
50
|
+
await context.send(`${sendUrl}`);
|
51
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { XMTPContext, AbstractedMember } from "@xmtp/message-kit";
|
2
|
+
import { getUserInfo } from "@xmtp/message-kit";
|
3
|
+
import type { skillAction } from "@xmtp/message-kit";
|
4
|
+
|
5
|
+
export const registerSkill: skillAction[] = [
|
6
|
+
{
|
7
|
+
skill: "/tip [usernames] [amount] [token]",
|
8
|
+
examples: ["/tip @vitalik 10 usdc"],
|
9
|
+
description: "Tip users in a specified token.",
|
10
|
+
handler: handleTipping,
|
11
|
+
params: {
|
12
|
+
username: {
|
13
|
+
default: "",
|
14
|
+
plural: true,
|
15
|
+
type: "username",
|
16
|
+
},
|
17
|
+
amount: {
|
18
|
+
default: 10,
|
19
|
+
type: "number",
|
20
|
+
},
|
21
|
+
token: {
|
22
|
+
default: "usdc",
|
23
|
+
type: "string",
|
24
|
+
values: ["eth", "dai", "usdc", "degen"],
|
25
|
+
},
|
26
|
+
},
|
27
|
+
},
|
28
|
+
];
|
29
|
+
|
30
|
+
export async function handleTipping(context: XMTPContext) {
|
31
|
+
const {
|
32
|
+
message: {
|
33
|
+
content: {
|
34
|
+
skill,
|
35
|
+
params: { amount, username },
|
36
|
+
},
|
37
|
+
sender,
|
38
|
+
},
|
39
|
+
} = context;
|
40
|
+
let receivers: AbstractedMember[] = [];
|
41
|
+
|
42
|
+
receivers = await Promise.all(
|
43
|
+
username.map((username: string) => getUserInfo(username)),
|
44
|
+
);
|
45
|
+
|
46
|
+
if (!sender || receivers.length === 0 || amount === 0) {
|
47
|
+
context.reply("Sender or receiver or amount not found.");
|
48
|
+
}
|
49
|
+
const receiverAddresses = receivers.map((receiver) => receiver.address);
|
50
|
+
|
51
|
+
context.sendTo(
|
52
|
+
`You received ${amount} tokens from ${sender.address}.`,
|
53
|
+
receiverAddresses,
|
54
|
+
);
|
55
|
+
|
56
|
+
// Notify sender of the transaction details
|
57
|
+
context.sendTo(
|
58
|
+
`You sent ${amount * receiverAddresses.length} tokens in total.`,
|
59
|
+
[sender.address],
|
60
|
+
);
|
61
|
+
}
|
@@ -1,31 +1,33 @@
|
|
1
|
-
import { run,
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import {
|
1
|
+
import { run, agentReply, replaceVariables } from "@xmtp/message-kit";
|
2
|
+
import { registerSkill as tippingSkill } from "./handlers/tipping.js";
|
3
|
+
import { registerSkill as paymentSkill } from "./handlers/payment.js";
|
4
|
+
import { registerSkill as gameSkill } from "./handlers/game.js";
|
5
|
+
import { registerSkill as helperSkill } from "./handlers/helpers.js";
|
6
|
+
import { systemPrompt } from "./prompt.js";
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
8
|
+
export const skills = [
|
9
|
+
{
|
10
|
+
name: "Group bot",
|
11
|
+
tag: "@bot",
|
12
|
+
description: "Group agent for tipping payments, games and more.",
|
13
|
+
skills: [...tippingSkill, ...paymentSkill, ...gameSkill, ...helperSkill],
|
14
|
+
},
|
15
|
+
];
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
const
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
run(
|
18
|
+
async (context) => {
|
19
|
+
const {
|
20
|
+
message: { sender },
|
21
|
+
runConfig,
|
22
|
+
} = context;
|
23
|
+
|
24
|
+
let prompt = await replaceVariables(
|
25
|
+
systemPrompt,
|
22
26
|
sender.address,
|
23
|
-
|
24
|
-
|
27
|
+
runConfig?.skills,
|
28
|
+
"@bot",
|
25
29
|
);
|
26
|
-
await
|
27
|
-
}
|
28
|
-
|
29
|
-
|
30
|
-
}
|
31
|
-
});
|
30
|
+
await agentReply(context, prompt);
|
31
|
+
},
|
32
|
+
{ skills },
|
33
|
+
);
|
@@ -1,45 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
}
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
let fineTunedPrompt = `
|
17
|
-
## Example response
|
18
|
-
|
19
|
-
1. If user wants to play a game, use the skill 'game' and specify the game type.
|
20
|
-
Hey! Sure let's do that.\n/game wordle
|
1
|
+
export const systemPrompt = `
|
2
|
+
{persona}
|
3
|
+
|
4
|
+
{rules}
|
5
|
+
|
6
|
+
{user_context}
|
7
|
+
|
8
|
+
{skills}
|
9
|
+
|
10
|
+
## Response Scenarios
|
11
|
+
|
12
|
+
1. If the user wants to play a game suggest direcly a game like wordle:
|
13
|
+
Let's play wordle!
|
14
|
+
/game wordle
|
21
15
|
|
22
16
|
2. When user wants to pay a specific token:
|
23
|
-
I'll help you pay 1 USDC to 0x123
|
17
|
+
I'll help you pay 1 USDC to 0x123...
|
18
|
+
/pay 1 [token] 0x123456789...
|
24
19
|
*This will return a url to pay
|
25
20
|
|
26
21
|
3. If the user wants to pay a eth domain:
|
27
|
-
I'll help you pay 1 USDC to vitalik.eth
|
22
|
+
I'll help you pay 1 USDC to vitalik.eth
|
23
|
+
Be aware that this only works on mobile with a installed wallet on Base network
|
24
|
+
/pay 1 vitalik.eth
|
28
25
|
*This will return a url to pay
|
29
26
|
|
30
27
|
4. If the user wants to pay a username:
|
31
|
-
I'll help you pay 1 USDC to @fabri
|
28
|
+
I'll help you pay 1 USDC to @fabri
|
29
|
+
Be aware that this only works on mobile with a installed wallet on Base network
|
30
|
+
/pay 1 @fabri
|
32
31
|
*This will return a url to pay
|
33
|
-
|
34
|
-
|
35
|
-
systemPrompt += fineTunedPrompt;
|
36
|
-
// Replace the variables in the system prompt
|
37
|
-
systemPrompt = PROMPT_REPLACE_VARIABLES(
|
38
|
-
systemPrompt,
|
39
|
-
userInfo?.address ?? "",
|
40
|
-
userInfo,
|
41
|
-
"@bot",
|
42
|
-
);
|
43
|
-
console.log(systemPrompt);
|
44
|
-
return systemPrompt;
|
45
|
-
}
|
32
|
+
|
33
|
+
`;
|
@@ -1,175 +0,0 @@
|
|
1
|
-
import { HandlerContext, SkillResponse } from "@xmtp/message-kit";
|
2
|
-
import { getUserInfo, clearInfoCache, isOnXMTP } from "@xmtp/message-kit";
|
3
|
-
import { isAddress } from "viem";
|
4
|
-
import { clearMemory } from "@xmtp/message-kit";
|
5
|
-
|
6
|
-
export const frameUrl = "https://ens.steer.fun/";
|
7
|
-
export const ensUrl = "https://app.ens.domains/";
|
8
|
-
export const baseTxUrl = "https://base-tx-frame.vercel.app";
|
9
|
-
|
10
|
-
export async function handleEns(
|
11
|
-
context: HandlerContext,
|
12
|
-
): Promise<SkillResponse | undefined> {
|
13
|
-
const {
|
14
|
-
message: {
|
15
|
-
sender,
|
16
|
-
content: { skill, params },
|
17
|
-
},
|
18
|
-
} = context;
|
19
|
-
|
20
|
-
if (skill == "reset") {
|
21
|
-
clearMemory();
|
22
|
-
return { code: 200, message: "Conversation reset." };
|
23
|
-
} else if (skill == "renew") {
|
24
|
-
// Destructure and validate parameters for the ens
|
25
|
-
const { domain } = params;
|
26
|
-
// Check if the user holds the domain
|
27
|
-
if (!domain) {
|
28
|
-
return {
|
29
|
-
code: 400,
|
30
|
-
message: "Missing required parameters. Please provide domain.",
|
31
|
-
};
|
32
|
-
}
|
33
|
-
|
34
|
-
const data = await getUserInfo(domain);
|
35
|
-
|
36
|
-
if (!data?.address || data?.address !== sender?.address) {
|
37
|
-
return {
|
38
|
-
code: 403,
|
39
|
-
message:
|
40
|
-
"Looks like this domain is not registered to you. Only the owner can renew it.",
|
41
|
-
};
|
42
|
-
}
|
43
|
-
|
44
|
-
// Generate URL for the ens
|
45
|
-
let url_ens = frameUrl + "frames/manage?name=" + domain;
|
46
|
-
return { code: 200, message: `${url_ens}` };
|
47
|
-
} else if (skill == "register") {
|
48
|
-
// Destructure and validate parameters for the ens
|
49
|
-
const { domain } = params;
|
50
|
-
|
51
|
-
if (!domain) {
|
52
|
-
return {
|
53
|
-
code: 400,
|
54
|
-
message: "Missing required parameters. Please provide domain.",
|
55
|
-
};
|
56
|
-
}
|
57
|
-
// Generate URL for the ens
|
58
|
-
let url_ens = ensUrl + domain;
|
59
|
-
return { code: 200, message: `${url_ens}` };
|
60
|
-
} else if (skill == "info") {
|
61
|
-
const { domain } = params;
|
62
|
-
|
63
|
-
const data = await getUserInfo(domain);
|
64
|
-
if (!data?.ensDomain) {
|
65
|
-
return {
|
66
|
-
code: 404,
|
67
|
-
message: "Domain not found.",
|
68
|
-
};
|
69
|
-
}
|
70
|
-
|
71
|
-
const formattedData = {
|
72
|
-
Address: data?.address,
|
73
|
-
"Avatar URL": data?.ensInfo?.avatar,
|
74
|
-
Description: data?.ensInfo?.description,
|
75
|
-
ENS: data?.ensDomain,
|
76
|
-
"Primary ENS": data?.ensInfo?.ens_primary,
|
77
|
-
GitHub: data?.ensInfo?.github,
|
78
|
-
Resolver: data?.ensInfo?.resolverAddress,
|
79
|
-
Twitter: data?.ensInfo?.twitter,
|
80
|
-
URL: `${ensUrl}${domain}`,
|
81
|
-
};
|
82
|
-
|
83
|
-
let message = "Domain information:\n\n";
|
84
|
-
for (const [key, value] of Object.entries(formattedData)) {
|
85
|
-
if (value) {
|
86
|
-
message += `${key}: ${value}\n`;
|
87
|
-
}
|
88
|
-
}
|
89
|
-
message += `\n\nWould you like to tip the domain owner for getting there first 🤣?`;
|
90
|
-
message = message.trim();
|
91
|
-
if (await isOnXMTP(context.client, context.v2client, sender?.address)) {
|
92
|
-
await context.send(
|
93
|
-
`Ah, this domains is in XMTP, you can message it directly: https://converse.xyz/dm/${domain}`,
|
94
|
-
);
|
95
|
-
}
|
96
|
-
return { code: 200, message };
|
97
|
-
} else if (skill == "check") {
|
98
|
-
const { domain } = params;
|
99
|
-
|
100
|
-
if (!domain) {
|
101
|
-
return {
|
102
|
-
code: 400,
|
103
|
-
message: "Please provide a domain name to check.",
|
104
|
-
};
|
105
|
-
}
|
106
|
-
|
107
|
-
const data = await getUserInfo(domain);
|
108
|
-
if (!data?.address) {
|
109
|
-
let message = `Looks like ${domain} is available! Here you can register it: ${ensUrl}${domain} or would you like to see some cool alternatives?`;
|
110
|
-
return {
|
111
|
-
code: 200,
|
112
|
-
message,
|
113
|
-
};
|
114
|
-
} else {
|
115
|
-
let message = `Looks like ${domain} is already registered!`;
|
116
|
-
await context.executeSkill("/cool " + domain);
|
117
|
-
return {
|
118
|
-
code: 404,
|
119
|
-
message,
|
120
|
-
};
|
121
|
-
}
|
122
|
-
} else if (skill == "tip") {
|
123
|
-
const { address } = params;
|
124
|
-
if (!address) {
|
125
|
-
return {
|
126
|
-
code: 400,
|
127
|
-
message: "Please provide an address to tip.",
|
128
|
-
};
|
129
|
-
}
|
130
|
-
const data = await getUserInfo(address);
|
131
|
-
let txUrl = `${baseTxUrl}/transaction/?transaction_type=send&buttonName=Tip%20${data?.ensDomain ?? ""}&amount=1&token=USDC&receiver=${
|
132
|
-
isAddress(address) ? address : data?.address
|
133
|
-
}`;
|
134
|
-
console.log(txUrl);
|
135
|
-
return {
|
136
|
-
code: 200,
|
137
|
-
message: txUrl,
|
138
|
-
};
|
139
|
-
} else if (skill == "cool") {
|
140
|
-
const { domain } = params;
|
141
|
-
//What about these cool alternatives?\
|
142
|
-
return {
|
143
|
-
code: 200,
|
144
|
-
message: `${generateCoolAlternatives(domain)}`,
|
145
|
-
};
|
146
|
-
} else {
|
147
|
-
return { code: 400, message: "Skill not found." };
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
export const generateCoolAlternatives = (domain: string) => {
|
152
|
-
const suffixes = ["lfg", "cool", "degen", "moon", "base", "gm"];
|
153
|
-
const alternatives = [];
|
154
|
-
for (let i = 0; i < 5; i++) {
|
155
|
-
const randomPosition = Math.random() < 0.5;
|
156
|
-
const baseDomain = domain.replace(/\.eth$/, ""); // Remove any existing .eth suffix
|
157
|
-
alternatives.push(
|
158
|
-
randomPosition
|
159
|
-
? `${suffixes[i]}${baseDomain}.eth`
|
160
|
-
: `${baseDomain}${suffixes[i]}.eth`,
|
161
|
-
);
|
162
|
-
}
|
163
|
-
|
164
|
-
const cool_alternativesFormat = alternatives
|
165
|
-
.map(
|
166
|
-
(alternative: string, index: number) => `${index + 1}. ${alternative} ✨`,
|
167
|
-
)
|
168
|
-
.join("\n");
|
169
|
-
return cool_alternativesFormat;
|
170
|
-
};
|
171
|
-
|
172
|
-
export async function clear() {
|
173
|
-
clearMemory();
|
174
|
-
clearInfoCache();
|
175
|
-
}
|
@@ -1,107 +0,0 @@
|
|
1
|
-
import { handleEns } from "./handler/ens.js";
|
2
|
-
import type { SkillGroup } from "@xmtp/message-kit";
|
3
|
-
|
4
|
-
export const skills: SkillGroup[] = [
|
5
|
-
{
|
6
|
-
name: "Ens Domain Bot",
|
7
|
-
tag: "@ens",
|
8
|
-
description: "Register ENS domains.",
|
9
|
-
skills: [
|
10
|
-
{
|
11
|
-
skill: "/register [domain]",
|
12
|
-
triggers: ["/register"],
|
13
|
-
handler: handleEns,
|
14
|
-
description:
|
15
|
-
"Register a new ENS domain. Returns a URL to complete the registration process.",
|
16
|
-
examples: ["/register vitalik.eth"],
|
17
|
-
params: {
|
18
|
-
domain: {
|
19
|
-
type: "string",
|
20
|
-
},
|
21
|
-
},
|
22
|
-
},
|
23
|
-
{
|
24
|
-
skill: "/exists",
|
25
|
-
examples: ["/exists"],
|
26
|
-
handler: handleEns,
|
27
|
-
triggers: ["/exists"],
|
28
|
-
description: "Check if an address is onboarded.",
|
29
|
-
params: {
|
30
|
-
address: {
|
31
|
-
type: "address",
|
32
|
-
},
|
33
|
-
},
|
34
|
-
},
|
35
|
-
{
|
36
|
-
skill: "/info [domain]",
|
37
|
-
triggers: ["/info"],
|
38
|
-
handler: handleEns,
|
39
|
-
description:
|
40
|
-
"Get detailed information about an ENS domain including owner, expiry date, and resolver.",
|
41
|
-
examples: ["/info nick.eth"],
|
42
|
-
params: {
|
43
|
-
domain: {
|
44
|
-
type: "string",
|
45
|
-
},
|
46
|
-
},
|
47
|
-
},
|
48
|
-
{
|
49
|
-
skill: "/renew [domain]",
|
50
|
-
triggers: ["/renew"],
|
51
|
-
handler: handleEns,
|
52
|
-
description:
|
53
|
-
"Extend the registration period of your ENS domain. Returns a URL to complete the renewal.",
|
54
|
-
examples: ["/renew fabri.base.eth"],
|
55
|
-
params: {
|
56
|
-
domain: {
|
57
|
-
type: "string",
|
58
|
-
},
|
59
|
-
},
|
60
|
-
},
|
61
|
-
{
|
62
|
-
skill: "/check [domain]",
|
63
|
-
triggers: ["/check"],
|
64
|
-
handler: handleEns,
|
65
|
-
examples: ["/check vitalik.eth", "/check fabri.base.eth"],
|
66
|
-
description: "Check if a domain is available.",
|
67
|
-
params: {
|
68
|
-
domain: {
|
69
|
-
type: "string",
|
70
|
-
},
|
71
|
-
},
|
72
|
-
},
|
73
|
-
{
|
74
|
-
skill: "/cool [domain]",
|
75
|
-
triggers: ["/cool"],
|
76
|
-
examples: ["/cool vitalik.eth"],
|
77
|
-
handler: handleEns,
|
78
|
-
description: "Get cool alternatives for a .eth domain.",
|
79
|
-
params: {
|
80
|
-
domain: {
|
81
|
-
type: "string",
|
82
|
-
},
|
83
|
-
},
|
84
|
-
},
|
85
|
-
{
|
86
|
-
skill: "/reset",
|
87
|
-
triggers: ["/reset"],
|
88
|
-
examples: ["/reset"],
|
89
|
-
handler: handleEns,
|
90
|
-
description: "Reset the conversation.",
|
91
|
-
params: {},
|
92
|
-
},
|
93
|
-
{
|
94
|
-
skill: "/tip [address]",
|
95
|
-
description: "Show a URL for tipping a domain owner.",
|
96
|
-
triggers: ["/tip"],
|
97
|
-
handler: handleEns,
|
98
|
-
examples: ["/tip 0x1234567890123456789012345678901234567890"],
|
99
|
-
params: {
|
100
|
-
address: {
|
101
|
-
type: "string",
|
102
|
-
},
|
103
|
-
},
|
104
|
-
},
|
105
|
-
],
|
106
|
-
},
|
107
|
-
];
|
@@ -1 +0,0 @@
|
|
1
|
-
KEY= # the private key of the agent wallet
|
@@ -1,29 +0,0 @@
|
|
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,40 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
HandlerContext,
|
3
|
-
AbstractedMember,
|
4
|
-
SkillResponse,
|
5
|
-
} from "@xmtp/message-kit";
|
6
|
-
import { getUserInfo } from "@xmtp/message-kit";
|
7
|
-
|
8
|
-
export async function handler(context: HandlerContext) {
|
9
|
-
const {
|
10
|
-
message: {
|
11
|
-
content: {
|
12
|
-
skill,
|
13
|
-
params: { amount, username },
|
14
|
-
},
|
15
|
-
sender,
|
16
|
-
},
|
17
|
-
} = context;
|
18
|
-
let receivers: AbstractedMember[] = [];
|
19
|
-
|
20
|
-
if (skill === "tip") {
|
21
|
-
receivers = await Promise.all(
|
22
|
-
username.map((username: string) => getUserInfo(username)),
|
23
|
-
);
|
24
|
-
}
|
25
|
-
if (!sender || receivers.length === 0 || amount === 0) {
|
26
|
-
context.reply("Sender or receiver or amount not found.");
|
27
|
-
}
|
28
|
-
const receiverAddresses = receivers.map((receiver) => receiver.address);
|
29
|
-
|
30
|
-
context.sendTo(
|
31
|
-
`You received ${amount} tokens from ${sender.address}.`,
|
32
|
-
receiverAddresses,
|
33
|
-
);
|
34
|
-
|
35
|
-
// Notify sender of the transaction details
|
36
|
-
context.sendTo(
|
37
|
-
`You sent ${amount * receiverAddresses.length} tokens in total.`,
|
38
|
-
[sender.address],
|
39
|
-
);
|
40
|
-
}
|