create-message-kit 1.2.11 → 1.2.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
}
|