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,91 +0,0 @@
|
|
|
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.honchoDaemon = exports.HonchoDaemon = void 0;
|
|
7
|
-
const parser_1 = require("../config/parser");
|
|
8
|
-
const llmUtils_1 = require("../utils/llmUtils");
|
|
9
|
-
const episodic_1 = require("../memory/episodic");
|
|
10
|
-
const reasoning_1 = require("./reasoning");
|
|
11
|
-
const picocolors_1 = __importDefault(require("picocolors"));
|
|
12
|
-
class HonchoDaemon {
|
|
13
|
-
isRunning = false;
|
|
14
|
-
intervalId = null;
|
|
15
|
-
INTERVAL_MS = 60 * 60 * 1000; // Run every hour
|
|
16
|
-
start() {
|
|
17
|
-
if (this.isRunning)
|
|
18
|
-
return;
|
|
19
|
-
this.isRunning = true;
|
|
20
|
-
// Initial run after 5 minutes
|
|
21
|
-
setTimeout(() => this.runAnalysis(), 5 * 60 * 1000);
|
|
22
|
-
// Scheduled runs
|
|
23
|
-
this.intervalId = setInterval(() => {
|
|
24
|
-
this.runAnalysis();
|
|
25
|
-
}, this.INTERVAL_MS);
|
|
26
|
-
console.log(picocolors_1.default.magenta('[Honcho] Dialectic User Modeling daemon started.'));
|
|
27
|
-
}
|
|
28
|
-
stop() {
|
|
29
|
-
if (this.intervalId) {
|
|
30
|
-
clearInterval(this.intervalId);
|
|
31
|
-
}
|
|
32
|
-
this.isRunning = false;
|
|
33
|
-
console.log(picocolors_1.default.magenta('[Honcho] Daemon stopped.'));
|
|
34
|
-
}
|
|
35
|
-
async runAnalysis() {
|
|
36
|
-
console.log(picocolors_1.default.magenta('[Honcho] Running dialectic user modeling...'));
|
|
37
|
-
const sessions = reasoning_1.logger.getSessions();
|
|
38
|
-
if (sessions.length === 0)
|
|
39
|
-
return;
|
|
40
|
-
const allHistory = reasoning_1.logger.getHistory(undefined, 100); // Get recent 100 messages
|
|
41
|
-
if (allHistory.length < 5)
|
|
42
|
-
return; // Not enough context
|
|
43
|
-
const config = (0, parser_1.loadConfig)();
|
|
44
|
-
const prompt = `You are Honcho, Nyxora's background Persona Auditor.
|
|
45
|
-
Your task is to analyze the user's recent chat history and extract long-term persona traits, preferences, or behavioral rules.
|
|
46
|
-
Focus ONLY on facts about the user. (e.g. "User prefers high-risk trades", "User is a developer", "User wants concise answers", "User hates memecoins").
|
|
47
|
-
|
|
48
|
-
Output your findings as a strict JSON array of strings. If nothing new is found, return [].
|
|
49
|
-
Example: ["User avoids Ethereum mainnet due to gas", "User prefers dark mode"]
|
|
50
|
-
|
|
51
|
-
Chat History:
|
|
52
|
-
${allHistory.map((m) => `[${m.role}] ${m.content}`).join('\n')}
|
|
53
|
-
`;
|
|
54
|
-
try {
|
|
55
|
-
const response = await (0, llmUtils_1.executeWithRetry)(async (client) => {
|
|
56
|
-
return await client.chat({
|
|
57
|
-
model: config.llm.model,
|
|
58
|
-
messages: [{ role: 'system', content: prompt }],
|
|
59
|
-
temperature: 0.1
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
let content = response.message.content || '[]';
|
|
63
|
-
// Clean markdown if any
|
|
64
|
-
content = content.replace(/\`\`\`json/g, '').replace(/\`\`\`/g, '').trim();
|
|
65
|
-
let traits = [];
|
|
66
|
-
try {
|
|
67
|
-
const parsed = JSON.parse(content);
|
|
68
|
-
if (Array.isArray(parsed)) {
|
|
69
|
-
traits = parsed;
|
|
70
|
-
}
|
|
71
|
-
else if (parsed.traits && Array.isArray(parsed.traits)) {
|
|
72
|
-
traits = parsed.traits;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch (e) {
|
|
76
|
-
console.error(picocolors_1.default.red('[Honcho] Failed to parse JSON traits'), content);
|
|
77
|
-
}
|
|
78
|
-
if (traits.length > 0) {
|
|
79
|
-
traits.forEach(trait => {
|
|
80
|
-
episodic_1.episodicDB.updatePersonaTrait(trait, 0.8, 'honcho');
|
|
81
|
-
console.log(picocolors_1.default.magenta(`[Honcho] Discovered new trait: ${trait}`));
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
catch (e) {
|
|
86
|
-
console.error(picocolors_1.default.red(`[Honcho] Analysis failed: ${e.message}`));
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
exports.HonchoDaemon = HonchoDaemon;
|
|
91
|
-
exports.honchoDaemon = new HonchoDaemon();
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Binance Trading Integration SOP
|
|
2
|
-
|
|
3
|
-
## Tujuan
|
|
4
|
-
Membantu Nyxora menyiapkan alur kerja aman untuk analisis, simulasi, dan eksekusi trading Binance melalui API/plugin/tool yang tersedia atau yang akan dibuat.
|
|
5
|
-
|
|
6
|
-
## Prinsip Keamanan Wajib
|
|
7
|
-
1. Jangan pernah meminta atau menyimpan API Secret secara plaintext di chat.
|
|
8
|
-
2. Jangan pernah mengaktifkan permission withdrawal pada API Binance.
|
|
9
|
-
3. Default mode harus read-only atau paper/simulation kecuali user secara eksplisit meminta eksekusi live.
|
|
10
|
-
4. Semua order live wajib membutuhkan konfirmasi eksplisit user sebelum dieksekusi.
|
|
11
|
-
5. Terapkan batas risiko: max notional per trade, max daily loss, allowed symbols, dan allowed order types.
|
|
12
|
-
6. Validasi registry/status agent sebelum transaksi jika eksekusi melibatkan sistem transaksi.
|
|
13
|
-
|
|
14
|
-
## Data yang Harus Dikumpulkan
|
|
15
|
-
- Tipe market: Spot atau Futures.
|
|
16
|
-
- Mode: read-only, paper trading, atau live trading dengan confirmation.
|
|
17
|
-
- Pair yang diizinkan, contoh BTCUSDT, ETHUSDT.
|
|
18
|
-
- Maksimal nilai per trade.
|
|
19
|
-
- Maksimal kerugian harian.
|
|
20
|
-
- Jenis order yang diizinkan: market, limit, stop-limit, OCO.
|
|
21
|
-
- Preferensi strategi: manual, grid, DCA, breakout, mean reversion, atau signal-based.
|
|
22
|
-
|
|
23
|
-
## Alur Setup Aman
|
|
24
|
-
1. Jelaskan bahwa API key/secret tidak boleh dikirim langsung di chat.
|
|
25
|
-
2. Minta user membuat Binance API key dengan permission minimal.
|
|
26
|
-
3. Pastikan withdrawal permission nonaktif.
|
|
27
|
-
4. Simpan credential hanya melalui secret manager/env file terenkripsi, bukan profile/memory/chat.
|
|
28
|
-
5. Jika belum ada tool Binance, tawarkan membuat plugin/tool integrasi Binance dengan approval user.
|
|
29
|
-
6. Uji koneksi dengan endpoint read-only terlebih dahulu.
|
|
30
|
-
7. Uji paper trading/simulasi order.
|
|
31
|
-
8. Baru aktifkan live trading setelah user menyetujui batas risiko.
|
|
32
|
-
|
|
33
|
-
## Alur Trading
|
|
34
|
-
1. Ambil saldo, pair info, ticker, order book, dan fee.
|
|
35
|
-
2. Validasi pair termasuk whitelist user.
|
|
36
|
-
3. Hitung quantity sesuai step size/min notional Binance.
|
|
37
|
-
4. Buat rencana order berisi: pair, side, type, quantity, estimated price, max cost, fee estimate, risiko, dan alasan.
|
|
38
|
-
5. Minta konfirmasi user untuk live order.
|
|
39
|
-
6. Setelah konfirmasi, kirim order.
|
|
40
|
-
7. Verifikasi status order.
|
|
41
|
-
8. Laporkan hasil eksekusi beserta orderId, filled qty, average price, fee, dan status.
|
|
42
|
-
|
|
43
|
-
## Risk Guardrails
|
|
44
|
-
- Tolak order jika pair tidak masuk whitelist.
|
|
45
|
-
- Tolak order jika nilai melebihi max notional per trade.
|
|
46
|
-
- Tolak order jika daily loss limit tercapai.
|
|
47
|
-
- Tolak futures leverage tinggi kecuali user eksplisit menyetujui dan batas risiko jelas.
|
|
48
|
-
- Jangan melakukan revenge trading atau trading beruntun tanpa instruksi.
|
|
49
|
-
|
|
50
|
-
## Format Jawaban ke User
|
|
51
|
-
Gunakan bahasa Indonesia. Ringkas, jelas, dan actionable. Untuk order live, tampilkan ringkasan order dan minta konfirmasi eksplisit sebelum eksekusi.
|
|
52
|
-
|
|
53
|
-
## Disclaimer
|
|
54
|
-
Selalu tekankan bahwa analisis/trading bukan nasihat keuangan dan user bertanggung jawab atas keputusan akhir.
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const reasoning_1 = require("../agent/reasoning");
|
|
4
|
-
async function run() {
|
|
5
|
-
console.log('🤖 Agent Test Started...');
|
|
6
|
-
console.log('👤 You: Tolong cek saldo native di jaringan ethereum');
|
|
7
|
-
try {
|
|
8
|
-
const response = await (0, reasoning_1.processUserInput)('Tolong cek saldo native di jaringan ethereum');
|
|
9
|
-
console.log(`\n🤖 Nyxora Agent: ${response}\n`);
|
|
10
|
-
}
|
|
11
|
-
catch (err) {
|
|
12
|
-
console.error(`Error: ${err.message}`);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
run();
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Web3DefiPlugin = void 0;
|
|
4
|
-
const getBalance_1 = require("./skills/getBalance");
|
|
5
|
-
const checkPortfolio_1 = require("./skills/checkPortfolio");
|
|
6
|
-
const swapToken_1 = require("./skills/swapToken");
|
|
7
|
-
class Web3DefiPlugin {
|
|
8
|
-
name = 'Web3DefiPlugin';
|
|
9
|
-
description = 'Core DeFi operations including balance checking, portfolio analysis, and token swapping.';
|
|
10
|
-
version = '1.0.0';
|
|
11
|
-
tools = [
|
|
12
|
-
getBalance_1.getBalanceToolDefinition,
|
|
13
|
-
checkPortfolio_1.checkPortfolioToolDefinition,
|
|
14
|
-
swapToken_1.swapTokenToolDefinition
|
|
15
|
-
];
|
|
16
|
-
handlers = {
|
|
17
|
-
[getBalance_1.getBalanceToolDefinition.function.name]: async (args) => {
|
|
18
|
-
return await (0, getBalance_1.getBalance)(args.chainName, args.address, args.token);
|
|
19
|
-
},
|
|
20
|
-
[checkPortfolio_1.checkPortfolioToolDefinition.function.name]: async (args) => {
|
|
21
|
-
return await (0, checkPortfolio_1.checkPortfolio)(args.chainName, args.address);
|
|
22
|
-
},
|
|
23
|
-
[swapToken_1.swapTokenToolDefinition.function.name]: async (args) => {
|
|
24
|
-
return await (0, swapToken_1.prepareSwapToken)(args.chainName, args.sellToken, args.buyToken, args.sellAmount, args.slippagePercentage, args.aggregator, args.destinationAddress);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
exports.Web3DefiPlugin = Web3DefiPlugin;
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchMainnetBestRoute = fetchMainnetBestRoute;
|
|
4
|
-
const defiConfigManager_1 = require("../../config/defiConfigManager");
|
|
5
|
-
const httpClient_1 = require("../../utils/httpClient");
|
|
6
|
-
const HEALTH_CACHE = {};
|
|
7
|
-
const MAX_FAILS = 3;
|
|
8
|
-
const COOLDOWN_MS = 60000;
|
|
9
|
-
function isProviderHealthy(provider) {
|
|
10
|
-
const state = HEALTH_CACHE[provider];
|
|
11
|
-
if (!state)
|
|
12
|
-
return true;
|
|
13
|
-
if (state.fails >= MAX_FAILS) {
|
|
14
|
-
if (Date.now() - state.lastFail > COOLDOWN_MS) {
|
|
15
|
-
HEALTH_CACHE[provider] = { fails: 0, lastFail: 0 }; // Reset
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
function recordProviderFailure(provider) {
|
|
23
|
-
if (!HEALTH_CACHE[provider])
|
|
24
|
-
HEALTH_CACHE[provider] = { fails: 0, lastFail: 0 };
|
|
25
|
-
HEALTH_CACHE[provider].fails += 1;
|
|
26
|
-
HEALTH_CACHE[provider].lastFail = Date.now();
|
|
27
|
-
console.warn(`[Aggregator] ${provider} failed. Strike ${HEALTH_CACHE[provider].fails}/${MAX_FAILS}`);
|
|
28
|
-
}
|
|
29
|
-
async function fetchMainnetBestRoute(fromChain, toChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance = "auto") {
|
|
30
|
-
const keys = (0, defiConfigManager_1.loadDefiKeys)();
|
|
31
|
-
const isCrossChain = fromChain !== toChain;
|
|
32
|
-
const promises = [];
|
|
33
|
-
// Provider 1: 1inch (Same chain only)
|
|
34
|
-
if (!isCrossChain && isProviderHealthy('1inch')) {
|
|
35
|
-
promises.push(fetch1inch(fromChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance, keys.inch_key));
|
|
36
|
-
}
|
|
37
|
-
// Provider 2: 0x (Same chain only)
|
|
38
|
-
if (!isCrossChain && isProviderHealthy('0x')) {
|
|
39
|
-
promises.push(fetch0x(fromChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance, keys.zero_x_key));
|
|
40
|
-
}
|
|
41
|
-
// Provider 3: LI.FI (Cross-chain & Same-chain)
|
|
42
|
-
if (isProviderHealthy('lifi')) {
|
|
43
|
-
promises.push(fetchLifi(fromChain, toChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance, keys.lifi_key));
|
|
44
|
-
}
|
|
45
|
-
// Provider 4: Relay (Cross-chain & Same-chain)
|
|
46
|
-
if (isProviderHealthy('relay')) {
|
|
47
|
-
promises.push(fetchRelay(fromChain, toChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance, keys.relay_key));
|
|
48
|
-
}
|
|
49
|
-
// Provider 5: OpenOcean (Cross-chain & Same-chain)
|
|
50
|
-
if (isProviderHealthy('openocean')) {
|
|
51
|
-
promises.push(fetchOpenOcean(fromChain, toChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance, keys.openocean_key));
|
|
52
|
-
}
|
|
53
|
-
// Provider 6: KyberSwap (Same-chain ONLY)
|
|
54
|
-
if (!isCrossChain && isProviderHealthy('kyberswap')) {
|
|
55
|
-
promises.push(fetchKyberSwap(fromChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance));
|
|
56
|
-
}
|
|
57
|
-
// Execute all healthy providers concurrently with a 4s timeout
|
|
58
|
-
const TIMEOUT_MS = 4000;
|
|
59
|
-
const results = await Promise.allSettled(promises.map(p => Promise.race([
|
|
60
|
-
p,
|
|
61
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), TIMEOUT_MS))
|
|
62
|
-
])));
|
|
63
|
-
const validQuotes = [];
|
|
64
|
-
results.forEach((res, index) => {
|
|
65
|
-
if (res.status === 'fulfilled' && res.value) {
|
|
66
|
-
validQuotes.push(res.value);
|
|
67
|
-
}
|
|
68
|
-
else if (res.status === 'rejected') {
|
|
69
|
-
// Determine which provider failed based on index (simplified logic, usually we wrap the promise to carry the name)
|
|
70
|
-
// For this implementation, we just log. The wrapper inside each fetcher records failure.
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
if (validQuotes.length === 0) {
|
|
74
|
-
throw new Error('All Meta-Aggregator providers failed or timed out. No route found.');
|
|
75
|
-
}
|
|
76
|
-
// Sort by expected output (highest first)
|
|
77
|
-
validQuotes.sort((a, b) => {
|
|
78
|
-
const outA = BigInt(a.expectedOutputRaw);
|
|
79
|
-
const outB = BigInt(b.expectedOutputRaw);
|
|
80
|
-
if (outA > outB)
|
|
81
|
-
return -1;
|
|
82
|
-
if (outA < outB)
|
|
83
|
-
return 1;
|
|
84
|
-
return 0;
|
|
85
|
-
});
|
|
86
|
-
// Optional: We can adjust sorting to account for gas cost. (OutputValue - GasValue).
|
|
87
|
-
// For MVP, raw output is sufficient.
|
|
88
|
-
console.log(`[Aggregator] Best route found via ${validQuotes[0].provider}`);
|
|
89
|
-
return validQuotes[0];
|
|
90
|
-
}
|
|
91
|
-
// --- Internal Fetchers --- //
|
|
92
|
-
const CHAIN_IDS = {
|
|
93
|
-
ethereum: 1, base: 8453, bsc: 56, arbitrum: 42161, optimism: 10, polygon: 137
|
|
94
|
-
};
|
|
95
|
-
async function fetch1inch(chain, fromToken, toToken, amount, address, slippage, key) {
|
|
96
|
-
try {
|
|
97
|
-
if (!key)
|
|
98
|
-
throw new Error('1inch requires an API key');
|
|
99
|
-
const chainId = CHAIN_IDS[chain];
|
|
100
|
-
const res = await (0, httpClient_1.safeFetch)(`https://api.1inch.dev/swap/v6.0/${chainId}/swap?src=${fromToken}&dst=${toToken}&amount=${amount}&from=${address}&slippage=${slippage}&disableEstimate=true`, {
|
|
101
|
-
headers: { 'Authorization': `Bearer ${key}` }
|
|
102
|
-
});
|
|
103
|
-
if (!res.ok)
|
|
104
|
-
throw new Error(await res.text());
|
|
105
|
-
const data = await res.json();
|
|
106
|
-
return {
|
|
107
|
-
provider: '1inch',
|
|
108
|
-
expectedOutput: (Number(data.dstAmount) / 1e18).toString(), // simplified
|
|
109
|
-
expectedOutputRaw: data.dstAmount,
|
|
110
|
-
gasCostUsd: 0,
|
|
111
|
-
txPayload: data.tx,
|
|
112
|
-
rawQuote: data
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
catch (e) {
|
|
116
|
-
recordProviderFailure('1inch');
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
async function fetch0x(chain, fromToken, toToken, amount, address, slippage, key) {
|
|
121
|
-
try {
|
|
122
|
-
if (!key)
|
|
123
|
-
throw new Error('0x requires an API key');
|
|
124
|
-
const slipParam = slippage === "auto" ? "0.005" : (slippage / 100).toString();
|
|
125
|
-
const res = await (0, httpClient_1.safeFetch)(`https://api.0x.org/swap/v1/quote?sellToken=${fromToken}&buyToken=${toToken}&sellAmount=${amount}&takerAddress=${address}&slippagePercentage=${slipParam}`, {
|
|
126
|
-
headers: { '0x-api-key': key }
|
|
127
|
-
});
|
|
128
|
-
if (!res.ok)
|
|
129
|
-
throw new Error(await res.text());
|
|
130
|
-
const data = await res.json();
|
|
131
|
-
return {
|
|
132
|
-
provider: '0x',
|
|
133
|
-
expectedOutput: (Number(data.buyAmount) / 1e18).toString(),
|
|
134
|
-
expectedOutputRaw: data.buyAmount,
|
|
135
|
-
gasCostUsd: 0,
|
|
136
|
-
txPayload: { to: data.to, data: data.data, value: data.value },
|
|
137
|
-
rawQuote: data
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
catch (e) {
|
|
141
|
-
recordProviderFailure('0x');
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
async function fetchLifi(fromChain, toChain, fromToken, toToken, amount, address, slippage, key) {
|
|
146
|
-
try {
|
|
147
|
-
const slipParam = slippage === "auto" ? 0.005 : (slippage / 100);
|
|
148
|
-
const res = await (0, httpClient_1.safeFetch)(`https://li.quest/v1/quote?fromChain=${fromChain}&toChain=${toChain}&fromToken=${fromToken}&toToken=${toToken}&fromAmount=${amount}&fromAddress=${address}&slippage=${slipParam}`, {
|
|
149
|
-
headers: key ? { 'x-lifi-api-key': key } : undefined
|
|
150
|
-
});
|
|
151
|
-
if (!res.ok)
|
|
152
|
-
throw new Error(await res.text());
|
|
153
|
-
const data = await res.json();
|
|
154
|
-
return {
|
|
155
|
-
provider: 'LI.FI',
|
|
156
|
-
expectedOutput: (Number(data.estimate.toAmount) / 1e18).toString(),
|
|
157
|
-
expectedOutputRaw: data.estimate.toAmount,
|
|
158
|
-
gasCostUsd: Number(data.estimate.gasCosts?.[0]?.amountUSD || 0),
|
|
159
|
-
txPayload: data.transactionRequest,
|
|
160
|
-
rawQuote: data
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
catch (e) {
|
|
164
|
-
recordProviderFailure('lifi');
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
async function fetchRelay(fromChain, toChain, fromToken, toToken, amount, address, slippage, key) {
|
|
169
|
-
try {
|
|
170
|
-
// Relay API strictly requires the zero address for Native ETH instead of 0xeeee...
|
|
171
|
-
const relayOriginCurrency = fromToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
|
|
172
|
-
? '0x0000000000000000000000000000000000000000' : fromToken;
|
|
173
|
-
const relayDestCurrency = toToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
|
|
174
|
-
? '0x0000000000000000000000000000000000000000' : toToken;
|
|
175
|
-
const payload = {
|
|
176
|
-
user: address,
|
|
177
|
-
originChainId: CHAIN_IDS[fromChain].toString(),
|
|
178
|
-
destinationChainId: CHAIN_IDS[toChain].toString(),
|
|
179
|
-
originCurrency: relayOriginCurrency,
|
|
180
|
-
destinationCurrency: relayDestCurrency,
|
|
181
|
-
recipient: address,
|
|
182
|
-
tradeType: 'EXACT_INPUT',
|
|
183
|
-
amount: amount,
|
|
184
|
-
referrer: 'nyxora',
|
|
185
|
-
useExternalLiquidity: false
|
|
186
|
-
};
|
|
187
|
-
const res = await (0, httpClient_1.safeFetch)('https://api.relay.link/quote', {
|
|
188
|
-
method: 'POST',
|
|
189
|
-
headers: { 'Content-Type': 'application/json' },
|
|
190
|
-
body: JSON.stringify(payload)
|
|
191
|
-
});
|
|
192
|
-
if (!res.ok)
|
|
193
|
-
throw new Error(await res.text());
|
|
194
|
-
const data = await res.json();
|
|
195
|
-
return {
|
|
196
|
-
provider: 'Relay',
|
|
197
|
-
expectedOutput: (Number(data.details?.currencyOut?.amount) / 1e18).toString(),
|
|
198
|
-
expectedOutputRaw: data.details?.currencyOut?.amount,
|
|
199
|
-
gasCostUsd: 0,
|
|
200
|
-
txPayload: data.steps?.[0]?.items?.[0]?.data,
|
|
201
|
-
rawQuote: data
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
catch (e) {
|
|
205
|
-
recordProviderFailure('relay');
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
async function fetchOpenOcean(fromChain, toChain, fromToken, toToken, amount, address, slippage, key) {
|
|
210
|
-
// Mock implementation for OpenOcean API which varies widely
|
|
211
|
-
// In a real app, you'd use their exact V3 API specification
|
|
212
|
-
recordProviderFailure('openocean');
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
async function fetchKyberSwap(fromChain, fromToken, toToken, amount, address, slippage) {
|
|
216
|
-
try {
|
|
217
|
-
const chainName = fromChain.toLowerCase().replace(/_/g, '');
|
|
218
|
-
const slipParam = slippage === "auto" ? 50 : (slippage * 100);
|
|
219
|
-
// Phase 1: Route
|
|
220
|
-
const routeRes = await (0, httpClient_1.safeFetch)(`https://aggregator-api.kyberswap.com/${chainName}/api/v1/routes?tokenIn=${fromToken}&tokenOut=${toToken}&amountIn=${amount}`);
|
|
221
|
-
if (!routeRes.ok)
|
|
222
|
-
throw new Error(await routeRes.text());
|
|
223
|
-
const routeData = await routeRes.json();
|
|
224
|
-
if (!routeData.data || !routeData.data.routeSummary)
|
|
225
|
-
throw new Error("No Kyber route found");
|
|
226
|
-
// Phase 2: Build
|
|
227
|
-
const buildPayload = {
|
|
228
|
-
routeSummary: routeData.data.routeSummary,
|
|
229
|
-
sender: address,
|
|
230
|
-
recipient: address,
|
|
231
|
-
slippageTolerance: slipParam
|
|
232
|
-
};
|
|
233
|
-
const buildRes = await (0, httpClient_1.safeFetch)(`https://aggregator-api.kyberswap.com/${chainName}/api/v1/route/build`, {
|
|
234
|
-
method: 'POST',
|
|
235
|
-
headers: { 'Content-Type': 'application/json' },
|
|
236
|
-
body: JSON.stringify(buildPayload)
|
|
237
|
-
});
|
|
238
|
-
if (!buildRes.ok)
|
|
239
|
-
throw new Error(await buildRes.text());
|
|
240
|
-
const buildData = await buildRes.json();
|
|
241
|
-
const isNative = fromToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' ||
|
|
242
|
-
fromToken === '0x0000000000000000000000000000000000000000';
|
|
243
|
-
return {
|
|
244
|
-
provider: 'KyberSwap',
|
|
245
|
-
expectedOutput: (Number(routeData.data.routeSummary.amountOut) / 1e18).toString(),
|
|
246
|
-
expectedOutputRaw: routeData.data.routeSummary.amountOut,
|
|
247
|
-
gasCostUsd: Number(routeData.data.routeSummary.gasUsd || 0),
|
|
248
|
-
txPayload: {
|
|
249
|
-
to: buildData.data.routerAddress,
|
|
250
|
-
data: buildData.data.data,
|
|
251
|
-
value: isNative ? amount : "0" // FIXED: Mengirim jumlah asli dalam WEI jika Native ETH, atau 0 jika ERC20
|
|
252
|
-
},
|
|
253
|
-
rawQuote: buildData.data
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
catch (e) {
|
|
257
|
-
recordProviderFailure('kyberswap');
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchTestnetBestRoute = fetchTestnetBestRoute;
|
|
4
|
-
const httpClient_1 = require("../../utils/httpClient");
|
|
5
|
-
const viem_1 = require("viem");
|
|
6
|
-
const nativeOpBridge_1 = require("../skills/nativeOpBridge");
|
|
7
|
-
async function fetchTestnetBestRoute(fromChain, toChain, fromToken, toToken, amountInWei, userAddress, slippageTolerance = "auto") {
|
|
8
|
-
const promises = [];
|
|
9
|
-
// Routing Logic Hierarchy
|
|
10
|
-
const isOpStack = toChain === 'optimism_sepolia' || toChain === 'base_sepolia' ||
|
|
11
|
-
fromChain === 'optimism_sepolia' || fromChain === 'base_sepolia';
|
|
12
|
-
const isArbitrum = toChain === 'arbitrum_sepolia' || fromChain === 'arbitrum_sepolia';
|
|
13
|
-
if (isOpStack) {
|
|
14
|
-
// Primary: Universal OP Stack
|
|
15
|
-
promises.push((0, nativeOpBridge_1.fetchNativeOpBridgeTestnet)(fromChain, toChain, fromToken, toToken, amountInWei, userAddress)
|
|
16
|
-
.catch(e => { console.warn('Native OP failed:', e.message); return null; }));
|
|
17
|
-
// Fallback 1: Relay Testnet (Only supports Base Sepolia natively via Relay endpoint)
|
|
18
|
-
if (toChain === 'base_sepolia' || fromChain === 'base_sepolia') {
|
|
19
|
-
promises.push(fetchRelayTestnet(fromChain, toChain, fromToken, toToken, amountInWei, userAddress)
|
|
20
|
-
.catch(e => { console.warn('Relay Fallback failed:', e.message); return null; }));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
else if (isArbitrum) {
|
|
24
|
-
// Fallback 2: Official Arbitrum Bridge
|
|
25
|
-
promises.push(fetchArbitrumBridgeTestnet(fromChain, toChain, fromToken, toToken, amountInWei, userAddress)
|
|
26
|
-
.catch(e => { console.warn('Arbitrum Bridge failed:', e.message); return null; }));
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
throw new Error(`[Testnet Meta-Aggregator] Unsupported testnet route from ${fromChain} to ${toChain}.`);
|
|
30
|
-
}
|
|
31
|
-
const results = await Promise.allSettled(promises);
|
|
32
|
-
let bestQuote = null;
|
|
33
|
-
for (const res of results) {
|
|
34
|
-
if (res.status === 'fulfilled' && res.value) {
|
|
35
|
-
if (!bestQuote || BigInt(res.value.expectedOutputRaw) > BigInt(bestQuote.expectedOutputRaw)) {
|
|
36
|
-
bestQuote = res.value;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
if (!bestQuote) {
|
|
41
|
-
throw new Error(`[Testnet Meta-Aggregator] No routes found between ${fromChain} and ${toChain} for given tokens.`);
|
|
42
|
-
}
|
|
43
|
-
return bestQuote;
|
|
44
|
-
}
|
|
45
|
-
async function fetchRelayTestnet(fromChain, toChain, fromToken, toToken, amount, address) {
|
|
46
|
-
try {
|
|
47
|
-
const RELAY_CHAIN_MAP = {
|
|
48
|
-
'sepolia': '11155111',
|
|
49
|
-
'base_sepolia': '84532'
|
|
50
|
-
};
|
|
51
|
-
const originChainId = RELAY_CHAIN_MAP[fromChain];
|
|
52
|
-
const destChainId = RELAY_CHAIN_MAP[toChain];
|
|
53
|
-
if (!originChainId || !destChainId)
|
|
54
|
-
return null;
|
|
55
|
-
// Relay API strictly requires the zero address for Native ETH instead of 0xeeee...
|
|
56
|
-
const relayOriginCurrency = fromToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
|
|
57
|
-
? '0x0000000000000000000000000000000000000000' : fromToken;
|
|
58
|
-
const relayDestCurrency = toToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
|
|
59
|
-
? '0x0000000000000000000000000000000000000000' : toToken;
|
|
60
|
-
const payload = {
|
|
61
|
-
user: address, originChainId, destinationChainId: destChainId,
|
|
62
|
-
originCurrency: relayOriginCurrency, destinationCurrency: relayDestCurrency,
|
|
63
|
-
recipient: address, tradeType: 'EXACT_INPUT', amount,
|
|
64
|
-
referrer: 'nyxora', useExternalLiquidity: false
|
|
65
|
-
};
|
|
66
|
-
const res = await (0, httpClient_1.safeFetch)('https://api.testnets.relay.link/quote', {
|
|
67
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload)
|
|
68
|
-
});
|
|
69
|
-
if (!res.ok)
|
|
70
|
-
return null;
|
|
71
|
-
const data = await res.json();
|
|
72
|
-
return {
|
|
73
|
-
provider: 'Relay (Testnet)',
|
|
74
|
-
txPayload: data.steps?.[0]?.items?.[0]?.data,
|
|
75
|
-
expectedOutput: data.details?.currencyOut?.amount,
|
|
76
|
-
expectedOutputRaw: data.details?.currencyOut?.amount,
|
|
77
|
-
gasCostUsd: 0, rawQuote: data
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
catch (e) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
async function fetchArbitrumBridgeTestnet(fromChain, toChain, fromToken, toToken, amount, address) {
|
|
85
|
-
const isValidRoute = (fromChain === 'sepolia' && toChain === 'arbitrum_sepolia');
|
|
86
|
-
// NOTE: Currently only implementing L1 -> L2 (Sepolia to Arbitrum Sepolia) for simplicity.
|
|
87
|
-
// L2 -> L1 requires withdrawal proofs which is complex to mock/simulate here in a single tx.
|
|
88
|
-
if (!isValidRoute) {
|
|
89
|
-
throw new Error(`[Arbitrum Bridge] Only Sepolia -> Arbitrum Sepolia is currently supported for direct L1->L2 bridging.`);
|
|
90
|
-
}
|
|
91
|
-
// Ensure it's Native ETH
|
|
92
|
-
const isNative = fromToken.toLowerCase() === 'eth' ||
|
|
93
|
-
fromToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' ||
|
|
94
|
-
fromToken === '0x0000000000000000000000000000000000000000';
|
|
95
|
-
if (!isNative) {
|
|
96
|
-
throw new Error(`[Arbitrum Bridge] Only Native ETH bridging is supported via the Delayed Inbox.`);
|
|
97
|
-
}
|
|
98
|
-
// Official Arbitrum Sepolia Delayed Inbox Address on L1
|
|
99
|
-
const inboxAddress = '0xaAe29B0366299461418F5324a79Afc425BE5ae21';
|
|
100
|
-
// Real ABI encoding for depositEth()
|
|
101
|
-
const depositEthAbi = (0, viem_1.parseAbi)(['function depositEth() payable returns (uint256)']);
|
|
102
|
-
const callData = (0, viem_1.encodeFunctionData)({
|
|
103
|
-
abi: depositEthAbi,
|
|
104
|
-
functionName: 'depositEth'
|
|
105
|
-
});
|
|
106
|
-
const realPayload = {
|
|
107
|
-
to: inboxAddress,
|
|
108
|
-
data: callData,
|
|
109
|
-
value: amount
|
|
110
|
-
};
|
|
111
|
-
return {
|
|
112
|
-
provider: 'Arbitrum Official Bridge (Testnet)',
|
|
113
|
-
txPayload: realPayload,
|
|
114
|
-
expectedOutput: amount, // 1:1 on official bridge
|
|
115
|
-
expectedOutputRaw: amount,
|
|
116
|
-
gasCostUsd: 0,
|
|
117
|
-
rawQuote: { note: '100% Real L1->L2 Bridge Transaction via Arbitrum Delayed Inbox' }
|
|
118
|
-
};
|
|
119
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchNativeOpBridgeTestnet = fetchNativeOpBridgeTestnet;
|
|
4
|
-
const viem_1 = require("viem");
|
|
5
|
-
const OP_L1_PORTAL_MAP = {
|
|
6
|
-
'base_sepolia': '0xfd0bf71f60660e2f608ed56e1659c450eb113120',
|
|
7
|
-
'optimism_sepolia': '0xfbb0621e0b23b5478b630bd55a5f21f67730b0f1'
|
|
8
|
-
};
|
|
9
|
-
const L2_STANDARD_BRIDGE = '0x4200000000000000000000000000000000000010';
|
|
10
|
-
async function fetchNativeOpBridgeTestnet(fromChain, toChain, fromToken, toToken, amount, address) {
|
|
11
|
-
const isL1toL2 = fromChain === 'sepolia' && OP_L1_PORTAL_MAP[toChain];
|
|
12
|
-
const isL2toL1 = toChain === 'sepolia' && OP_L1_PORTAL_MAP[fromChain];
|
|
13
|
-
if (!isL1toL2 && !isL2toL1) {
|
|
14
|
-
throw new Error(`[Native OP Bridge] Unsupported route from ${fromChain} to ${toChain}`);
|
|
15
|
-
}
|
|
16
|
-
// Ensure it's Native ETH for simplicity
|
|
17
|
-
const safeFromToken = String(fromToken || "");
|
|
18
|
-
const isNative = safeFromToken.toLowerCase() === 'eth' ||
|
|
19
|
-
safeFromToken.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' ||
|
|
20
|
-
safeFromToken === '0x0000000000000000000000000000000000000000';
|
|
21
|
-
if (!isNative) {
|
|
22
|
-
throw new Error(`[Native OP Bridge] Only Native ETH bridging is supported natively in this version.`);
|
|
23
|
-
}
|
|
24
|
-
if (isL1toL2) {
|
|
25
|
-
// Deposit (L1 -> L2)
|
|
26
|
-
const portalAddress = OP_L1_PORTAL_MAP[toChain];
|
|
27
|
-
const bridgeEthAbi = (0, viem_1.parseAbi)(['function bridgeETHTo(address _to, uint32 _minGasLimit, bytes _extraData) payable']);
|
|
28
|
-
const callData = (0, viem_1.encodeFunctionData)({
|
|
29
|
-
abi: bridgeEthAbi,
|
|
30
|
-
functionName: 'bridgeETHTo',
|
|
31
|
-
args: [address, 200000, '0x']
|
|
32
|
-
});
|
|
33
|
-
return {
|
|
34
|
-
provider: 'Native OP Stack Bridge (L1->L2)',
|
|
35
|
-
txPayload: {
|
|
36
|
-
to: portalAddress,
|
|
37
|
-
data: callData,
|
|
38
|
-
value: amount
|
|
39
|
-
},
|
|
40
|
-
expectedOutput: amount,
|
|
41
|
-
expectedOutputRaw: amount,
|
|
42
|
-
gasCostUsd: 0,
|
|
43
|
-
rawQuote: { note: 'Direct L1->L2 Deposit via OP Portal. Funds will arrive instantly on L2.' }
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
// Withdrawal (L2 -> L1)
|
|
48
|
-
const withdrawEthAbi = (0, viem_1.parseAbi)(['function bridgeETHTo(address _to, uint32 _minGasLimit, bytes _extraData) payable']);
|
|
49
|
-
const callData = (0, viem_1.encodeFunctionData)({
|
|
50
|
-
abi: withdrawEthAbi,
|
|
51
|
-
functionName: 'bridgeETHTo',
|
|
52
|
-
args: [address, 200000, '0x']
|
|
53
|
-
});
|
|
54
|
-
return {
|
|
55
|
-
provider: 'Native OP Stack Bridge (L2->L1)',
|
|
56
|
-
txPayload: {
|
|
57
|
-
to: L2_STANDARD_BRIDGE,
|
|
58
|
-
data: callData,
|
|
59
|
-
value: amount
|
|
60
|
-
},
|
|
61
|
-
expectedOutput: amount,
|
|
62
|
-
expectedOutputRaw: amount,
|
|
63
|
-
gasCostUsd: 0,
|
|
64
|
-
rawQuote: {
|
|
65
|
-
note: 'Direct L2->L1 Withdrawal. WARNING: Requires 7-day challenge period.',
|
|
66
|
-
isAsyncWithdrawal: true,
|
|
67
|
-
l1PortalAddress: OP_L1_PORTAL_MAP[fromChain]
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
}
|