nyxora 1.5.8 → 1.6.0
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 +4 -4
- package/package.json +14 -2
- package/packages/core/package.json +1 -1
- package/packages/core/src/agent/limitOrderManager.ts +193 -0
- package/packages/core/src/agent/reasoning.d.ts.map +1 -0
- package/packages/core/src/agent/reasoning.ts +466 -0
- package/packages/core/src/agent/transactionManager.ts +49 -0
- package/packages/core/src/agent/updateProfile.ts +47 -0
- package/packages/core/src/config/parser.d.ts.map +1 -0
- package/packages/core/src/config/parser.ts +106 -0
- package/packages/core/src/config/paths.ts +33 -0
- package/packages/core/src/gateway/cli.d.ts.map +1 -0
- package/packages/core/src/gateway/cli.ts +130 -0
- package/packages/core/src/gateway/server.ts +234 -0
- package/packages/core/src/gateway/setup.ts +276 -0
- package/packages/core/src/gateway/telegram.ts +157 -0
- package/packages/core/src/gateway/test.ts +16 -0
- package/packages/core/src/gateway/tracker.ts +70 -0
- package/packages/core/src/memory/logger.d.ts.map +1 -0
- package/packages/core/src/memory/logger.ts +121 -0
- package/packages/core/src/system/pluginManager.ts +91 -0
- package/packages/core/src/system/skills/browseWeb.ts +50 -0
- package/packages/core/src/system/skills/executeShell.ts +33 -0
- package/packages/core/src/system/skills/installSkill.ts +51 -0
- package/packages/core/src/system/skills/readFile.ts +33 -0
- package/packages/core/src/system/skills/updateSecurityPolicy.ts +55 -0
- package/packages/core/src/system/skills/writeFile.ts +40 -0
- package/packages/core/src/utils/formatter.ts +30 -0
- package/packages/core/src/utils/state.ts +10 -0
- package/packages/core/src/web3/config.d.ts.map +1 -0
- package/packages/core/src/web3/config.ts +43 -0
- package/packages/core/src/web3/skills/bridgeToken.ts +247 -0
- package/packages/core/src/web3/skills/checkAddress.ts +54 -0
- package/packages/core/src/web3/skills/checkPortfolio.ts +130 -0
- package/packages/core/src/web3/skills/checkSecurity.ts +71 -0
- package/packages/core/src/web3/skills/createWallet.ts +32 -0
- package/packages/core/src/web3/skills/customTx.ts +117 -0
- package/packages/core/src/web3/skills/getBalance.d.ts.map +1 -0
- package/packages/core/src/web3/skills/getBalance.ts +86 -0
- package/packages/core/src/web3/skills/getMyAddress.ts +26 -0
- package/packages/core/src/web3/skills/getPrice.ts +43 -0
- package/packages/core/src/web3/skills/marketAnalysis.ts +73 -0
- package/packages/core/src/web3/skills/mintNft.ts +146 -0
- package/packages/core/src/web3/skills/swapToken.ts +246 -0
- package/packages/core/src/web3/skills/transfer.ts +142 -0
- package/packages/core/src/web3/utils/tokens.ts +114 -0
- package/packages/dashboard/package.json +1 -1
- package/packages/dashboard/src/App.css +184 -0
- package/packages/dashboard/src/App.tsx +527 -0
- package/packages/dashboard/src/BalanceWidget.tsx +65 -0
- package/packages/dashboard/src/MarketWidget.tsx +73 -0
- package/packages/dashboard/src/Memory.tsx +110 -0
- package/packages/dashboard/src/Overview.tsx +157 -0
- package/packages/dashboard/src/PendingTransactions.tsx +75 -0
- package/packages/dashboard/src/Settings.tsx +230 -0
- package/packages/dashboard/src/Skills.tsx +78 -0
- package/packages/dashboard/src/SwapWidget.tsx +141 -0
- package/packages/dashboard/src/TransactionWidget.tsx +95 -0
- package/packages/dashboard/src/assets/hero.png +0 -0
- package/packages/dashboard/src/assets/react.svg +1 -0
- package/packages/dashboard/src/assets/vite.svg +1 -0
- package/packages/dashboard/src/index.css +509 -0
- package/packages/dashboard/src/main.tsx +10 -0
- package/packages/dashboard/src/overview.css +304 -0
- package/packages/dashboard/src/utils/api.ts +24 -0
- package/packages/policy/package.json +1 -1
- package/packages/policy/src/server.ts +195 -0
- package/packages/signer/package.json +1 -1
- package/packages/signer/src/crypto.ts +44 -0
- package/packages/signer/src/server.ts +126 -0
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Nyxora Agent 🤖
|
|
2
2
|
**Production-Grade Secure AI Execution Framework for Web3 Agents.**
|
|
3
3
|
|
|
4
|
-
[](https://github.com/perasyudha/Nyxora)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](#️-advanced-security-threat-model)
|
|
7
7
|
[](#️-advanced-security-threat-model)
|
|
8
8
|
[](#️-advanced-security-threat-model)
|
|
9
9
|
|
|
10
|
-
Nyxora (v1.
|
|
10
|
+
Nyxora (v1.6.0) is a **secure, non-custodial runtime infrastructure for autonomous onchain agents** built with a robust Monorepo architecture (Node.js & React). Designed for autonomous workflows with a premium Glassmorphism UI dashboard and strict client-side key isolation.
|
|
11
11
|
|
|
12
12
|
It operates under an institutional-grade **Cryptographically Bound Human-in-the-Loop** execution model, ensuring that Remote AIs (LLMs) never have unilateral access to your funds.
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ It operates under an institutional-grade **Cryptographically Bound Human-in-the-
|
|
|
15
15
|
|
|
16
16
|
## 🔥 Key Features
|
|
17
17
|
|
|
18
|
-
### Advanced Security Architecture (v1.
|
|
18
|
+
### Advanced Security Architecture (v1.6.0)
|
|
19
19
|
* **3-Tier IPC Architecture**: Nyxora is split into isolated processes: **Core** (LLM Runtime), **Policy Engine** (Guardrails on port 3001), and **Signer Vault** (Isolated Key Manager on Unix Sockets).
|
|
20
20
|
* **Cryptographically Bound Approval**: Policy changes and transactions requested by the AI are drafted as hashes (`sha256`). Approval via the UI requires a challenge nonce, preventing Man-in-the-Middle (MITM) attacks.
|
|
21
21
|
* **Immutable Policy Guardrails**: Transaction limits (e.g. `max_usd_per_tx`) are strictly enforced by the Policy Engine. The LLM has zero write-access to bypass these rules.
|
|
@@ -57,7 +57,7 @@ To dive deeper into the technical details of our Zero-Knowledge security archite
|
|
|
57
57
|
## 🚀 Quick Start & Installation
|
|
58
58
|
|
|
59
59
|
### Local Development & Execution
|
|
60
|
-
With the new v1.
|
|
60
|
+
With the new v1.6.0 Monorepo architecture, launching Nyxora is completely automated via the internal `launcher.ts` orchestrator.
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
git clone https://github.com/perasyudha/Nyxora.git
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nyxora",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"workspaces": [
|
|
5
5
|
"packages/*"
|
|
6
6
|
],
|
|
@@ -11,12 +11,24 @@
|
|
|
11
11
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"@clack/prompts": "^1.4.0",
|
|
15
|
+
"better-sqlite3": "^12.10.0",
|
|
14
16
|
"concurrently": "^9.2.1",
|
|
17
|
+
"cors": "^2.8.6",
|
|
15
18
|
"dotenv": "^17.4.2",
|
|
19
|
+
"express": "^5.2.1",
|
|
20
|
+
"express-rate-limit": "^7.5.0",
|
|
21
|
+
"helmet": "^8.0.0",
|
|
16
22
|
"jsonwebtoken": "^9.0.2",
|
|
23
|
+
"node-telegram-bot-api": "^0.67.0",
|
|
24
|
+
"open": "^11.0.0",
|
|
25
|
+
"openai": "^6.39.0",
|
|
17
26
|
"picocolors": "^1.1.1",
|
|
18
27
|
"ts-node": "^10.9.2",
|
|
19
|
-
"typescript": "^6.0.3"
|
|
28
|
+
"typescript": "^6.0.3",
|
|
29
|
+
"viem": "^2.51.0",
|
|
30
|
+
"yaml": "^2.9.0",
|
|
31
|
+
"zod": "^3.23.8"
|
|
20
32
|
},
|
|
21
33
|
"devDependencies": {
|
|
22
34
|
"@types/jsonwebtoken": "^9.0.5",
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { loadConfig } from '../config/parser';
|
|
4
|
+
import { getPath } from '../config/paths';
|
|
5
|
+
import { ChainName } from '../web3/config';
|
|
6
|
+
import { resolveToken } from '../web3/utils/tokens';
|
|
7
|
+
import { prepareSwapToken, executeSwap } from '../web3/skills/swapToken';
|
|
8
|
+
import { txManager } from './transactionManager';
|
|
9
|
+
import { processUserInput } from './reasoning';
|
|
10
|
+
|
|
11
|
+
export interface LimitOrder {
|
|
12
|
+
id: string;
|
|
13
|
+
chainName: ChainName;
|
|
14
|
+
fromToken: string;
|
|
15
|
+
toToken: string;
|
|
16
|
+
amountStr: string;
|
|
17
|
+
targetPriceUsd: number;
|
|
18
|
+
condition: 'above' | 'below';
|
|
19
|
+
status: 'pending' | 'executed' | 'cancelled' | 'failed';
|
|
20
|
+
createdAt: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class LimitOrderManager {
|
|
24
|
+
private filePath: string;
|
|
25
|
+
private orders: LimitOrder[] = [];
|
|
26
|
+
private monitorInterval: NodeJS.Timeout | null = null;
|
|
27
|
+
|
|
28
|
+
constructor() {
|
|
29
|
+
const config = loadConfig();
|
|
30
|
+
this.filePath = getPath(config.memory?.path ? config.memory.path.replace('memory.json', 'orders.json') : 'orders.json');
|
|
31
|
+
this.loadOrders();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private loadOrders() {
|
|
35
|
+
if (fs.existsSync(this.filePath)) {
|
|
36
|
+
try {
|
|
37
|
+
const data = fs.readFileSync(this.filePath, 'utf-8');
|
|
38
|
+
this.orders = JSON.parse(data);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
this.orders = [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private saveOrders() {
|
|
46
|
+
try {
|
|
47
|
+
fs.writeFileSync(this.filePath, JSON.stringify(this.orders, null, 2));
|
|
48
|
+
} catch (error) {}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public createOrder(chainName: ChainName, fromToken: string, toToken: string, amountStr: string, targetPriceUsd: number, condition: 'above' | 'below'): string {
|
|
52
|
+
const id = `order_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
|
|
53
|
+
const order: LimitOrder = {
|
|
54
|
+
id, chainName, fromToken, toToken, amountStr, targetPriceUsd, condition, status: 'pending', createdAt: Date.now()
|
|
55
|
+
};
|
|
56
|
+
this.orders.push(order);
|
|
57
|
+
this.saveOrders();
|
|
58
|
+
return `Limit order created successfully. ID: ${id}. The system will monitor ${fromToken} price on ${chainName} and execute the swap to ${toToken} when price is ${condition} $${targetPriceUsd}.`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public listOrders(): string {
|
|
62
|
+
const pending = this.orders.filter(o => o.status === 'pending');
|
|
63
|
+
if (pending.length === 0) return "No active limit orders.";
|
|
64
|
+
let report = "Active Limit Orders:\n";
|
|
65
|
+
pending.forEach(o => {
|
|
66
|
+
report += `- [${o.id}] Swap ${o.amountStr} ${o.fromToken} -> ${o.toToken} on ${o.chainName} when ${o.fromToken} is ${o.condition} $${o.targetPriceUsd}\n`;
|
|
67
|
+
});
|
|
68
|
+
return report;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public cancelOrder(id: string): string {
|
|
72
|
+
const order = this.orders.find(o => o.id === id);
|
|
73
|
+
if (!order) return `Order ${id} not found.`;
|
|
74
|
+
if (order.status !== 'pending') return `Order ${id} cannot be cancelled because it is ${order.status}.`;
|
|
75
|
+
order.status = 'cancelled';
|
|
76
|
+
this.saveOrders();
|
|
77
|
+
return `Order ${id} cancelled successfully.`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public startMonitor() {
|
|
81
|
+
if (this.monitorInterval) clearInterval(this.monitorInterval);
|
|
82
|
+
// Monitor every 60 seconds
|
|
83
|
+
this.monitorInterval = setInterval(() => this.checkOrders(), 60000);
|
|
84
|
+
console.log('[LimitOrderManager] Order monitoring started (interval: 60s)');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private async checkOrders() {
|
|
88
|
+
const pending = this.orders.filter(o => o.status === 'pending');
|
|
89
|
+
if (pending.length === 0) return;
|
|
90
|
+
|
|
91
|
+
for (const order of pending) {
|
|
92
|
+
try {
|
|
93
|
+
let tokenAddress = resolveToken(order.fromToken, order.chainName);
|
|
94
|
+
if (tokenAddress === "0x0000000000000000000000000000000000000000") {
|
|
95
|
+
tokenAddress = resolveToken("W" + order.fromToken, order.chainName);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const res = await fetch(`https://api.dexscreener.com/latest/dex/tokens/${tokenAddress}`);
|
|
99
|
+
if (!res.ok) continue;
|
|
100
|
+
const data = await res.json();
|
|
101
|
+
if (!data.pairs || data.pairs.length === 0) continue;
|
|
102
|
+
|
|
103
|
+
let pair = data.pairs.find((p: any) => p.chainId === order.chainName) || data.pairs[0];
|
|
104
|
+
const currentPrice = parseFloat(pair.priceUsd);
|
|
105
|
+
|
|
106
|
+
let shouldExecute = false;
|
|
107
|
+
if (order.condition === 'above' && currentPrice >= order.targetPriceUsd) shouldExecute = true;
|
|
108
|
+
if (order.condition === 'below' && currentPrice <= order.targetPriceUsd) shouldExecute = true;
|
|
109
|
+
|
|
110
|
+
if (shouldExecute) {
|
|
111
|
+
console.log(`[LimitOrderManager] Condition met for order ${order.id}. Current price $${currentPrice} is ${order.condition} $${order.targetPriceUsd}. Executing...`);
|
|
112
|
+
|
|
113
|
+
// 1. Prepare Swap
|
|
114
|
+
const prepareResult = await prepareSwapToken(order.chainName, order.fromToken, order.toToken, order.amountStr, 'auto');
|
|
115
|
+
|
|
116
|
+
// 2. Extract Tx ID
|
|
117
|
+
const txMatch = prepareResult.match(/Transaction ID: ([\w-]+)\./);
|
|
118
|
+
if (!txMatch) {
|
|
119
|
+
order.status = 'failed';
|
|
120
|
+
this.saveOrders();
|
|
121
|
+
processUserInput(`Limit order ${order.id} execution failed during preparation. Output: ${prepareResult}`, 'system').catch(() => {});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const txId = txMatch[1];
|
|
126
|
+
const tx = txManager.getTransaction(txId);
|
|
127
|
+
if (!tx) throw new Error("Transaction not found in manager");
|
|
128
|
+
|
|
129
|
+
// 3. Execute Swap automatically (bypass policy with autoApprove: true)
|
|
130
|
+
const executeResult = await executeSwap(order.chainName, tx.details, true);
|
|
131
|
+
|
|
132
|
+
if (executeResult.includes('executed') || executeResult.includes('successful')) {
|
|
133
|
+
txManager.updateStatus(txId, 'executed', executeResult);
|
|
134
|
+
order.status = 'executed';
|
|
135
|
+
this.saveOrders();
|
|
136
|
+
processUserInput(`Limit order ${order.id} just EXECUTED automatically! Price hit $${currentPrice}. Swap result: ${executeResult}. Please notify the user immediately!`, 'system').catch(() => {});
|
|
137
|
+
} else {
|
|
138
|
+
txManager.updateStatus(txId, 'failed', executeResult);
|
|
139
|
+
order.status = 'failed';
|
|
140
|
+
this.saveOrders();
|
|
141
|
+
processUserInput(`Limit order ${order.id} FAILED to execute. Price hit $${currentPrice} but execution failed: ${executeResult}. Please notify the user.`, 'system').catch(() => {});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch (error: any) {
|
|
145
|
+
console.error(`[LimitOrderManager] Error checking order ${order.id}:`, error.message);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export const limitOrderManager = new LimitOrderManager();
|
|
152
|
+
|
|
153
|
+
export const createLimitOrderToolDefinition = {
|
|
154
|
+
type: "function",
|
|
155
|
+
function: {
|
|
156
|
+
name: "create_limit_order",
|
|
157
|
+
description: "Creates an automatic cut-loss or take-profit limit order. The system will automatically execute the swap when the price condition is met.",
|
|
158
|
+
parameters: {
|
|
159
|
+
type: "object",
|
|
160
|
+
properties: {
|
|
161
|
+
chainName: { type: "string", enum: ["ethereum", "base", "bsc", "arbitrum", "optimism", "sepolia"] },
|
|
162
|
+
fromToken: { type: "string", description: "Token to sell" },
|
|
163
|
+
toToken: { type: "string", description: "Token to buy" },
|
|
164
|
+
amountStr: { type: "string", description: "Amount to sell" },
|
|
165
|
+
targetPriceUsd: { type: "number", description: "Target price in USD for the fromToken" },
|
|
166
|
+
condition: { type: "string", enum: ["above", "below"], description: "Trigger when price goes above (take-profit) or below (cut-loss) target" }
|
|
167
|
+
},
|
|
168
|
+
required: ["chainName", "fromToken", "toToken", "amountStr", "targetPriceUsd", "condition"],
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export const listLimitOrdersToolDefinition = {
|
|
174
|
+
type: "function",
|
|
175
|
+
function: {
|
|
176
|
+
name: "list_limit_orders",
|
|
177
|
+
description: "Lists all active automated limit orders.",
|
|
178
|
+
parameters: { type: "object", properties: {}, required: [] },
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const cancelLimitOrderToolDefinition = {
|
|
183
|
+
type: "function",
|
|
184
|
+
function: {
|
|
185
|
+
name: "cancel_limit_order",
|
|
186
|
+
description: "Cancels an active limit order by ID.",
|
|
187
|
+
parameters: {
|
|
188
|
+
type: "object",
|
|
189
|
+
properties: { id: { type: "string" } },
|
|
190
|
+
required: ["id"],
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning.d.ts","sourceRoot":"","sources":["reasoning.ts"],"names":[],"mappings":"AAkBA,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmFrE"}
|