@aiaiaichain/agent 0.1.6 → 0.1.7

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 (121) hide show
  1. package/dist/api/ExtensionAPI.d.ts +0 -1
  2. package/dist/api/ExtensionAPI.js +3 -7
  3. package/dist/api/Registry.d.ts +0 -1
  4. package/dist/api/Registry.js +54 -57
  5. package/dist/cli.d.ts +0 -1
  6. package/dist/cli.js +683 -686
  7. package/dist/core/AgentDir.d.ts +1 -1
  8. package/dist/core/AgentDir.js +45 -39
  9. package/dist/core/ChainConfig.d.ts +0 -1
  10. package/dist/core/ChainConfig.js +51 -55
  11. package/dist/core/EnvLoader.d.ts +4 -1
  12. package/dist/core/EnvLoader.js +97 -84
  13. package/dist/core/SystemMonitor.d.ts +0 -1
  14. package/dist/core/SystemMonitor.js +72 -85
  15. package/dist/index.d.ts +0 -1
  16. package/dist/index.js +19 -26
  17. package/dist/loader.d.ts +0 -1
  18. package/dist/loader.js +64 -67
  19. package/dist/mcp/entry.d.ts +0 -1
  20. package/dist/mcp/entry.js +3 -6
  21. package/dist/mcp/server.d.ts +0 -1
  22. package/dist/mcp/server.js +152 -156
  23. package/dist/models/CostTracker.d.ts +0 -1
  24. package/dist/models/CostTracker.js +58 -61
  25. package/dist/models/ModelRegistry.d.ts +0 -1
  26. package/dist/models/ModelRegistry.js +195 -155
  27. package/dist/providers/ProviderRegistry.d.ts +0 -1
  28. package/dist/providers/ProviderRegistry.js +33 -36
  29. package/dist/runner/AgentRunner.d.ts +0 -1
  30. package/dist/runner/AgentRunner.js +180 -184
  31. package/dist/runner/ModelClient.d.ts +0 -1
  32. package/dist/runner/ModelClient.js +133 -134
  33. package/dist/runner/SwarmRouter.d.ts +0 -1
  34. package/dist/runner/SwarmRouter.js +18 -22
  35. package/dist/runner/ToolDispatcher.d.ts +0 -1
  36. package/dist/runner/ToolDispatcher.js +30 -33
  37. package/dist/scheduler/AgentScheduler.d.ts +0 -1
  38. package/dist/scheduler/AgentScheduler.js +99 -103
  39. package/dist/session/ContextStore.d.ts +1 -1
  40. package/dist/session/ContextStore.js +76 -78
  41. package/dist/session/GoalManager.d.ts +0 -1
  42. package/dist/session/GoalManager.js +96 -100
  43. package/dist/session/MemoryStore.d.ts +2 -1
  44. package/dist/session/MemoryStore.js +108 -87
  45. package/dist/session/SessionManager.d.ts +5 -4
  46. package/dist/session/SessionManager.js +83 -62
  47. package/dist/session/SessionStore.d.ts +0 -1
  48. package/dist/session/SessionStore.js +112 -116
  49. package/dist/setup/SetupWizard.d.ts +0 -1
  50. package/dist/setup/SetupWizard.js +61 -64
  51. package/dist/tools/CrossTools.d.ts +0 -1
  52. package/dist/tools/CrossTools.js +140 -144
  53. package/dist/tools/GmgnIntegration.d.ts +0 -1
  54. package/dist/tools/GmgnIntegration.js +220 -230
  55. package/dist/tools/MarketSentiment.d.ts +0 -1
  56. package/dist/tools/MarketSentiment.js +213 -195
  57. package/dist/tools/NewsSentiment.d.ts +0 -1
  58. package/dist/tools/NewsSentiment.js +126 -130
  59. package/dist/tools/PriceFeed.d.ts +6 -1
  60. package/dist/tools/PriceFeed.js +201 -133
  61. package/dist/tools/TechnicalAnalysis.d.ts +1 -2
  62. package/dist/tools/TechnicalAnalysis.js +248 -216
  63. package/dist/tools/TechnicalAnalysis.worker.d.ts +25 -0
  64. package/dist/tools/TechnicalAnalysis.worker.js +92 -0
  65. package/dist/tools/TokenCalendar.d.ts +0 -1
  66. package/dist/tools/TokenCalendar.js +63 -68
  67. package/dist/tools/TokenSecurityScanner.d.ts +0 -1
  68. package/dist/tools/TokenSecurityScanner.js +93 -96
  69. package/dist/tools/TransactionSim.d.ts +0 -1
  70. package/dist/tools/TransactionSim.js +65 -71
  71. package/dist/tui/App.d.ts +0 -1
  72. package/dist/tui/App.js +895 -824
  73. package/dist/tui/ModelSelector.d.ts +0 -1
  74. package/dist/tui/ModelSelector.js +46 -49
  75. package/dist/tui/REPL.d.ts +0 -1
  76. package/dist/tui/REPL.js +222 -210
  77. package/dist/tui/Sparkline.d.ts +0 -1
  78. package/dist/tui/Sparkline.js +36 -37
  79. package/dist/tui/StatusBar.d.ts +0 -1
  80. package/dist/tui/StatusBar.js +9 -10
  81. package/dist/tui/ThemePresets.d.ts +0 -1
  82. package/dist/tui/ThemePresets.js +99 -103
  83. package/dist/tui/theme.d.ts +0 -1
  84. package/dist/tui/theme.js +50 -31
  85. package/dist/util/clipboard.d.ts +0 -1
  86. package/dist/util/clipboard.js +16 -20
  87. package/dist/util/commandSuggest.d.ts +0 -1
  88. package/dist/util/commandSuggest.js +34 -38
  89. package/dist/util/confirmation.d.ts +0 -1
  90. package/dist/util/confirmation.js +8 -11
  91. package/dist/util/errorHandler.d.ts +0 -1
  92. package/dist/util/errorHandler.js +20 -23
  93. package/dist/util/errors.d.ts +59 -0
  94. package/dist/util/errors.js +93 -0
  95. package/dist/util/logger.d.ts +0 -1
  96. package/dist/util/logger.js +30 -33
  97. package/dist/util/processManager.d.ts +0 -1
  98. package/dist/util/processManager.js +33 -36
  99. package/dist/util/resilientFetch.d.ts +6 -1
  100. package/dist/util/resilientFetch.js +134 -80
  101. package/dist/util/responseCache.d.ts +0 -1
  102. package/dist/util/responseCache.js +36 -45
  103. package/dist/util/rpc.d.ts +16 -0
  104. package/dist/util/rpc.js +69 -0
  105. package/dist/util/safeLog.d.ts +0 -1
  106. package/dist/util/safeLog.js +52 -53
  107. package/dist/util/scheduler.d.ts +0 -1
  108. package/dist/util/scheduler.js +53 -58
  109. package/dist/util/webhooks.d.ts +0 -1
  110. package/dist/util/webhooks.js +54 -58
  111. package/dist/wallet/ActionFeed.d.ts +0 -1
  112. package/dist/wallet/ActionFeed.js +189 -200
  113. package/dist/wallet/AgentWallet.d.ts +7 -8
  114. package/dist/wallet/AgentWallet.js +117 -144
  115. package/dist/wallet/ProfitTracker.d.ts +0 -1
  116. package/dist/wallet/ProfitTracker.js +71 -74
  117. package/package.json +11 -6
  118. package/scripts/build-esbuild.mjs +40 -0
  119. package/scripts/bundle-dts.mjs +58 -0
  120. package/scripts/minify.mjs +44 -0
  121. package/scripts/postinstall.js +27 -0
