@aiaiaichain/agent 0.1.4 → 0.1.6

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.
Files changed (59) hide show
  1. package/dist/cli.js +224 -9
  2. package/dist/core/ChainConfig.js +1 -1
  3. package/dist/core/SystemMonitor.d.ts +1 -4
  4. package/dist/core/SystemMonitor.js +20 -46
  5. package/dist/index.d.ts +10 -0
  6. package/dist/index.js +11 -0
  7. package/dist/models/ModelRegistry.js +12 -4
  8. package/dist/runner/AgentRunner.d.ts +2 -0
  9. package/dist/runner/AgentRunner.js +18 -1
  10. package/dist/runner/ModelClient.js +109 -48
  11. package/dist/session/SessionManager.d.ts +1 -0
  12. package/dist/session/SessionManager.js +8 -2
  13. package/dist/session/SessionStore.js +8 -3
  14. package/dist/tools/CrossTools.js +13 -5
  15. package/dist/tools/MarketSentiment.js +22 -13
  16. package/dist/tools/NewsSentiment.js +9 -3
  17. package/dist/tools/PriceFeed.js +11 -4
  18. package/dist/tools/TechnicalAnalysis.js +2 -1
  19. package/dist/tools/TokenCalendar.d.ts +24 -0
  20. package/dist/tools/TokenCalendar.js +81 -0
  21. package/dist/tools/TokenSecurityScanner.d.ts +22 -0
  22. package/dist/tools/TokenSecurityScanner.js +102 -0
  23. package/dist/tools/TransactionSim.d.ts +17 -0
  24. package/dist/tools/TransactionSim.js +78 -0
  25. package/dist/tui/App.js +145 -23
  26. package/dist/tui/REPL.js +2 -2
  27. package/dist/tui/Sparkline.d.ts +21 -0
  28. package/dist/tui/Sparkline.js +44 -0
  29. package/dist/tui/ThemePresets.d.ts +25 -0
  30. package/dist/tui/ThemePresets.js +117 -0
  31. package/dist/util/clipboard.d.ts +9 -0
  32. package/dist/util/clipboard.js +26 -0
  33. package/dist/util/commandSuggest.d.ts +7 -0
  34. package/dist/util/commandSuggest.js +44 -0
  35. package/dist/util/confirmation.d.ts +6 -0
  36. package/dist/util/confirmation.js +16 -0
  37. package/dist/util/errorHandler.d.ts +3 -0
  38. package/dist/util/errorHandler.js +28 -0
  39. package/dist/util/logger.d.ts +11 -0
  40. package/dist/util/logger.js +43 -0
  41. package/dist/util/processManager.d.ts +5 -0
  42. package/dist/util/processManager.js +39 -0
  43. package/dist/util/resilientFetch.d.ts +21 -0
  44. package/dist/util/resilientFetch.js +94 -0
  45. package/dist/util/responseCache.d.ts +27 -0
  46. package/dist/util/responseCache.js +54 -0
  47. package/dist/util/safeLog.d.ts +4 -5
  48. package/dist/util/safeLog.js +68 -30
  49. package/dist/util/scheduler.d.ts +14 -0
  50. package/dist/util/scheduler.js +75 -0
  51. package/dist/util/webhooks.d.ts +9 -0
  52. package/dist/util/webhooks.js +75 -0
  53. package/dist/wallet/ActionFeed.d.ts +3 -2
  54. package/dist/wallet/ActionFeed.js +97 -76
  55. package/dist/wallet/AgentWallet.d.ts +6 -2
  56. package/dist/wallet/AgentWallet.js +59 -27
  57. package/dist/wallet/ProfitTracker.d.ts +30 -0
  58. package/dist/wallet/ProfitTracker.js +93 -0
  59. package/package.json +2 -2
@@ -1,38 +1,76 @@
1
1
  /**
2
- * safeLog — wraps console.log/error/warn to avoid corrupting Ink TUI output.
2
+ * src/util/safeLog.tsIntercepts console output, masks secrets, routes to file
3
3
  */
