nyxora 1.1.8 → 1.3.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 CHANGED
@@ -18,11 +18,15 @@ With a beautiful, real-time dashboard inspired by modern control centers, Nyxora
18
18
  * **Omnichannel Approvals**: Approve or reject pending transactions directly from the Web Dashboard's UI or via Telegram Inline Keyboard buttons on the go!
19
19
  * **Strict API Auth**: The local Express server is protected via ephemeral Session Tokens (`x-nyxora-token`) and Strict CORS, preventing unauthorized local API requests.
20
20
 
21
- ### ⛓️ Web3 DeFi Skills
21
+ ### ⛓️ Web3 DeFi Skills (Pro-Trader AI)
22
22
  * **Multi-Chain Support**: Operate across Ethereum, Base, BSC, Arbitrum, Optimism, and Sepolia Testnet.
23
+ * **Wallet Generation**: Instruct the AI to generate new EVM wallets on the fly securely (Keys are never saved).
23
24
  * **Native Wallet Operations**: Autonomously check balances and transfer native tokens using securely injected wallets.
24
- * **Market Intelligence**: Fetch live crypto prices and 24h market movements via CoinGecko integration.
25
- * **DeFi Token Swapping**: The agent can autonomously simulate liquidity routes and execute token swaps with gas fee estimations.
25
+ * **Advanced Market Intelligence**: Fetch live crypto prices, 24h market movements, FDV, and liquidity via CoinGecko and DexScreener integrations.
26
+ * **Anti-Rugpull & Security Scanner**: Nyxora can scan smart contracts via GoPlus Labs to detect Honeypots, Hidden Taxes, and malicious proxy upgrades before you buy.
27
+ * **PNL & Portfolio Tracking**: The AI scans your wallets and multiplies balances by live DEX prices to give you real-time Net Worth estimations.
28
+ * **DeFi Token Swapping & Bridging**: The agent can autonomously simulate liquidity routes and execute token swaps or cross-chain bridges with gas fee estimations.
29
+ * **Automated Limit Orders (Take-Profit/Cut-Loss)**: Set rules (e.g., "Sell my PEPE if price drops below $0.001"). Nyxora runs a background cron monitor and automatically executes the swap while you sleep without requiring manual approval!
26
30
 
27
31
  ### 💻 The Interface (Live Canvas)
28
32
  * **Premium Glassmorphism UI**: A gorgeous, resizable split-pane interface.
package/SECURITY.md CHANGED
@@ -14,7 +14,9 @@ Instead, please send an email to the repository owner or reach out privately. We
14
14
  When using Nyxora, you are configuring an autonomous agent that has direct access to your injected Web3 Wallet's private key.
15
15
 
16
16
  1. **Protect Your Keystore**: Your private key is encrypted and stored in `~/.nyxora/keystore.json`. While it is encrypted using `AES-256-GCM`, you must still treat it and your **Master Password** as highly sensitive. NEVER share your `keystore.json` or your Master Password with anyone.
