create-message-kit 1.2.8 → 1.2.10

Sign up to get free protection for your applications and to get access to all the features.
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
+