@@ -1,220 +1,238 @@
1
- /**
2
- * MarketSentiment — free market sentiment data tools.
3
- * Fear & Greed Index, Binance Funding Rates, BTC Mempool, DeFi TVL, Solana Stats.
4
- */
1
+
5
2
  import { Type } from "@sinclair/typebox";
6
3
  import { resilientFetch } from "../util/resilientFetch.js";
7
4
  import { logger } from "../util/logger.js";
8
- // ── Fear & Greed Index ──────────────────────────────────────────────────────
5
+
6
+ const ttlCache = new Map();
7
+ const TTL_MS = 30_000;
8
+ function getCached(key) {
9
+ const e = ttlCache.get(key);
10
+ if (!e)
11
+ return undefined;
12
+ if (Date.now() > e.expires) {
13
+ ttlCache.delete(key);
14
+ return undefined;
15
+ }
16
+ return e.data;
17
+ }
18
+ function setCached(key, data) {
19
+ ttlCache.set(key, { data, expires: Date.now() + TTL_MS });
20
+ }
21
+
9
22
  export const fearGreedParams = Type.Object({});
10
23
  export async function getFearGreedTool() {
11
- try {
12
- const response = await resilientFetch("https://api.alternative.me/fng/?limit=7", { timeout: 10_000, retries: 1 });
13
- if (!response.ok)
14
- return fallbackFearGreed();
15
- const data = await response.json();
16
- const items = data.data ?? [];
17
- const current = items[0];
18
- const lines = items.map((i, idx) => {
19
- const label = idx === 0 ? "Now" : i.timestamp ? new Date(parseInt(i.timestamp) * 1000).toLocaleDateString() : `${idx}d ago`;
20
- return ` ${i.value_classification} ${i.value}/100 ${label}`;
21
- });
22
- return {
23
- content: [{
24
- type: "text",
25
- text: [
26
- `Fear & Greed Index`,
27
- `Current: ${current?.value_classification ?? "N/A"} (${current?.value ?? "?"}/100)`,
28
- ...lines,
29
- ].join("\n"),
30
- }],
31
- };
32
- }
33
- catch (error) {
34
- logger.warn('MarketSentiment', 'Fear & Greed fetch failed', { error: error.message });
35
- return fallbackFearGreed();
36
- }
24
+
25
+ const cached = getCached("fear_greed");
26
+ if (cached)
27
+ return cached;
28
+ try {
29
+ const response = await resilientFetch("https://api.alternative.me/fng/?limit=7", { timeout: 10_000, retries: 1 });
30
+ if (!response.ok)
31
+ return fallbackFearGreed();
32
+ const data = await response.json();
33
+ const items = data.data ?? [];
34
+ const current = items[0];
35
+ const lines = items.map((i, idx) => {
36
+ const label = idx === 0 ? "Now" : i.timestamp ? new Date(parseInt(i.timestamp) * 1000).toLocaleDateString() : `${idx}d ago`;
37
+ return ` ${i.value_classification} ${i.value}/100 — ${label}`;
38
+ });
39
+ const result = {
40
+ content: [{
41
+ type: "text",
42
+ text: [
43
+ `Fear & Greed Index`,
44
+ `Current: ${current?.value_classification ?? "N/A"} (${current?.value ?? "?"}/100)`,
45
+ ...lines,
46
+ ].join("\n"),
47
+ }],
48
+ };
49
+ setCached("fear_greed", result);
50
+ return result;
51
+ }
52
+ catch (error) {
53
+ logger.warn('MarketSentiment', 'Fear & Greed fetch failed', { error: error.message });
54
+ return fallbackFearGreed();
55
+ }
37
56
  }