17
- 2. **Human-in-the-Loop Verification**: The agent is restricted from making unilateral transactions. Always review the exact details of the transaction when prompted to "Approve" or "Reject" on the Web Dashboard or Telegram Inline Keyboard before confirming.
18
- 3. **Use Testnets**: While getting started or testing new skills, ALWAYS use a testnet (e.g., Sepolia) and a wallet containing only testnet funds.
19
- 4. **Do Not Share Your `memory.json`**: The agent's memory may contain sensitive conversational data or addresses you've interacted with. Be cautious before sharing the `memory.json` export.
20
- 5. **API Keys**: Treat your OpenAI, Gemini, and other LLM provider API keys as highly confidential. Rotate them immediately if you suspect a compromise.
17
+ 2. **Human-in-the-Loop Verification**: For standard actions, the agent is restricted from making unilateral transactions. Always review the exact details of the transaction when prompted to "Approve" or "Reject" on the Web Dashboard or Telegram Inline Keyboard before confirming.
18
+ 3. **Limit Order Automation Risk**: If you use the AI to create a **Limit Order** (Take-profit or Cut-loss), the system WILL execute the transaction automatically in the background when the price condition is met. This intentionally bypasses the Human-in-the-Loop verification for speed. Use this feature with caution.
19
+ 4. **Wallet Generation**: When you ask the AI to create a new wallet, it generates the Private Key and Seed Phrase locally and displays it once. It does NOT save it anywhere. You are responsible for immediately backing up this information.
20
+ 5. **Use Testnets**: While getting started or testing new skills, ALWAYS use a testnet (e.g., Sepolia) and a wallet containing only testnet funds.
21
+ 6. **Do Not Share Your `memory.json`**: The agent's memory may contain sensitive conversational data, generated seed phrases, or addresses you've interacted with. Be cautious before sharing the `memory.json` export.
22
+ 7. **API Keys**: Treat your OpenAI, Gemini, and other LLM provider API keys as highly confidential. Rotate them immediately if you suspect a compromise.
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cancelLimitOrderToolDefinition = exports.listLimitOrdersToolDefinition = exports.createLimitOrderToolDefinition = exports.limitOrderManager = exports.LimitOrderManager = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const parser_1 = require("../config/parser");
9
+ const paths_1 = require("../config/paths");
10
+ const tokens_1 = require("../web3/utils/tokens");
11
+ const swapToken_1 = require("../web3/skills/swapToken");
12
+ const transactionManager_1 = require("./transactionManager");
13
+ const reasoning_1 = require("./reasoning");
14
+ class LimitOrderManager {
15
+ filePath;
16
+ orders = [];
17
+ monitorInterval = null;
18
+ constructor() {
19
+ const config = (0, parser_1.loadConfig)();
20
+ this.filePath = (0, paths_1.getPath)(config.memory?.path ? config.memory.path.replace('memory.json', 'orders.json') : 'orders.json');
21
+ this.loadOrders();
22
+ }
23
+ loadOrders() {
24
+ if (fs_1.default.existsSync(this.filePath)) {
25
+ try {
26
+ const data = fs_1.default.readFileSync(this.filePath, 'utf-8');
27
+ this.orders = JSON.parse(data);
28
+ }
29
+ catch (error) {
30
+ this.orders = [];
31
+ }
32
+ }
33
+ }
34
+ saveOrders() {
35
+ try {
36
+ fs_1.default.writeFileSync(this.filePath, JSON.stringify(this.orders, null, 2));
37
+ }
38
+ catch (error) { }
39
+ }
40
+ createOrder(chainName, fromToken, toToken, amountStr, targetPriceUsd, condition) {
41
+ const id = `order_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
42
+ const order = {
43
+ id, chainName, fromToken, toToken, amountStr, targetPriceUsd, condition, status: 'pending', createdAt: Date.now()
44
+ };
45
+ this.orders.push(order);
46
+ this.saveOrders();
47
+ 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}.`;
48
+ }
49
+ listOrders() {
50
+ const pending = this.orders.filter(o => o.status === 'pending');
51
+ if (pending.length === 0)
52
+ return "No active limit orders.";
53
+ let report = "Active Limit Orders:\n";
54
+ pending.forEach(o => {
55
+ report += `- [${o.id}] Swap ${o.amountStr} ${o.fromToken} -> ${o.toToken} on ${o.chainName} when ${o.fromToken} is ${o.condition} $${o.targetPriceUsd}\n`;
56
+ });
57
+ return report;
58
+ }
59
+ cancelOrder(id) {
60
+ const order = this.orders.find(o => o.id === id);
61
+ if (!order)
62
+ return `Order ${id} not found.`;
63
+ if (order.status !== 'pending')
64
+ return `Order ${id} cannot be cancelled because it is ${order.status}.`;
65
+ order.status = 'cancelled';
66
+ this.saveOrders();
67
+ return `Order ${id} cancelled successfully.`;
68
+ }
69
+ startMonitor() {
70
+ if (this.monitorInterval)
71
+ clearInterval(this.monitorInterval);
72
+ // Monitor every 60 seconds
73
+ this.monitorInterval = setInterval(() => this.checkOrders(), 60000);
74
+ console.log('[LimitOrderManager] Order monitoring started (interval: 60s)');
75
+ }
76
+ async checkOrders() {
77
+ const pending = this.orders.filter(o => o.status === 'pending');
78
+ if (pending.length === 0)
79
+ return;
80
+ for (const order of pending) {
81
+ try {
82
+ let tokenAddress = (0, tokens_1.resolveToken)(order.fromToken, order.chainName);
83
+ if (tokenAddress === "0x0000000000000000000000000000000000000000") {
84
+ tokenAddress = (0, tokens_1.resolveToken)("W" + order.fromToken, order.chainName);
85
+ }
86
+ const res = await fetch(`https://api.dexscreener.com/latest/dex/tokens/${tokenAddress}`);
87
+ if (!res.ok)
88
+ continue;
89
+ const data = await res.json();
90
+ if (!data.pairs || data.pairs.length === 0)
91
+ continue;
92
+ let pair = data.pairs.find((p) => p.chainId === order.chainName) || data.pairs[0];
93
+ const currentPrice = parseFloat(pair.priceUsd);
94
+ let shouldExecute = false;
95
+ if (order.condition === 'above' && currentPrice >= order.targetPriceUsd)
96
+ shouldExecute = true;
97
+ if (order.condition === 'below' && currentPrice <= order.targetPriceUsd)
98
+ shouldExecute = true;
99
+ if (shouldExecute) {
100
+ console.log(`[LimitOrderManager] Condition met for order ${order.id}. Current price $${currentPrice} is ${order.condition} $${order.targetPriceUsd}. Executing...`);
101
+ // 1. Prepare Swap
102
+ const prepareResult = await (0, swapToken_1.prepareSwapToken)(order.chainName, order.fromToken, order.toToken, order.amountStr, 'auto');
103
+ // 2. Extract Tx ID
104
+ const txMatch = prepareResult.match(/Transaction ID: ([\w-]+)\./);
105
+ if (!txMatch) {
106
+ order.status = 'failed';
107
+ this.saveOrders();
108
+ (0, reasoning_1.processUserInput)(`Limit order ${order.id} execution failed during preparation. Output: ${prepareResult}`, 'system').catch(() => { });
109
+ continue;
110
+ }
111
+ const txId = txMatch[1];
112
+ const tx = transactionManager_1.txManager.getTransaction(txId);
113
+ if (!tx)
114
+ throw new Error("Transaction not found in manager");
115
+ // 3. Execute Swap automatically
116
+ const executeResult = await (0, swapToken_1.executeSwap)(order.chainName, tx.details);
117
+ if (executeResult.includes('successful')) {
118
+ transactionManager_1.txManager.updateStatus(txId, 'executed', executeResult);
119
+ order.status = 'executed';
120
+ this.saveOrders();
121
+ (0, reasoning_1.processUserInput)(`Limit order ${order.id} just EXECUTED automatically! Price hit $${currentPrice}. Swap result: ${executeResult}. Please notify the user immediately!`, 'system').catch(() => { });
122
+ }
123
+ else {
124
+ transactionManager_1.txManager.updateStatus(txId, 'failed', executeResult);
125
+ order.status = 'failed';
126
+ this.saveOrders();
127
+ (0, reasoning_1.processUserInput)(`Limit order ${order.id} FAILED to execute. Price hit $${currentPrice} but execution failed: ${executeResult}. Please notify the user.`, 'system').catch(() => { });
128
+ }
129
+ }
130
+ }
131
+ catch (error) {
132
+ console.error(`[LimitOrderManager] Error checking order ${order.id}:`, error.message);
133
+ }
134
+ }
135
+ }
136
+ }
137
+ exports.LimitOrderManager = LimitOrderManager;
138
+ exports.limitOrderManager = new LimitOrderManager();
139
+ exports.createLimitOrderToolDefinition = {
140
+ type: "function",
141
+ function: {
142
+ name: "create_limit_order",
143
+ description: "Creates an automatic cut-loss or take-profit limit order. The system will automatically execute the swap when the price condition is met.",
144
+ parameters: {
145
+ type: "object",
146
+ properties: {
147
+ chainName: { type: "string", enum: ["ethereum", "base", "bsc", "arbitrum", "optimism", "sepolia"] },
148
+ fromToken: { type: "string", description: "Token to sell" },
149
+ toToken: { type: "string", description: "Token to buy" },
150
+ amountStr: { type: "string", description: "Amount to sell" },
151
+ targetPriceUsd: { type: "number", description: "Target price in USD for the fromToken" },
152
+ condition: { type: "string", enum: ["above", "below"], description: "Trigger when price goes above (take-profit) or below (cut-loss) target" }
153
+ },
154
+ required: ["chainName", "fromToken", "toToken", "amountStr", "targetPriceUsd", "condition"],
155
+ },
156
+ },
157
+ };
158
+ exports.listLimitOrdersToolDefinition = {
159
+ type: "function",
160
+ function: {
161
+ name: "list_limit_orders",
162
+ description: "Lists all active automated limit orders.",
163
+ parameters: { type: "object", properties: {}, required: [] },
164
+ },
165
+ };
166
+ exports.cancelLimitOrderToolDefinition = {
167
+ type: "function",
168
+ function: {
169
+ name: "cancel_limit_order",
170
+ description: "Cancels an active limit order by ID.",
171
+ parameters: {
172
+ type: "object",
173
+ properties: { id: { type: "string" } },
174
+ required: ["id"],
175
+ },
176
+ },
177
+ };
@@ -14,6 +14,14 @@ const getBalance_1 = require("../web3/skills/getBalance");
14
14
  const transfer_1 = require("../web3/skills/transfer");
