nyxora 26.7.2 → 26.7.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/CHANGELOG.md +95 -47
- package/README.md +23 -19
- package/bin/nyxora.mjs +4 -6
- package/dist/launcher.js +44 -8
- package/dist/packages/core/src/agent/bridgeWatcher.js +3 -2
- package/dist/packages/core/src/agent/cronManager.js +2 -2
- package/dist/packages/core/src/agent/llmProvider.js +242 -0
- package/dist/packages/core/src/agent/nyxDaemon.js +97 -0
- package/dist/packages/core/src/agent/osAgent.js +203 -29
- package/dist/packages/core/src/agent/reasoning.js +353 -60
- package/dist/packages/core/src/agent/reasoningScratchpad.js +47 -0
- package/dist/packages/core/src/agent/transactionManager.js +36 -31
- package/dist/packages/core/src/agent/web3Agent.js +263 -37
- package/dist/packages/core/src/cognitive/cognitiveManager.js +63 -10
- package/dist/packages/core/src/config/parser.js +10 -4
- package/dist/packages/core/src/gateway/chat.js +56 -13
- package/dist/packages/core/src/gateway/cli.js +3 -0
- package/dist/packages/core/src/gateway/discordAdapter.js +81 -0
- package/dist/packages/core/src/gateway/server.js +58 -9
- package/dist/packages/core/src/gateway/setup-ml.js +64 -0
- package/dist/packages/core/src/gateway/setup.js +39 -3
- package/dist/packages/core/src/gateway/telegram.js +120 -24
- package/dist/packages/core/src/memory/episodic.js +47 -3
- package/dist/packages/core/src/memory/logger.js +120 -2
- package/dist/packages/core/src/memory/promotionEngine.js +18 -5
- package/dist/packages/core/src/system/agentskills.js +10 -0
- package/dist/packages/core/src/system/plugins/GoogleWorkspacePlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemCorePlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemExternalPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemPluginInstallerPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemSocialPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemWebPlugin.js +1 -1
- package/dist/packages/core/src/system/plugins/SystemWorkspacePlugin.js +3 -3
- package/dist/packages/core/src/system/plugins/createSkill.js +1 -1
- package/dist/packages/core/src/system/skillExtractor.js +16 -5
- package/dist/packages/core/src/system/skills/forgetMemory.js +6 -4
- package/dist/packages/core/src/system/skills/scheduleTask.js +7 -2
- package/dist/packages/core/src/test_mainnet.js +45 -0
- package/dist/packages/core/src/utils/contextSummarizer.js +82 -0
- package/dist/packages/core/src/utils/skillManager.js +1 -1
- package/dist/packages/core/src/utils/streamSimulator.js +85 -0
- package/dist/packages/core/src/web3/aggregator/providers/ArbitrumBridgeProvider.js +28 -11
- package/dist/packages/core/src/web3/aggregator/providers/OpBridgeProvider.js +41 -27
- package/dist/packages/core/src/web3/aggregator/providers/TestnetSwapProvider.js +65 -0
- package/dist/packages/core/src/web3/aggregator/routeSelector.js +7 -1
- package/dist/packages/core/src/web3/plugins/Web3DefiPlugin.js +1 -1
- package/dist/packages/core/src/web3/plugins/Web3MarketPlugin.js +5 -125
- package/dist/packages/core/src/web3/plugins/Web3SecurityPlugin.js +1 -1
- package/dist/packages/core/src/web3/plugins/Web3WalletPlugin.js +1 -1
- package/dist/packages/core/src/web3/skills/bridgeToken.js +19 -4
- package/dist/packages/core/src/web3/skills/checkAddress.js +2 -0
- package/dist/packages/core/src/web3/skills/checkPortfolio.js +22 -2
- package/dist/packages/core/src/web3/skills/checkSecurity.js +2 -0
- package/dist/packages/core/src/web3/skills/confirmPendingTx.js +1 -1
- package/dist/packages/core/src/web3/skills/createLimitOrder.js +15 -1
- package/dist/packages/core/src/web3/skills/customTx.js +3 -0
- package/dist/packages/core/src/web3/skills/defiLending.js +2 -0
- package/dist/packages/core/src/web3/skills/getBalance.js +2 -0
- package/dist/packages/core/src/web3/skills/getPrice.js +134 -27
- package/dist/packages/core/src/web3/skills/getTxHistory.js +2 -0
- package/dist/packages/core/src/web3/skills/marketAnalysis.js +28 -191
- package/dist/packages/core/src/web3/skills/mintNft.js +3 -0
- package/dist/packages/core/src/web3/skills/provideLiquidity.js +16 -12
- package/dist/packages/core/src/web3/skills/revokeApprovals.js +2 -0
- package/dist/packages/core/src/web3/skills/swapToken.js +20 -2
- package/dist/packages/core/src/web3/skills/transfer.js +2 -0
- package/dist/packages/core/src/web3/skills/yieldVault.js +2 -0
- package/dist/packages/core/src/web3/utils/chains.js +19 -0
- package/dist/packages/core/src/web3/utils/marketEngine.js +26 -33
- package/dist/packages/signer/src/NyxoraSigner.js +181 -0
- package/dist/packages/signer/src/index.js +17 -0
- package/dist/packages/signer/src/server.js +25 -161
- package/launcher.ts +38 -9
- package/package.json +6 -2
- package/packages/core/package.json +21 -10
- package/packages/core/src/agent/bridgeWatcher.ts +3 -2
- package/packages/core/src/agent/cronManager.ts +2 -2
- package/packages/core/src/agent/llmProvider.ts +219 -0
- package/packages/core/src/agent/nyxDaemon.ts +104 -0
- package/packages/core/src/agent/osAgent.ts +230 -32
- package/packages/core/src/agent/reasoning.ts +376 -64
- package/packages/core/src/agent/reasoningScratchpad.ts +45 -0
- package/packages/core/src/agent/transactionManager.ts +36 -28
- package/packages/core/src/agent/web3Agent.ts +291 -40
- package/packages/core/src/cognitive/cognitiveManager.ts +65 -10
- package/packages/core/src/cognitive/prompts/web3/market-analysis.md +24 -0
- package/packages/core/src/cognitive/prompts/web3/portfolio-review.md +29 -0
- package/packages/core/src/cognitive/prompts/web3/risk-assessment.md +28 -0
- package/packages/core/src/cognitive/prompts/web3/trade-planning.md +30 -0
- package/packages/core/src/config/parser.ts +15 -4
- package/packages/core/src/gateway/chat.ts +57 -15
- package/packages/core/src/gateway/cli.ts +4 -0
- package/packages/core/src/gateway/discordAdapter.ts +87 -0
- package/packages/core/src/gateway/server.ts +66 -10
- package/packages/core/src/gateway/setup-ml.ts +68 -0
- package/packages/core/src/gateway/setup.ts +41 -3
- package/packages/core/src/gateway/telegram.ts +138 -27
- package/packages/core/src/memory/episodic.ts +64 -3
- package/packages/core/src/memory/logger.ts +142 -2
- package/packages/core/src/memory/promotionEngine.ts +19 -5
- package/packages/core/src/system/agentskills.ts +10 -0
- package/packages/core/src/system/plugins/GoogleWorkspacePlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemCorePlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemExternalPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemPluginInstallerPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemSocialPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemWebPlugin.ts +1 -1
- package/packages/core/src/system/plugins/SystemWorkspacePlugin.ts +3 -3
- package/packages/core/src/system/plugins/createSkill.ts +1 -1
- package/packages/core/src/system/skillExtractor.ts +16 -5
- package/packages/core/src/system/skills/forgetMemory.ts +7 -4
- package/packages/core/src/system/skills/scheduleTask.ts +7 -2
- package/packages/core/src/utils/contextSummarizer.ts +100 -0
- package/packages/core/src/utils/skillManager.ts +1 -1
- package/packages/core/src/utils/streamSimulator.ts +88 -0
- package/packages/core/src/web3/aggregator/providers/ArbitrumBridgeProvider.ts +30 -11
- package/packages/core/src/web3/aggregator/providers/OpBridgeProvider.ts +43 -29
- package/packages/core/src/web3/aggregator/routeSelector.ts +6 -1
- package/packages/core/src/web3/plugins/Web3DefiPlugin.ts +1 -1
- package/packages/core/src/web3/plugins/Web3MarketPlugin.ts +6 -125
- package/packages/core/src/web3/plugins/Web3SecurityPlugin.ts +1 -1
- package/packages/core/src/web3/plugins/Web3WalletPlugin.ts +1 -1
- package/packages/core/src/web3/skills/bridgeToken.ts +21 -7
- package/packages/core/src/web3/skills/checkAddress.ts +2 -0
- package/packages/core/src/web3/skills/checkPortfolio.ts +23 -2
- package/packages/core/src/web3/skills/checkSecurity.ts +2 -0
- package/packages/core/src/web3/skills/confirmPendingTx.ts +1 -1
- package/packages/core/src/web3/skills/createLimitOrder.ts +17 -2
- package/packages/core/src/web3/skills/customTx.ts +3 -0
- package/packages/core/src/web3/skills/defiLending.ts +2 -0
- package/packages/core/src/web3/skills/getBalance.ts +2 -0
- package/packages/core/src/web3/skills/getPrice.ts +134 -30
- package/packages/core/src/web3/skills/getTxHistory.ts +2 -0
- package/packages/core/src/web3/skills/marketAnalysis.ts +45 -188
- package/packages/core/src/web3/skills/mintNft.ts +3 -0
- package/packages/core/src/web3/skills/provideLiquidity.ts +16 -10
- package/packages/core/src/web3/skills/revokeApprovals.ts +2 -0
- package/packages/core/src/web3/skills/swapToken.ts +20 -3
- package/packages/core/src/web3/skills/transfer.ts +2 -0
- package/packages/core/src/web3/skills/yieldVault.ts +2 -0
- package/packages/core/src/web3/utils/chains.ts +12 -0
- package/packages/core/src/web3/utils/marketEngine.ts +27 -33
- package/packages/dashboard/dist/assets/index-BTfp141V.js +18 -0
- package/packages/dashboard/dist/assets/index-DK2sTU47.css +1 -0
- package/packages/dashboard/dist/index.html +2 -2
- package/packages/dashboard/package.json +10 -10
- package/packages/mcp-server/dist/server.js +5 -1
- package/packages/mcp-server/package.json +6 -6
- package/packages/mcp-server/src/server.ts +11 -7
- package/packages/policy/package.json +3 -3
- package/packages/signer/package.json +16 -6
- package/packages/signer/src/NyxoraSigner.ts +161 -0
- package/packages/signer/src/index.ts +1 -0
- package/packages/signer/src/server.ts +25 -135
- package/dist/packages/core/src/agent/honchoDaemon.js +0 -91
- package/dist/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +0 -54
- package/dist/packages/core/src/gateway/test.js +0 -15
- package/dist/packages/core/src/web3/Web3DefiPlugin.js +0 -28
- package/dist/packages/core/src/web3/aggregator/aggregatorMainnet.js +0 -260
- package/dist/packages/core/src/web3/aggregator/aggregatorTestnet.js +0 -119
- package/dist/packages/core/src/web3/skills/nativeOpBridge.js +0 -71
- package/packages/core/src/agent/honchoDaemon.ts +0 -96
- package/packages/core/src/cognitive/prompts/autonomous/binance-trading-integration.md +0 -41
- package/packages/core/src/plugin/registry.test.ts +0 -46
- package/packages/core/src/utils/formatter.test.ts +0 -41
- package/packages/dashboard/dist/assets/index-CSoNa5cx.css +0 -1
- package/packages/dashboard/dist/assets/index-DbRWEoSr.js +0 -16
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { parseUnits, formatUnits } from 'viem';
|
|
2
|
-
import { ChainName, SUPPORTED_CHAIN_NAMES } from '../config';
|
|
2
|
+
import { ChainName, SUPPORTED_CHAIN_NAMES, normalizeChainName } from '../config';
|
|
3
3
|
import { getAddress, submitTransaction } from '../utils/vaultClient';
|
|
4
4
|
import { txManager } from '../../agent/transactionManager';
|
|
5
5
|
import { resolveToken } from '../utils/tokens';
|
|
6
6
|
import { routeTransaction } from '../aggregator/defiRouter';
|
|
7
|
-
|
|
7
|
+
import { logger } from '../../memory/logger';
|
|
8
|
+
import { loadConfig } from '../../config/parser';
|
|
8
9
|
export async function prepareBridgeToken(
|
|
9
10
|
fromChain: ChainName,
|
|
10
11
|
toChain: ChainName,
|
|
@@ -15,8 +16,8 @@ export async function prepareBridgeToken(
|
|
|
15
16
|
slippagePercent?: number | "auto"
|
|
16
17
|
): Promise<string> {
|
|
17
18
|
try {
|
|
18
|
-
fromChain =
|
|
19
|
-
toChain =
|
|
19
|
+
fromChain = normalizeChainName(fromChain);
|
|
20
|
+
toChain = normalizeChainName(toChain);
|
|
20
21
|
if (!fromChain || !toChain) throw new Error("Source or destination chain not provided by AI.");
|
|
21
22
|
if (!amountStr) throw new Error("Bridge amount not provided by AI.");
|
|
22
23
|
|
|
@@ -52,8 +53,21 @@ export async function prepareBridgeToken(
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
const amountWei = parseUnits(amountStr, decimals).toString();
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
// Front-to-Back Slippage Architecture
|
|
58
|
+
const userProfile = logger.getUserProfile();
|
|
59
|
+
const maxSlippage = userProfile?.max_slippage || 1.0;
|
|
60
|
+
const config = loadConfig();
|
|
61
|
+
const cfgSlippage = (config.agent as any)?.default_slippage;
|
|
62
|
+
|
|
63
|
+
let finalSlippage = slippagePercent;
|
|
64
|
+
if (finalSlippage === undefined || finalSlippage === null || finalSlippage === "auto") {
|
|
65
|
+
finalSlippage = (cfgSlippage === "auto" || !cfgSlippage) ? 0.5 : parseFloat(cfgSlippage as string);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (typeof finalSlippage !== 'number' || isNaN(finalSlippage)) finalSlippage = 0.5;
|
|
69
|
+
if (finalSlippage > maxSlippage) finalSlippage = maxSlippage;
|
|
70
|
+
const slippage = finalSlippage;
|
|
57
71
|
// --- Pre-flight Balance Check ---
|
|
58
72
|
const { validateTransactionBalances } = await import('../utils/balanceChecker');
|
|
59
73
|
const balanceCheck = await validateTransactionBalances(fromChain, userAddress, fromTokenAddress, amountWei);
|
|
@@ -111,7 +125,7 @@ export const bridgeTokenToolDefinition = {
|
|
|
111
125
|
tokenSymbol: { type: "string" },
|
|
112
126
|
amountStr: { type: "string" },
|
|
113
127
|
mode: { type: "string", enum: ["auto", "manual"], default: "auto" },
|
|
114
|
-
providerName: { type: "string", enum: ["auto", "lifi", "relay"], default: "auto" },
|
|
128
|
+
providerName: { type: "string", enum: ["auto", "lifi", "relay", "op_bridge_testnet", "arbitrum_bridge_testnet"], default: "auto", description: "The preferred provider. Use 'op_bridge_testnet' (for OP/Base Sepolia), 'arbitrum_bridge_testnet' (for Arb Sepolia), or 'relay' (testnet fallback)." },
|
|
115
129
|
slippagePercent: { type: "number" }
|
|
116
130
|
},
|
|
117
131
|
required: ["fromChain", "toChain", "tokenSymbol", "amountStr"],
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { isAddress } from 'viem';
|
|
2
3
|
import { getPublicClient, ChainName, SUPPORTED_CHAIN_NAMES } from '../config';
|
|
3
4
|
|
|
4
5
|
export async function checkAddress(chainName: ChainName, address: string): Promise<string> {
|
|
5
6
|
try {
|
|
7
|
+
chainName = normalizeChainName(chainName);
|
|
6
8
|
if (!isAddress(address)) {
|
|
7
9
|
return `Address validation failed: '${address}' is not a valid Web3 address format.`;
|
|
8
10
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { formatEther, formatUnits } from 'viem';
|
|
2
3
|
import { getPublicClient, ChainName, SUPPORTED_CHAIN_NAMES } from '../config';
|
|
3
4
|
import { TOKEN_MAP, ERC20_ABI } from '../utils/tokens';
|
|
@@ -8,6 +9,7 @@ const CACHE_TTL = 5000; // 5 seconds TTL
|
|
|
8
9
|
|
|
9
10
|
export async function checkPortfolio(chainName: ChainName, address?: `0x${string}`): Promise<string> {
|
|
10
11
|
try {
|
|
12
|
+
chainName = normalizeChainName(chainName);
|
|
11
13
|
const client = getPublicClient(chainName);
|
|
12
14
|
|
|
13
15
|
let targetAddress = address;
|
|
@@ -139,9 +141,28 @@ export async function checkPortfolio(chainName: ChainName, address?: `0x${string
|
|
|
139
141
|
try {
|
|
140
142
|
const data = await safeFetchJson<any>(url);
|
|
141
143
|
if (data.pairs) {
|
|
144
|
+
data.pairs.sort((a: any, b: any) => (b.liquidity?.usd || 0) - (a.liquidity?.usd || 0));
|
|
145
|
+
const chainMatched = new Set<string>();
|
|
146
|
+
|
|
142
147
|
data.pairs.forEach((p: any) => {
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
const baseAddr = String(p.baseToken?.address || "").toLowerCase();
|
|
149
|
+
const quoteAddr = String(p.quoteToken?.address || "").toLowerCase();
|
|
150
|
+
const priceUsd = parseFloat(p.priceUsd || "0");
|
|
151
|
+
const priceNative = parseFloat(p.priceNative || "0");
|
|
152
|
+
|
|
153
|
+
if (baseAddr && priceUsd > 0) {
|
|
154
|
+
if (!priceMap[baseAddr] || (!chainMatched.has(baseAddr) && p.chainId === chainName)) {
|
|
155
|
+
priceMap[baseAddr] = priceUsd;
|
|
156
|
+
if (p.chainId === chainName) chainMatched.add(baseAddr);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (quoteAddr && priceUsd > 0 && priceNative > 0) {
|
|
161
|
+
const quotePriceUsd = priceUsd / priceNative;
|
|
162
|
+
if (!priceMap[quoteAddr] || (!chainMatched.has(quoteAddr) && p.chainId === chainName)) {
|
|
163
|
+
priceMap[quoteAddr] = quotePriceUsd;
|
|
164
|
+
if (p.chainId === chainName) chainMatched.add(quoteAddr);
|
|
165
|
+
}
|
|
145
166
|
}
|
|
146
167
|
});
|
|
147
168
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { ChainName, SUPPORTED_CHAIN_NAMES } from '../config';
|
|
2
3
|
import { safeFetchJson } from '../../utils/httpClient';
|
|
3
4
|
|
|
@@ -16,6 +17,7 @@ const CHAIN_IDS: Record<ChainName, number> = {
|
|
|
16
17
|
|
|
17
18
|
export async function checkTokenSecurity(chainName: ChainName, contractAddress: string): Promise<string> {
|
|
18
19
|
try {
|
|
20
|
+
chainName = normalizeChainName(chainName);
|
|
19
21
|
const chainId = CHAIN_IDS[chainName];
|
|
20
22
|
if (chainName === 'sepolia') {
|
|
21
23
|
return `Security check API (GoPlus) does not support Sepolia testnet. Try a mainnet token.`;
|
|
@@ -78,7 +78,7 @@ export const confirmPendingTxToolDefinition = {
|
|
|
78
78
|
type: "function",
|
|
79
79
|
function: {
|
|
80
80
|
name: "confirm_pending_tx",
|
|
81
|
-
description: "Approve or reject a pending transaction. Use this tool when a transaction has been queued and the user replies with a confirmation (like 'Yes' or 'Ya') or a rejection (like 'No' or 'Tidak').",
|
|
81
|
+
description: "Approve or reject a pending transaction. Use this tool when a transaction has been queued and the user replies with a confirmation (like 'Yes' or 'Ya') or a rejection (like 'No' or 'Tidak'). CRITICAL RULE: DO NOT call any other tool (like write_local_file) simultaneously with this one. Output ONLY this tool.",
|
|
82
82
|
parameters: {
|
|
83
83
|
type: "object",
|
|
84
84
|
properties: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { logger } from '../../memory/logger';
|
|
2
3
|
import { txManager } from '../../agent/transactionManager';
|
|
3
|
-
|
|
4
|
+
import { loadConfig } from '../../config/parser';
|
|
4
5
|
export async function createLimitOrder(
|
|
5
6
|
tokenSymbol: string,
|
|
6
7
|
tokenAddress: string,
|
|
@@ -11,6 +12,20 @@ export async function createLimitOrder(
|
|
|
11
12
|
slippageTolerance?: number
|
|
12
13
|
): Promise<string> {
|
|
13
14
|
try {
|
|
15
|
+
// Front-to-Back Slippage Architecture
|
|
16
|
+
const userProfile = logger.getUserProfile();
|
|
17
|
+
const maxSlippage = userProfile?.max_slippage || 1.0;
|
|
18
|
+
const config = loadConfig();
|
|
19
|
+
const cfgSlippage = (config.agent as any)?.default_slippage;
|
|
20
|
+
|
|
21
|
+
let finalSlippage = slippageTolerance;
|
|
22
|
+
if (finalSlippage === undefined || finalSlippage === null) {
|
|
23
|
+
finalSlippage = (cfgSlippage === "auto" || !cfgSlippage) ? 0.5 : parseFloat(cfgSlippage as string);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (typeof finalSlippage !== 'number' || isNaN(finalSlippage)) finalSlippage = 0.5;
|
|
27
|
+
if (finalSlippage > maxSlippage) finalSlippage = maxSlippage;
|
|
28
|
+
|
|
14
29
|
const orderData = {
|
|
15
30
|
token_symbol: tokenSymbol,
|
|
16
31
|
token_address: tokenAddress,
|
|
@@ -18,7 +33,7 @@ export async function createLimitOrder(
|
|
|
18
33
|
trigger_price_usd: triggerPriceUsd,
|
|
19
34
|
action,
|
|
20
35
|
amount_usd: amountUsd,
|
|
21
|
-
slippage_tolerance:
|
|
36
|
+
slippage_tolerance: finalSlippage
|
|
22
37
|
};
|
|
23
38
|
|
|
24
39
|
const orderId = logger.createLimitOrder(orderData);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { ChainName, SUPPORTED_CHAIN_NAMES } from '../config';
|
|
2
3
|
import { txManager } from '../../agent/transactionManager';
|
|
3
4
|
import { submitTransaction } from '../utils/vaultClient';
|
|
@@ -10,6 +11,7 @@ export async function prepareCustomTx(
|
|
|
10
11
|
description: string = "Custom transaction"
|
|
11
12
|
): Promise<string> {
|
|
12
13
|
try {
|
|
14
|
+
chainName = normalizeChainName(chainName);
|
|
13
15
|
if (!chainName || !toAddress || !data) throw new Error("Missing required parameters for custom transaction.");
|
|
14
16
|
const { getAddress } = await import('../utils/vaultClient');
|
|
15
17
|
const userAddress = await getAddress();
|
|
@@ -56,6 +58,7 @@ export const customTxToolDefinition = {
|
|
|
56
58
|
};
|
|
57
59
|
|
|
58
60
|
export async function executeCustomTx(chainName: string, details: any, autoApprove: boolean = false): Promise<string> {
|
|
61
|
+
chainName = normalizeChainName(chainName);
|
|
59
62
|
// Fix HMAC mismatch by guaranteeing amountWei exists to match valueWei
|
|
60
63
|
const processedDetails = {
|
|
61
64
|
...details,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { parseUnits } from 'viem';
|
|
2
3
|
import { getPublicClient, getAddress, ChainName, SUPPORTED_CHAIN_NAMES } from '../config';
|
|
3
4
|
import { txManager } from '../../agent/transactionManager';
|
|
@@ -31,6 +32,7 @@ const AAVE_V3_POOLS: Record<string, `0x${string}`> = {
|
|
|
31
32
|
|
|
32
33
|
export async function prepareAaveSupply(chainName: ChainName, tokenAddressOrSymbol: string, amountStr: string): Promise<string> {
|
|
33
34
|
try {
|
|
35
|
+
chainName = normalizeChainName(chainName);
|
|
34
36
|
if (!chainName || !tokenAddressOrSymbol || !amountStr) throw new Error("Missing protocol/chain/token parameters for DeFi operation.");
|
|
35
37
|
const publicClient = getPublicClient(chainName);
|
|
36
38
|
const userAddress = await getAddress();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { formatEther, formatUnits } from 'viem';
|
|
2
3
|
import { getPublicClient, ChainName, SUPPORTED_CHAIN_NAMES } from '../config';
|
|
3
4
|
import { ERC20_ABI, resolveToken, getTokenMetadata } from '../utils/tokens';
|
|
@@ -5,6 +6,7 @@ import { saveTokenToWhitelist } from '../../utils/userWhitelistManager';
|
|
|
5
6
|
|
|
6
7
|
export async function getBalance(chainName: ChainName, address?: `0x${string}`, token?: string): Promise<string> {
|
|
7
8
|
try {
|
|
9
|
+
chainName = normalizeChainName(chainName);
|
|
8
10
|
const client = getPublicClient(chainName);
|
|
9
11
|
|
|
10
12
|
let targetAddress = address;
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import { safeFetchJson } from '../../utils/httpClient';
|
|
2
2
|
import { loadMarketKeys } from '../../config/marketConfigManager';
|
|
3
|
+
import { loadConfig } from '../../config/parser';
|
|
3
4
|
|
|
4
5
|
export const getPriceToolDefinition = {
|
|
5
6
|
type: "function",
|
|
6
7
|
function: {
|
|
7
|
-
name: "
|
|
8
|
-
description: "Fetches the current price of a cryptocurrency.",
|
|
8
|
+
name: "get_price_and_fiat_value",
|
|
9
|
+
description: "Fetches the current price of a cryptocurrency and performs perfect fiat/amount conversion.",
|
|
9
10
|
parameters: {
|
|
10
11
|
type: "object",
|
|
11
12
|
properties: {
|
|
12
13
|
coinId: {
|
|
13
14
|
type: "string",
|
|
14
|
-
description: "The CoinGecko ID of the coin (e.g., 'ethereum', 'bitcoin', '
|
|
15
|
+
description: "The CoinGecko ID of the coin, its symbol, or its exact Contract Address (e.g., 'ethereum', 'bitcoin', 'jrny', '0x123...'). For low-cap/DEX tokens, ALWAYS use the Contract Address if available."
|
|
15
16
|
},
|
|
16
17
|
currency: {
|
|
17
18
|
type: "string",
|
|
18
|
-
description: "The fiat currency to convert to (e.g., 'usd', 'idr', 'eur', 'jpy').
|
|
19
|
+
description: "The fiat currency to convert to (e.g., 'usd', 'idr', 'eur', 'jpy'). If omitted, it automatically defaults to the user's configured base fiat."
|
|
20
|
+
},
|
|
21
|
+
amount: {
|
|
22
|
+
type: "number",
|
|
23
|
+
description: "Optional. The number of tokens. If provided, the tool calculates the total fiat value exactly."
|
|
19
24
|
}
|
|
20
25
|
},
|
|
21
26
|
required: ["coinId"]
|
|
@@ -23,34 +28,133 @@ export const getPriceToolDefinition = {
|
|
|
23
28
|
}
|
|
24
29
|
};
|
|
25
30
|
|
|
26
|
-
export async function getPrice(coinId: string, currency
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
export async function getPrice(coinId: string, currency?: string, amount?: number): Promise<string> {
|
|
32
|
+
const config = loadConfig();
|
|
33
|
+
const defaultFiat = config.agent?.base_fiat || 'usd';
|
|
34
|
+
const cur = String(currency || defaultFiat).toLowerCase();
|
|
35
|
+
const curUpper = cur.toUpperCase();
|
|
36
|
+
const keys = loadMarketKeys();
|
|
37
|
+
|
|
38
|
+
// Helper to fetch USDT -> Target Fiat rate
|
|
39
|
+
async function getUsdtToFiatRate(): Promise<number> {
|
|
40
|
+
if (cur === 'usd' || cur === 'usdt') return 1;
|
|
41
|
+
// Tier 1 for Fiat: CoinGecko
|
|
42
|
+
try {
|
|
43
|
+
const isPro = !!keys.coingecko_key;
|
|
44
|
+
const baseUrl = isPro ? 'https://pro-api.coingecko.com/api/v3' : 'https://api.coingecko.com/api/v3';
|
|
45
|
+
const headers = isPro ? { 'x-cg-pro-api-key': keys.coingecko_key } : undefined;
|
|
46
|
+
const data = await safeFetchJson<any>(`${baseUrl}/simple/price?ids=tether&vs_currencies=${cur}`, { headers });
|
|
47
|
+
if (data && data.tether && data.tether[cur]) return data.tether[cur];
|
|
48
|
+
} catch (e) {}
|
|
49
|
+
// Tier 2 for Fiat: CoinMarketCap
|
|
50
|
+
if (keys.cmc_key) {
|
|
51
|
+
try {
|
|
52
|
+
const data = await safeFetchJson<any>(`https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest?slug=tether&convert=${curUpper}`, {
|
|
53
|
+
headers: { 'X-CMC_PRO_API_KEY': keys.cmc_key }
|
|
54
|
+
});
|
|
55
|
+
const coinList = Object.values(data?.data || {});
|
|
56
|
+
if (coinList[0] && (coinList[0] as any).quote[curUpper]) return (coinList[0] as any).quote[curUpper].price;
|
|
57
|
+
} catch (e) {}
|
|
40
58
|
}
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const fiatRate = await getUsdtToFiatRate();
|
|
63
|
+
if (fiatRate === 0 && cur !== 'usd') {
|
|
64
|
+
return `❌ **Failed to fetch fiat exchange rate** for **USDT -> ${curUpper}**.`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let tokenUsdPrice = 0;
|
|
68
|
+
let change24h = 0;
|
|
69
|
+
let source = '';
|
|
70
|
+
let tokenName = coinId.toUpperCase();
|
|
71
|
+
|
|
72
|
+
// TIER 1: CoinMarketCap (Token -> USD)
|
|
73
|
+
if (keys.cmc_key && tokenUsdPrice === 0) {
|
|
74
|
+
try {
|
|
75
|
+
const url = `https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest?slug=${coinId.toLowerCase()}&convert=USD`;
|
|
76
|
+
const data = await safeFetchJson<any>(url, { headers: { 'X-CMC_PRO_API_KEY': keys.cmc_key } });
|
|
77
|
+
const coin: any = Object.values(data?.data || {})[0];
|
|
78
|
+
if (coin && coin.quote && coin.quote.USD) {
|
|
79
|
+
tokenUsdPrice = coin.quote.USD.price;
|
|
80
|
+
change24h = coin.quote.USD.percent_change_24h;
|
|
81
|
+
tokenName = coin.symbol;
|
|
82
|
+
source = 'CoinMarketCap Pro';
|
|
83
|
+
}
|
|
84
|
+
} catch(e) {}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// TIER 2: CoinGecko (Token -> USD)
|
|
88
|
+
if (tokenUsdPrice === 0) {
|
|
89
|
+
try {
|
|
90
|
+
const isPro = !!keys.coingecko_key;
|
|
91
|
+
const baseUrl = isPro ? 'https://pro-api.coingecko.com/api/v3' : 'https://api.coingecko.com/api/v3';
|
|
92
|
+
const headers = isPro ? { 'x-cg-pro-api-key': keys.coingecko_key } : undefined;
|
|
93
|
+
const url = `${baseUrl}/simple/price?ids=${coinId}&vs_currencies=usd&include_24hr_change=true`;
|
|
94
|
+
const data = await safeFetchJson<any>(url, { headers });
|
|
95
|
+
if (data && data[coinId]) {
|
|
96
|
+
tokenUsdPrice = data[coinId].usd;
|
|
97
|
+
change24h = data[coinId].usd_24h_change || 0;
|
|
98
|
+
source = `CoinGecko ${isPro ? 'Pro' : 'Public'}`;
|
|
99
|
+
}
|
|
100
|
+
} catch(e) {}
|
|
101
|
+
}
|
|
41
102
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
103
|
+
// TIER 3: Nyxora Python ML Engine (For obscure/low-cap DEX tokens)
|
|
104
|
+
if (tokenUsdPrice === 0) {
|
|
105
|
+
try {
|
|
106
|
+
const mlData = await safeFetchJson<any>(`http://localhost:8000/web3/analyze?query=${coinId}&chain=ethereum`);
|
|
107
|
+
if (mlData && mlData.currentPrice) {
|
|
108
|
+
tokenUsdPrice = mlData.currentPrice;
|
|
109
|
+
change24h = mlData.priceChange24h || 0;
|
|
110
|
+
tokenName = mlData.officialSymbol || coinId.toUpperCase();
|
|
111
|
+
source = 'ML Engine (On-Chain/DEX Routing)';
|
|
112
|
+
}
|
|
113
|
+
} catch(e) {}
|
|
114
|
+
}
|
|
49
115
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
116
|
+
// TIER 4: DexScreener (Direct CA or Symbol Search)
|
|
117
|
+
if (tokenUsdPrice === 0) {
|
|
118
|
+
try {
|
|
119
|
+
const data = await safeFetchJson<any>(`https://api.dexscreener.com/latest/dex/search?q=${coinId}`);
|
|
120
|
+
if (data.pairs && data.pairs.length > 0) {
|
|
121
|
+
const pair = data.pairs[0];
|
|
122
|
+
tokenUsdPrice = Number(pair.priceUsd);
|
|
123
|
+
change24h = pair.priceChange?.h24 || 0;
|
|
124
|
+
tokenName = pair.baseToken.symbol;
|
|
125
|
+
source = 'DexScreener';
|
|
126
|
+
}
|
|
127
|
+
} catch(e) {}
|
|
55
128
|
}
|
|
129
|
+
|
|
130
|
+
if (tokenUsdPrice === 0) {
|
|
131
|
+
return `❌ **Failed to fetch price:** Could not find price data for **${coinId.toUpperCase()}** on CMC, CoinGecko, or DexScreener.`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Final Math: Amount * Token(USD) * USDT(Fiat Rate)
|
|
135
|
+
const finalPricePerUnit = tokenUsdPrice * fiatRate;
|
|
136
|
+
const isPositive = change24h >= 0;
|
|
137
|
+
const arrow = isPositive ? '📈 🟩 +' : '📉 🟥 ';
|
|
138
|
+
|
|
139
|
+
const formatter = new Intl.NumberFormat(cur === 'idr' ? 'id-ID' : 'en-US', { style: 'currency', currency: curUpper });
|
|
140
|
+
const priceFormatted = formatter.format(finalPricePerUnit);
|
|
141
|
+
const changeFormatted = change24h ? change24h.toFixed(2) : '0.00';
|
|
142
|
+
|
|
143
|
+
let report = `💰 **Price Update for ${tokenName}**\n\n`;
|
|
144
|
+
if (amount !== undefined && amount !== null) {
|
|
145
|
+
const totalVal = amount * finalPricePerUnit;
|
|
146
|
+
const totalFormatted = formatter.format(totalVal);
|
|
147
|
+
report += `- **Amount**: ${amount} ${tokenName}\n`;
|
|
148
|
+
report += `- **Price per Unit (${curUpper})**: \`${priceFormatted}\`\n`;
|
|
149
|
+
report += `- **Total Value**: \`${totalFormatted}\`\n`;
|
|
150
|
+
} else {
|
|
151
|
+
report += `- **Price (${curUpper})**: \`${priceFormatted}\`\n`;
|
|
152
|
+
}
|
|
153
|
+
report += `- **24h Change**: ${arrow}${changeFormatted}%\n`;
|
|
154
|
+
if (cur !== 'usd' && cur !== 'usdt') {
|
|
155
|
+
report += `- **USDT Rate**: \`${formatter.format(fiatRate)}\` / USDT\n`;
|
|
156
|
+
}
|
|
157
|
+
report += `_Source: ${source} (Token) | Live Fiat Oracle (USDT Rate)_`;
|
|
158
|
+
|
|
159
|
+
return report;
|
|
56
160
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeChainName } from '../utils/chains';
|
|
1
2
|
import { loadConfig } from '../../config/parser';
|
|
2
3
|
import { getAddress, ChainName } from '../config';
|
|
3
4
|
import { formatUnits } from 'viem';
|
|
@@ -18,6 +19,7 @@ const CHAIN_IDS: Record<string, number> = {
|
|
|
18
19
|
|
|
19
20
|
export async function getTxHistory(chainName: ChainName, address?: string, days: number = 30): Promise<string> {
|
|
20
21
|
try {
|
|
22
|
+
chainName = normalizeChainName(chainName);
|
|
21
23
|
const targetAddress = address || await getAddress();
|
|
22
24
|
const chainId = CHAIN_IDS[chainName];
|
|
23
25
|
if (!chainId) {
|