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.
Files changed (2) hide show
  1. package/package.json +13 -6
  2. package/terafab.js +228 -61
package/package.json CHANGED
@@ -1,13 +1,20 @@
1
1
  {
2
2
  "name": "terafab-cli",
3
- "version": "1.1.6",
4
- "description": "Official CLI for Terafabpay - Swap & Monero Bridge",
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
- "terafab": "terafab.js"
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
- function getVaultKey() {
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
- const config = JSON.parse(fs.readFileSync(VAULT_PATH, 'utf8'));
16
- return config.k;
17
- } catch (e) { return null; }
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
- program
23
- .name('terafab')
24
- .description('Terafabpay CLI - Swap & Bridge Tools')
25
- .version('1.1.5');
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('Start a no-KYC swap to Monero (No TX required)')
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 res = await fetch(`${API_BASE}/v1/xmr/create`, {
37
- method: 'POST',
38
- headers: { 'Content-Type': 'application/json' },
39
- body: JSON.stringify({ from: o.from, amount: o.amount, address: o.address })
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
- // --- PUBLIC TOOLS ---
57
- program.command('status').action(async () => {
58
- const res = await fetch(`${API_BASE}/v1/watcher`);
59
- const d = await res.json();
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('xmr:quote').option('-f, --from <c>', 'sol').option('-a, --amount <n>', '0.1').action(async (o) => {
64
- const res = await fetch(`${API_BASE}/v1/xmr/quote?from=${o.from}&amount=${o.amount}`);
65
- const d = await res.json();
66
- console.log(d.error ? `❌ ${d.error}` : `💎 Estimate: ~${d.estimatedAmount} XMR`);
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:create').action(() => {
70
- const w = ethers.Wallet.createRandom();
71
- console.log(`✅ Address: ${w.address}\n🔑 Key: ${w.privateKey}`);
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
- // --- AI & TRAINING (Auth required) ---
75
- program.command('auth').argument('<key>').action((key) => {
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
- const key = getVaultKey();
82
- if (!key) { console.log('❌ Inference requires Training-TX.'); return; }
83
- const res = await fetch(`${API_BASE}/v1/inference`, {
84
- method: 'POST',
85
- headers: { 'Content-Type': 'application/json' },
86
- body: JSON.stringify({ prompt, txHash: key })
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();