15
15
  const getPrice_1 = require("../web3/skills/getPrice");
16
16
  const swapToken_1 = require("../web3/skills/swapToken");
17
+ const bridgeToken_1 = require("../web3/skills/bridgeToken");
18
+ const mintNft_1 = require("../web3/skills/mintNft");
19
+ const customTx_1 = require("../web3/skills/customTx");
20
+ const createWallet_1 = require("../web3/skills/createWallet");
21
+ const checkSecurity_1 = require("../web3/skills/checkSecurity");
22
+ const marketAnalysis_1 = require("../web3/skills/marketAnalysis");
23
+ const checkPortfolio_1 = require("../web3/skills/checkPortfolio");
24
+ const limitOrderManager_1 = require("./limitOrderManager");
17
25
  const paths_1 = require("../config/paths");
18
26
  exports.logger = new logger_1.Logger();
19
27
  let currentKeyIndex = 0;
@@ -140,7 +148,22 @@ async function processUserInput(input, role = 'user') {
140
148
  model: config.llm.model,
141
149
  temperature: config.llm.temperature,
142
150
  messages: messages,
143
- tools: [getBalance_1.getBalanceToolDefinition, transfer_1.transferToolDefinition, getPrice_1.getPriceToolDefinition, swapToken_1.swapTokenToolDefinition],
151
+ tools: [
152
+ getBalance_1.getBalanceToolDefinition,
153
+ transfer_1.transferToolDefinition,
154
+ getPrice_1.getPriceToolDefinition,
155
+ swapToken_1.swapTokenToolDefinition,
156
+ bridgeToken_1.bridgeTokenToolDefinition,
157
+ mintNft_1.mintNftToolDefinition,
158
+ customTx_1.customTxToolDefinition,
159
+ createWallet_1.createWalletToolDefinition,
160
+ checkSecurity_1.checkSecurityToolDefinition,
161
+ marketAnalysis_1.marketAnalysisToolDefinition,
162
+ checkPortfolio_1.checkPortfolioToolDefinition,
163
+ limitOrderManager_1.createLimitOrderToolDefinition,
164
+ limitOrderManager_1.listLimitOrdersToolDefinition,
165
+ limitOrderManager_1.cancelLimitOrderToolDefinition
166
+ ],
144
167
  tool_choice: "auto",
145
168
  });
