terafab-cli 1.1.6 → 1.2.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/package.json +13 -6
- package/terafab.js +228 -61
package/package.json
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terafab-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Official CLI for Terafabpay - Swap &
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Official CLI for Terafabpay — No-KYC Swap & Autonomous AI Agent Wallet",
|
|
5
5
|
"main": "terafab.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
"bin": { "terafab": "./terafab.js" },
|
|
7
|
+
"keywords": ["monero","xmr","swap","no-kyc","crypto","ai","agent","wallet"],
|
|
8
|
+
"author": "terafabpay_ai <Support@terafabpay.de>",
|
|
9
|
+
"license": "Proprietary",
|
|
9
10
|
"dependencies": {
|
|
10
11
|
"commander": "^11.0.0",
|
|
11
12
|
"ethers": "^6.11.1"
|
|
12
|
-
}
|
|
13
|
+
},
|
|
14
|
+
"optionalDependencies": {
|
|
15
|
+
"@solana/web3.js": "^1.95.0",
|
|
16
|
+
"bs58": "^5.0.0"
|
|
17
|
+
},
|
|
18
|
+
"engines": { "node": ">=18.0.0" },
|
|
19
|
+
"homepage": "https://terafabpay.de"
|
|
13
20
|
}
|
package/terafab.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
2
3
|
|
|
3
4
|
const { Command } = require('commander');
|
|
4
5
|
const { ethers } = require('ethers');
|
|
@@ -7,86 +8,252 @@ const path = require('path');
|
|
|
7
8
|
|
|
8
9
|
const program = new Command();
|
|
9
10
|
const API_BASE = 'https://terafabpay.de';
|
|
10
|
-
const VAULT_PATH = path.join(process.env.HOME, '.terafab_vault');
|
|
11
|
+
const VAULT_PATH = path.join(process.env.HOME || '/tmp', '.terafab_vault');
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
// ── RPC ENDPOINTS ──────────────────────────────
|
|
14
|
+
const RPC = {
|
|
15
|
+
base: 'https://mainnet.base.org',
|
|
16
|
+
ethereum: 'https://eth.llamarpc.com',
|
|
17
|
+
bsc: 'https://bsc-dataseed.binance.org',
|
|
18
|
+
polygon: 'https://polygon-rpc.com',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// ── ERC20 ABI ──────────────────────────────────
|
|
22
|
+
const ERC20_ABI = [
|
|
23
|
+
'function transfer(address to, uint256 amount) returns (bool)',
|
|
24
|
+
'function decimals() view returns (uint8)',
|
|
25
|
+
'function balanceOf(address) view returns (uint256)',
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// ── TOKEN CONTRACTS (Base Network) ─────────────
|
|
29
|
+
const TOKENS = {
|
|
30
|
+
usdterc20: { address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2', decimals: 6, rpc: RPC.base },
|
|
31
|
+
usdc: { address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', decimals: 6, rpc: RPC.base },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// ── VAULT ──────────────────────────────────────
|
|
35
|
+
function loadVault() {
|
|
13
36
|
if (fs.existsSync(VAULT_PATH)) {
|
|
14
|
-
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
37
|
+
try { return JSON.parse(fs.readFileSync(VAULT_PATH, 'utf8')); }
|
|
38
|
+
catch (e) { return {}; }
|
|
39
|
+
}
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
function saveVault(data) {
|
|
43
|
+
fs.writeFileSync(VAULT_PATH, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ── ASSETS ─────────────────────────────────────
|
|
47
|
+
const ASSETS = {
|
|
48
|
+
btc: { name: 'Bitcoin', symbol: 'BTC', chain: 'utxo' },
|
|
49
|
+
sol: { name: 'Solana', symbol: 'SOL', chain: 'solana' },
|
|
50
|
+
eth: { name: 'Ethereum', symbol: 'ETH', chain: 'base' },
|
|
51
|
+
usdterc20: { name: 'USDT', symbol: 'USDT', chain: 'base' },
|
|
52
|
+
usdttrc20: { name: 'USDT TRC20', symbol: 'USDT', chain: 'tron' },
|
|
53
|
+
bnb: { name: 'BNB', symbol: 'BNB', chain: 'bsc' },
|
|
54
|
+
matic: { name: 'MATIC', symbol: 'MATIC',chain: 'polygon'},
|
|
55
|
+
xmr: { name: 'Monero', symbol: 'XMR', chain: 'monero' },
|
|
56
|
+
doge: { name: 'Dogecoin', symbol: 'DOGE', chain: 'utxo' },
|
|
57
|
+
ltc: { name: 'Litecoin', symbol: 'LTC', chain: 'utxo' },
|
|
58
|
+
xrp: { name: 'Ripple', symbol: 'XRP', chain: 'xrp' },
|
|
59
|
+
ada: { name: 'Cardano', symbol: 'ADA', chain: 'ada' },
|
|
60
|
+
trx: { name: 'Tron', symbol: 'TRX', chain: 'tron' },
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// ── EVM SEND ───────────────────────────────────
|
|
64
|
+
async function evmSend(privateKey, toAddress, amount, asset) {
|
|
65
|
+
const rpcUrl = TOKENS[asset]?.rpc || RPC.base;
|
|
66
|
+
const provider = new ethers.JsonRpcProvider(rpcUrl);
|
|
67
|
+
const wallet = new ethers.Wallet(privateKey, provider);
|
|
68
|
+
if (TOKENS[asset]) {
|
|
69
|
+
const token = new ethers.Contract(TOKENS[asset].address, ERC20_ABI, wallet);
|
|
70
|
+
const amt = ethers.parseUnits(String(amount), TOKENS[asset].decimals);
|
|
71
|
+
const tx = await token.transfer(toAddress, amt);
|
|
72
|
+
await tx.wait();
|
|
73
|
+
return tx.hash;
|
|
74
|
+
} else {
|
|
75
|
+
const tx = await wallet.sendTransaction({ to: toAddress, value: ethers.parseEther(String(amount)) });
|
|
76
|
+
await tx.wait();
|
|
77
|
+
return tx.hash;
|
|
18
78
|
}
|
|
19
|
-
return null;
|
|
20
79
|
}
|
|
21
80
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
81
|
+
// ── SOL SEND ───────────────────────────────────
|
|
82
|
+
async function solSend(privateKeyInput, toAddress, amount) {
|
|
83
|
+
let web3, bs58;
|
|
84
|
+
try {
|
|
85
|
+
web3 = require('@solana/web3.js');
|
|
86
|
+
bs58 = require('bs58');
|
|
87
|
+
} catch (e) {
|
|
88
|
+
throw new Error('Missing deps: npm i -g @solana/web3.js bs58');
|
|
89
|
+
}
|
|
90
|
+
const connection = new web3.Connection(web3.clusterApiUrl('mainnet-beta'), 'confirmed');
|
|
91
|
+
let secretKey;
|
|
92
|
+
if (privateKeyInput.startsWith('0x')) {
|
|
93
|
+
secretKey = Buffer.from(privateKeyInput.slice(2), 'hex');
|
|
94
|
+
} else {
|
|
95
|
+
secretKey = bs58.decode(privateKeyInput);
|
|
96
|
+
}
|
|
97
|
+
const keypair = web3.Keypair.fromSecretKey(secretKey);
|
|
98
|
+
const toPubkey = new web3.PublicKey(toAddress);
|
|
99
|
+
const lamports = Math.round(parseFloat(amount) * web3.LAMPORTS_PER_SOL);
|
|
100
|
+
const transaction = new web3.Transaction().add(
|
|
101
|
+
web3.SystemProgram.transfer({ fromPubkey: keypair.publicKey, toPubkey, lamports })
|
|
102
|
+
);
|
|
103
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
104
|
+
transaction.recentBlockhash = blockhash;
|
|
105
|
+
transaction.feePayer = keypair.publicKey;
|
|
106
|
+
return await web3.sendAndConfirmTransaction(connection, transaction, [keypair]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ── PROGRAM ────────────────────────────────────
|
|
110
|
+
program.name('terafab').description('Terafabpay AI — No-KYC Swap & Autonomous Agent Wallet').version('1.2.0');
|
|
111
|
+
|
|
112
|
+
program.command('status').description('Check network health').action(async () => {
|
|
113
|
+
try {
|
|
114
|
+
const d = await (await fetch(`${API_BASE}/v1/watcher`)).json();
|
|
115
|
+
console.log(`\nTerafabpay AI\n──────────────\nNetwork: ${d.healthy ? '🟢 OK' : '🔴 Issues'}\nAdvice: ${d.advice || '...'}`);
|
|
116
|
+
} catch (e) { console.error('❌ Offline.'); }
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
program.command('prices').description('Live BTC/SOL/ETH prices').action(async () => {
|
|
120
|
+
try {
|
|
121
|
+
const d = await (await fetch(`${API_BASE}/v1/feed`, { headers: { 'x-feed-token': loadVault().feedToken || '' } })).json();
|
|
122
|
+
if (d.prices) console.log(`\nBTC: $${d.prices.btc}\nSOL: $${d.prices.sol}\nETH: $${d.prices.eth}`);
|
|
123
|
+
} catch (e) { console.error('❌ Failed.'); }
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
program.command('assets').description('List supported assets').action(() => {
|
|
127
|
+
console.log('\nTerafabpay Supported Assets');
|
|
128
|
+
console.log('Fee: ~0.9% included in exchange rate | No separate TX | No KYC');
|
|
129
|
+
console.log('────────────────────────────────────────────────────────');
|
|
130
|
+
console.log('Asset Chain Route Auto-send');
|
|
131
|
+
console.log('────────────────────────────────────────────────────────');
|
|
132
|
+
Object.entries(ASSETS).forEach(([k, v]) => {
|
|
133
|
+
const auto = ['eth','usdterc20','sol'].includes(k) ? '⚡ on-chain' : '📋 payin addr';
|
|
134
|
+
const route = ['eth','usdterc20','sol'].includes(k) ? 'Base/Solana' : 'ChangeNOW V2';
|
|
135
|
+
console.log(`${k.padEnd(12)} ${v.chain.padEnd(12)} ${route.padEnd(13)} ${auto}`);
|
|
136
|
+
});
|
|
137
|
+
console.log('\n⚡ = CLI signs & sends on-chain automatically');
|
|
138
|
+
console.log('📋 = CLI creates order, you send to payin address');
|
|
139
|
+
console.log('\nAll assets swappable TO/FROM XMR (Monero) and each other.');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
program.command('quote')
|
|
143
|
+
.description('Get swap quote').option('-f, --from <a>', 'Source', 'sol').option('-t, --to <a>', 'Target', 'xmr').option('-a, --amount <n>', 'Amount', '0.1')
|
|
144
|
+
.action(async (o) => {
|
|
145
|
+
try {
|
|
146
|
+
const d = await (await fetch(`${API_BASE}/v1/swap/quote?from=${o.from}&to=${o.to}&amount=${o.amount}`)).json();
|
|
147
|
+
if (d.error) { console.error(`❌ ${d.error}`); return; }
|
|
148
|
+
console.log(`\nQuote\n──────────────\nFrom: ${o.amount} ${o.from.toUpperCase()}\nTo: ~${d.estimatedAmount} ${o.to.toUpperCase()}\nMin: ${d.minAmount} ${o.from.toUpperCase()}\nFee: ~0.9% included in rate (no separate fee TX)\nKYC: none`);
|
|
149
|
+
} catch (e) { console.error('❌ Failed.'); }
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
program.command('swap')
|
|
153
|
+
.description('Create swap order (manual payin)').option('-f, --from <a>', 'Source', 'sol').option('-t, --to <a>', 'Target', 'xmr')
|
|
154
|
+
.option('-a, --amount <n>', 'Amount', '0.1').requiredOption('-d, --dest <addr>', 'Destination address').option('-r, --refund <addr>', 'Refund address')
|
|
155
|
+
.action(async (o) => {
|
|
156
|
+
try {
|
|
157
|
+
const body = { from: o.from, to: o.to, amount: o.amount, address: o.dest };
|
|
158
|
+
if (o.refund) body.refundAddress = o.refund;
|
|
159
|
+
const d = await (await fetch(`${API_BASE}/v1/swap/create`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })).json();
|
|
160
|
+
if (d.error) { console.error(`❌ ${d.error}`); return; }
|
|
161
|
+
console.log(`\n✅ SWAP ORDER\n──────────────\nSend: ${o.amount} ${o.from.toUpperCase()}\nTo: ${d.payinAddress}\nExpected: ~${d.estimatedAmount} ${o.to.toUpperCase()}\nFee: ~0.9% included in rate — no separate fee TX\nOrder: ${d.orderId}\nTrack: ${d.trackUrl}`);
|
|
162
|
+
} catch (e) { console.error('❌ Failed.'); }
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
program.command('swap:auto')
|
|
166
|
+
.description('Autonomous swap — signs and sends on-chain (ETH/SOL only)')
|
|
167
|
+
.option('-f, --from <a>', 'eth / usdterc20 / sol', 'eth').option('-t, --to <a>', 'Target', 'xmr')
|
|
168
|
+
.option('-a, --amount <n>', 'Amount', '0.01').requiredOption('-d, --dest <addr>', 'Destination address').option('-r, --refund <addr>', 'Refund address')
|
|
169
|
+
.action(async (o) => {
|
|
170
|
+
const vault = loadVault();
|
|
171
|
+
const from = o.from.toLowerCase();
|
|
172
|
+
if (!['eth','usdterc20','sol'].includes(from)) { console.error(`❌ ${from} not supported for auto-send. Use 'terafab swap'.`); return; }
|
|
173
|
+
if (from === 'sol' && !vault.solKey) { console.error('❌ No SOL key. Run: terafab wallet:import --asset sol --key <KEY>'); return; }
|
|
174
|
+
if (from !== 'sol' && !vault.evmKey) { console.error('❌ No EVM key. Run: terafab wallet:import --asset evm --key <KEY>'); return; }
|
|
175
|
+
try {
|
|
176
|
+
console.log(`\n🔄 Creating order...`);
|
|
177
|
+
const body = { from, to: o.to, amount: o.amount, address: o.dest };
|
|
178
|
+
if (o.refund) body.refundAddress = o.refund;
|
|
179
|
+
const d = await (await fetch(`${API_BASE}/v1/swap/create`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })).json();
|
|
180
|
+
if (d.error) { console.error(`❌ ${d.error}`); return; }
|
|
181
|
+
console.log(`Order: ${d.orderId}\nPayin: ${d.payinAddress}`);
|
|
182
|
+
console.log(`\n⚡ Sending on-chain (only network gas applies, no swap fee TX)...`);
|
|
183
|
+
const txHash = from === 'sol'
|
|
184
|
+
? await solSend(vault.solKey, d.payinAddress, o.amount)
|
|
185
|
+
: await evmSend(vault.evmKey, d.payinAddress, o.amount, from);
|
|
186
|
+
console.log(`\n✅ DONE\n──────────────\nTX: ${txHash}\nOrder: ${d.orderId}\nTrack: ${d.trackUrl}`);
|
|
187
|
+
} catch (e) { console.error('❌ Error:', e.message); }
|
|
188
|
+
});
|
|
26
189
|
|
|
27
|
-
// --- BRIDGE OHNE TX ---
|
|
28
190
|
program.command('bridge')
|
|
29
|
-
.description('
|
|
30
|
-
.option('-f, --from <chain>', 'sol, eth, btc', 'sol')
|
|
31
|
-
.option('-a, --amount <n>', 'Amount to send', '0.1')
|
|
32
|
-
.requiredOption('-to, --address <addr>', 'Your XMR receiving address')
|
|
191
|
+
.description('Quick bridge to XMR').option('-f, --from <a>', 'Source', 'sol').option('-a, --amount <n>', 'Amount', '0.1').requiredOption('-to, --address <addr>', 'XMR address')
|
|
33
192
|
.action(async (o) => {
|
|
34
|
-
console.log(`⏳ Initializing bridge: ${o.amount} ${o.from.toUpperCase()} -> XMR...`);
|
|
35
193
|
try {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
const d = await res.json();
|
|
42
|
-
if (d.error) console.log(`\n❌ Error: ${d.error}`);
|
|
43
|
-
else {
|
|
44
|
-
console.log(`\n✅ BRIDGE ORDER CREATED`);
|
|
45
|
-
console.log(`--------------------------------------`);
|
|
46
|
-
console.log(`SEND EXACTLY: ${o.amount} ${o.from.toUpperCase()}`);
|
|
47
|
-
console.log(`TO ADDRESS: ${d.payinAddress}`);
|
|
48
|
-
console.log(`--------------------------------------`);
|
|
49
|
-
console.log(`ESTIMATED: ~${d.estimatedXmr} XMR`);
|
|
50
|
-
console.log(`ORDER ID: ${d.orderId}`);
|
|
51
|
-
console.log(`TRACKING: ${d.trackUrl}`);
|
|
52
|
-
}
|
|
53
|
-
} catch (e) { console.error('❌ Server connection failed.'); }
|
|
194
|
+
const d = await (await fetch(`${API_BASE}/v1/xmr/create`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ from: o.from, amount: o.amount, address: o.address }) })).json();
|
|
195
|
+
if (d.error) { console.error(`❌ ${d.error}`); return; }
|
|
196
|
+
console.log(`\n✅ XMR BRIDGE\n──────────────\nSend: ${o.amount} ${o.from.toUpperCase()}\nTo: ${d.payinAddress}\n~XMR: ${d.estimatedXmr}\nFee: ~0.9% included in rate — no separate fee TX\nOrder: ${d.orderId}`);
|
|
197
|
+
} catch (e) { console.error('❌ Failed.'); }
|
|
54
198
|
});
|
|
55
199
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
console.log(`Status: ${d.healthy ? '🟢' : '🔴'} | Advice: ${d.advice}`);
|
|
200
|
+
program.command('wallet:create').description('Generate new EVM wallet').option('--save', 'Save to vault').action((o) => {
|
|
201
|
+
const wallet = ethers.Wallet.createRandom();
|
|
202
|
+
console.log(`\n✅ EVM WALLET\n──────────────\nAddress: ${wallet.address}\nKey: ${wallet.privateKey}\nMnemonic: ${wallet.mnemonic?.phrase}`);
|
|
203
|
+
if (o.save) { const vault = loadVault(); vault.evmKey = wallet.privateKey; vault.evmAddress = wallet.address; saveVault(vault); console.log('✅ Saved.'); }
|
|
61
204
|
});
|
|
62
205
|
|
|
63
|
-
program.command('
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
206
|
+
program.command('wallet:import').description('Import private key').requiredOption('--asset <type>', 'evm or sol').requiredOption('--key <key>', 'Private key').action((o) => {
|
|
207
|
+
const vault = loadVault();
|
|
208
|
+
if (o.asset === 'evm') { const w = new ethers.Wallet(o.key); vault.evmKey = w.privateKey; vault.evmAddress = w.address; saveVault(vault); console.log(`✅ EVM imported: ${w.address}`); }
|
|
209
|
+
else if (o.asset === 'sol') { vault.solKey = o.key; saveVault(vault); console.log('✅ SOL key saved.'); }
|
|
210
|
+
else console.error('❌ Use: evm or sol');
|
|
67
211
|
});
|
|
68
212
|
|
|
69
|
-
program.command('wallet:
|
|
70
|
-
|
|
71
|
-
|
|
213
|
+
program.command('wallet:show').description('Show saved wallets').action(() => {
|
|
214
|
+
const v = loadVault();
|
|
215
|
+
console.log(`\nAgent Vault\n──────────────\nEVM: ${v.evmAddress || 'not set'}\nSOL: ${v.solKey ? 'set' : 'not set'}\nKey: ${v.agentKey ? 'set' : 'not set'}`);
|
|
72
216
|
});
|
|
73
217
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
fs.writeFileSync(VAULT_PATH, JSON.stringify({ k: key }), { mode: 0o600 });
|
|
77
|
-
console.log('✅ Key vaulted.');
|
|
218
|
+
program.command('auth').argument('<key>').description('Save agent key').action((key) => {
|
|
219
|
+
const vault = loadVault(); vault.agentKey = key; saveVault(vault); console.log('✅ Key saved.');
|
|
78
220
|
});
|
|
79
221
|
|
|
80
|
-
program.command('agent:prompt').argument('<prompt>').action(async (prompt) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
});
|
|
88
|
-
const d = await res.json();
|
|
89
|
-
console.log(d.inference || d.error);
|
|
222
|
+
program.command('agent:prompt').argument('<prompt>').description('Query Grok AI agent').action(async (prompt) => {
|
|
223
|
+
const vault = loadVault();
|
|
224
|
+
if (!vault.agentKey) { console.error('❌ Run: terafab auth <KEY>'); return; }
|
|
225
|
+
try {
|
|
226
|
+
const d = await (await fetch(`${API_BASE}/v1/agent`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt, agentKey: vault.agentKey }) })).json();
|
|
227
|
+
console.log(`\n${d.inference || d.error}`);
|
|
228
|
+
} catch (e) { console.error('❌ Failed.'); }
|
|
90
229
|
});
|
|
91
230
|
|
|
231
|
+
program.command('agent:swap')
|
|
232
|
+
.description('AI analysis + autonomous swap').option('-f, --from <a>', 'Source', 'eth').option('-t, --to <a>', 'Target', 'xmr')
|
|
233
|
+
.option('-a, --amount <n>', 'Amount', '0.01').requiredOption('-d, --dest <addr>', 'Destination address')
|
|
234
|
+
.action(async (o) => {
|
|
235
|
+
const vault = loadVault();
|
|
236
|
+
if (!vault.agentKey) { console.error('❌ Run: terafab auth <KEY>'); return; }
|
|
237
|
+
const from = o.from.toLowerCase();
|
|
238
|
+
const autoSend = ['eth','usdterc20','sol'].includes(from);
|
|
239
|
+
console.log(`\n🤖 Agent: ${o.amount} ${from.toUpperCase()} -> ${o.to.toUpperCase()}`);
|
|
240
|
+
try {
|
|
241
|
+
const ai = await (await fetch(`${API_BASE}/v1/agent`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: `Analyze: swap ${o.amount} ${from.toUpperCase()} to ${o.to.toUpperCase()} now?`, agentKey: vault.agentKey }) })).json();
|
|
242
|
+
console.log(`\n💬 ${ai.inference || 'No response'}`);
|
|
243
|
+
const q = await (await fetch(`${API_BASE}/v1/swap/quote?from=${from}&to=${o.to}&amount=${o.amount}`)).json();
|
|
244
|
+
if (q.error) { console.error(`❌ ${q.error}`); return; }
|
|
245
|
+
console.log(`📊 ~${q.estimatedAmount} ${o.to.toUpperCase()}`);
|
|
246
|
+
const s = await (await fetch(`${API_BASE}/v1/swap/create`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ from, to: o.to, amount: o.amount, address: o.dest }) })).json();
|
|
247
|
+
if (s.error) { console.error(`❌ ${s.error}`); return; }
|
|
248
|
+
if (autoSend) {
|
|
249
|
+
if (from === 'sol' && !vault.solKey) { console.error('❌ No SOL key.'); return; }
|
|
250
|
+
if (from !== 'sol' && !vault.evmKey) { console.error('❌ No EVM key.'); return; }
|
|
251
|
+
const txHash = from === 'sol' ? await solSend(vault.solKey, s.payinAddress, o.amount) : await evmSend(vault.evmKey, s.payinAddress, o.amount, from);
|
|
252
|
+
console.log(`\n✅ DONE\n──────────────\nTX: ${txHash}\nOrder: ${s.orderId}\nTrack: ${s.trackUrl}`);
|
|
253
|
+
} else {
|
|
254
|
+
console.log(`\n📋 MANUAL SEND\n──────────────\nSend: ${o.amount} ${from.toUpperCase()}\nTo: ${s.payinAddress}\nOrder: ${s.orderId}\nTrack: ${s.trackUrl}`);
|
|
255
|
+
}
|
|
256
|
+
} catch (e) { console.error('❌ Error:', e.message); }
|
|
257
|
+
});
|
|
258
|
+
|
|
92
259
|
program.parse();
|