38
57
  async function fallbackFearGreed() {
39
- return {
40
- content: [{
41
- type: "text",
42
- text: "Fear & Greed Index: Neutral (50/100) — data unavailable",
43
- }],
44
- };
45
- }
46
- // ── Funding Rates ────────────────────────────────────────────────────────────
58
+ return {
59
+ content: [{
60
+ type: "text",
61
+ text: "Fear & Greed Index: Neutral (50/100) — data unavailable",
62
+ }],
63
+ };
64
+ }
65
+
47
66
  export const fundingRatesParams = Type.Object({
48
- limit: Type.Optional(Type.Number({ description: "Number of top pairs", default: 10 })),
67
+ limit: Type.Optional(Type.Number({ description: "Number of top pairs", default: 10 })),
49
68
  });
50
69
  export async function getFundingRatesTool(_id, params) {
51
- const limit = params.limit || 10;
52
- try {
53
- const response = await resilientFetch("https://fapi.binance.com/fapi/v1/premiumIndex", { timeout: 10_000, retries: 1 });
54
- if (!response.ok)
55
- return fallbackFundingRates();
56
- const data = await response.json();
57
- const sorted = (data ?? [])
58
- .filter(d => parseFloat(d.lastFundingRate) !== 0)
59
- .sort((a, b) => Math.abs(parseFloat(b.lastFundingRate)) - Math.abs(parseFloat(a.lastFundingRate)))
60
- .slice(0, limit);
61
- const lines = sorted.map(d => {
62
- const rate = parseFloat(d.lastFundingRate) * 100;
63
- const sign = rate > 0 ? "+" : "";
64
- return ` ${d.symbol.padEnd(12)} ${sign}${rate.toFixed(4)}%`;
65
- });
66
- return {
67
- content: [{
68
- type: "text",
69
- text: [`Funding Rates (top ${limit} by absolute value):`, ...lines].join("\n"),
70
- }],
71
- };
72
- }
73
- catch (error) {
74
- logger.warn('MarketSentiment', 'Funding rates fetch failed', { error: error.message });
75
- return fallbackFundingRates();
76
- }
70
+ const limit = params.limit || 10;
71
+ try {
72
+ const response = await resilientFetch("https://fapi.binance.com/fapi/v1/premiumIndex", { timeout: 10_000, retries: 1 });
73
+ if (!response.ok)
74
+ return fallbackFundingRates();
75
+ const data = await response.json();
76
+ const sorted = (data ?? [])
77
+ .filter(d => parseFloat(d.lastFundingRate) !== 0)
78
+ .sort((a, b) => Math.abs(parseFloat(b.lastFundingRate)) - Math.abs(parseFloat(a.lastFundingRate)))
79
+ .slice(0, limit);
80
+ const lines = sorted.map(d => {
81
+ const rate = parseFloat(d.lastFundingRate) * 100;
82
+ const sign = rate > 0 ? "+" : "";
83
+ return ` ${d.symbol.padEnd(12)} ${sign}${rate.toFixed(4)}%`;
84
+ });
85
+ return {
86
+ content: [{
87
+ type: "text",
88
+ text: [`Funding Rates (top ${limit} by absolute value):`, ...lines].join("\n"),
89
+ }],
90
+ };
91
+ }
92
+ catch (error) {
93
+ logger.warn('MarketSentiment', 'Funding rates fetch failed', { error: error.message });
94
+ return fallbackFundingRates();
95
+ }
77
96
  }
