nyxora 1.6.2 → 1.6.3
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/README.md +22 -12
- package/SECURITY.md +25 -21
- package/assets/raw-diagram.png +0 -0
- package/assets/security-flow.png +0 -0
- package/bin/nyxora.mjs +236 -0
- package/launcher.js +8 -3
- package/launcher.ts +28 -1
- package/package.json +11 -7
- package/packages/core/package.json +4 -3
- package/packages/core/src/agent/reasoning.ts +10 -8
- package/packages/core/src/config/parser.ts +2 -1
- package/packages/core/src/gateway/cli.ts +2 -64
- package/packages/core/src/gateway/server.ts +89 -8
- package/packages/core/src/gateway/setup-cli.ts +7 -0
- package/packages/core/src/gateway/setup.ts +51 -28
- package/packages/core/src/gateway/telegram.ts +147 -89
- package/packages/core/src/memory/logger.ts +63 -7
- package/packages/core/src/system/pluginManager.ts +48 -34
- package/packages/core/src/utils/state.ts +15 -2
- package/packages/core/src/web3/config.ts +18 -3
- package/packages/core/src/web3/skills/marketAnalysis.ts +43 -17
- package/packages/core/src/web3/skills/swapToken.ts +9 -1
- package/packages/dashboard/dist/assets/index-BTP1WrFj.js +194 -0
- package/packages/dashboard/dist/assets/index-POJM-7Fd.css +1 -0
- package/packages/dashboard/dist/favicon.svg +1 -1
- package/packages/dashboard/dist/index.html +2 -2
- package/packages/dashboard/package-lock.json +2 -2
- package/packages/dashboard/package.json +1 -1
- package/packages/dashboard/public/favicon.svg +1 -1
- package/packages/dashboard/src/App.tsx +224 -167
- package/packages/dashboard/src/Settings.tsx +55 -0
- package/packages/dashboard/src/Skills.tsx +8 -1
- package/packages/dashboard/src/index.css +146 -35
- package/packages/policy/package.json +1 -1
- package/packages/policy/src/server.ts +21 -28
- package/packages/signer/package.json +1 -1
- package/packages/signer/src/server.ts +39 -13
- package/bin/nyxora.js +0 -13
- package/packages/dashboard/dist/assets/index-BK4qmIy6.js +0 -200
- package/packages/dashboard/dist/assets/index-C1m4ohce.css +0 -1
- package/packages/dashboard/src/Memory.tsx +0 -110
|
@@ -3,44 +3,70 @@ import { resolveToken } from '../utils/tokens';
|
|
|
3
3
|
|
|
4
4
|
export async function analyzeMarket(chainName: ChainName, tokenAddressOrSymbol: string): Promise<string> {
|
|
5
5
|
try {
|
|
6
|
-
|
|
6
|
+
const cleanSymbol = tokenAddressOrSymbol.replace('$', '').toLowerCase();
|
|
7
|
+
|
|
8
|
+
// 1. Primary Engine: CoinGecko Global
|
|
7
9
|
try {
|
|
8
|
-
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const cgSearchRes = await fetch(`https://api.coingecko.com/api/v3/search?query=${cleanSymbol}`);
|
|
11
|
+
if (cgSearchRes.ok) {
|
|
12
|
+
const searchData = await cgSearchRes.json();
|
|
13
|
+
const foundCoin = searchData.coins?.find((c: any) => c.symbol.toLowerCase() === cleanSymbol || c.id === cleanSymbol);
|
|
14
|
+
|
|
15
|
+
if (foundCoin) {
|
|
16
|
+
const cgCoinRes = await fetch(`https://api.coingecko.com/api/v3/coins/${foundCoin.id}`);
|
|
17
|
+
if (cgCoinRes.ok) {
|
|
18
|
+
const coinData = await cgCoinRes.json();
|
|
19
|
+
let report = `📈 **Market Analysis for ${coinData.name} (${coinData.symbol.toUpperCase()})** [Global via CoinGecko]\n\n`;
|
|
20
|
+
report += `**Price:** $${coinData.market_data?.current_price?.usd || 0}\n`;
|
|
21
|
+
report += `**Market Cap:** $${Number(coinData.market_data?.market_cap?.usd || 0).toLocaleString()}\n`;
|
|
22
|
+
report += `**24h Volume:** $${Number(coinData.market_data?.total_volume?.usd || 0).toLocaleString()}\n\n`;
|
|
23
|
+
report += `**Price Change:**\n`;
|
|
24
|
+
report += `- 1h: ${coinData.market_data?.price_change_percentage_1h_in_currency?.usd?.toFixed(2) || 0}% \n`;
|
|
25
|
+
report += `- 24h: ${coinData.market_data?.price_change_percentage_24h?.toFixed(2) || 0}% \n`;
|
|
26
|
+
report += `- 7d: ${coinData.market_data?.price_change_percentage_7d?.toFixed(2) || 0}% \n\n`;
|
|
27
|
+
report += `**Rank:** #${coinData.market_cap_rank || 'N/A'}\n`;
|
|
28
|
+
return report;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
13
31
|
}
|
|
14
32
|
} catch (e) {
|
|
15
|
-
|
|
33
|
+
console.warn("CoinGecko analysis failed, falling back to DexScreener...", e);
|
|
16
34
|
}
|
|
17
35
|
|
|
18
|
-
|
|
19
|
-
|
|
36
|
+
// 2. Fallback Engine: DexScreener Cross-Chain Search
|
|
37
|
+
let query = tokenAddressOrSymbol;
|
|
38
|
+
try {
|
|
39
|
+
const resolved = resolveToken(tokenAddressOrSymbol, chainName);
|
|
40
|
+
if (resolved !== "0x0000000000000000000000000000000000000000") {
|
|
41
|
+
query = resolved; // Use exact address if resolved locally
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {}
|
|
44
|
+
|
|
45
|
+
const dexSearchUrl = `https://api.dexscreener.com/latest/dex/search?q=${query}`;
|
|
46
|
+
const res = await fetch(dexSearchUrl);
|
|
20
47
|
if (!res.ok) {
|
|
21
48
|
throw new Error(`DexScreener API Error: ${res.statusText}`);
|
|
22
49
|
}
|
|
23
50
|
|
|
24
51
|
const data = await res.json();
|
|
25
52
|
if (!data.pairs || data.pairs.length === 0) {
|
|
26
|
-
return `No market data found for
|
|
53
|
+
return `No market data found for '${tokenAddressOrSymbol}' on CoinGecko or DexScreener across any chain.`;
|
|
27
54
|
}
|
|
28
55
|
|
|
29
|
-
// Filter pairs by chain if possible, Dexscreener chain IDs are strings like 'ethereum', 'bsc', 'base', 'arbitrum', 'optimism'
|
|
30
56
|
let pair = data.pairs.find((p: any) => p.chainId === chainName);
|
|
31
57
|
if (!pair) {
|
|
32
|
-
pair = data.pairs[0];
|
|
58
|
+
pair = data.pairs[0];
|
|
33
59
|
}
|
|
34
60
|
|
|
35
|
-
let report = `📈 **Market Analysis for ${pair.baseToken.name} (${pair.baseToken.symbol})** on ${pair.chainId.toUpperCase()}\n\n`;
|
|
61
|
+
let report = `📈 **Market Analysis for ${pair.baseToken.name} (${pair.baseToken.symbol})** on ${pair.chainId.toUpperCase()} [Cross-Chain Fallback: DexScreener]\n\n`;
|
|
36
62
|
report += `**Price:** $${pair.priceUsd}\n`;
|
|
37
63
|
report += `**Liquidity (USD):** $${Number(pair.liquidity?.usd || 0).toLocaleString()}\n`;
|
|
38
64
|
report += `**FDV:** $${Number(pair.fdv || 0).toLocaleString()}\n`;
|
|
39
65
|
report += `**24h Volume:** $${Number(pair.volume?.h24 || 0).toLocaleString()}\n\n`;
|
|
40
66
|
report += `**Price Change:**\n`;
|
|
41
|
-
report += `- 5m: ${pair.priceChange?.m5}% \n`;
|
|
42
|
-
report += `- 1h: ${pair.priceChange?.h1}% \n`;
|
|
43
|
-
report += `- 24h: ${pair.priceChange?.h24}% \n\n`;
|
|
67
|
+
report += `- 5m: ${pair.priceChange?.m5 || 0}% \n`;
|
|
68
|
+
report += `- 1h: ${pair.priceChange?.h1 || 0}% \n`;
|
|
69
|
+
report += `- 24h: ${pair.priceChange?.h24 || 0}% \n\n`;
|
|
44
70
|
report += `**DEX:** ${pair.dexId} (${pair.url})\n`;
|
|
45
71
|
|
|
46
72
|
return report;
|
|
@@ -53,7 +79,7 @@ export const marketAnalysisToolDefinition = {
|
|
|
53
79
|
type: "function",
|
|
54
80
|
function: {
|
|
55
81
|
name: "analyze_market",
|
|
56
|
-
description: "Fetches live market data (Price, Liquidity, Volume, FDV, Price Change)
|
|
82
|
+
description: "Fetches live market data (Price, Liquidity, Volume, FDV, Price Change) globally across all chains using CoinGecko and DexScreener.",
|
|
57
83
|
parameters: {
|
|
58
84
|
type: "object",
|
|
59
85
|
properties: {
|
|
@@ -2,6 +2,7 @@ import { parseUnits, formatUnits } from 'viem';
|
|
|
2
2
|
import { getPublicClient, getAddress, ChainName } from '../config';
|
|
3
3
|
import { txManager } from '../../agent/transactionManager';
|
|
4
4
|
import { resolveToken, ERC20_ABI } from '../utils/tokens';
|
|
5
|
+
import crypto from 'crypto';
|
|
5
6
|
|
|
6
7
|
const CHAIN_IDS: Record<ChainName, number> = {
|
|
7
8
|
ethereum: 1,
|
|
@@ -169,7 +170,7 @@ export async function executeSwap(chainName: ChainName, params: any, autoApprove
|
|
|
169
170
|
const { txRequest, needsApprove, fromTokenAddress, approvalAddress, amountWei } = params;
|
|
170
171
|
const token = process.env.INTERNAL_AUTH_TOKEN;
|
|
171
172
|
|
|
172
|
-
const payload = {
|
|
173
|
+
const payload: any = {
|
|
173
174
|
type: 'swap',
|
|
174
175
|
chainName,
|
|
175
176
|
autoApprove,
|
|
@@ -182,6 +183,13 @@ export async function executeSwap(chainName: ChainName, params: any, autoApprove
|
|
|
182
183
|
}
|
|
183
184
|
};
|
|
184
185
|
|
|
186
|
+
if (autoApprove && token) {
|
|
187
|
+
// Generate internal HMAC signature for autoApprove bypass
|
|
188
|
+
// using the transaction chainName as a quick deterministic unique string
|
|
189
|
+
// In a real scenario, use a specific txId or nonce.
|
|
190
|
+
payload.internalSignature = crypto.createHmac('sha256', token).update(chainName + amountWei).digest('hex');
|
|
191
|
+
}
|
|
192
|
+
|
|
185
193
|
const res = await fetch('http://127.0.0.1:3001/request-tx', {
|
|
186
194
|
method: 'POST',
|
|
187
195
|
headers: {
|