create-message-kit 1.2.8 → 1.2.10
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 +1 -1
- package/package.json +1 -1
- package/templates/agent/.cursorrules +3 -5
- package/templates/experimental/.cursorrules +3 -5
- package/templates/experimental/.env.example +5 -1
- package/templates/experimental/package.json +1 -0
- package/templates/experimental/src/index.ts +1 -2
- package/templates/experimental/src/lib/usdc.ts +99 -0
- package/templates/experimental/src/lib/xmtp.ts +4 -1
- package/templates/experimental/src/skills/cash.ts +114 -0
- package/templates/gpt/.cursorrules +3 -5
package/index.js
CHANGED
@@ -7,7 +7,7 @@ import { default as fs } from "fs-extra";
|
|
7
7
|
import { isCancel } from "@clack/prompts";
|
8
8
|
import { detect } from "detect-package-manager";
|
9
9
|
import pc from "picocolors";
|
10
|
-
const defVersion = "1.2.
|
10
|
+
const defVersion = "1.2.10";
|
11
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
12
12
|
|
13
13
|
// Read package.json to get the version
|
package/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
### Check if a Domain is Available
|
6
6
|
|
7
|
-
|
7
|
+
|
8
8
|
import { ensUrl } from "../index.js";
|
9
9
|
import { XMTPContext } from "@xmtp/message-kit";
|
10
10
|
import type { Skill } from "@xmtp/message-kit";
|
@@ -54,7 +54,7 @@ export async function handler(context: XMTPContext) {
|
|
54
54
|
|
55
55
|
### Generate a payment request
|
56
56
|
|
57
|
-
|
57
|
+
|
58
58
|
import { XMTPContext } from "@xmtp/message-kit";
|
59
59
|
import type { Skill } from "@xmtp/message-kit";
|
60
60
|
|
@@ -111,12 +111,10 @@ export async function handler(context: XMTPContext) {
|
|
111
111
|
|
112
112
|
await context.requestPayment(amount, token, receiverAddress);
|
113
113
|
}
|
114
|
-
```
|
115
114
|
|
116
115
|
|
117
116
|
## Types
|
118
117
|
|
119
|
-
```typescript
|
120
118
|
import { XMTPContext } from "../lib/xmtp.js";
|
121
119
|
import { ClientOptions, GroupMember } from "@xmtp/node-sdk";
|
122
120
|
import { ContentTypeId } from "@xmtp/content-type-primitives";
|
@@ -224,4 +222,4 @@ export interface AbstractedMember {
|
|
224
222
|
|
225
223
|
export type MetadataValue = string | number | boolean;
|
226
224
|
export type Metadata = Record<string, MetadataValue | MetadataValue[]>;
|
227
|
-
|
225
|
+
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
### Check if a Domain is Available
|
6
6
|
|
7
|
-
|
7
|
+
|
8
8
|
import { ensUrl } from "../index.js";
|
9
9
|
import { XMTPContext } from "@xmtp/message-kit";
|
10
10
|
import type { Skill } from "@xmtp/message-kit";
|
@@ -54,7 +54,7 @@ export async function handler(context: XMTPContext) {
|
|
54
54
|
|
55
55
|
### Generate a payment request
|
56
56
|
|
57
|
-
|
57
|
+
|
58
58
|
import { XMTPContext } from "@xmtp/message-kit";
|
59
59
|
import type { Skill } from "@xmtp/message-kit";
|
60
60
|
|
@@ -111,12 +111,10 @@ export async function handler(context: XMTPContext) {
|
|
111
111
|
|
112
112
|
await context.requestPayment(amount, token, receiverAddress);
|
113
113
|
}
|
114
|
-
```
|
115
114
|
|
116
115
|
|
117
116
|
## Types
|
118
117
|
|
119
|
-
```typescript
|
120
118
|
import { XMTPContext } from "../lib/xmtp.js";
|
121
119
|
import { ClientOptions, GroupMember } from "@xmtp/node-sdk";
|
122
120
|
import { ContentTypeId } from "@xmtp/content-type-primitives";
|
@@ -224,4 +222,4 @@ export interface AbstractedMember {
|
|
224
222
|
|
225
223
|
export type MetadataValue = string | number | boolean;
|
226
224
|
export type Metadata = Record<string, MetadataValue | MetadataValue[]>;
|
227
|
-
|
225
|
+
|
@@ -1,2 +1,6 @@
|
|
1
|
+
OPENAI_API_KEY= # the API key for OpenAI
|
2
|
+
TEST_ENCRYPTION_KEY= # the encryption key for the test wallet
|
1
3
|
KEY= # the private key of the wallet
|
2
|
-
|
4
|
+
RESEND_API_KEY= # the API key for Resend
|
5
|
+
FRAMEDL_API_KEY= # the API key for Framedl
|
6
|
+
ALCHEMY_SDK= # the API key for Alchemy
|
@@ -5,7 +5,6 @@ import {
|
|
5
5
|
XMTPContext,
|
6
6
|
Agent,
|
7
7
|
xmtpClient,
|
8
|
-
V3Client,
|
9
8
|
} from "@xmtp/message-kit";
|
10
9
|
import fs from "fs";
|
11
10
|
import { systemPrompt } from "./prompt.js";
|
@@ -49,5 +48,5 @@ run(
|
|
49
48
|
fs.writeFileSync("example_prompt.md", prompt);
|
50
49
|
await agentReply(context, prompt);
|
51
50
|
},
|
52
|
-
{ agent },
|
51
|
+
{ agent, experimental: true },
|
53
52
|
);
|
@@ -0,0 +1,99 @@
|
|
1
|
+
import fs from "fs";
|
2
|
+
import path from "path";
|
3
|
+
import { generatePrivateKey } from "viem/accounts";
|
4
|
+
import { ethers } from "ethers";
|
5
|
+
|
6
|
+
// Define the Base network RPC URL
|
7
|
+
const baseRpcUrl = "https://mainnet.base.org";
|
8
|
+
|
9
|
+
// Create a provider
|
10
|
+
const provider = new ethers.JsonRpcProvider(baseRpcUrl);
|
11
|
+
|
12
|
+
// USDC contract address on Base (replace with actual address)
|
13
|
+
const usdcAddress = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"; // Replace with the correct USDC contract address
|
14
|
+
|
15
|
+
// ERC-20 ABI (balanceOf and transfer functions)
|
16
|
+
const erc20Abi = [
|
17
|
+
"function balanceOf(address owner) view returns (uint256)",
|
18
|
+
"function transfer(address to, uint256 amount) returns (bool)",
|
19
|
+
];
|
20
|
+
|
21
|
+
export class USDCWallet {
|
22
|
+
walletDir: string;
|
23
|
+
senderAddress: string;
|
24
|
+
privateKey: string;
|
25
|
+
agentAddress: string;
|
26
|
+
usdcContract: ethers.Contract;
|
27
|
+
wallet: ethers.Wallet;
|
28
|
+
|
29
|
+
constructor(senderAddress: string) {
|
30
|
+
this.senderAddress = senderAddress;
|
31
|
+
this.walletDir = path.join(process.cwd(), `./.data/usdcwallets`);
|
32
|
+
if (!fs.existsSync(this.walletDir)) {
|
33
|
+
fs.mkdirSync(this.walletDir, { recursive: true });
|
34
|
+
console.warn("USDC wallet created and saved successfully.");
|
35
|
+
}
|
36
|
+
|
37
|
+
const walletFilePath = path.join(this.walletDir, `${senderAddress}.usdc`);
|
38
|
+
|
39
|
+
if (fs.existsSync(walletFilePath)) {
|
40
|
+
const walletData = fs.readFileSync(walletFilePath, "utf8");
|
41
|
+
this.privateKey = walletData.match(/KEY=(.+)/)?.[1]?.trim() ?? "";
|
42
|
+
} else {
|
43
|
+
this.privateKey = generatePrivateKey();
|
44
|
+
let usdcWallet = new ethers.Wallet(this.privateKey, provider);
|
45
|
+
const walletData = `KEY=${this.privateKey}\nADDRESS=${usdcWallet.address}`;
|
46
|
+
fs.writeFileSync(walletFilePath, walletData);
|
47
|
+
}
|
48
|
+
|
49
|
+
// Initialize wallet and USDC contract
|
50
|
+
this.wallet = new ethers.Wallet(this.privateKey, provider);
|
51
|
+
this.agentAddress = this.wallet.address;
|
52
|
+
this.usdcContract = new ethers.Contract(usdcAddress, erc20Abi, this.wallet);
|
53
|
+
}
|
54
|
+
|
55
|
+
async checkBalances(): Promise<{ usdc: number; eth: number }> {
|
56
|
+
try {
|
57
|
+
// Check USDC balance
|
58
|
+
console.log(this.agentAddress);
|
59
|
+
const usdcBalance = await this.usdcContract.balanceOf(this.agentAddress);
|
60
|
+
const formattedUsdcBalance = ethers.formatUnits(usdcBalance, 6); // USDC has 6 decimals
|
61
|
+
console.warn(`USDC Balance: ${formattedUsdcBalance}`);
|
62
|
+
|
63
|
+
// Check ETH balance
|
64
|
+
const ethBalance = await provider.getBalance(this.agentAddress);
|
65
|
+
const formattedEthBalance = ethers.formatUnits(ethBalance, 18);
|
66
|
+
console.warn(`ETH Balance: ${formattedEthBalance}`);
|
67
|
+
|
68
|
+
return {
|
69
|
+
usdc: parseFloat(formattedUsdcBalance),
|
70
|
+
eth: parseFloat(formattedEthBalance),
|
71
|
+
};
|
72
|
+
} catch (error) {
|
73
|
+
console.error("Error fetching balances:", error);
|
74
|
+
return { usdc: 0, eth: 0 };
|
75
|
+
}
|
76
|
+
}
|
77
|
+
async transferUsdc(to: string, amount: number) {
|
78
|
+
if (!ethers.isAddress(to)) {
|
79
|
+
throw new Error("Invalid recipient address");
|
80
|
+
} else if (typeof amount !== "number" || amount <= 0) {
|
81
|
+
throw new Error("Invalid transfer amount");
|
82
|
+
}
|
83
|
+
try {
|
84
|
+
const amountInWei = ethers.parseUnits(amount.toString(), 6); // USDC has 6 decimals
|
85
|
+
const adminAgent = new USDCWallet(to);
|
86
|
+
const tx = await this.usdcContract.transfer(
|
87
|
+
adminAgent.agentAddress,
|
88
|
+
amountInWei,
|
89
|
+
);
|
90
|
+
const receipt = await tx.wait();
|
91
|
+
if (receipt.status !== 1) {
|
92
|
+
throw new Error("Transaction failed or was reverted");
|
93
|
+
}
|
94
|
+
} catch (error) {
|
95
|
+
console.warn(`Transferred ${amount} USDC to ${to}.`);
|
96
|
+
throw error;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
@@ -92,6 +92,7 @@ export async function addToGroup(
|
|
92
92
|
groupId: string,
|
93
93
|
client: V3Client,
|
94
94
|
address: string,
|
95
|
+
asAdmin: boolean = false,
|
95
96
|
): Promise<{ code: number; message: string }> {
|
96
97
|
try {
|
97
98
|
let lowerAddress = address.toLowerCase();
|
@@ -104,10 +105,12 @@ export async function addToGroup(
|
|
104
105
|
const group = await client.conversations.getConversationById(groupId);
|
105
106
|
console.warn("Adding to group", group?.id);
|
106
107
|
await group?.sync();
|
107
|
-
//DON'T TOUCH THIS LINE
|
108
108
|
await group?.addMembers([lowerAddress]);
|
109
109
|
console.warn("Added member to group");
|
110
110
|
await group?.sync();
|
111
|
+
if (asAdmin) {
|
112
|
+
await group?.addSuperAdmin(lowerAddress);
|
113
|
+
}
|
111
114
|
const members = await group?.members();
|
112
115
|
console.warn("Number of members", members?.length);
|
113
116
|
|
@@ -0,0 +1,114 @@
|
|
1
|
+
import { XMTPContext } from "@xmtp/message-kit";
|
2
|
+
import type { Skill } from "@xmtp/message-kit";
|
3
|
+
import { USDCWallet } from "../lib/usdc.js";
|
4
|
+
|
5
|
+
export const cash: Skill[] = [
|
6
|
+
{
|
7
|
+
skill: "/balance",
|
8
|
+
handler: balanceHandler,
|
9
|
+
examples: ["/balance"],
|
10
|
+
params: {},
|
11
|
+
description: "Check your balance.",
|
12
|
+
},
|
13
|
+
{
|
14
|
+
skill: "/fund [amount]",
|
15
|
+
handler: fundHandler,
|
16
|
+
examples: ["/fund 1", "/fund 10"],
|
17
|
+
params: {
|
18
|
+
amount: {
|
19
|
+
type: "number",
|
20
|
+
default: "",
|
21
|
+
},
|
22
|
+
},
|
23
|
+
description: "Fund your wallet. Returns a url to fund your wallet.",
|
24
|
+
},
|
25
|
+
{
|
26
|
+
skill: "/transfer [address] [amount]",
|
27
|
+
handler: transferHandler,
|
28
|
+
examples: ["/transfer 0x40f08f0f853d1c42c61815652b7ccd5a50f0be09 1"],
|
29
|
+
params: {},
|
30
|
+
description: "Transfer USDC to another address.",
|
31
|
+
},
|
32
|
+
];
|
33
|
+
|
34
|
+
async function balanceHandler(context: XMTPContext) {
|
35
|
+
const {
|
36
|
+
message: { sender },
|
37
|
+
} = context;
|
38
|
+
const usdcWallet = new USDCWallet(sender.address);
|
39
|
+
const { usdc } = await usdcWallet.checkBalances();
|
40
|
+
await context.send(
|
41
|
+
`Your balance is ${usdc} USDC. let me know if you want check again or to fund your wallet.`,
|
42
|
+
);
|
43
|
+
}
|
44
|
+
|
45
|
+
async function fundHandler(context: XMTPContext) {
|
46
|
+
try {
|
47
|
+
const {
|
48
|
+
message: {
|
49
|
+
sender,
|
50
|
+
content: {
|
51
|
+
params: { amount },
|
52
|
+
},
|
53
|
+
},
|
54
|
+
} = context;
|
55
|
+
const usdcWallet = new USDCWallet(sender.address);
|
56
|
+
const { usdc } = await usdcWallet.checkBalances();
|
57
|
+
const MAX_USDC = 10;
|
58
|
+
|
59
|
+
if (usdc >= MAX_USDC) {
|
60
|
+
await context.send(`Your balance is maxed out at ${MAX_USDC} USDC.`);
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
|
64
|
+
const remainingLimit = MAX_USDC - usdc;
|
65
|
+
let fundAmount: number;
|
66
|
+
|
67
|
+
if (!amount) {
|
68
|
+
const options = Array.from(
|
69
|
+
{ length: Math.floor(remainingLimit) },
|
70
|
+
(_, i) => (i + 1).toString(),
|
71
|
+
);
|
72
|
+
const response = await context.awaitResponse(
|
73
|
+
`Please specify the amount of USDC to prefund (1 to ${remainingLimit}):`,
|
74
|
+
options,
|
75
|
+
);
|
76
|
+
fundAmount = parseInt(response);
|
77
|
+
} else {
|
78
|
+
fundAmount = parseInt(amount);
|
79
|
+
}
|
80
|
+
|
81
|
+
if (isNaN(fundAmount) || fundAmount <= 0 || fundAmount > remainingLimit) {
|
82
|
+
await context.send(
|
83
|
+
`Invalid amount. Please specify a value between 1 and ${remainingLimit} USDC.`,
|
84
|
+
);
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
|
88
|
+
await context.requestPayment(fundAmount, "USDC", usdcWallet.agentAddress);
|
89
|
+
await context.send(
|
90
|
+
"After funding, let me know so I can check your balance.",
|
91
|
+
);
|
92
|
+
} catch (error) {
|
93
|
+
await context.send(
|
94
|
+
"An error occurred while processing your request. Please try again.",
|
95
|
+
);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
async function transferHandler(context: XMTPContext) {
|
100
|
+
const {
|
101
|
+
message: {
|
102
|
+
sender,
|
103
|
+
content: {
|
104
|
+
params: { address, amount },
|
105
|
+
},
|
106
|
+
},
|
107
|
+
} = context;
|
108
|
+
const usdcWallet = new USDCWallet(sender.address);
|
109
|
+
if (amount > 10) {
|
110
|
+
await context.send("You can only transfer up to 10 USDC at a time.");
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
await usdcWallet.transferUsdc(address, amount);
|
114
|
+
}
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
### Check if a Domain is Available
|
6
6
|
|
7
|
-
|
7
|
+
|
8
8
|
import { ensUrl } from "../index.js";
|
9
9
|
import { XMTPContext } from "@xmtp/message-kit";
|
10
10
|
import type { Skill } from "@xmtp/message-kit";
|
@@ -54,7 +54,7 @@ export async function handler(context: XMTPContext) {
|
|
54
54
|
|
55
55
|
### Generate a payment request
|
56
56
|
|
57
|
-
|
57
|
+
|
58
58
|
import { XMTPContext } from "@xmtp/message-kit";
|
59
59
|
import type { Skill } from "@xmtp/message-kit";
|
60
60
|
|
@@ -111,12 +111,10 @@ export async function handler(context: XMTPContext) {
|
|
111
111
|
|
112
112
|
await context.requestPayment(amount, token, receiverAddress);
|
113
113
|
}
|
114
|
-
```
|
115
114
|
|
116
115
|
|
117
116
|
## Types
|
118
117
|
|
119
|
-
```typescript
|
120
118
|
import { XMTPContext } from "../lib/xmtp.js";
|
121
119
|
import { ClientOptions, GroupMember } from "@xmtp/node-sdk";
|
122
120
|
import { ContentTypeId } from "@xmtp/content-type-primitives";
|
@@ -224,4 +222,4 @@ export interface AbstractedMember {
|
|
224
222
|
|
225
223
|
export type MetadataValue = string | number | boolean;
|
226
224
|
export type Metadata = Record<string, MetadataValue | MetadataValue[]>;
|
227
|
-
|
225
|
+
|