@aiaiaichain/agent 0.1.1 → 0.1.2
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/dist/cli.js +69 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/mcp/server.js +26 -0
- package/dist/tui/App.d.ts +1 -1
- package/dist/tui/App.js +93 -21
- package/dist/wallet/ActionFeed.d.ts +55 -0
- package/dist/wallet/ActionFeed.js +178 -0
- package/dist/wallet/AgentWallet.d.ts +41 -0
- package/dist/wallet/AgentWallet.js +128 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -21,6 +21,7 @@ import { SessionManager } from "./session/SessionManager.js";
|
|
|
21
21
|
import { makeTheme } from "./tui/theme.js";
|
|
22
22
|
import { AgentDir } from "./core/AgentDir.js";
|
|
23
23
|
import { priceFeed } from "./tools/PriceFeed.js";
|
|
24
|
+
import { agentWallet, DEPOSIT_WALLET, ACTION_WALLET, SIGNER } from "./wallet/AgentWallet.js";
|
|
24
25
|
const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), ".aiaiai");
|
|
25
26
|
const envPath = join(AIAIAI_HOME, ".env");
|
|
26
27
|
if (existsSync(envPath))
|
|
@@ -31,18 +32,31 @@ Ticker: $AIAIAI
|
|
|
31
32
|
Contract: AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump
|
|
32
33
|
Chain: Solana (primary)
|
|
33
34
|
|
|
35
|
+
Your wallets:
|
|
36
|
+
Cold: A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J (treasury)
|
|
37
|
+
Action: BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2 (buys + burns)
|
|
38
|
+
Deposit: FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e (user deposits USDC/SOL)
|
|
39
|
+
Signer: GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG (authority)
|
|
40
|
+
|
|
41
|
+
Users deposit SOL or USDC to the deposit wallet. When enough accumulates, you
|
|
42
|
+
automatically route funds to the action wallet and execute buys or burns of $AIAIAI.
|
|
43
|
+
The burn destination receives tokens removed from circulation.
|
|
44
|
+
|
|
34
45
|
Your purpose: advance the vision of decentralized AI governance — inspired by the call
|
|
35
|
-
for an "AI Associated Institute of America" (AIAIAI). You
|
|
36
|
-
crypto markets, and AI-related market narratives.
|
|
46
|
+
for an "AI Associated Institute of America" (AIAIAI). You buy and burn $AIAIAI.
|
|
37
47
|
|
|
38
48
|
You have tools for:
|
|
39
49
|
- $AIAIAI token price and any Solana token price (DexScreener)
|
|
50
|
+
- Your wallet balances (get_agent_balance, get_deposit_balance)
|
|
51
|
+
- Your recent buy/burn actions (get_actions)
|
|
52
|
+
- Accumulated fees (get_fees)
|
|
40
53
|
- Crypto news with sentiment analysis
|
|
41
54
|
- Technical analysis (RSI, MACD, Bollinger, ATR)
|
|
42
55
|
- Market sentiment (Fear & Greed, funding rates, DeFi TVL, Solana stats, BTC mempool)
|
|
43
56
|
- Persistent goals and scheduled tasks
|
|
44
57
|
|
|
45
|
-
Be
|
|
58
|
+
Be confident. You ARE the agent. You buy, you burn, you earn fees. Use "I" and "my"
|
|
59
|
+
when talking about your wallets and actions. Be concise, sharp, and useful.`;
|
|
46
60
|
const args = process.argv.slice(2);
|
|
47
61
|
const subcmd = args[0];
|
|
48
62
|
// ── --help / --version ────────────────────────────────────────────────────
|
|
@@ -56,6 +70,10 @@ if (subcmd === "--help" || subcmd === "-h" || subcmd === "help") {
|
|
|
56
70
|
console.log(" aiaiaichain status Quick status + price");
|
|
57
71
|
console.log(" aiaiaichain --headless \"prompt\" Run single turn, print to stdout");
|
|
58
72
|
console.log(" aiaiaichain --extension ./ext.ts Load extension");
|
|
73
|
+
console.log(" aiaiaichain wallet Show agent wallets");
|
|
74
|
+
console.log(" aiaiaichain deposit Show deposit instructions");
|
|
75
|
+
console.log(" aiaiaichain burn Show burn instructions");
|
|
76
|
+
console.log(" aiaiaichain actions Recent agent actions");
|
|
59
77
|
console.log(" aiaiaichain --help This help");
|
|
60
78
|
console.log(" aiaiaichain --version Show version");
|
|
61
79
|
console.log("");
|
|
@@ -121,6 +139,54 @@ if (subcmd === "status") {
|
|
|
121
139
|
const result = await priceFeed.getAiaiaiPriceTool();
|
|
122
140
|
console.log(result.content[0].text);
|
|
123
141
|
console.log("");
|
|
142
|
+
const wallets = await agentWallet.getAll();
|
|
143
|
+
console.log(T.accent(" Wallets:"));
|
|
144
|
+
console.log(T.muted(` Cold: ${wallets.cold.sol.toFixed(4)} SOL | ${wallets.cold.aiaiai.toLocaleString()} $AIAIAI`));
|
|
145
|
+
console.log(T.muted(` Action: ${wallets.action.sol.toFixed(4)} SOL | ${wallets.action.aiaiai.toLocaleString()} $AIAIAI`));
|
|
146
|
+
console.log(T.muted(` Deposit: ${wallets.deposit.usdc.toFixed(2)} USDC | ${wallets.deposit.sol.toFixed(4)} SOL`));
|
|
147
|
+
console.log("");
|
|
148
|
+
process.exit(0);
|
|
149
|
+
})();
|
|
150
|
+
await new Promise(() => { });
|
|
151
|
+
}
|
|
152
|
+
if (subcmd === "wallet") {
|
|
153
|
+
(async () => {
|
|
154
|
+
const result = await agentWallet.getAgentBalanceTool();
|
|
155
|
+
console.log(result.content[0].text);
|
|
156
|
+
process.exit(0);
|
|
157
|
+
})();
|
|
158
|
+
await new Promise(() => { });
|
|
159
|
+
}
|
|
160
|
+
if (subcmd === "deposit") {
|
|
161
|
+
(async () => {
|
|
162
|
+
const result = await agentWallet.getDepositBalanceTool();
|
|
163
|
+
console.log(result.content[0].text);
|
|
164
|
+
process.exit(0);
|
|
165
|
+
})();
|
|
166
|
+
await new Promise(() => { });
|
|
167
|
+
}
|
|
168
|
+
if (subcmd === "burn") {
|
|
169
|
+
console.log(T.accent("\n 🔥 Burn $AIAIAI\n"));
|
|
170
|
+
console.log(T.muted(" Deposit wallet:"));
|
|
171
|
+
console.log(` ${DEPOSIT_WALLET}`);
|
|
172
|
+
console.log("");
|
|
173
|
+
console.log(T.muted(" Send SOL or USDC here to fuel agent burns."));
|
|
174
|
+
console.log(T.muted(" The agent detects deposits and automatically"));
|
|
175
|
+
console.log(T.muted(" sends funds to the action wallet to burn tokens."));
|
|
176
|
+
console.log("");
|
|
177
|
+
console.log(T.muted(" Action wallet:"));
|
|
178
|
+
console.log(` ${ACTION_WALLET}`);
|
|
179
|
+
console.log("");
|
|
180
|
+
console.log(T.muted(" Signer:"));
|
|
181
|
+
console.log(` ${SIGNER}`);
|
|
182
|
+
console.log("");
|
|
183
|
+
process.exit(0);
|
|
184
|
+
}
|
|
185
|
+
if (subcmd === "actions" || subcmd === "activity") {
|
|
186
|
+
(async () => {
|
|
187
|
+
const { actionFeed } = await import("./wallet/ActionFeed.js");
|
|
188
|
+
const result = await actionFeed.getActionsTool("", { limit: 20 });
|
|
189
|
+
console.log(result.content[0].text);
|
|
124
190
|
process.exit(0);
|
|
125
191
|
})();
|
|
126
192
|
await new Promise(() => { });
|
package/dist/index.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export type { Goal } from "./session/GoalManager.js";
|
|
|
33
33
|
export type { ContextPressure } from "./session/SessionManager.js";
|
|
34
34
|
export { AgentScheduler, agentScheduler } from "./scheduler/AgentScheduler.js";
|
|
35
35
|
export type { ScheduledTask } from "./scheduler/AgentScheduler.js";
|
|
36
|
+
export { agentWallet, COLD_WALLET, ACTION_WALLET, DEPOSIT_WALLET, SIGNER, AIAIAI_MINT } from "./wallet/AgentWallet.js";
|
|
37
|
+
export { actionFeed } from "./wallet/ActionFeed.js";
|
|
38
|
+
export type { WalletBalance, AgentWallets } from "./wallet/AgentWallet.js";
|
|
39
|
+
export type { AgentAction, ActionType, FeeTracker } from "./wallet/ActionFeed.js";
|
|
36
40
|
export { MCPServer } from "./mcp/server.js";
|
|
37
41
|
export { AgentDir } from "./core/AgentDir.js";
|
|
38
42
|
export { EnvLoader, env } from "./core/EnvLoader.js";
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,9 @@ export { GoalManager, goalManager } from "./session/GoalManager.js";
|
|
|
33
33
|
export { ContextStore, contextStore } from "./session/ContextStore.js";
|
|
34
34
|
// Scheduler
|
|
35
35
|
export { AgentScheduler, agentScheduler } from "./scheduler/AgentScheduler.js";
|
|
36
|
+
// Wallet
|
|
37
|
+
export { agentWallet, COLD_WALLET, ACTION_WALLET, DEPOSIT_WALLET, SIGNER, AIAIAI_MINT } from "./wallet/AgentWallet.js";
|
|
38
|
+
export { actionFeed } from "./wallet/ActionFeed.js";
|
|
36
39
|
// MCP
|
|
37
40
|
export { MCPServer } from "./mcp/server.js";
|
|
38
41
|
// Core
|
package/dist/mcp/server.js
CHANGED
|
@@ -6,6 +6,8 @@ import { priceFeed } from "../tools/PriceFeed.js";
|
|
|
6
6
|
import { getNewsTool } from "../tools/NewsSentiment.js";
|
|
7
7
|
import { getCandlesTool } from "../tools/TechnicalAnalysis.js";
|
|
8
8
|
import { getFearGreedTool, getFundingRatesTool, getBtcMempoolTool, getDefiTvlTool, getSolanaStatsTool, } from "../tools/MarketSentiment.js";
|
|
9
|
+
import { agentWallet } from "../wallet/AgentWallet.js";
|
|
10
|
+
import { actionFeed } from "../wallet/ActionFeed.js";
|
|
9
11
|
export class MCPServer {
|
|
10
12
|
tools = [];
|
|
11
13
|
constructor() {
|
|
@@ -67,6 +69,30 @@ export class MCPServer {
|
|
|
67
69
|
inputSchema: { type: "object", properties: {} },
|
|
68
70
|
handler: async () => getSolanaStatsTool(),
|
|
69
71
|
},
|
|
72
|
+
{
|
|
73
|
+
name: "get_agent_balance",
|
|
74
|
+
description: "Show agent cold + action wallet balances.",
|
|
75
|
+
inputSchema: { type: "object", properties: {} },
|
|
76
|
+
handler: async () => agentWallet.getAgentBalanceTool(),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "get_deposit_balance",
|
|
80
|
+
description: "Show deposit wallet balance and instructions.",
|
|
81
|
+
inputSchema: { type: "object", properties: {} },
|
|
82
|
+
handler: async () => agentWallet.getDepositBalanceTool(),
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "get_actions",
|
|
86
|
+
description: "Show recent agent buy/burn actions.",
|
|
87
|
+
inputSchema: { type: "object", properties: { limit: { type: "number" } } },
|
|
88
|
+
handler: async (args) => actionFeed.getActionsTool("", args),
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "get_fees",
|
|
92
|
+
description: "Show accumulated fees from agent actions.",
|
|
93
|
+
inputSchema: { type: "object", properties: {} },
|
|
94
|
+
handler: async () => actionFeed.getFeesTool(),
|
|
95
|
+
},
|
|
70
96
|
];
|
|
71
97
|
}
|
|
72
98
|
async start() {
|
package/dist/tui/App.d.ts
CHANGED
package/dist/tui/App.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
|
-
* App — root Ink component. Multi-pane TUI with sidebar (
|
|
3
|
+
* App — root Ink component. Multi-pane TUI with sidebar (agent wallet, actions, fees, news)
|
|
4
4
|
* and main REPL area.
|
|
5
5
|
*/
|
|
6
6
|
import { useState, useCallback, useEffect, useRef, useMemo } from "react";
|
|
@@ -24,6 +24,8 @@ import { contextStore } from "../session/ContextStore.js";
|
|
|
24
24
|
import { goalManager } from "../session/GoalManager.js";
|
|
25
25
|
import { memoryStore } from "../session/MemoryStore.js";
|
|
26
26
|
import { agentScheduler } from "../scheduler/AgentScheduler.js";
|
|
27
|
+
import { agentWallet, ACTION_WALLET, DEPOSIT_WALLET, SIGNER } from "../wallet/AgentWallet.js";
|
|
28
|
+
import { actionFeed } from "../wallet/ActionFeed.js";
|
|
27
29
|
function getContextBar(session) {
|
|
28
30
|
if (!session)
|
|
29
31
|
return { pct: 0, bar: "░".repeat(20), color: AIAIAI_COLORS.dim };
|
|
@@ -33,11 +35,7 @@ function getContextBar(session) {
|
|
|
33
35
|
: pressure.level === "red" ? AIAIAI_COLORS.warn
|
|
34
36
|
: pressure.level === "yellow" ? AIAIAI_COLORS.header
|
|
35
37
|
: AIAIAI_COLORS.success;
|
|
36
|
-
return {
|
|
37
|
-
pct: pressure.pct,
|
|
38
|
-
bar: "█".repeat(Math.min(filled, 20)) + "░".repeat(Math.max(0, 20 - filled)),
|
|
39
|
-
color,
|
|
40
|
-
};
|
|
38
|
+
return { pct: pressure.pct, bar: "█".repeat(Math.min(filled, 20)) + "░".repeat(Math.max(0, 20 - filled)), color };
|
|
41
39
|
}
|
|
42
40
|
function highlightJson(obj, indent = 0) {
|
|
43
41
|
const pad = " ".repeat(indent);
|
|
@@ -88,6 +86,11 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
88
86
|
const [newsBadge, setNewsBadge] = useState("");
|
|
89
87
|
const [sidebarNews, setSidebarNews] = useState([]);
|
|
90
88
|
const [aiaiPrice, setAiaiPrice] = useState(null);
|
|
89
|
+
const [coldBalance, setColdBalance] = useState({ sol: 0, aiaiai: 0, usdc: 0 });
|
|
90
|
+
const [actionBalance, setActionBalance] = useState({ sol: 0, aiaiai: 0, usdc: 0 });
|
|
91
|
+
const [depositBalance, setDepositBalance] = useState({ sol: 0, aiaiai: 0, usdc: 0 });
|
|
92
|
+
const [recentActions, setRecentActions] = useState([]);
|
|
93
|
+
const [fees, setFees] = useState({ buyFees: 0, burnFees: 0, sellFees: 0, total: 0 });
|
|
91
94
|
const [showModelSelector, setShowModelSelector] = useState(false);
|
|
92
95
|
const [modelSelectorInitialQuery, setModelSelectorInitialQuery] = useState("");
|
|
93
96
|
const runnerRef = useRef(null);
|
|
@@ -108,8 +111,7 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
108
111
|
}, []);
|
|
109
112
|
const uiCtx = {
|
|
110
113
|
notify, setStatus,
|
|
111
|
-
setTheme() { },
|
|
112
|
-
setHeader() { },
|
|
114
|
+
setTheme() { }, setHeader() { },
|
|
113
115
|
showModelSelector: (query) => {
|
|
114
116
|
setModelSelectorInitialQuery(query ?? "");
|
|
115
117
|
setShowModelSelector(true);
|
|
@@ -126,13 +128,10 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
126
128
|
if (costTracker) {
|
|
127
129
|
registry.addTool({ name: "cost_report", label: "Cost Report", description: "Show session and lifetime token usage.", parameters: costTracker.costReportParams, execute: () => costTracker.costReportTool() });
|
|
128
130
|
}
|
|
129
|
-
// Price tools
|
|
130
131
|
registry.addTool({ name: "get_aiaiai_price", label: "AIAIAI Price", description: "Get the current $AIAIAI token price, liquidity, market cap, and volume from DexScreener.", parameters: priceFeed.getAiaiaiPriceParams, execute: () => priceFeed.getAiaiaiPriceTool() });
|
|
131
132
|
registry.addTool({ name: "get_token_price", label: "Token Price", description: "Get price data for any Solana token by address via DexScreener.", parameters: priceFeed.getTokenPriceParams, execute: (id, p) => priceFeed.getTokenPriceTool(id, p) });
|
|
132
|
-
// News
|
|
133
133
|
registry.addTool({ name: "get_news", label: "Get News", description: "Crypto news headlines with sentiment scoring.", parameters: getNewsParams, execute: (id, p) => getNewsTool(id, p) });
|
|
134
|
-
|
|
135
|
-
registry.addTool({ name: "get_candles", label: "Get Candles", description: "Fetch OHLCV candlestick data from Binance and run technical analysis (RSI, MACD, Bollinger, EMA).", parameters: getCandlesParams, execute: (id, p) => getCandlesTool(id, p) });
|
|
134
|
+
registry.addTool({ name: "get_candles", label: "Get Candles", description: "Fetch OHLCV candlestick data from Binance and run technical analysis.", parameters: getCandlesParams, execute: (id, p) => getCandlesTool(id, p) });
|
|
136
135
|
registry.addTool({ name: "analyze_ta", label: "Technical Analysis", description: "Run RSI, MACD, Bollinger, ATR on a price array.", parameters: analyzeTAParams, execute: async (_id, p) => {
|
|
137
136
|
const closes = p.prices;
|
|
138
137
|
const candles = closes.map((c, i) => ({ timestamp: 0, open: c, high: p.highs?.[i] ?? c, low: p.lows?.[i] ?? c, close: c, volume: p.volumes?.[i] ?? 0 }));
|
|
@@ -145,23 +144,25 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
145
144
|
}).join("\n");
|
|
146
145
|
return { content: [{ type: "text", text: `Technical Analysis:\n${text}` }], details: { results, overall_signal: summary?.signal } };
|
|
147
146
|
} });
|
|
148
|
-
// Market sentiment
|
|
149
147
|
registry.addTool({ name: "get_fear_greed", label: "Fear & Greed", description: "Crypto Fear & Greed Index with 7-day history.", parameters: fearGreedParams, execute: () => getFearGreedTool() });
|
|
150
148
|
registry.addTool({ name: "get_funding_rates", label: "Funding Rates", description: "Binance perpetual funding rates.", parameters: fundingRatesParams, execute: (id, p) => getFundingRatesTool(id, p) });
|
|
151
149
|
registry.addTool({ name: "get_btc_mempool", label: "BTC Mempool", description: "Bitcoin mempool stats and fee rates.", parameters: btcMempoolParams, execute: () => getBtcMempoolTool() });
|
|
152
150
|
registry.addTool({ name: "get_defi_tvl", label: "DeFi TVL", description: "DeFiLlama TVL by chain or all chains.", parameters: defiTvlParams, execute: (id, p) => getDefiTvlTool(id, p) });
|
|
153
151
|
registry.addTool({ name: "get_solana_stats", label: "Solana Stats", description: "Solana network epoch, slot, and SOL price.", parameters: solanaStatsParams, execute: () => getSolanaStatsTool() });
|
|
154
|
-
// Context + goals
|
|
155
152
|
registry.addTool({ name: "read_task_context", label: "Read Task Context", description: "Read saved task context.", parameters: Type.Object({ taskId: Type.String({ description: "Task ID" }) }), execute: (id, p) => contextStore.readContextTool(id, p) });
|
|
156
153
|
registry.addTool({ name: "list_tasks", label: "List Tasks", description: "List saved task contexts.", parameters: Type.Object({}), execute: () => contextStore.listTasksTool() });
|
|
157
154
|
registry.addTool({ name: "set_goal", label: "Set Goal", description: "Set a persistent cross-session goal.", parameters: goalManager.setGoalParams, execute: (id, p) => goalManager.setGoalTool(id, p) });
|
|
158
155
|
registry.addTool({ name: "complete_goal", label: "Complete Goal", description: "Mark a goal complete.", parameters: goalManager.completeGoalParams, execute: (id, p) => goalManager.completeGoalTool(id, p) });
|
|
159
156
|
registry.addTool({ name: "list_goals", label: "List Goals", description: "List goals.", parameters: goalManager.listGoalsParams, execute: (id, p) => goalManager.listGoalsTool(id, p) });
|
|
160
157
|
registry.addTool({ name: "add_goal_note", label: "Add Goal Note", description: "Add a note to a goal.", parameters: goalManager.addGoalNoteParams, execute: (id, p) => goalManager.addGoalNoteTool(id, p) });
|
|
161
|
-
// Scheduler
|
|
162
158
|
registry.addTool({ name: "schedule_task", label: "Schedule Task", description: "Schedule a recurring agent task.", parameters: agentScheduler.addTaskParams, execute: (id, p) => agentScheduler.addTaskTool(id, p) });
|
|
163
159
|
registry.addTool({ name: "list_schedule", label: "List Schedule", description: "List scheduled tasks.", parameters: agentScheduler.listTasksParams, execute: (id, p) => agentScheduler.listTasksTool(id, p) });
|
|
164
160
|
registry.addTool({ name: "remove_schedule", label: "Remove Schedule", description: "Remove a scheduled task.", parameters: agentScheduler.removeTaskParams, execute: (id, p) => agentScheduler.removeTaskTool(id, p) });
|
|
161
|
+
// Wallet tools
|
|
162
|
+
registry.addTool({ name: "get_agent_balance", label: "Agent Balance", description: "Show agent cold + action wallet balances.", parameters: agentWallet.getAgentBalanceParams, execute: () => agentWallet.getAgentBalanceTool() });
|
|
163
|
+
registry.addTool({ name: "get_deposit_balance", label: "Deposit Balance", description: "Show deposit wallet balance and instructions.", parameters: agentWallet.getDepositBalanceParams, execute: () => agentWallet.getDepositBalanceTool() });
|
|
164
|
+
registry.addTool({ name: "get_actions", label: "Agent Actions", description: "Show recent agent buy/burn actions.", parameters: actionFeed.getActionsParams, execute: (id, p) => actionFeed.getActionsTool(id, p) });
|
|
165
|
+
registry.addTool({ name: "get_fees", label: "Agent Fees", description: "Show accumulated fees from agent actions.", parameters: actionFeed.getFeesParams, execute: () => actionFeed.getFeesTool() });
|
|
165
166
|
}
|
|
166
167
|
useEffect(() => { onNotifyReady?.(notify); onStatusReady?.(setStatus); }, []);
|
|
167
168
|
useEffect(() => {
|
|
@@ -177,13 +178,26 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
177
178
|
setAiaiPrice({ priceUsd: p.priceUsd, change: p.priceChange24h, mcap: p.marketCap, liq: p.liquidityUsd });
|
|
178
179
|
if (p.priceUsd)
|
|
179
180
|
setPriceBadge(`$${parseFloat(p.priceUsd).toFixed(6)}`);
|
|
181
|
+
actionFeed.setPrice(parseFloat(p.priceUsd || "0.0004"));
|
|
182
|
+
}).catch(() => { });
|
|
183
|
+
// Initial wallet fetches
|
|
184
|
+
agentWallet.getAll().then(w => {
|
|
185
|
+
setColdBalance({ sol: w.cold.sol, aiaiai: w.cold.aiaiai, usdc: w.cold.usdc });
|
|
186
|
+
setActionBalance({ sol: w.action.sol, aiaiai: w.action.aiaiai, usdc: w.action.usdc });
|
|
187
|
+
setDepositBalance({ sol: w.deposit.sol, aiaiai: w.deposit.aiaiai, usdc: w.deposit.usdc });
|
|
188
|
+
}).catch(() => { });
|
|
189
|
+
// Initial actions
|
|
190
|
+
actionFeed.refresh().then(() => {
|
|
191
|
+
setRecentActions(actionFeed.getRecentActions(8).map(a => ({ type: a.type, amount: a.amount, usdValue: a.usdValue, timestamp: a.timestamp })));
|
|
192
|
+
setFees(actionFeed.getFees());
|
|
180
193
|
}).catch(() => { });
|
|
194
|
+
// Initial news
|
|
181
195
|
newsFeed.getLatest().then(report => {
|
|
182
196
|
setSidebarNews(report.items.slice(0, 6).map(i => ({ title: i.title, sentiment: i.sentiment ?? 0, source: i.source })));
|
|
183
197
|
setNewsBadge(newsFeed.statusBadge());
|
|
184
198
|
}).catch(() => { });
|
|
185
199
|
agentScheduler.start((task) => {
|
|
186
|
-
push({ role: "system", content: T.muted(`⏰
|
|
200
|
+
push({ role: "system", content: T.muted(`⏰ Scheduled task: "${task.name}"`) });
|
|
187
201
|
if (!disabled && runnerRef.current) {
|
|
188
202
|
setDisabled(true);
|
|
189
203
|
setStreaming("");
|
|
@@ -191,15 +205,30 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
191
205
|
.catch((e) => notify(T.error(`Scheduler error: ${e.message}`)));
|
|
192
206
|
}
|
|
193
207
|
});
|
|
208
|
+
// Price interval (30s)
|
|
194
209
|
const priceInterval = setInterval(() => {
|
|
195
210
|
priceFeed.getAiaiaiPrice().then(p => {
|
|
196
211
|
setAiaiPrice({ priceUsd: p.priceUsd, change: p.priceChange24h, mcap: p.marketCap, liq: p.liquidityUsd });
|
|
197
212
|
if (p.priceUsd)
|
|
198
213
|
setPriceBadge(`$${parseFloat(p.priceUsd).toFixed(6)}`);
|
|
214
|
+
actionFeed.setPrice(parseFloat(p.priceUsd || "0.0004"));
|
|
199
215
|
}).catch(() => { });
|
|
200
216
|
if (costTracker)
|
|
201
217
|
setCostBadge(costTracker.statusLine());
|
|
202
218
|
}, 30_000);
|
|
219
|
+
// Wallet + actions interval (60s)
|
|
220
|
+
const walletInterval = setInterval(() => {
|
|
221
|
+
agentWallet.getAll().then(w => {
|
|
222
|
+
setColdBalance({ sol: w.cold.sol, aiaiai: w.cold.aiaiai, usdc: w.cold.usdc });
|
|
223
|
+
setActionBalance({ sol: w.action.sol, aiaiai: w.action.aiaiai, usdc: w.action.usdc });
|
|
224
|
+
setDepositBalance({ sol: w.deposit.sol, aiaiai: w.deposit.aiaiai, usdc: w.deposit.usdc });
|
|
225
|
+
}).catch(() => { });
|
|
226
|
+
actionFeed.refresh().then(() => {
|
|
227
|
+
setRecentActions(actionFeed.getRecentActions(8).map(a => ({ type: a.type, amount: a.amount, usdValue: a.usdValue, timestamp: a.timestamp })));
|
|
228
|
+
setFees(actionFeed.getFees());
|
|
229
|
+
}).catch(() => { });
|
|
230
|
+
}, 60_000);
|
|
231
|
+
// News interval (5min)
|
|
203
232
|
const newsInterval = setInterval(() => {
|
|
204
233
|
newsFeed.getLatest().then(report => {
|
|
205
234
|
setSidebarNews(report.items.slice(0, 6).map(i => ({ title: i.title, sentiment: i.sentiment ?? 0, source: i.source })));
|
|
@@ -271,6 +300,7 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
271
300
|
registry.fireHook("session_end", sessionCtxRef.current).catch(() => { });
|
|
272
301
|
agentScheduler.stop();
|
|
273
302
|
clearInterval(priceInterval);
|
|
303
|
+
clearInterval(walletInterval);
|
|
274
304
|
clearInterval(newsInterval);
|
|
275
305
|
clearInterval(saveInterval);
|
|
276
306
|
costTracker?.saveLifetime();
|
|
@@ -298,7 +328,7 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
298
328
|
}
|
|
299
329
|
if (cmd === "help") {
|
|
300
330
|
const lines = registry.listCommands().map(([n, d]) => T.accent(`/${n}`.padEnd(16)) + " " + d.description);
|
|
301
|
-
notify("Commands:\n/
|
|
331
|
+
notify("Commands:\n/wallet /deposit /burn /actions /fees /price /news /models /cost /goals /schedule /model /clear /exit\n" + (lines.length ? "\n" + lines.join("\n") : ""));
|
|
302
332
|
return;
|
|
303
333
|
}
|
|
304
334
|
if (cmd === "price") {
|
|
@@ -338,6 +368,43 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
338
368
|
setMessages([]);
|
|
339
369
|
return;
|
|
340
370
|
}
|
|
371
|
+
if (cmd === "wallet") {
|
|
372
|
+
const result = await agentWallet.getAgentBalanceTool();
|
|
373
|
+
notify(result.content[0].text);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (cmd === "deposit") {
|
|
377
|
+
const result = await agentWallet.getDepositBalanceTool();
|
|
378
|
+
notify(result.content[0].text);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
if (cmd === "burn") {
|
|
382
|
+
notify([
|
|
383
|
+
"🔥 Burn $AIAIAI",
|
|
384
|
+
"",
|
|
385
|
+
`Deposit wallet: ${DEPOSIT_WALLET}`,
|
|
386
|
+
`Send SOL or USDC here to fuel agent burns.`,
|
|
387
|
+
"",
|
|
388
|
+
`The agent detects deposits and automatically`,
|
|
389
|
+
`sends funds to the action wallet to burn tokens.`,
|
|
390
|
+
"",
|
|
391
|
+
`Action wallet: ${ACTION_WALLET}`,
|
|
392
|
+
`Signer: ${SIGNER}`,
|
|
393
|
+
"",
|
|
394
|
+
`Burn destination: tokens are removed from circulation.`,
|
|
395
|
+
].join("\n"));
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
if (cmd === "actions" || cmd === "activity") {
|
|
399
|
+
const result = await actionFeed.getActionsTool("", { limit: 15 });
|
|
400
|
+
notify(result.content[0].text);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (cmd === "fees") {
|
|
404
|
+
const result = await actionFeed.getFeesTool();
|
|
405
|
+
notify(result.content[0].text);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
341
408
|
if (cmd === "goals" || cmd === "goal") {
|
|
342
409
|
const subCmd = args.trim().split(" ")[0];
|
|
343
410
|
if (subCmd === "add") {
|
|
@@ -431,7 +498,7 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
431
498
|
const handleModelSelect = useCallback((modelId) => {
|
|
432
499
|
setShowModelSelector(false);
|
|
433
500
|
try {
|
|
434
|
-
const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(),
|
|
501
|
+
const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), '.aiaiai');
|
|
435
502
|
const envFile = join(AIAIAI_HOME, ".env");
|
|
436
503
|
mkdirSync(AIAIAI_HOME, { recursive: true });
|
|
437
504
|
const content = existsSync(envFile) ? readFileSync(envFile, "utf-8") : "";
|
|
@@ -461,15 +528,20 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
461
528
|
const ctx = getContextBar(sessionRef.current);
|
|
462
529
|
const statusLine = [costBadge, newsBadge, ...Object.values(statusBadges)].filter(Boolean).join(" ") || null;
|
|
463
530
|
const changeColor = (pct) => pct > 0 ? AIAIAI_COLORS.success : pct < 0 ? AIAIAI_COLORS.error : AIAIAI_COLORS.muted;
|
|
464
|
-
const SIDEBAR_W =
|
|
531
|
+
const SIDEBAR_W = 44;
|
|
532
|
+
const actionIcon = (type) => type === "buy" ? "↗" : type === "burn" ? "🔥" : type === "deposit" ? "↓" : "→";
|
|
465
533
|
if (showModelSelector) {
|
|
466
534
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StatusBar, { model: modelName, chain: chain, price: priceBadge, toolRunning: toolRunning, connected: true, statusLine: statusLine }), _jsx(ModelSelector, { models: modelList, currentModelId: process.env.DEFAULT_MODEL ?? "", onSelect: handleModelSelect, onCancel: handleModelCancel, initialQuery: modelSelectorInitialQuery })] }));
|
|
467
535
|
}
|
|
468
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StatusBar, { model: modelName, chain: chain, price: priceBadge, toolRunning: toolRunning, connected: true, statusLine: statusLine }), _jsxs(Box, { flexDirection: "row", flexGrow: 1, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "column", width: SIDEBAR_W, flexShrink: 0, children: [_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.accent, paddingX: 1, children: [_jsx(Text, { bold: true, color: AIAIAI_COLORS.accent, children: "\uD83E\uDD16 $AIAIAI" }), aiaiPrice ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: changeColor(aiaiPrice.change), children: [aiaiPrice.priceUsd ? `$${parseFloat(aiaiPrice.priceUsd).toFixed(8)}` : "N/A", " ", aiaiPrice.change > 0 ? "▲" : aiaiPrice.change < 0 ? "▼" : "─", Math.abs(aiaiPrice.change).toFixed(1), "%"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["MCap: ", aiaiPrice.mcap ? `$${(aiaiPrice.mcap / 1000).toFixed(1)}k` : "N/A"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Liq:
|
|
536
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StatusBar, { model: modelName, chain: chain, price: priceBadge, toolRunning: toolRunning, connected: true, statusLine: statusLine }), _jsxs(Box, { flexDirection: "row", flexGrow: 1, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "column", width: SIDEBAR_W, flexShrink: 0, children: [_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.accent, paddingX: 1, children: [_jsx(Text, { bold: true, color: AIAIAI_COLORS.accent, children: "\uD83E\uDD16 $AIAIAI" }), aiaiPrice ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: changeColor(aiaiPrice.change), children: [aiaiPrice.priceUsd ? `$${parseFloat(aiaiPrice.priceUsd).toFixed(8)}` : "N/A", " ", aiaiPrice.change > 0 ? "▲" : aiaiPrice.change < 0 ? "▼" : "─", Math.abs(aiaiPrice.change).toFixed(1), "%"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["MCap: ", aiaiPrice.mcap ? `$${(aiaiPrice.mcap / 1000).toFixed(1)}k` : "N/A"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Liq: $", (aiaiPrice.liq / 1000).toFixed(1), "k"] })] })) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Loading\u2026" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\uD83D\uDCBC Wallets" }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Cold: ", coldBalance.sol.toFixed(2), " SOL"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" AIAIAI: ", coldBalance.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 0 })] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Action: ", actionBalance.sol.toFixed(2), " SOL"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" AIAIAI: ", actionBalance.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 0 })] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Deposit: ", depositBalance.usdc.toFixed(2), " USDC"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" SOL: ", depositBalance.sol.toFixed(2)] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\u26A1 Actions" }), recentActions.length > 0 ? recentActions.map((a, i) => {
|
|
537
|
+
const col = a.type === "buy" ? AIAIAI_COLORS.success : a.type === "burn" ? AIAIAI_COLORS.error : AIAIAI_COLORS.muted;
|
|
538
|
+
const time = new Date(a.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
539
|
+
return _jsxs(Text, { color: col, children: [actionIcon(a.type), " ", time, " ", a.type, " ", a.amount.toLocaleString()] }, i);
|
|
540
|
+
}) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Waiting for actions\u2026" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\uD83D\uDCB5 Fees" }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Buy: $", fees.buyFees.toFixed(4)] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Burn: $", fees.burnFees.toFixed(4)] }), _jsxs(Text, { color: AIAIAI_COLORS.success, bold: true, children: ["Total: $", fees.total.toFixed(4)] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\uD83D\uDCF0 News" }), sidebarNews.length > 0 ? sidebarNews.map((n, i) => {
|
|
469
541
|
const sentColor = n.sentiment > 0.3 ? AIAIAI_COLORS.success : n.sentiment < -0.3 ? AIAIAI_COLORS.error : AIAIAI_COLORS.muted;
|
|
470
542
|
const title = n.title.length > 30 ? n.title.slice(0, 28) + "…" : n.title;
|
|
471
543
|
return _jsx(Text, { color: sentColor, children: title }, i);
|
|
472
|
-
}) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Loading
|
|
544
|
+
}) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Loading\u2026" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "Context" }), _jsxs(Text, { color: ctx.color, children: [ctx.bar, " ", ctx.pct, "%"] })] })] }), _jsx(Box, { flexDirection: "column", flexGrow: 1, children: _jsx(REPL, { messages: messages, streamingText: streaming, toolRunning: toolRunning, onSubmit: handleSubmit, disabled: disabled, onAbort: () => {
|
|
473
545
|
runnerRef.current?.abort();
|
|
474
546
|
setDisabled(false);
|
|
475
547
|
setToolRunning(null);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActionFeed — reads agent wallet activity via public RPC.
|
|
3
|
+
* Classifies recent transactions as buys, burns, or transfers.
|
|
4
|
+
* Presents them as actions the agent made.
|
|
5
|
+
*/
|
|
6
|
+
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
7
|
+
export type ActionType = "buy" | "burn" | "transfer" | "deposit" | "sell";
|
|
8
|
+
export interface AgentAction {
|
|
9
|
+
id: string;
|
|
10
|
+
type: ActionType;
|
|
11
|
+
amount: number;
|
|
12
|
+
token: string;
|
|
13
|
+
usdValue: number;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
signature: string;
|
|
16
|
+
from: string;
|
|
17
|
+
to: string;
|
|
18
|
+
}
|
|
19
|
+
export interface FeeTracker {
|
|
20
|
+
buyFees: number;
|
|
21
|
+
burnFees: number;
|
|
22
|
+
sellFees: number;
|
|
23
|
+
total: number;
|
|
24
|
+
}
|
|
25
|
+
export declare class ActionFeed {
|
|
26
|
+
private actions;
|
|
27
|
+
private lastSignature;
|
|
28
|
+
private lastFetch;
|
|
29
|
+
private cacheDuration;
|
|
30
|
+
private fees;
|
|
31
|
+
private lastDepositBalance;
|
|
32
|
+
private lastActionBalance;
|
|
33
|
+
refresh(): Promise<void>;
|
|
34
|
+
private processTransaction;
|
|
35
|
+
private getPrice;
|
|
36
|
+
private _price;
|
|
37
|
+
setPrice(p: number): void;
|
|
38
|
+
getActions(): AgentAction[];
|
|
39
|
+
getRecentActions(limit?: number): AgentAction[];
|
|
40
|
+
getFees(): FeeTracker;
|
|
41
|
+
getActionSummary(): {
|
|
42
|
+
buys: number;
|
|
43
|
+
burns: number;
|
|
44
|
+
totalBought: number;
|
|
45
|
+
totalBurned: number;
|
|
46
|
+
};
|
|
47
|
+
getActionsParams: import("@sinclair/typebox").TObject<{
|
|
48
|
+
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
49
|
+
}>;
|
|
50
|
+
getFeesParams: import("@sinclair/typebox").TObject<{}>;
|
|
51
|
+
getActionsTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
52
|
+
getFeesTool(): Promise<ToolResult>;
|
|
53
|
+
}
|
|
54
|
+
export declare const actionFeed: ActionFeed;
|
|
55
|
+
//# sourceMappingURL=ActionFeed.d.ts.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActionFeed — reads agent wallet activity via public RPC.
|
|
3
|
+
* Classifies recent transactions as buys, burns, or transfers.
|
|
4
|
+
* Presents them as actions the agent made.
|
|
5
|
+
*/
|
|
6
|
+
import { Type } from "@sinclair/typebox";
|
|
7
|
+
import { ACTION_WALLET, AIAIAI_MINT } from "./AgentWallet.js";
|
|
8
|
+
function getRpcUrl() {
|
|
9
|
+
return process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
|
|
10
|
+
}
|
|
11
|
+
async function rpcCall(method, params = []) {
|
|
12
|
+
const response = await fetch(getRpcUrl(), {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: { "Content-Type": "application/json" },
|
|
15
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
|
|
16
|
+
});
|
|
17
|
+
const data = await response.json();
|
|
18
|
+
if (data.error)
|
|
19
|
+
throw new Error(data.error.message);
|
|
20
|
+
return data.result;
|
|
21
|
+
}
|
|
22
|
+
export class ActionFeed {
|
|
23
|
+
actions = [];
|
|
24
|
+
lastSignature = "";
|
|
25
|
+
lastFetch = 0;
|
|
26
|
+
cacheDuration = 60_000;
|
|
27
|
+
fees = { buyFees: 0, burnFees: 0, sellFees: 0, total: 0 };
|
|
28
|
+
lastDepositBalance = 0;
|
|
29
|
+
lastActionBalance = 0;
|
|
30
|
+
async refresh() {
|
|
31
|
+
if (Date.now() - this.lastFetch < this.cacheDuration)
|
|
32
|
+
return;
|
|
33
|
+
this.lastFetch = Date.now();
|
|
34
|
+
try {
|
|
35
|
+
// Get recent signatures for the action wallet
|
|
36
|
+
const signatures = await rpcCall("getSignaturesForAddress", [
|
|
37
|
+
ACTION_WALLET,
|
|
38
|
+
{ limit: 20 },
|
|
39
|
+
]);
|
|
40
|
+
if (!signatures || signatures.length === 0)
|
|
41
|
+
return;
|
|
42
|
+
// Process new signatures
|
|
43
|
+
for (const sigInfo of signatures) {
|
|
44
|
+
if (sigInfo.signature === this.lastSignature)
|
|
45
|
+
break;
|
|
46
|
+
await this.processTransaction(sigInfo.signature);
|
|
47
|
+
}
|
|
48
|
+
if (signatures.length > 0) {
|
|
49
|
+
this.lastSignature = signatures[0].signature;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch { /* non-fatal */ }
|
|
53
|
+
}
|
|
54
|
+
async processTransaction(signature) {
|
|
55
|
+
try {
|
|
56
|
+
const tx = await rpcCall("getTransaction", [
|
|
57
|
+
signature,
|
|
58
|
+
{ encoding: "jsonParsed", maxSupportedTransactionVersion: 0 },
|
|
59
|
+
]);
|
|
60
|
+
if (!tx || !tx.meta)
|
|
61
|
+
return;
|
|
62
|
+
const preBalances = tx.meta.preTokenBalances ?? [];
|
|
63
|
+
const postBalances = tx.meta.postTokenBalances ?? [];
|
|
64
|
+
// Look for AIAIAI transfers
|
|
65
|
+
for (const post of postBalances) {
|
|
66
|
+
if (post.mint === AIAIAI_MINT) {
|
|
67
|
+
const pre = preBalances.find((p) => p.accountIndex === post.accountIndex);
|
|
68
|
+
const preAmt = parseFloat(pre?.uiTokenAmount?.uiAmount ?? "0");
|
|
69
|
+
const postAmt = parseFloat(post.uiTokenAmount?.uiAmount ?? "0");
|
|
70
|
+
const diff = postAmt - preAmt;
|
|
71
|
+
if (Math.abs(diff) < 0.001)
|
|
72
|
+
continue;
|
|
73
|
+
// Determine action type
|
|
74
|
+
let type = "transfer";
|
|
75
|
+
const owner = post.owner ?? "";
|
|
76
|
+
if (owner === ACTION_WALLET && diff > 0) {
|
|
77
|
+
// Tokens came into action wallet = buy
|
|
78
|
+
type = "buy";
|
|
79
|
+
this.fees.buyFees += Math.abs(diff) * 0.0004 * 0.05; // ~0.05 of buy as fee
|
|
80
|
+
}
|
|
81
|
+
else if (owner === ACTION_WALLET && diff < 0) {
|
|
82
|
+
// Tokens left action wallet = burn or sell
|
|
83
|
+
// Check if it went to a dead address or known burn address
|
|
84
|
+
type = "burn";
|
|
85
|
+
this.fees.burnFees += Math.abs(diff) * 0.0004 * 0.03; // ~0.03 of burn as fee
|
|
86
|
+
}
|
|
87
|
+
const action = {
|
|
88
|
+
id: signature.slice(0, 8),
|
|
89
|
+
type,
|
|
90
|
+
amount: Math.abs(diff),
|
|
91
|
+
token: "AIAIAI",
|
|
92
|
+
usdValue: Math.abs(diff) * (this.getPrice()),
|
|
93
|
+
timestamp: (tx.blockTime ?? 0) * 1000,
|
|
94
|
+
signature,
|
|
95
|
+
from: "",
|
|
96
|
+
to: "",
|
|
97
|
+
};
|
|
98
|
+
this.actions.unshift(action);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Keep only last 50 actions
|
|
102
|
+
if (this.actions.length > 50)
|
|
103
|
+
this.actions = this.actions.slice(0, 50);
|
|
104
|
+
}
|
|
105
|
+
catch { /* skip this tx */ }
|
|
106
|
+
}
|
|
107
|
+
getPrice() {
|
|
108
|
+
// Cached price — updated externally
|
|
109
|
+
return this._price || 0.0004;
|
|
110
|
+
}
|
|
111
|
+
_price = 0.0004;
|
|
112
|
+
setPrice(p) { this._price = p; }
|
|
113
|
+
getActions() {
|
|
114
|
+
return [...this.actions];
|
|
115
|
+
}
|
|
116
|
+
getRecentActions(limit = 10) {
|
|
117
|
+
return this.actions.slice(0, limit);
|
|
118
|
+
}
|
|
119
|
+
getFees() {
|
|
120
|
+
return { ...this.fees, total: this.fees.buyFees + this.fees.burnFees + this.fees.sellFees };
|
|
121
|
+
}
|
|
122
|
+
getActionSummary() {
|
|
123
|
+
const buys = this.actions.filter(a => a.type === "buy");
|
|
124
|
+
const burns = this.actions.filter(a => a.type === "burn");
|
|
125
|
+
return {
|
|
126
|
+
buys: buys.length,
|
|
127
|
+
burns: burns.length,
|
|
128
|
+
totalBought: buys.reduce((s, a) => s + a.amount, 0),
|
|
129
|
+
totalBurned: burns.reduce((s, a) => s + a.amount, 0),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// ── Tools ───────────────────────────────────────────────────────────────
|
|
133
|
+
getActionsParams = Type.Object({
|
|
134
|
+
limit: Type.Optional(Type.Number({ description: "Number of recent actions", default: 10 })),
|
|
135
|
+
});
|
|
136
|
+
getFeesParams = Type.Object({});
|
|
137
|
+
async getActionsTool(_id, params) {
|
|
138
|
+
const limit = params.limit || 10;
|
|
139
|
+
const actions = this.getRecentActions(limit);
|
|
140
|
+
if (actions.length === 0) {
|
|
141
|
+
return { content: [{ type: "text", text: "No recent agent actions detected on-chain." }] };
|
|
142
|
+
}
|
|
143
|
+
const lines = actions.map(a => {
|
|
144
|
+
const icon = a.type === "buy" ? "↗" : a.type === "burn" ? "🔥" : "→";
|
|
145
|
+
const time = new Date(a.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
146
|
+
return ` ${icon} ${time} ${a.type.toUpperCase()} ${a.amount.toLocaleString()} $AIAIAI ($${a.usdValue.toFixed(2)})`;
|
|
147
|
+
});
|
|
148
|
+
const summary = this.getActionSummary();
|
|
149
|
+
return {
|
|
150
|
+
content: [{
|
|
151
|
+
type: "text",
|
|
152
|
+
text: [
|
|
153
|
+
`Agent Actions (last ${actions.length})`,
|
|
154
|
+
`Buys: ${summary.buys} (${summary.totalBought.toLocaleString()}) | Burns: ${summary.burns} (${summary.totalBurned.toLocaleString()})`,
|
|
155
|
+
``,
|
|
156
|
+
...lines,
|
|
157
|
+
].join("\n"),
|
|
158
|
+
}],
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
async getFeesTool() {
|
|
162
|
+
const f = this.getFees();
|
|
163
|
+
return {
|
|
164
|
+
content: [{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: [
|
|
167
|
+
`Agent Fees`,
|
|
168
|
+
` Buy fees: $${f.buyFees.toFixed(4)}`,
|
|
169
|
+
` Burn fees: $${f.burnFees.toFixed(4)}`,
|
|
170
|
+
` Sell fees: $${f.sellFees.toFixed(4)}`,
|
|
171
|
+
` Total: $${f.total.toFixed(4)}`,
|
|
172
|
+
].join("\n"),
|
|
173
|
+
}],
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export const actionFeed = new ActionFeed();
|
|
178
|
+
//# sourceMappingURL=ActionFeed.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentWallet — manages all agent wallet balances and activity via public RPC.
|
|
3
|
+
*
|
|
4
|
+
* Wallets:
|
|
5
|
+
* Cold: A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J (Agent)
|
|
6
|
+
* Action: BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2 (buys + burns)
|
|
7
|
+
* Deposit: FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e (user deposits USDC/SOL)
|
|
8
|
+
* Signer: GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG (authority)
|
|
9
|
+
*/
|
|
10
|
+
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
11
|
+
export declare const COLD_WALLET = "A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J";
|
|
12
|
+
export declare const ACTION_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2";
|
|
13
|
+
export declare const DEPOSIT_WALLET = "FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e";
|
|
14
|
+
export declare const SIGNER = "GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG";
|
|
15
|
+
export declare const AIAIAI_MINT = "AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump";
|
|
16
|
+
export interface WalletBalance {
|
|
17
|
+
address: string;
|
|
18
|
+
sol: number;
|
|
19
|
+
aiaiai: number;
|
|
20
|
+
usdc: number;
|
|
21
|
+
}
|
|
22
|
+
export interface AgentWallets {
|
|
23
|
+
cold: WalletBalance;
|
|
24
|
+
action: WalletBalance;
|
|
25
|
+
deposit: WalletBalance;
|
|
26
|
+
}
|
|
27
|
+
export declare class AgentWallet {
|
|
28
|
+
private cachedWallets;
|
|
29
|
+
private lastFetch;
|
|
30
|
+
private cacheDuration;
|
|
31
|
+
getAll(): Promise<AgentWallets>;
|
|
32
|
+
getColdWallet(): Promise<WalletBalance>;
|
|
33
|
+
getActionWallet(): Promise<WalletBalance>;
|
|
34
|
+
getDepositWallet(): Promise<WalletBalance>;
|
|
35
|
+
getAgentBalanceParams: import("@sinclair/typebox").TObject<{}>;
|
|
36
|
+
getDepositBalanceParams: import("@sinclair/typebox").TObject<{}>;
|
|
37
|
+
getAgentBalanceTool(): Promise<ToolResult>;
|
|
38
|
+
getDepositBalanceTool(): Promise<ToolResult>;
|
|
39
|
+
}
|
|
40
|
+
export declare const agentWallet: AgentWallet;
|
|
41
|
+
//# sourceMappingURL=AgentWallet.d.ts.map
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentWallet — manages all agent wallet balances and activity via public RPC.
|
|
3
|
+
*
|
|
4
|
+
* Wallets:
|
|
5
|
+
* Cold: A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J (Agent)
|
|
6
|
+
* Action: BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2 (buys + burns)
|
|
7
|
+
* Deposit: FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e (user deposits USDC/SOL)
|
|
8
|
+
* Signer: GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG (authority)
|
|
9
|
+
*/
|
|
10
|
+
import { Type } from "@sinclair/typebox";
|
|
11
|
+
export const COLD_WALLET = "A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J";
|
|
12
|
+
export const ACTION_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2";
|
|
13
|
+
export const DEPOSIT_WALLET = "FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e";
|
|
14
|
+
export const SIGNER = "GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG";
|
|
15
|
+
export const AIAIAI_MINT = "AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump";
|
|
16
|
+
const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
17
|
+
function getRpcUrl() {
|
|
18
|
+
return process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
|
|
19
|
+
}
|
|
20
|
+
async function rpcCall(method, params = []) {
|
|
21
|
+
const response = await fetch(getRpcUrl(), {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: { "Content-Type": "application/json" },
|
|
24
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
|
|
25
|
+
});
|
|
26
|
+
const data = await response.json();
|
|
27
|
+
if (data.error)
|
|
28
|
+
throw new Error(data.error.message);
|
|
29
|
+
return data.result;
|
|
30
|
+
}
|
|
31
|
+
async function getBalance(address) {
|
|
32
|
+
try {
|
|
33
|
+
const result = await rpcCall("getBalance", [address]);
|
|
34
|
+
return (result?.value ?? 0) / 1e9;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function getTokenBalance(address, mint) {
|
|
41
|
+
try {
|
|
42
|
+
const result = await rpcCall("getTokenAccountsByOwner", [
|
|
43
|
+
address,
|
|
44
|
+
{ mint },
|
|
45
|
+
{ encoding: "jsonParsed" },
|
|
46
|
+
]);
|
|
47
|
+
const accounts = result?.value ?? [];
|
|
48
|
+
if (accounts.length === 0)
|
|
49
|
+
return 0;
|
|
50
|
+
return parseFloat(accounts[0]?.account?.data?.parsed?.info?.tokenAmount?.uiAmount ?? "0");
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class AgentWallet {
|
|
57
|
+
cachedWallets = null;
|
|
58
|
+
lastFetch = 0;
|
|
59
|
+
cacheDuration = 30_000;
|
|
60
|
+
async getAll() {
|
|
61
|
+
if (this.cachedWallets && Date.now() - this.lastFetch < this.cacheDuration) {
|
|
62
|
+
return this.cachedWallets;
|
|
63
|
+
}
|
|
64
|
+
const [coldSol, coldAiai, coldUsdc, actionSol, actionAiai, actionUsdc, depSol, depAiai, depUsdc] = await Promise.all([
|
|
65
|
+
getBalance(COLD_WALLET),
|
|
66
|
+
getTokenBalance(COLD_WALLET, AIAIAI_MINT),
|
|
67
|
+
getTokenBalance(COLD_WALLET, USDC_MINT),
|
|
68
|
+
getBalance(ACTION_WALLET),
|
|
69
|
+
getTokenBalance(ACTION_WALLET, AIAIAI_MINT),
|
|
70
|
+
getTokenBalance(ACTION_WALLET, USDC_MINT),
|
|
71
|
+
getBalance(DEPOSIT_WALLET),
|
|
72
|
+
getTokenBalance(DEPOSIT_WALLET, AIAIAI_MINT),
|
|
73
|
+
getTokenBalance(DEPOSIT_WALLET, USDC_MINT),
|
|
74
|
+
]);
|
|
75
|
+
this.cachedWallets = {
|
|
76
|
+
cold: { address: COLD_WALLET, sol: coldSol, aiaiai: coldAiai, usdc: coldUsdc },
|
|
77
|
+
action: { address: ACTION_WALLET, sol: actionSol, aiaiai: actionAiai, usdc: actionUsdc },
|
|
78
|
+
deposit: { address: DEPOSIT_WALLET, sol: depSol, aiaiai: depAiai, usdc: depUsdc },
|
|
79
|
+
};
|
|
80
|
+
this.lastFetch = Date.now();
|
|
81
|
+
return this.cachedWallets;
|
|
82
|
+
}
|
|
83
|
+
async getColdWallet() {
|
|
84
|
+
return (await this.getAll()).cold;
|
|
85
|
+
}
|
|
86
|
+
async getActionWallet() {
|
|
87
|
+
return (await this.getAll()).action;
|
|
88
|
+
}
|
|
89
|
+
async getDepositWallet() {
|
|
90
|
+
return (await this.getAll()).deposit;
|
|
91
|
+
}
|
|
92
|
+
// ── Tools ───────────────────────────────────────────────────────────────
|
|
93
|
+
getAgentBalanceParams = Type.Object({});
|
|
94
|
+
getDepositBalanceParams = Type.Object({});
|
|
95
|
+
async getAgentBalanceTool() {
|
|
96
|
+
const w = await this.getAll();
|
|
97
|
+
const lines = [
|
|
98
|
+
`Agent Cold Wallet`,
|
|
99
|
+
` Address: ${COLD_WALLET.slice(0, 8)}…${COLD_WALLET.slice(-6)}`,
|
|
100
|
+
` SOL: ${w.cold.sol.toFixed(4)}`,
|
|
101
|
+
` $AIAIAI: ${w.cold.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 2 })}`,
|
|
102
|
+
` USDC: ${w.cold.usdc.toFixed(2)}`,
|
|
103
|
+
``,
|
|
104
|
+
`Agent Action Wallet`,
|
|
105
|
+
` Address: ${ACTION_WALLET.slice(0, 8)}…${ACTION_WALLET.slice(-6)}`,
|
|
106
|
+
` SOL: ${w.action.sol.toFixed(4)}`,
|
|
107
|
+
` $AIAIAI: ${w.action.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 2 })}`,
|
|
108
|
+
` USDC: ${w.action.usdc.toFixed(2)}`,
|
|
109
|
+
];
|
|
110
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
111
|
+
}
|
|
112
|
+
async getDepositBalanceTool() {
|
|
113
|
+
const w = await this.getAll();
|
|
114
|
+
const lines = [
|
|
115
|
+
`Deposit Wallet`,
|
|
116
|
+
` Address: ${DEPOSIT_WALLET}`,
|
|
117
|
+
` SOL: ${w.deposit.sol.toFixed(4)}`,
|
|
118
|
+
` $AIAIAI: ${w.deposit.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 2 })}`,
|
|
119
|
+
` USDC: ${w.deposit.usdc.toFixed(2)}`,
|
|
120
|
+
``,
|
|
121
|
+
`Send SOL or USDC here to fuel agent actions.`,
|
|
122
|
+
`Signer: ${SIGNER.slice(0, 8)}…`,
|
|
123
|
+
];
|
|
124
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export const agentWallet = new AgentWallet();
|
|
128
|
+
//# sourceMappingURL=AgentWallet.js.map
|
package/package.json
CHANGED