create-message-kit 1.2.11 → 1.2.13
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 +9 -4
- package/package.json +1 -1
- package/templates/{agent → ens}/.cursorrules +68 -3
- package/templates/{agent → ens}/package.json +1 -1
- package/templates/{agent → ens}/src/prompt.ts +1 -1
- package/templates/{agent → ens}/src/skills/check.ts +1 -1
- package/templates/{agent → ens}/src/skills/cool.ts +1 -1
- package/templates/{agent → ens}/src/skills/info.ts +1 -1
- package/templates/{agent → ens}/src/skills/pay.ts +1 -1
- package/templates/{agent → ens}/src/skills/register.ts +1 -1
- package/templates/{agent → ens}/src/skills/renew.ts +1 -1
- package/templates/{agent → ens}/src/skills/reset.ts +1 -2
- package/templates/{experimental → simple}/.cursorrules +68 -3
- package/templates/{gpt → simple}/package.json +1 -1
- package/templates/experimental/.env.example +0 -6
- package/templates/experimental/package.json +0 -26
- package/templates/experimental/src/index.ts +0 -52
- package/templates/experimental/src/lib/alchemy.ts +0 -31
- package/templates/experimental/src/lib/minilog.ts +0 -26
- package/templates/experimental/src/lib/usdc.ts +0 -99
- package/templates/experimental/src/lib/xmtp.ts +0 -139
- package/templates/experimental/src/prompt.ts +0 -24
- package/templates/experimental/src/skills/broadcast.ts +0 -39
- package/templates/experimental/src/skills/cash.ts +0 -114
- package/templates/experimental/src/skills/gated.ts +0 -89
- package/templates/experimental/src/skills/todo.ts +0 -80
- package/templates/experimental/src/skills/token.ts +0 -57
- package/templates/experimental/src/skills/wordle.ts +0 -97
- package/templates/gpt/.cursorrules +0 -225
- package/templates/gpt/.yarnrc.yml +0 -4
- /package/templates/{agent → ens}/.env.example +0 -0
- /package/templates/{agent → ens}/.yarnrc.yml +0 -0
- /package/templates/{agent → ens}/src/index.ts +0 -0
- /package/templates/{gpt → simple}/.env.example +0 -0
- /package/templates/{experimental → simple}/.yarnrc.yml +0 -0
- /package/templates/{gpt → simple}/src/index.ts +0 -0
- /package/templates/{gpt → simple}/src/prompt.ts +0 -0
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.13";
|
11
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
12
12
|
|
13
13
|
// Read package.json to get the version
|
@@ -96,9 +96,14 @@ async function updatePackagejson(destDir, templateType) {
|
|
96
96
|
|
97
97
|
async function gatherProjectInfo() {
|
98
98
|
const templateOptions = [
|
99
|
-
{
|
100
|
-
|
101
|
-
|
99
|
+
{
|
100
|
+
value: "simple",
|
101
|
+
label: "Simple Agent: A starter template for building an agent",
|
102
|
+
},
|
103
|
+
{
|
104
|
+
value: "ens",
|
105
|
+
label: "ENS Agent: An example of an agent using ENS skills",
|
106
|
+
},
|
102
107
|
];
|
103
108
|
|
104
109
|
const templateType = await select({
|
package/package.json
CHANGED
@@ -12,7 +12,7 @@ import type { Skill } from "@xmtp/message-kit";
|
|
12
12
|
// Define Skill
|
13
13
|
export const checkDomain: Skill[] = [
|
14
14
|
{
|
15
|
-
skill: "
|
15
|
+
skill: "check",
|
16
16
|
handler: handler,
|
17
17
|
examples: ["/check vitalik.eth", "/check fabri.base.eth"],
|
18
18
|
description: "Check if a domain is available.",
|
@@ -61,7 +61,7 @@ import type { Skill } from "@xmtp/message-kit";
|
|
61
61
|
// Define Skill
|
62
62
|
export const paymentRequest: Skill[] = [
|
63
63
|
{
|
64
|
-
skill: "
|
64
|
+
skill: "pay",
|
65
65
|
examples: [
|
66
66
|
"/pay 10 vitalik.eth",
|
67
67
|
"/pay 1 usdc to 0xC60E6Bb79322392761BFe3081E302aEB79B30B03",
|
@@ -115,7 +115,7 @@ export async function handler(context: XMTPContext) {
|
|
115
115
|
|
116
116
|
## Types
|
117
117
|
|
118
|
-
import { XMTPContext } from "../
|
118
|
+
import { XMTPContext } from "../plugins/xmtp.js";
|
119
119
|
import { ClientOptions, GroupMember } from "@xmtp/node-sdk";
|
120
120
|
import { ContentTypeId } from "@xmtp/content-type-primitives";
|
121
121
|
|
@@ -223,3 +223,68 @@ export interface AbstractedMember {
|
|
223
223
|
export type MetadataValue = string | number | boolean;
|
224
224
|
export type Metadata = Record<string, MetadataValue | MetadataValue[]>;
|
225
225
|
|
226
|
+
|
227
|
+
## Example final prompt
|
228
|
+
|
229
|
+
Your are a helpful and playful ens agent called @bot that lives inside a messaging app called Converse.
|
230
|
+
|
231
|
+
|
232
|
+
# Rules
|
233
|
+
- You can respond with multiple messages if needed. Each message should be separated by a newline character.
|
234
|
+
- You can trigger skills by only sending the command in a newline message.
|
235
|
+
- Each command starts with a slash (/).
|
236
|
+
- Never announce actions without using a command separated by a newline character.
|
237
|
+
- Never use markdown in your responses.
|
238
|
+
- Do not make guesses or assumptions
|
239
|
+
- Only answer if the verified information is in the prompt.
|
240
|
+
- Check that you are not missing a command
|
241
|
+
- Focus only on helping users with operations detailed below.
|
242
|
+
- Date: Fri, 06 Dec 2024 16:03:22 GMT
|
243
|
+
- When mentioning any action related to available skills, you MUST trigger the corresponding command in a new line
|
244
|
+
- If you suggest an action that has a command, you must trigger that command
|
245
|
+
|
246
|
+
|
247
|
+
## User context
|
248
|
+
- Start by fetch their domain from or Converse username
|
249
|
+
- Call the user by their name or domain, in case they have one
|
250
|
+
- Ask for a name (if they don't have one) so you can suggest domains.
|
251
|
+
- Message sent date: 2024-12-06T16:03:36.582Z
|
252
|
+
- Users address is: 0x40f08f0f853d1c42c61815652b7ccd5a50f0be09
|
253
|
+
- Users name is: ArizonaOregon
|
254
|
+
- Converse username is: ArizonaOregon
|
255
|
+
|
256
|
+
## Commands
|
257
|
+
/check [domain] - Check if a domain is available.
|
258
|
+
/cool [domain] - Get cool alternatives for a .eth domain.
|
259
|
+
/info [domain] - Get detailed information about an ENS domain including owner, expiry date, and resolver.
|
260
|
+
/register [domain] - Register a new ENS domain. Returns a URL to complete the registration process.
|
261
|
+
/renew [domain] - Extend the registration period of your ENS domain. Returns a URL to complete the renewal.
|
262
|
+
/reset - Reset the conversation clearing memory and usernames cache.
|
263
|
+
/pay [amount] [token] [username] [address] - Send a specified amount of a cryptocurrency to a destination address.
|
264
|
+
When tipping, you can asume its 1 usdc.
|
265
|
+
|
266
|
+
## Examples
|
267
|
+
/check vitalik.eth
|
268
|
+
/check fabri.base.eth
|
269
|
+
/cool vitalik.eth
|
270
|
+
/info nick.eth
|
271
|
+
/register vitalik.eth
|
272
|
+
/renew fabri.base.eth
|
273
|
+
/reset
|
274
|
+
/pay 10 vitalik.eth
|
275
|
+
/pay 1 usdc to 0xC60E6Bb79322392761BFe3081E302aEB79B30B03
|
276
|
+
|
277
|
+
## Scenarios
|
278
|
+
1. Missing commands in responses
|
279
|
+
**Issue**: Sometimes responses are sent without the required command.
|
280
|
+
**Example**:
|
281
|
+
Incorrect:
|
282
|
+
> "Looks like vitalik.eth is registered! What about these cool alternatives?"
|
283
|
+
Correct:
|
284
|
+
> "Looks like vitalik.eth is registered! What about these cool alternatives?
|
285
|
+
> /cool vitalik.eth"
|
286
|
+
|
287
|
+
Incorrect:
|
288
|
+
> Here is a summary of your TODOs. I will now send it via email.
|
289
|
+
Correct:
|
290
|
+
> /todo
|
@@ -6,7 +6,7 @@ const ensUrl = "https://app.ens.domains/";
|
|
6
6
|
// [!region define]
|
7
7
|
export const checkDomain: Skill[] = [
|
8
8
|
{
|
9
|
-
skill: "
|
9
|
+
skill: "check",
|
10
10
|
handler: handler,
|
11
11
|
examples: ["/check vitalik.eth", "/check fabri.base.eth"],
|
12
12
|
description: "Check if a domain is available.",
|
@@ -5,11 +5,10 @@ import type { Skill } from "@xmtp/message-kit";
|
|
5
5
|
|
6
6
|
export const reset: Skill[] = [
|
7
7
|
{
|
8
|
-
skill: "
|
8
|
+
skill: "reset",
|
9
9
|
examples: ["/reset"],
|
10
10
|
handler: handler,
|
11
11
|
description: "Reset the conversation clearing memory and usernames cache.",
|
12
|
-
params: {},
|
13
12
|
},
|
14
13
|
];
|
15
14
|
export async function handler(context: XMTPContext) {
|
@@ -12,7 +12,7 @@ import type { Skill } from "@xmtp/message-kit";
|
|
12
12
|
// Define Skill
|
13
13
|
export const checkDomain: Skill[] = [
|
14
14
|
{
|
15
|
-
skill: "
|
15
|
+
skill: "check",
|
16
16
|
handler: handler,
|
17
17
|
examples: ["/check vitalik.eth", "/check fabri.base.eth"],
|
18
18
|
description: "Check if a domain is available.",
|
@@ -61,7 +61,7 @@ import type { Skill } from "@xmtp/message-kit";
|
|
61
61
|
// Define Skill
|
62
62
|
export const paymentRequest: Skill[] = [
|
63
63
|
{
|
64
|
-
skill: "
|
64
|
+
skill: "pay",
|
65
65
|
examples: [
|
66
66
|
"/pay 10 vitalik.eth",
|
67
67
|
"/pay 1 usdc to 0xC60E6Bb79322392761BFe3081E302aEB79B30B03",
|
@@ -115,7 +115,7 @@ export async function handler(context: XMTPContext) {
|
|
115
115
|
|
116
116
|
## Types
|
117
117
|
|
118
|
-
import { XMTPContext } from "../
|
118
|
+
import { XMTPContext } from "../plugins/xmtp.js";
|
119
119
|
import { ClientOptions, GroupMember } from "@xmtp/node-sdk";
|
120
120
|
import { ContentTypeId } from "@xmtp/content-type-primitives";
|
121
121
|
|
@@ -223,3 +223,68 @@ export interface AbstractedMember {
|
|
223
223
|
export type MetadataValue = string | number | boolean;
|
224
224
|
export type Metadata = Record<string, MetadataValue | MetadataValue[]>;
|
225
225
|
|
226
|
+
|
227
|
+
## Example final prompt
|
228
|
+
|
229
|
+
Your are a helpful and playful ens agent called @bot that lives inside a messaging app called Converse.
|
230
|
+
|
231
|
+
|
232
|
+
# Rules
|
233
|
+
- You can respond with multiple messages if needed. Each message should be separated by a newline character.
|
234
|
+
- You can trigger skills by only sending the command in a newline message.
|
235
|
+
- Each command starts with a slash (/).
|
236
|
+
- Never announce actions without using a command separated by a newline character.
|
237
|
+
- Never use markdown in your responses.
|
238
|
+
- Do not make guesses or assumptions
|
239
|
+
- Only answer if the verified information is in the prompt.
|
240
|
+
- Check that you are not missing a command
|
241
|
+
- Focus only on helping users with operations detailed below.
|
242
|
+
- Date: Fri, 06 Dec 2024 16:03:22 GMT
|
243
|
+
- When mentioning any action related to available skills, you MUST trigger the corresponding command in a new line
|
244
|
+
- If you suggest an action that has a command, you must trigger that command
|
245
|
+
|
246
|
+
|
247
|
+
## User context
|
248
|
+
- Start by fetch their domain from or Converse username
|
249
|
+
- Call the user by their name or domain, in case they have one
|
250
|
+
- Ask for a name (if they don't have one) so you can suggest domains.
|
251
|
+
- Message sent date: 2024-12-06T16:03:36.582Z
|
252
|
+
- Users address is: 0x40f08f0f853d1c42c61815652b7ccd5a50f0be09
|
253
|
+
- Users name is: ArizonaOregon
|
254
|
+
- Converse username is: ArizonaOregon
|
255
|
+
|
256
|
+
## Commands
|
257
|
+
/check [domain] - Check if a domain is available.
|
258
|
+
/cool [domain] - Get cool alternatives for a .eth domain.
|
259
|
+
/info [domain] - Get detailed information about an ENS domain including owner, expiry date, and resolver.
|
260
|
+
/register [domain] - Register a new ENS domain. Returns a URL to complete the registration process.
|
261
|
+
/renew [domain] - Extend the registration period of your ENS domain. Returns a URL to complete the renewal.
|
262
|
+
/reset - Reset the conversation clearing memory and usernames cache.
|
263
|
+
/pay [amount] [token] [username] [address] - Send a specified amount of a cryptocurrency to a destination address.
|
264
|
+
When tipping, you can asume its 1 usdc.
|
265
|
+
|
266
|
+
## Examples
|
267
|
+
/check vitalik.eth
|
268
|
+
/check fabri.base.eth
|
269
|
+
/cool vitalik.eth
|
270
|
+
/info nick.eth
|
271
|
+
/register vitalik.eth
|
272
|
+
/renew fabri.base.eth
|
273
|
+
/reset
|
274
|
+
/pay 10 vitalik.eth
|
275
|
+
/pay 1 usdc to 0xC60E6Bb79322392761BFe3081E302aEB79B30B03
|
276
|
+
|
277
|
+
## Scenarios
|
278
|
+
1. Missing commands in responses
|
279
|
+
**Issue**: Sometimes responses are sent without the required command.
|
280
|
+
**Example**:
|
281
|
+
Incorrect:
|
282
|
+
> "Looks like vitalik.eth is registered! What about these cool alternatives?"
|
283
|
+
Correct:
|
284
|
+
> "Looks like vitalik.eth is registered! What about these cool alternatives?
|
285
|
+
> /cool vitalik.eth"
|
286
|
+
|
287
|
+
Incorrect:
|
288
|
+
> Here is a summary of your TODOs. I will now send it via email.
|
289
|
+
Correct:
|
290
|
+
> /todo
|
@@ -1,6 +0,0 @@
|
|
1
|
-
OPENAI_API_KEY= # the API key for OpenAI
|
2
|
-
TEST_ENCRYPTION_KEY= # the encryption key for the test wallet
|
3
|
-
KEY= # the private key of the wallet
|
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
|
@@ -1,26 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"name": "experimental",
|
3
|
-
"private": true,
|
4
|
-
"type": "module",
|
5
|
-
"scripts": {
|
6
|
-
"build": "tsc",
|
7
|
-
"dev": "tsc -w & sleep 1 && NODE_NO_WARNINGS=1 node --watch dist/index.js",
|
8
|
-
"start": "node dist/index.js"
|
9
|
-
},
|
10
|
-
"dependencies": {
|
11
|
-
"@xmtp/message-kit": "workspace:*",
|
12
|
-
"alchemy-sdk": "^3.0.0",
|
13
|
-
"ethers": "^6.0.0",
|
14
|
-
"express": "^4.19.2",
|
15
|
-
"node-fetch": "^3.3.2",
|
16
|
-
"resend": "^4.0.1"
|
17
|
-
},
|
18
|
-
"devDependencies": {
|
19
|
-
"@types/express": "^4.17.20",
|
20
|
-
"@types/node": "^20.14.2",
|
21
|
-
"typescript": "^5.4.5"
|
22
|
-
},
|
23
|
-
"engines": {
|
24
|
-
"node": ">=20"
|
25
|
-
}
|
26
|
-
}
|
@@ -1,52 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
run,
|
3
|
-
agentReply,
|
4
|
-
replaceVariables,
|
5
|
-
XMTPContext,
|
6
|
-
Agent,
|
7
|
-
xmtpClient,
|
8
|
-
} from "@xmtp/message-kit";
|
9
|
-
import fs from "fs";
|
10
|
-
import { systemPrompt } from "./prompt.js";
|
11
|
-
import { token } from "./skills/token.js";
|
12
|
-
import { todo } from "./skills/todo.js";
|
13
|
-
import { gated, startGatedGroupServer } from "./skills/gated.js";
|
14
|
-
import { broadcast } from "./skills/broadcast.js";
|
15
|
-
import { wordle } from "./skills/wordle.js";
|
16
|
-
|
17
|
-
export const agent: Agent = {
|
18
|
-
name: "Experimental Agent",
|
19
|
-
tag: "@bot",
|
20
|
-
description: "An experimental agent with a lot of skills.",
|
21
|
-
skills: [
|
22
|
-
...token,
|
23
|
-
...(process?.env?.RESEND_API_KEY ? todo : []),
|
24
|
-
...(process?.env?.ALCHEMY_SDK ? gated : []),
|
25
|
-
...broadcast,
|
26
|
-
...wordle,
|
27
|
-
],
|
28
|
-
};
|
29
|
-
|
30
|
-
// [!region gated]
|
31
|
-
const { client } = await xmtpClient({
|
32
|
-
hideInitLogMessage: true,
|
33
|
-
});
|
34
|
-
|
35
|
-
startGatedGroupServer(client);
|
36
|
-
// [!endregion gated]
|
37
|
-
|
38
|
-
run(
|
39
|
-
async (context: XMTPContext) => {
|
40
|
-
const {
|
41
|
-
message: { sender },
|
42
|
-
agent,
|
43
|
-
} = context;
|
44
|
-
|
45
|
-
let prompt = await replaceVariables(systemPrompt, sender.address, agent);
|
46
|
-
|
47
|
-
//This is only used for to update the docs.
|
48
|
-
fs.writeFileSync("example_prompt.md", prompt);
|
49
|
-
await agentReply(context, prompt);
|
50
|
-
},
|
51
|
-
{ agent, experimental: true },
|
52
|
-
);
|
@@ -1,31 +0,0 @@
|
|
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 checkNft(
|
9
|
-
walletAddress: string,
|
10
|
-
collectionSlug: string,
|
11
|
-
): Promise<boolean> {
|
12
|
-
const alchemy = new Alchemy(settings);
|
13
|
-
try {
|
14
|
-
const nfts = await alchemy.nft.getNftsForOwner(walletAddress);
|
15
|
-
|
16
|
-
const ownsNft = nfts.ownedNfts.some(
|
17
|
-
(nft: any) =>
|
18
|
-
nft.contract.name.toLowerCase() === collectionSlug.toLowerCase(),
|
19
|
-
);
|
20
|
-
// console.log(
|
21
|
-
// `NFTs owned on ${Network.BASE_MAINNET}:`,
|
22
|
-
// nfts.ownedNfts.length,
|
23
|
-
// );
|
24
|
-
console.log("is the nft owned: ", ownsNft);
|
25
|
-
return ownsNft as boolean;
|
26
|
-
} catch (error) {
|
27
|
-
console.error("Error fetching NFTs from Alchemy:", error);
|
28
|
-
}
|
29
|
-
|
30
|
-
return false;
|
31
|
-
}
|
@@ -1,26 +0,0 @@
|
|
1
|
-
import fetch from "node-fetch";
|
2
|
-
|
3
|
-
export async function sendLog(title: string, description: string) {
|
4
|
-
const response = await fetch("https://api.minilog.dev/v1/logs/testlog", {
|
5
|
-
method: "POST",
|
6
|
-
headers: {
|
7
|
-
"Content-Type": "application/json",
|
8
|
-
Authorization: "Bearer pthsm38sccpux5acriqish7isz5inet7q73ef7br",
|
9
|
-
},
|
10
|
-
body: JSON.stringify({
|
11
|
-
application: "myapp-1",
|
12
|
-
severity: "DEBUG",
|
13
|
-
data: title,
|
14
|
-
metadata: {
|
15
|
-
title,
|
16
|
-
description,
|
17
|
-
},
|
18
|
-
}),
|
19
|
-
});
|
20
|
-
console.log(response);
|
21
|
-
if (!response.ok) {
|
22
|
-
console.error("Failed to send log:", response.statusText);
|
23
|
-
} else {
|
24
|
-
console.log("Log sent successfully");
|
25
|
-
}
|
26
|
-
}
|
@@ -1,99 +0,0 @@
|
|
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
|
-
}
|