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 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.8";
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-message-kit",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -4,7 +4,7 @@
4
4
 
5
5
  ### Check if a Domain is Available
6
6
 
7
- ```typescript
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
- ```typescript
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
- ```typescript
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
- ```typescript
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
- OPENAI_API_KEY= # sk-proj-...
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
@@ -10,6 +10,7 @@
10
10
  "dependencies": {
11
11
  "@xmtp/message-kit": "workspace:*",
12
12
  "alchemy-sdk": "^3.0.0",
13
+ "ethers": "^6.0.0",
13
14
  "express": "^4.19.2",
14
15
  "node-fetch": "^3.3.2",
15
16
  "resend": "^4.0.1"
@@ -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
- ```typescript
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
- ```typescript
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
+