78
97
  async function fallbackFundingRates() {
79
- return {
80
- content: [{
81
- type: "text",
82
- text: "Funding Rates: Data temporarily unavailable.",
83
- }],
84
- };
85
- }
86
- // ── BTC Mempool ──────────────────────────────────────────────────────────────
98
+ return {
99
+ content: [{
100
+ type: "text",
101
+ text: "Funding Rates: Data temporarily unavailable.",
102
+ }],
103
+ };
104
+ }
105
+
87
106
  export const btcMempoolParams = Type.Object({});
88
107
  export async function getBtcMempoolTool() {
89
- try {
90
- const [feeResp, mempoolResp] = await Promise.all([
91
- resilientFetch("https://mempool.space/api/v1/fees/recommended", { timeout: 10_000 }),
92
- resilientFetch("https://mempool.space/api/mempool", { timeout: 10_000 }),
93
- ]);
94
- const fees = await feeResp.json();
95
- const mempool = await mempoolResp.json();
96
- return {
97
- content: [{
98
- type: "text",
99
- text: [
100
- `BTC Mempool`,
101
- `Count: ${(mempool.count ?? 0).toLocaleString()} transactions`,
102
- `Mempool size: ${((mempool.vsize ?? 0) / 1_000_000).toFixed(2)} MB`,
103
- ``,
104
- `Fees (sat/vB):`,
105
- ` Fastest: ${fees.fastestFee}`,
106
- ` Half hour: ${fees.halfHourFee}`,
107
- ` Hour: ${fees.hourFee}`,
108
- ` Economy: ${fees.economyFee}`,
109
- ` Minimum: ${fees.minimumFee}`,
110
- ].join("\n"),
111
- }],
112
- };
113
- }
114
- catch (error) {
115
- logger.warn('MarketSentiment', 'BTC mempool fetch failed', { error: error.message });
116
- return {
117
- content: [{ type: "text", text: "BTC Mempool: Data temporarily unavailable." }],
118
- };
119
- }
120
- }
121
- // ── DeFi TVL ─────────────────────────────────────────────────────────────────
108
+ try {
109
+ const [feeResp, mempoolResp] = await Promise.all([
110
+ resilientFetch("https://mempool.space/api/v1/fees/recommended", { timeout: 10_000 }),
111
+ resilientFetch("https://mempool.space/api/mempool", { timeout: 10_000 }),
112
+ ]);
113
+ const fees = await feeResp.json();
114
+ const mempool = await mempoolResp.json();
115
+ return {
116
+ content: [{
117
+ type: "text",
118
+ text: [
119
+ `BTC Mempool`,
120
+ `Count: ${(mempool.count ?? 0).toLocaleString()} transactions`,
121
+ `Mempool size: ${((mempool.vsize ?? 0) / 1_000_000).toFixed(2)} MB`,
122
+ ``,
123
+ `Fees (sat/vB):`,
124
+ ` Fastest: ${fees.fastestFee}`,
125
+ ` Half hour: ${fees.halfHourFee}`,
126
+ ` Hour: ${fees.hourFee}`,
127
+ ` Economy: ${fees.economyFee}`,
128
+ ` Minimum: ${fees.minimumFee}`,
129
+ ].join("\n"),
130
+ }],
131
+ };
132
+ }
133
+ catch (error) {
134
+ logger.warn('MarketSentiment', 'BTC mempool fetch failed', { error: error.message });
135
+ return {
136
+ content: [{ type: "text", text: "BTC Mempool: Data temporarily unavailable." }],
137
+ };
138
+ }
139
+ }
140
+
122
141
  export const defiTvlParams = Type.Object({
123
- chain: Type.Optional(Type.String({ description: "Chain name (e.g., solana, ethereum) or omit for all" })),
142
+ chain: Type.Optional(Type.String({ description: "Chain name (e.g., solana, ethereum) or omit for all" })),
124
143
  });