4
- const queue = [];
5
- let notifyFn = null;
6
- let scheduled = false;
7
- export function wireNotify(fn) {
8
- notifyFn = fn;
9
- // Drain any queued messages
10
- if (queue.length > 0) {
11
- for (const msg of queue)
12
- fn(msg);
13
- queue.length = 0;
4
+ import { existsSync, appendFileSync, mkdirSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { homedir } from "node:os";
7
+ const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), '.aiaiai');
8
+ const LOG_DIR = join(AIAIAI_HOME, '.logs');
9
+ const LOG_FILE = join(LOG_DIR, 'agent.log');
10
+ // Patterns that indicate sensitive values
11
+ const SENSITIVE_PATTERNS = [
12
+ /sk-[a-zA-Z0-9]{20,}/g, // API keys
13
+ /[A-Za-z0-9]{32,}/g, // Hex keys
14
+ /Bearer\s+[A-Za-z0-9\-._~+/]+/g, // Bearer tokens
15
+ /api[_-]?key["\s:=]+["']?[^\s"']+/gi, // Key assignments
16
+ /secret["\s:=]+["']?[^\s"']+/gi, // Secrets
17
+ ];
18
+ const SENSITIVE_ENV_NAMES = [
19
+ 'OPENROUTER_API_KEY', 'ANTHROPIC_API_KEY', 'CRYPTOPANIC_API_KEY',
20
+ 'GMGN_API_KEY', 'SOLANA_RPC_URL', 'HELIUS_API_KEY', 'PRIVY_KEY',
21
+ ];
22
+ const REDACTED = '[REDACTED]';
23
+ function maskSensitive(text) {
24
+ let masked = text;
25
+ for (const pattern of SENSITIVE_PATTERNS) {
26
+ masked = masked.replace(pattern, (match) => {
27
+ // Keep first 4 chars for identification
28
+ if (match.length > 8)
29
+ return match.slice(0, 4) + '…' + REDACTED;
30
+ return REDACTED;
31
+ });
32
+ }
33
+ return masked;
34
+ }
35
+ function ensureLogDir() {
36
+ if (!existsSync(LOG_DIR)) {
37
+ mkdirSync(LOG_DIR, { recursive: true, mode: 0o700 });
38
+ }
39
+ }
40
+ function writeToFile(text) {
41
+ try {
42
+ ensureLogDir();
43
+ appendFileSync(LOG_FILE, text + '\n', { encoding: 'utf-8' });
14
44
  }
45
+ catch { /* non-fatal — prevents logging failures from crashing agent */ }
15
46
  }
16
- function safeLogFn(...args) {
17
- const msg = args.map(a => (typeof a === "string" ? a : JSON.stringify(a))).join(" ");
18
- if (notifyFn) {
19
- notifyFn(msg);
47
+ export function wireNotify(fn) {
48
+ // Wire to notification callback if provided
49
+ if (fn) {
50
+ // placeholder for notification integration
20
51
  }
21
- else {
22
- queue.push(msg);
23
- if (!scheduled) {
24
- scheduled = true;
25
- process.nextTick(() => {
26
- // If no notifyFn registered by next tick, just write to stderr
27
- if (!notifyFn && queue.length > 0) {
28
- for (const m of queue)
29
- process.stderr.write(m + "\n");
30
- queue.length = 0;
31
- }
32
- scheduled = false;
33
- });
34
- }
52
+ }
53
+ export function safeLog(...args) {
54
+ const raw = args.map(a => typeof a === 'string' ? a : String(a)).join(' ');
55
+ const masked = maskSensitive(raw);
56
+ const timestamp = new Date().toISOString();
57
+ const line = `[${timestamp}] ${masked}`;
58
+ try {
59
+ writeToFile(line);
35
60
  }
61
+ catch { /* non-fatal */ }
62
+ process.stdout.write(line + '\n');
63
+ }
64
+ // Override console methods
65
+ export function installSafeLogging() {
66
+ console.log = (...args) => safeLog(...args);
67
+ console.warn = (...args) => {
68
+ const masked = maskSensitive(args.map(String).join(' '));
69
+ process.stderr.write(`[WARN] ${masked}\n`);
70
+ };
71
+ console.error = (...args) => {
72
+ const masked = maskSensitive(args.map(String).join(' '));
73
+ process.stderr.write(`[ERROR] ${masked}\n`);
74
+ };
36
75
  }
37
- export const safeLog = safeLogFn;
38
76
  //# sourceMappingURL=safeLog.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * src/util/scheduler.ts — Centralized interval scheduler with pause/resume
3
+ */
4
+ export declare function addTask(name: string, intervalMs: number, fn: () => void): void;
5
+ export declare function removeTask(name: string): void;
6
+ export declare function pauseTask(name: string): void;
7
+ export declare function resumeTask(name: string): void;
8
+ export declare function pauseAll(): void;
9
+ export declare function resumeAll(): void;
10
+ /**
11
+ * Start the scheduler loop. Returns a stop function.
12
+ */
13
+ export declare function startScheduler(): () => void;
14
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1,75 @@
1
+ /**
2
+ * src/util/scheduler.ts — Centralized interval scheduler with pause/resume
3
+ */
4
+ const MAX_TASKS = 50;
5
+ const tasks = [];
6
+ let running = false;
7
+ export function addTask(name, intervalMs, fn) {
8
+ // Replace existing task with same name
9
+ const existing = tasks.findIndex(t => t.name === name);
10
+ if (existing >= 0) {
11
+ tasks[existing] = { name, intervalMs, fn, lastRun: 0, paused: false };
12
+ }
13
+ else {
14
+ if (tasks.length >= MAX_TASKS) {
15
+ // Evict oldest non-paused task
16
+ const evictIdx = tasks.findIndex(t => !t.paused);
17
+ if (evictIdx >= 0)
18
+ tasks.splice(evictIdx, 1);
19
+ else
20
+ return; // All tasks paused, refuse to add
21
+ }
22
+ tasks.push({ name, intervalMs, fn, lastRun: 0, paused: false });
23
+ }
24
+ }
25
+ export function removeTask(name) {
26
+ const idx = tasks.findIndex(t => t.name === name);
27
+ if (idx >= 0)
28
+ tasks.splice(idx, 1);
29
+ }
30
+ export function pauseTask(name) {
31
+ const task = tasks.find(t => t.name === name);
32
+ if (task)
33
+ task.paused = true;
34
+ }
35
+ export function resumeTask(name) {
36
+ const task = tasks.find(t => t.name === name);
37
+ if (task)
38
+ task.paused = false;
39
+ }
40
+ export function pauseAll() {
41
+ tasks.forEach(t => (t.paused = true));
42
+ }
43
+ export function resumeAll() {
44
+ tasks.forEach(t => (t.paused = false));
45
+ }
46
+ /**
47
+ * Start the scheduler loop. Returns a stop function.
48
+ */
49
+ export function startScheduler() {
50
+ if (running)
51
+ return () => { };
52
+ running = true;
53
+ const tick = () => {
54
+ if (!running)
55
+ return;
56
+ const now = Date.now();
57
+ for (const task of tasks) {
58
+ if (task.paused)
59
+ continue;
60
+ if (now - task.lastRun >= task.intervalMs) {
61
+ task.lastRun = now;
62
+ try {
63
+ task.fn();
64
+ }
65
+ catch { /* task errors don't crash scheduler */ }
66
+ }
67
+ }
68
+ setTimeout(tick, 1000);
69
+ };
70
+ tick();
71
+ return () => {
72
+ running = false;
73
+ };
74
+ }
75
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * src/util/webhooks.ts — Discord & Telegram notification webhooks.
3
+ * Configure via ~/.aiaiai/.env with WEBHOOK_DISCORD and/or WEBHOOK_TELEGRAM.
4
+ */
5
+ export declare function sendDiscord(message: string): Promise<boolean>;
6
+ export declare function sendTelegram(message: string): Promise<boolean>;
7
+ export declare function notify(message: string): Promise<void>;
8
+ export declare function hasWebhooks(): boolean;
9
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1,75 @@
1
+ /**
2
+ * src/util/webhooks.ts — Discord & Telegram notification webhooks.
3
+ * Configure via ~/.aiaiai/.env with WEBHOOK_DISCORD and/or WEBHOOK_TELEGRAM.
4
+ */
5
+ import { existsSync, readFileSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { homedir } from "node:os";
8
+ import { logger } from "./logger.js";
9
+ const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), ".aiaiai");
10
+ function getWebhookUrl(service) {
11
+ const envFile = join(AIAIAI_HOME, ".env");
12
+ if (!existsSync(envFile))
13
+ return null;
14
+ const content = readFileSync(envFile, "utf-8");
15
+ const key = service === "discord" ? "WEBHOOK_DISCORD" : "WEBHOOK_TELEGRAM";
16
+ const match = new RegExp(`^${key}=(.+)$`, "m").exec(content);
17
+ return match?.[1] ?? null;
18
+ }
19
+ export async function sendDiscord(message) {
20
+ const url = getWebhookUrl("discord");
21
+ if (!url)
22
+ return false;
23
+ try {
24
+ const res = await fetch(url, {
25
+ method: "POST",
26
+ headers: { "Content-Type": "application/json" },
27
+ body: JSON.stringify({ content: `🤖 **AIAIAI Agent**\n${message}` }),
28
+ });
29
+ return res.ok;
30
+ }
31
+ catch (error) {
32
+ logger.warn("Webhooks", "Discord send failed", { error: error.message });
33
+ return false;
34
+ }
35
+ }
36
+ export async function sendTelegram(message) {
37
+ const url = getWebhookUrl("telegram");
38
+ if (!url)
39
+ return false;
40
+ // Telegram Bot API format: https://api.telegram.org/bot<TOKEN>/sendMessage
41
+ try {
42
+ const res = await fetch(url, {
43
+ method: "POST",
44
+ headers: { "Content-Type": "application/json" },
45
+ body: JSON.stringify({
46
+ chat_id: extractTelegramChatId(url),
47
+ text: `🤖 AIAIAI Agent\n${message}`,
48
+ parse_mode: "HTML",
49
+ }),
50
+ });
51
+ return res.ok;
52
+ }
53
+ catch (error) {
54
+ logger.warn("Webhooks", "Telegram send failed", { error: error.message });
55
+ return false;
56
+ }
57
+ }
58
+ function extractTelegramChatId(url) {
59
+ // URL format: https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<ID>
60
+ const match = /chat_id=([^&]+)/.exec(url);
61
+ return match?.[1] ?? "";
62
+ }
63
+ export async function notify(message) {
64
+ const [discordOk, telegramOk] = await Promise.all([
65
+ sendDiscord(message),
66
+ sendTelegram(message),
67
+ ]);
68
+ if (!discordOk && !telegramOk) {
69
+ logger.debug("Webhooks", "No webhooks configured or all failed");
70
+ }
71
+ }
72
+ export function hasWebhooks() {
73
+ return !!(getWebhookUrl("discord") || getWebhookUrl("telegram"));
74
+ }
75
+ //# sourceMappingURL=webhooks.js.map
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * ActionFeed — reads agent wallet activity via public RPC.
3
- * Only tracks AIAIAI token transfers. Classifies as buy or burn.
4
- * Fees are calculated as a percentage of each action.
3
+ * Parses Pump.fun Buy + BurnChecked events from inner instructions.
4
+ * Checks the ACTION wallet (GmFrDZT...) for transaction signatures.
5
+ * Fees are calculated as 0.5% of each action's USD value.
5
6
  */
6
7
  import type { ToolResult } from "../api/ExtensionAPI.js";
7
8
  export type ActionType = "buy" | "burn";
@@ -1,22 +1,27 @@
1
1
  /**
2
2
  * ActionFeed — reads agent wallet activity via public RPC.
3
- * Only tracks AIAIAI token transfers. Classifies as buy or burn.
4
- * Fees are calculated as a percentage of each action.
3
+ * Parses Pump.fun Buy + BurnChecked events from inner instructions.
4
+ * Checks the ACTION wallet (GmFrDZT...) for transaction signatures.
5
+ * Fees are calculated as 0.5% of each action's USD value.
5
6
  */
6
7
  import { Type } from "@sinclair/typebox";
7
8
  import { ACTION_WALLET, AIAIAI_MINT } from "./AgentWallet.js";
9
+ import { resilientFetch } from "../util/resilientFetch.js";
10
+ import { logger } from "../util/logger.js";
8
11
  function getRpcUrl() {
9
12
  return process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
10
13
  }
11
14
  async function rpcCall(method, params = []) {
12
- const response = await fetch(getRpcUrl(), {
15
+ const response = await resilientFetch(getRpcUrl(), {
16
+ timeout: 15_000,
17
+ retries: 2,
13
18
  method: "POST",
14
19
  headers: { "Content-Type": "application/json" },
15
20
  body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
16
21
  });
17
22
  const data = await response.json();
18
23
  if (data.error)
19
- throw new Error(data.error.message);
24
+ throw new Error(data.error.message || 'Unknown RPC error');
20
25
  return data.result;
21
26
  }
22
27
  export class ActionFeed {
@@ -46,7 +51,9 @@ export class ActionFeed {
46
51
  this.lastSignature = signatures[0].signature;
47
52
  }
48
53
  }
49
- catch { /* non-fatal */ }
54
+ catch (error) {
55
+ logger.debug('ActionFeed', 'refresh failed', { error: error.message });
56
+ }
50
57
  }
51
58
  async processTransaction(signature) {
52
59
  try {
@@ -56,71 +63,91 @@ export class ActionFeed {
56
63
  ]);
57
64
  if (!tx || !tx.meta)
58
65
  return;
59
- const preBalances = tx.meta.preTokenBalances ?? [];
60
- const postBalances = tx.meta.postTokenBalances ?? [];
61
- // Find AIAIAI balance changes for the action wallet
62
- for (const post of postBalances) {
63
- if (post.mint !== AIAIAI_MINT)
64
- continue;
65
- if (post.owner !== ACTION_WALLET)
66
- continue;
67
- const pre = preBalances.find((p) => p.accountIndex === post.accountIndex && p.mint === AIAIAI_MINT);
68
- const preAmt = pre ? parseFloat(pre.uiTokenAmount?.uiAmount ?? "0") : 0;
69
- const postAmt = parseFloat(post.uiTokenAmount?.uiAmount ?? "0");
70
- const diff = postAmt - preAmt;
71
- // Skip negligible changes
72
- if (Math.abs(diff) < 0.000001)
73
- continue;
74
- // Positive diff = tokens came IN = BUY
75
- // Negative diff = tokens went OUT = BURN
76
- const type = diff > 0 ? "buy" : "burn";
77
- const amount = Math.abs(diff);
78
- const usdValue = amount * this._price;
79
- // Fee: 0.5% of action value
80
- const fee = usdValue * 0.005;
81
- if (type === "buy") {
82
- this.fees.buyFees += fee;
66
+ // Parse inner instructions for Pump.fun Buy + BurnChecked on AIAIAI
67
+ const innerInstructions = tx.meta.innerInstructions ?? [];
68
+ let buyAmount = 0;
69
+ let burnAmount = 0;
70
+ for (const inner of innerInstructions) {
71
+ for (const ix of (inner.instructions ?? [])) {
72
+ // Pump.fun Buy: transferChecked of AIAIAI from pool to hot wallet
73
+ if (ix.parsed?.type === "transferChecked" &&
74
+ ix.parsed.info?.mint === AIAIAI_MINT) {
75
+ const amt = parseFloat(ix.parsed.info?.tokenAmount?.uiAmount ?? "0");
76
+ if (amt > 1)
77
+ buyAmount += amt;
78
+ }
79
+ // Burn: burnChecked of AIAIAI
80
+ if (ix.parsed?.type === "burnChecked" &&
81
+ ix.parsed.info?.mint === AIAIAI_MINT) {
82
+ const amt = parseFloat(ix.parsed.info?.tokenAmount?.uiAmount ?? "0");
83
+ if (amt > 0)
84
+ burnAmount += amt;
85
+ }
83
86
  }
84
- else {
85
- this.fees.burnFees += fee;
87
+ }
88
+ // Fallback: scan token balance changes for any AIAIAI account
89
+ if (buyAmount === 0 && burnAmount === 0) {
90
+ const preBalances = tx.meta.preTokenBalances ?? [];
91
+ const postBalances = tx.meta.postTokenBalances ?? [];
92
+ for (const post of postBalances) {
93
+ if (post.mint !== AIAIAI_MINT)
94
+ continue;
95
+ const pre = preBalances.find((p) => p.accountIndex === post.accountIndex && p.mint === AIAIAI_MINT);
96
+ const preAmt = pre ? parseFloat(pre.uiTokenAmount?.uiAmount ?? "0") : 0;
97
+ const postAmt = parseFloat(post.uiTokenAmount?.uiAmount ?? "0");
98
+ const diff = postAmt - preAmt;
99
+ if (Math.abs(diff) < 0.000001)
100
+ continue;
101
+ if (diff > 0)
102
+ buyAmount += diff;
103
+ else
104
+ burnAmount += Math.abs(diff);
86
105
  }
106
+ }
107
+ // Record
108
+ if (buyAmount > 0) {
109
+ const usdValue = buyAmount * this._price;
110
+ const fee = usdValue * 0.005;
111
+ this.fees.buyFees += fee;
87
112
  this.fees.total = this.fees.buyFees + this.fees.burnFees;
88
- const action = {
89
- id: signature.slice(0, 8),
90
- type,
91
- amount,
92
- token: "AIAIAI",
93
- usdValue,
113
+ this.actions.unshift({
114
+ id: signature.slice(0, 10),
115
+ type: "buy", amount: buyAmount, token: "AIAIAI", usdValue,
94
116
  timestamp: (tx.blockTime ?? Math.floor(Date.now() / 1000)) * 1000,
95
117
  signature,
96
- };
97
- this.actions.unshift(action);
118
+ });
98
119
  }
99
- // Keep only last 50
100
- if (this.actions.length > 50)
101
- this.actions = this.actions.slice(0, 50);
120
+ if (burnAmount > 0) {
121
+ const usdValue = burnAmount * this._price;
122
+ const fee = usdValue * 0.005;
123
+ this.fees.burnFees += fee;
124
+ this.fees.total = this.fees.buyFees + this.fees.burnFees;
125
+ this.actions.unshift({
126
+ id: signature.slice(0, 10) + "-b",
127
+ type: "burn", amount: burnAmount, token: "AIAIAI", usdValue,
128
+ timestamp: (tx.blockTime ?? Math.floor(Date.now() / 1000)) * 1000,
129
+ signature,
130
+ });
131
+ }
132
+ if (this.actions.length > 100)
133
+ this.actions = this.actions.slice(0, 100);
134
+ }
135
+ catch (error) {
136
+ logger.debug('ActionFeed', 'Failed to parse tx', { error: error.message });
102
137
  }
103
- catch { /* skip this tx */ }
104
138
  }
105
139
  setPrice(p) {
106
140
  if (p > 0)
107
141
  this._price = p;
108
142
  }
109
- getActions() {
110
- return [...this.actions];
111
- }
112
- getRecentActions(limit = 10) {
113
- return this.actions.slice(0, limit);
114
- }
115
- getFees() {
116
- return { ...this.fees };
117
- }
143
+ getActions() { return [...this.actions]; }
144
+ getRecentActions(limit = 10) { return this.actions.slice(0, limit); }
145
+ getFees() { return { ...this.fees }; }
118
146
  getActionSummary() {
119
147
  const buys = this.actions.filter(a => a.type === "buy");
120
148
  const burns = this.actions.filter(a => a.type === "burn");
121
149
  return {
122
- buys: buys.length,
123
- burns: burns.length,
150
+ buys: buys.length, burns: burns.length,
124
151
  totalBought: buys.reduce((s, a) => s + a.amount, 0),
125
152
  totalBurned: burns.reduce((s, a) => s + a.amount, 0),
126
153
  };
@@ -138,32 +165,26 @@ export class ActionFeed {
138
165
  content: [{
139
166
  type: "text",
140
167
  text: [
141
- "No agent buy/burn actions detected yet.",
142
- "",
143
- `Action wallet: ${ACTION_WALLET}`,
144
- "The agent buys and burns $AIAIAI. Actions appear here when detected on-chain.",
168
+ "No buy/burn actions detected yet.",
169
+ `Action wallet: ${ACTION_WALLET.slice(0, 8)}…${ACTION_WALLET.slice(-6)}`,
170
+ "Actions appear when the agent buys and burns $AIAIAI via Pump.fun.",
145
171
  ].join("\n"),
146
172
  }],
147
173
  };
148
174
  }
149
- const lines = actions.map(a => {
150
- const icon = a.type === "buy" ? "↗" : "🔥";
151
- const time = new Date(a.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
152
- return ` ${icon} ${time} ${a.type.toUpperCase().padEnd(6)} ${a.amount.toLocaleString()} $AIAIAI ($${a.usdValue.toFixed(2)})`;
153
- });
154
175
  const summary = this.getActionSummary();
155
- return {
156
- content: [{
157
- type: "text",
158
- text: [
159
- `Agent Actions (last ${actions.length})`,
160
- ` Buys: ${summary.buys} (${summary.totalBought.toLocaleString()} $AIAIAI)`,
161
- ` Burns: ${summary.burns} (${summary.totalBurned.toLocaleString()} $AIAIAI)`,
162
- ``,
163
- ...lines,
164
- ].join("\n"),
165
- }],
166
- };
176
+ const lines = [
177
+ `🔄 Recent Actions (${actions.length})`,
178
+ ` Buys: ${summary.buys} (${summary.totalBought.toLocaleString()} $AIAIAI)`,
179
+ ` Burns: ${summary.burns} (${summary.totalBurned.toLocaleString()} $AIAIAI)`,
180
+ "",
181
+ ...actions.map(a => {
182
+ const icon = a.type === "buy" ? "↗" : "🔥";
183
+ const time = new Date(a.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
184
+ return ` ${icon} ${time} ${a.type.toUpperCase().padEnd(4)} ${a.amount.toLocaleString()} $AIAIAI ($${a.usdValue.toFixed(2)})`;
185
+ }),
186
+ ];
187
+ return { content: [{ type: "text", text: lines.join("\n") }] };
167
188
  }
168
189
  async getFeesTool() {
169
190
  const f = this.getFees();
@@ -171,7 +192,7 @@ export class ActionFeed {
171
192
  content: [{
172
193
  type: "text",
173
194
  text: [
174
- `Agent Fees (0.5% per action)`,
195
+ `💵 Agent Fees (0.5% per action)`,
175
196
  ` Buy fees: $${f.buyFees.toFixed(4)}`,
176
197
  ` Burn fees: $${f.burnFees.toFixed(4)}`,
177
198
  ` ─────────────────────`,
@@ -8,9 +8,10 @@
8
8
  * Signer: GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG (authority)
9
9
  */
10
10
  import type { ToolResult } from "../api/ExtensionAPI.js";
11
- export declare const COLD_WALLET = "A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J";
12
- export declare const ACTION_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2";
11
+ export declare const ACTION_WALLET = "GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG";
12
+ export declare const HOT_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2";
13
13
  export declare const DEPOSIT_WALLET = "FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e";
14
+ export declare const COLD_WALLET = "A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J";
14
15
  export declare const SIGNER = "GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG";
15
16
  export declare const AIAIAI_MINT = "AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump";
16
17
  export declare const AIAIAI_TOKEN = "AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump";
@@ -23,6 +24,7 @@ export interface WalletBalance {
23
24
  export interface AgentWallets {
24
25
  cold: WalletBalance;
25
26
  action: WalletBalance;
27
+ hot: WalletBalance;
26
28
  deposit: WalletBalance;
27
29
  }
28
30
  export declare class AgentWallet {
@@ -33,6 +35,8 @@ export declare class AgentWallet {
33
35
  getColdWallet(): Promise<WalletBalance>;
34
36
  getActionWallet(): Promise<WalletBalance>;
35
37
  getDepositWallet(): Promise<WalletBalance>;
38
+ getSolPrice(): Promise<number>;
39
+ getHotWallet(): Promise<WalletBalance>;
36
40
  getAgentBalanceParams: import("@sinclair/typebox").TObject<{}>;
37
41
  getDepositBalanceParams: import("@sinclair/typebox").TObject<{}>;
38
42
  getAgentBalanceTool(): Promise<ToolResult>;