146
169
  const responseMessage = response.choices[0].message;
@@ -160,46 +183,76 @@ async function processUserInput(input, role = 'user') {
160
183
  if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
161
184
  for (const _toolCall of responseMessage.tool_calls) {
162
185
  const toolCall = _toolCall;
163
- if (toolCall.function.name === 'get_balance') {
164
- const args = JSON.parse(toolCall.function.arguments);
165
- const balanceResult = await (0, getBalance_1.getBalance)(args.chainName, args.address);
166
- exports.logger.addEntry({
167
- role: 'tool',
168
- tool_call_id: toolCall.id,
169
- name: toolCall.function.name,
170
- content: balanceResult,
171
- });
172
- }
173
- else if (toolCall.function.name === 'transfer_native') {
174
- const args = JSON.parse(toolCall.function.arguments);
175
- const transferResult = await (0, transfer_1.transferNative)(args.chainName, args.toAddress, args.amountEth);
176
- exports.logger.addEntry({
177
- role: 'tool',
178
- tool_call_id: toolCall.id,
179
- name: toolCall.function.name,
180
- content: transferResult,
181
- });
182
- }
183
- else if (toolCall.function.name === 'get_price') {
184
- const args = JSON.parse(toolCall.function.arguments);
185
- const priceResult = await (0, getPrice_1.getPrice)(args.coinId);
186
- exports.logger.addEntry({
187
- role: 'tool',
188
- tool_call_id: toolCall.id,
189
- name: toolCall.function.name,
190
- content: priceResult,
191
- });
192
- }
193
- else if (toolCall.function.name === 'swap_token') {
194
- const args = JSON.parse(toolCall.function.arguments);
195
- const swapResult = await (0, swapToken_1.swapToken)(args.chainName, args.fromToken, args.toToken, args.amount);
196
- exports.logger.addEntry({
197
- role: 'tool',
198
- tool_call_id: toolCall.id,
199
- name: toolCall.function.name,
200
- content: swapResult,
201
- });
186
+ let result = "";
187
+ const args = JSON.parse(toolCall.function.arguments);
188
+ const toolName = toolCall.function.name;
189
+ switch (toolName) {
190
+ case 'get_balance': {
191
+ result = await (0, getBalance_1.getBalance)(args.chainName, args.address, args.token);
192
+ break;
193
+ }
194
+ case 'transfer_token':
195
+ case 'transfer_native': {
196
+ result = await (0, transfer_1.prepareTransfer)(args.chainName, args.toAddress, args.amountStr || args.amountEth, args.token);
197
+ break;
198
+ }
199
+ case 'get_price': {
200
+ result = await (0, getPrice_1.getPrice)(args.coinId);
201
+ break;
202
+ }
203
+ case 'swap_token': {
204
+ result = await (0, swapToken_1.prepareSwapToken)(args.chainName, args.fromToken, args.toToken, args.amountStr || args.amount, args.mode, args.providerName);
205
+ break;
206
+ }
207
+ case 'bridge_token': {
208
+ result = await (0, bridgeToken_1.prepareBridgeToken)(args.fromChainName, args.toChainName, args.fromToken, args.toToken, args.amountStr, args.mode, args.providerName);
209
+ break;
210
+ }
211
+ case 'mint_nft': {
212
+ result = await (0, mintNft_1.prepareMintNft)(args.chainName, args.contractAddress, args.functionSignature, args.argsStr, args.valueEth);
213
+ break;
214
+ }
215
+ case 'custom_tx': {
216
+ result = await (0, customTx_1.prepareCustomTx)(args.chainName, args.toAddress, args.dataHex, args.valueEth, args.gasLimitStr);
217
+ break;
218
+ }
219
+ case 'create_wallet': {
220
+ result = await (0, createWallet_1.createWallet)();
221
+ break;
222
+ }
223
+ case 'check_token_security': {
224
+ result = await (0, checkSecurity_1.checkTokenSecurity)(args.chainName, args.contractAddress);
225
+ break;
226
+ }
227
+ case 'analyze_market': {
228
+ result = await (0, marketAnalysis_1.analyzeMarket)(args.chainName, args.tokenAddressOrSymbol);
229
+ break;
230
+ }
231
+ case 'check_portfolio': {
232
+ result = await (0, checkPortfolio_1.checkPortfolio)(args.chainName, args.address);
233
+ break;
234
+ }
235
+ case 'create_limit_order': {
236
+ result = limitOrderManager_1.limitOrderManager.createOrder(args.chainName, args.fromToken, args.toToken, args.amountStr, args.targetPriceUsd, args.condition);
237
+ break;
238
+ }
239
+ case 'list_limit_orders': {
240
+ result = limitOrderManager_1.limitOrderManager.listOrders();
241
+ break;
242
+ }
243
+ case 'cancel_limit_order': {
244
+ result = limitOrderManager_1.limitOrderManager.cancelOrder(args.id);
245
+ break;
246
+ }
247
+ default:
248
+ result = `Error: Tool ${toolName} is not implemented.`;
202
249
  }
250
+ exports.logger.addEntry({
251
+ role: 'tool',
252
+ tool_call_id: toolCall.id,
253
+ name: toolName,
254
+ content: result,
255
+ });
203
256
  }
204
257
  // Second call to get the final answer after tool execution
205
258
  const secondMessages = [
@@ -12,12 +12,14 @@ const reasoning_1 = require("../agent/reasoning");
12
12
  const parser_1 = require("../config/parser");
13
13
  const tracker_1 = require("./tracker");
14
14
  const transactionManager_1 = require("../agent/transactionManager");
15
+ const limitOrderManager_1 = require("../agent/limitOrderManager");
15
16
  const transfer_1 = require("../web3/skills/transfer");
16
17
  const swapToken_1 = require("../web3/skills/swapToken");
17
18
  const getBalance_1 = require("../web3/skills/getBalance");
18
- const transfer_2 = require("../web3/skills/transfer");
19
19
  const getPrice_1 = require("../web3/skills/getPrice");
20
- const swapToken_2 = require("../web3/skills/swapToken");
20
+ const bridgeToken_1 = require("../web3/skills/bridgeToken");
21
+ const mintNft_1 = require("../web3/skills/mintNft");
22
+ const customTx_1 = require("../web3/skills/customTx");
21
23
  const telegram_1 = require("./telegram");
22
24
  const formatter_1 = require("../utils/formatter");
23
25
  // Intercept console.log and console.error
@@ -94,9 +96,12 @@ app.get('/api/logs', (req, res) => {
94
96
  app.get('/api/skills', (req, res) => {
95
97
  res.json([
96
98
  getBalance_1.getBalanceToolDefinition,
97
- transfer_2.transferToolDefinition,
99
+ transfer_1.transferToolDefinition,
98
100
  getPrice_1.getPriceToolDefinition,
99
- swapToken_2.swapTokenToolDefinition
101
+ swapToken_1.swapTokenToolDefinition,
102
+ bridgeToken_1.bridgeTokenToolDefinition,
103
+ mintNft_1.mintNftToolDefinition,
104
+ customTx_1.customTxToolDefinition
100
105
  ]);
101
106
  });
102
107
  app.get('/api/transactions', (req, res) => {
@@ -110,10 +115,19 @@ app.post('/api/transactions/:id/approve', async (req, res) => {
110
115
  try {
111
116
  let result = '';
112
117
  if (tx.type === 'transfer') {
113
- result = await (0, transfer_1.executeTransfer)(tx.chainName, tx.details.toAddress, tx.details.amountEth);
118
+ result = await (0, transfer_1.executeTransfer)(tx.chainName, tx.details);
114
119
  }
115
120
  else if (tx.type === 'swap') {
116
- result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details.fromToken, tx.details.toToken, tx.details.amount);
121
+ result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details);
122
+ }
123
+ else if (tx.type === 'bridge') {
124
+ result = await (0, bridgeToken_1.executeBridge)(tx.chainName, tx.details);
125
+ }
126
+ else if (tx.type === 'mint') {
127
+ result = await (0, mintNft_1.executeMintNft)(tx.chainName, tx.details);
128
+ }
129
+ else if (tx.type === 'custom') {
130
+ result = await (0, customTx_1.executeCustomTx)(tx.chainName, tx.details);
117
131
  }
118
132
  transactionManager_1.txManager.updateStatus(id, 'executed', result);
119
133
  // Add programmatic beautiful message directly to chat
@@ -167,6 +181,7 @@ app.use((req, res, next) => {
167
181
  }
168
182
  });
169
183
  function startServer() {
184
+ limitOrderManager_1.limitOrderManager.startMonitor();
170
185
  const PORT = process.env.PORT || 3000;
171
186
  app.listen(PORT, () => {
172
187
  console.log(`🤖 Nyxora API Server running on port ${PORT}`);
@@ -10,6 +10,9 @@ const parser_1 = require("../config/parser");
10
10
  const transactionManager_1 = require("../agent/transactionManager");
11
11
  const transfer_1 = require("../web3/skills/transfer");
12
12
  const swapToken_1 = require("../web3/skills/swapToken");
13
+ const bridgeToken_1 = require("../web3/skills/bridgeToken");
14
+ const mintNft_1 = require("../web3/skills/mintNft");
15
+ const customTx_1 = require("../web3/skills/customTx");
13
16
  const formatter_1 = require("../utils/formatter");
14
17
  function startTelegramBot() {
15
18
  const config = (0, parser_1.loadConfig)();
@@ -25,6 +28,11 @@ function startTelegramBot() {
25
28
  const text = msg.text;
26
29
  if (!text)
27
30
  return;
31
+ if (text === '/clear') {
32
+ reasoning_1.logger.clear();
33
+ bot.sendMessage(chatId, '✅ Memori AI telah dihapus. Mari kita mulai obrolan baru!');
34
+ return;
35
+ }
28
36
  // Log incoming message
29
37
  console.log(`[Telegram] Received from ${msg.from?.first_name}: ${text}`);
30
38
  // Send typing action to Telegram
@@ -73,10 +81,19 @@ function startTelegramBot() {
73
81
  try {
74
82
  let result = '';
75
83
  if (tx.type === 'transfer') {
76
- result = await (0, transfer_1.executeTransfer)(tx.chainName, tx.details.toAddress, tx.details.amountEth);
84
+ result = await (0, transfer_1.executeTransfer)(tx.chainName, tx.details);
77
85
  }
78
86
  else if (tx.type === 'swap') {
79
- result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details.fromToken, tx.details.toToken, tx.details.amount);
87
+ result = await (0, swapToken_1.executeSwap)(tx.chainName, tx.details);
88
+ }
89
+ else if (tx.type === 'bridge') {
90
+ result = await (0, bridgeToken_1.executeBridge)(tx.chainName, tx.details);
91
+ }
92
+ else if (tx.type === 'mint') {
93
+ result = await (0, mintNft_1.executeMintNft)(tx.chainName, tx.details);
94
+ }
95
+ else if (tx.type === 'custom') {
96
+ result = await (0, customTx_1.executeCustomTx)(tx.chainName, tx.details);
80
97
  }
81
98
  transactionManager_1.txManager.updateStatus(txId, 'executed', result);
82
99
  const prettyMsg = (0, formatter_1.formatTransactionSuccess)(tx, result);