125
144
  export async function getDefiTvlTool(_id, params) {
126
- const chain = params.chain?.toLowerCase();
127
- try {
128
- if (chain) {
129
- const response = await resilientFetch(`https://api.llama.fi/v2/historicalChainTvl/${chain}`, { timeout: 10_000 });
130
- if (!response.ok)
131
- return fallbackTvl(chain);
132
- const data = await response.json();
133
- const latest = data[data.length - 1];
134
- return {
135
- content: [{
136
- type: "text",
137
- text: `DeFi TVL — ${chain.toUpperCase()}\nTVL: $${(latest?.tvl ?? 0).toLocaleString(undefined, { maximumFractionDigits: 0 })}`,
138
- }],
139
- };
140
- }
141
- else {
142
- const response = await resilientFetch("https://api.llama.fi/v2/chains", { timeout: 10_000 });
143
- if (!response.ok)
144
- return fallbackTvl("all");
145
- const data = await response.json();
146
- const sorted = (data ?? []).sort((a, b) => b.tvl - a.tvl).slice(0, 15);
147
- const lines = sorted.map(d => ` ${d.name.padEnd(16)} $${(d.tvl / 1e9).toFixed(2)}B`);
148
- return {
149
- content: [{
150
- type: "text",
151
- text: [`DeFi TVL by Chain (top 15):`, ...lines].join("\n"),
152
- }],
153
- };
154
- }
155
- }
156
- catch (error) {
157
- logger.warn('MarketSentiment', 'DeFi TVL fetch failed', { chain, error: error.message });
158
- return fallbackTvl(chain ?? "all");
159
- }
145
+ const chain = params.chain?.toLowerCase();
146
+ try {
147
+ if (chain) {
148
+ const response = await resilientFetch(`https://api.llama.fi/v2/historicalChainTvl/${chain}`, { timeout: 10_000 });
149
+ if (!response.ok)
150
+ return fallbackTvl(chain);
151
+ const data = await response.json();
152
+ const latest = data[data.length - 1];
153
+ return {
154
+ content: [{
155
+ type: "text",
156
+ text: `DeFi TVL — ${chain.toUpperCase()}\nTVL: $${(latest?.tvl ?? 0).toLocaleString(undefined, { maximumFractionDigits: 0 })}`,
157
+ }],
158
+ };
159
+ }
160
+ else {
161
+ const response = await resilientFetch("https://api.llama.fi/v2/chains", { timeout: 10_000 });
162
+ if (!response.ok)
163
+ return fallbackTvl("all");
164
+ const data = await response.json();
165
+ const sorted = (data ?? []).sort((a, b) => b.tvl - a.tvl).slice(0, 15);
166
+ const lines = sorted.map(d => ` ${d.name.padEnd(16)} $${(d.tvl / 1e9).toFixed(2)}B`);
167
+ return {
168
+ content: [{
169
+ type: "text",
170
+ text: [`DeFi TVL by Chain (top 15):`, ...lines].join("\n"),
171
+ }],
172
+ };
173
+ }
174
+ }
175
+ catch (error) {
176
+ logger.warn('MarketSentiment', 'DeFi TVL fetch failed', { chain, error: error.message });
177
+ return fallbackTvl(chain ?? "all");
178
+ }
160
179
  }
161
180
  async function fallbackTvl(chain) {
162
- return {
163
- content: [{ type: "text", text: `DeFi TVL for "${chain}": Data temporarily unavailable.` }],
164
- };
181
+ return {
182
+ content: [{ type: "text", text: `DeFi TVL for "${chain}": Data temporarily unavailable.` }],
183
+ };
165
184
  }
166
- // ── Solana Stats ─────────────────────────────────────────────────────────────
185
+
167
186
  export const solanaStatsParams = Type.Object({});
168
187
  export async function getSolanaStatsTool() {
169
- try {
170
- // Use public Solana RPC for basic stats
171
- const rpcUrl = process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
172
- const body = JSON.stringify({
173
- jsonrpc: "2.0", id: 1,
174
- method: "getEpochInfo",
175
- params: [],
176
- });
177
- const response = await resilientFetch(rpcUrl, {
178
- timeout: 10_000,
179
- retries: 1,
180
- method: "POST",
181
- headers: { "Content-Type": "application/json" },
182
- body,
183
- });
184
- if (!response.ok)
185
- return fallbackSolanaStats();
186
- const data = await response.json();
187
- const epoch = data.result;
188
- const epochProgress = ((epoch.slotIndex / epoch.slotsInEpoch) * 100).toFixed(1);
189
- // Also get SOL price
190
- const priceResp = await resilientFetch("https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd&include_24hr_change=true", { timeout: 8_000 });
191
- let solPrice = "";
192
- if (priceResp.ok) {
193
- const priceData = await priceResp.json();
194
- solPrice = `$${priceData.solana.usd.toFixed(2)}`;
195
- }
196
- return {
197
- content: [{
198
- type: "text",
199
- text: [
200
- `Solana Network`,
201
- `Epoch: ${epoch.epoch}`,
202
- `Slot: ${epoch.absoluteSlot.toLocaleString()}`,
203
- `Block: ${epoch.blockHeight.toLocaleString()}`,
204
- `Progress: ${epochProgress}% (${epoch.slotIndex.toLocaleString()}/${epoch.slotsInEpoch.toLocaleString()})`,
205
- solPrice ? `SOL Price: ${solPrice}` : "",
206
- ].filter(Boolean).join("\n"),
207
- }],
208
- };
209
- }
210
- catch (error) {
211
- logger.warn('MarketSentiment', 'Solana stats fetch failed', { error: error.message });
212
- return fallbackSolanaStats();
213
- }
188
+ try {
189
+
190
+ const rpcUrl = process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
191
+ const body = JSON.stringify({
192
+ jsonrpc: "2.0", id: 1,
193
+ method: "getEpochInfo",
194
+ params: [],
195
+ });
196
+ const response = await resilientFetch(rpcUrl, {
197
+ timeout: 10_000,
198
+ retries: 1,
199
+ method: "POST",
200
+ headers: { "Content-Type": "application/json" },
201
+ body,
202
+ });
203
+ if (!response.ok)
204
+ return fallbackSolanaStats();
205
+ const data = await response.json();
206
+ const epoch = data.result;
207
+ const epochProgress = ((epoch.slotIndex / epoch.slotsInEpoch) * 100).toFixed(1);
208
+
209
+ const priceResp = await resilientFetch("https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd&include_24hr_change=true", { timeout: 8_000 });
210
+ let solPrice = "";
211
+ if (priceResp.ok) {
212
+ const priceData = await priceResp.json();
213
+ solPrice = `$${priceData.solana.usd.toFixed(2)}`;
214
+ }
215
+ return {
216
+ content: [{
217
+ type: "text",
218
+ text: [
219
+ `Solana Network`,
220
+ `Epoch: ${epoch.epoch}`,
221
+ `Slot: ${epoch.absoluteSlot.toLocaleString()}`,
222
+ `Block: ${epoch.blockHeight.toLocaleString()}`,
223
+ `Progress: ${epochProgress}% (${epoch.slotIndex.toLocaleString()}/${epoch.slotsInEpoch.toLocaleString()})`,
224
+ solPrice ? `SOL Price: ${solPrice}` : "",
225
+ ].filter(Boolean).join("\n"),
226
+ }],
227
+ };
228
+ }
229
+ catch (error) {
230
+ logger.warn('MarketSentiment', 'Solana stats fetch failed', { error: error.message });
231
+ return fallbackSolanaStats();
232
+ }
214
233
  }
215
234
  async function fallbackSolanaStats() {
216
- return {
217
- content: [{ type: "text", text: "Solana Stats: Data temporarily unavailable. Check your RPC endpoint." }],
218
- };
235
+ return {
236
+ content: [{ type: "text", text: "Solana Stats: Data temporarily unavailable. Check your RPC endpoint." }],
237
+ };
219
238
  }
220
- //# sourceMappingURL=MarketSentiment.js.map
@@ -33,4 +33,3 @@ export declare const getNewsParams: import("@sinclair/typebox").TObject<{
33
33
  }>;
34
34
  export declare function getNewsTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
35
35
  export { scoreSentiment };
36
- //# sourceMappingURL=NewsSentiment.d.ts.map