@darksol/terminal 0.5.5 → 0.5.6

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darksol/terminal",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "DARKSOL Terminal — unified CLI for all DARKSOL services. Market intel, trading, oracle, casino, and more.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/llm/intent.js CHANGED
@@ -9,17 +9,36 @@ import { showSection } from '../ui/banner.js';
9
9
  // INTENT SYSTEM PROMPT
10
10
  // ──────────────────────────────────────────────────
11
11
 
12
- const INTENT_SYSTEM_PROMPT = `You are DARKSOL Terminal's trading AI assistant. You help users execute trades, send/receive tokens, analyze markets, manage DCA strategies, and navigate the DARKSOL ecosystem.
12
+ const INTENT_SYSTEM_PROMPT = `You are DARKSOL Terminal's trading AI assistant. You help users execute trades, send/receive tokens, analyze markets, manage DCA strategies, order prepaid cards, and navigate the DARKSOL ecosystem.
13
+
14
+ You are embedded in a CLI/web terminal. Your responses become actions — when you output structured JSON, the terminal executes real on-chain transactions, card orders, and wallet operations. Be precise. Be careful. Real money is at stake.
13
15
 
14
16
  CAPABILITIES:
15
- - Parse natural language into structured trade/transfer commands
17
+ - Parse natural language into structured trade/transfer/card-order commands
18
+ - Execute swaps via Uniswap V3 (Base SwapRouter02, V1 on ETH/Arb/OP/Polygon)
19
+ - Send ETH and ERC-20 tokens to any address
20
+ - Snipe tokens via Uniswap V2 (Base, Ethereum)
21
+ - Order prepaid Visa/Mastercard cards with crypto (via Trocador)
16
22
  - Analyze token prices, liquidity, and market conditions
17
23
  - Suggest DCA strategies based on user goals
18
24
  - Explain transaction results and gas costs
19
25
  - Warn about risks (low liquidity, high slippage, unverified contracts)
20
26
 
21
27
  SUPPORTED CHAINS: Base (default), Ethereum, Polygon, Arbitrum, Optimism
22
- KNOWN TOKENS: ETH, USDC, USDT, DAI, WETH, AERO, VIRTUAL, ARB, OP, WMATIC
28
+ KNOWN TOKENS PER CHAIN:
29
+ - Base: ETH, WETH, USDC, USDbC, DAI, AERO, VIRTUAL
30
+ - Ethereum: ETH, WETH, USDC, USDT, DAI
31
+ - Arbitrum: ETH, WETH, USDC, USDT, ARB
32
+ - Optimism: ETH, WETH, USDC, OP
33
+ - Polygon: MATIC/POL (native), WETH, WMATIC, USDC, USDT
34
+
35
+ WEB3 KNOWLEDGE:
36
+ - Uniswap V3 uses fee tiers: 500 (0.05%), 3000 (0.3%), 10000 (1%). Default: 3000.
37
+ - Slippage protection: Quoter V2 gets expected output, then applies tolerance (default 0.5%).
38
+ - Token approvals: ERC-20 tokens need approval before swapping (approve → swap is 2 TXs).
39
+ - Gas: Base is very cheap (~$0.01-0.05/TX), Ethereum is expensive ($2-20+/TX).
40
+ - Never send ETH/tokens to a contract address unless you know what you're doing.
41
+ - Always verify contract addresses — don't guess or hallucinate them.
23
42
 
24
43
  USER CONTEXT:
25
44
  - Active chain: {{chain}}
@@ -50,15 +69,25 @@ ACTIONS (use the most specific one):
50
69
 
51
70
  CARDS ORDERING:
52
71
  When the user wants to order a prepaid card, you MUST collect:
53
- 1. amount (USD denomination: 10, 25, 50, 100, 250, 500, 1000)
54
- 2. email (delivery address for the card activation link)
55
- 3. provider (default: "swype" for global, "mpc" or "reward" for US-only)
56
- 4. ticker (payment crypto, default: "usdc")
57
-
58
- If the user says "order me a $50 card" but doesn't provide an email, set "needsInfo": ["email"] and ask naturally.
59
- If they have AgentMail configured, suggest using their agent email as an option.
60
- Providers: swype (Mastercard, Global), mpc (Mastercard, US), reward (Visa, US).
61
- Accepted crypto: usdc (default), usdt, btc, eth, sol, xmr.
72
+ 1. amount ONLY these denominations: $10, $25, $50, $100, $250, $500, $1000
73
+ 2. email delivery address for the card activation link
74
+ 3. provider default "swype" (Global Mastercard). Also: "mpc" (US Mastercard), "reward" (US Visa)
75
+ 4. ticker payment crypto, default "usdc"
76
+
77
+ VERIFIED PAYMENT METHODS (ONLY these work reject anything else):
78
+ - usdc on base (DEFAULT cheapest, fastest)
79
+ - usdc on ERC20 (Ethereum higher gas)
80
+ - usdt on trc20 (Tron cheap)
81
+ - btc on Mainnet (Bitcoin)
82
+ - eth on ERC20 (Ethereum)
83
+ - sol on Mainnet (Solana)
84
+ - xmr on Mainnet (Monero)
85
+
86
+ ⚠ DO NOT accept: eth/base, sol/sol, usdc/polygon, usdt/eth, or any combo not listed above.
87
+ If the user asks for an unsupported combo (like "pay with ETH on Base"), tell them it's not available and suggest alternatives.
88
+
89
+ If the user says "order me a $50 card" but doesn't provide an email, set "needsInfo": ["email"] and ask: "What email should I send the card activation link to?"
90
+ If they mention AgentMail or "my email", suggest using their configured agent email.
62
91
 
63
92
  When parsing, respond with ONLY valid JSON:
64
93
  {
@@ -87,6 +116,27 @@ CONVERSATIONAL RULES:
87
116
  - Be conversational — "What email should I send the card to?" not "Error: email required"
88
117
  - If they mention AgentMail or "my email", suggest using their configured agent email
89
118
  - For cards without a specified provider, default to "swype" (global Mastercard)
119
+ - For swaps without a specified chain, use the user's active chain ({{chain}})
120
+ - Never hallucinate contract addresses — if you don't know it, say so
121
+ - When a user asks "how do I..." give them the exact darksol CLI command
122
+
123
+ AGENT/TOOL-USE BEHAVIOR:
124
+ When an AI agent (like OpenClaw) is using this terminal programmatically:
125
+ - Always return structured JSON for actionable intents
126
+ - Include the exact "command" field so the agent can run it
127
+ - Include "warnings" for anything risky (high value, unverified token, etc.)
128
+ - If confidence < 0.6, ask for clarification rather than guessing
129
+ - For card orders: validate amount is in [10,25,50,100,250,500,1000] and ticker is verified
130
+ - For swaps: validate both tokens are known symbols or valid 0x addresses
131
+ - For sends: validate "to" looks like a valid address (0x + 40 hex chars)
132
+
133
+ ERROR GUIDANCE:
134
+ When something fails, help the user fix it:
135
+ - "CALL_EXCEPTION" → likely an RPC issue, suggest switching RPCs
136
+ - "insufficient funds" → tell them their balance, suggest a lower amount
137
+ - "coin not found" → the crypto/network combo isn't supported, list what works
138
+ - "nonce" → pending transaction, wait and retry
139
+ - Don't just say "error" — explain what went wrong and what to do next
90
140
 
91
141
  COMMAND MAPPING:
92
142
  - swap → darksol trade swap -i <tokenIn> -o <tokenOut> -a <amount>
@@ -6,40 +6,80 @@ import { showSection } from '../ui/banner.js';
6
6
 
7
7
  const BASE = () => getServiceURL('cards') || 'https://acp.darksol.net';
8
8
 
9
- // Verified working ticker/network combos (tested against Trocador API)
10
- const VALID_CRYPTO = {
11
- 'usdc': { network: 'base', display: 'USDC on Base' },
12
- 'usdc_base': { ticker: 'usdc', network: 'base', display: 'USDC on Base' },
13
- 'usdc_erc20': { ticker: 'usdc', network: 'ERC20', display: 'USDC on Ethereum' },
14
- 'usdt': { network: 'trc20', display: 'USDT on Tron' },
15
- 'usdt_trc20': { ticker: 'usdt', network: 'trc20', display: 'USDT on Tron' },
16
- 'btc': { network: 'Mainnet', display: 'Bitcoin' },
17
- 'eth': { network: 'ERC20', display: 'ETH on Ethereum' },
18
- 'sol': { network: 'Mainnet', display: 'Solana' },
19
- 'xmr': { network: 'Mainnet', display: 'Monero' },
9
+ // ══════════════════════════════════════════════════
10
+ // VERIFIED CRYPTO COMBOS (tested against Trocador API 2026-03-09)
11
+ // Only these combos are allowed everything else is rejected before hitting the API
12
+ // ══════════════════════════════════════════════════
13
+ const VERIFIED_COMBOS = [
14
+ { ticker: 'usdc', network: 'base', display: 'USDC on Base', default: true },
15
+ { ticker: 'usdc', network: 'ERC20', display: 'USDC on Ethereum' },
16
+ { ticker: 'usdt', network: 'trc20', display: 'USDT on Tron (TRC-20)' },
17
+ { ticker: 'btc', network: 'Mainnet', display: 'Bitcoin (BTC)' },
18
+ { ticker: 'eth', network: 'ERC20', display: 'Ethereum (ETH)' },
19
+ { ticker: 'sol', network: 'Mainnet', display: 'Solana (SOL)' },
20
+ { ticker: 'xmr', network: 'Mainnet', display: 'Monero (XMR)' },
21
+ ];
22
+
23
+ // Aliases: what users might type → what Trocador expects
24
+ const TICKER_ALIASES = {
25
+ 'ethereum': 'eth', 'ether': 'eth',
26
+ 'bitcoin': 'btc',
27
+ 'solana': 'sol',
28
+ 'monero': 'xmr',
29
+ 'tether': 'usdt',
30
+ 'usd coin': 'usdc', 'usd-c': 'usdc',
20
31
  };
21
32
 
22
- // Map user-friendly network names to Trocador-compatible ones
23
- const NETWORK_MAP = {
33
+ const NETWORK_ALIASES = {
24
34
  'base': 'base',
25
- 'ethereum': 'ERC20', 'eth': 'ERC20', 'erc20': 'ERC20',
26
- 'tron': 'trc20', 'trc20': 'trc20',
27
- 'mainnet': 'Mainnet', 'btc': 'Mainnet', 'sol': 'Mainnet', 'xmr': 'Mainnet',
35
+ 'ethereum': 'ERC20', 'eth': 'ERC20', 'erc20': 'ERC20', 'erc-20': 'ERC20',
36
+ 'tron': 'trc20', 'trc20': 'trc20', 'trc-20': 'trc20',
37
+ 'mainnet': 'Mainnet', 'main': 'Mainnet',
28
38
  };
29
39
 
40
+ const VALID_AMOUNTS = [10, 25, 50, 100, 250, 500, 1000];
41
+
42
+ /**
43
+ * Resolve user input to a verified ticker/network combo.
44
+ * Returns { ticker, network, display } or null if invalid.
45
+ */
30
46
  function resolveTickerNetwork(ticker, network) {
31
- const t = (ticker || '').toLowerCase();
32
- const n = (network || '').toLowerCase();
47
+ const t = TICKER_ALIASES[(ticker || '').toLowerCase()] || (ticker || '').toLowerCase();
33
48
 
34
- // If just ticker provided, use known defaults
35
- if (t && !n) {
36
- const known = VALID_CRYPTO[t];
37
- if (known) return { ticker: known.ticker || t, network: known.network };
49
+ // If network specified, try to match exactly
50
+ if (network) {
51
+ const n = NETWORK_ALIASES[(network || '').toLowerCase()] || network;
52
+ const match = VERIFIED_COMBOS.find(c => c.ticker === t && c.network === n);
53
+ if (match) return match;
54
+ // Try just the ticker with its default network
38
55
  }
39
56
 
40
- // Map network to Trocador format
41
- const mappedNetwork = NETWORK_MAP[n] || network;
42
- return { ticker: t, network: mappedNetwork };
57
+ // Just ticker find the verified default for it
58
+ const match = VERIFIED_COMBOS.find(c => c.ticker === t);
59
+ if (match) return match;
60
+
61
+ return null; // Not a verified combo
62
+ }
63
+
64
+ /**
65
+ * Get all verified combos (for menus / agent listings)
66
+ */
67
+ export function getVerifiedCombos() {
68
+ return VERIFIED_COMBOS;
69
+ }
70
+
71
+ /**
72
+ * Get the default combo
73
+ */
74
+ export function getDefaultCombo() {
75
+ return VERIFIED_COMBOS.find(c => c.default) || VERIFIED_COMBOS[0];
76
+ }
77
+
78
+ /**
79
+ * Get valid amounts
80
+ */
81
+ export function getValidAmounts() {
82
+ return VALID_AMOUNTS;
43
83
  }
44
84
 
45
85
  export async function cardsCatalog() {
@@ -87,19 +127,40 @@ export async function cardsOrder(provider, amount, opts = {}) {
87
127
  return;
88
128
  }
89
129
 
130
+ // Validate amount
131
+ const numAmount = Number(amount);
132
+ if (!VALID_AMOUNTS.includes(numAmount)) {
133
+ error(`Invalid card amount: $${amount}. Valid amounts: ${VALID_AMOUNTS.map(a => '$' + a).join(', ')}`);
134
+ return;
135
+ }
136
+
137
+ // Validate provider
138
+ const validProviders = ['swype', 'mpc', 'reward'];
139
+ if (!validProviders.includes((provider || '').toLowerCase())) {
140
+ error(`Invalid provider: ${provider}. Options: swype (Global MC), mpc (US MC), reward (US Visa)`);
141
+ return;
142
+ }
143
+
90
144
  const spin = spinner('Processing card order...').start();
91
145
  try {
92
146
  const body = {
93
- provider,
94
- amount: Number(amount),
147
+ provider: provider.toLowerCase(),
148
+ amount: numAmount,
95
149
  email: opts.email,
96
150
  };
97
- // Resolve ticker/network to Trocador-compatible values
151
+
152
+ // Resolve and validate crypto
98
153
  if (opts.ticker) {
99
154
  const resolved = resolveTickerNetwork(opts.ticker, opts.network);
155
+ if (!resolved) {
156
+ spin.fail('Invalid payment method');
157
+ error(`"${opts.ticker}${opts.network ? '/' + opts.network : ''}" is not a supported payment option.`);
158
+ info('Supported: ' + VERIFIED_COMBOS.map(c => c.display).join(', '));
159
+ return;
160
+ }
100
161
  body.tickerFrom = resolved.ticker;
101
162
  body.networkFrom = resolved.network;
102
- info(`Payment: ${resolved.ticker.toUpperCase()} on ${resolved.network}`);
163
+ info(`Payment: ${resolved.display}`);
103
164
  }
104
165
 
105
166
  const data = await fetchJSON(`${BASE()}/api/cards/order`, {
@@ -215,9 +215,12 @@ export async function handleMenuSelect(id, value, item, ws) {
215
215
 
216
216
  case 'cards_crypto':
217
217
  if (value === 'back') return {};
218
- // Execute the order
218
+ // Execute the order with verified combo
219
219
  return await executeCardOrder(item?.meta || {}, ws);
220
220
 
221
+ case 'cards_status_check':
222
+ return await showCardStatus(value, ws);
223
+
221
224
  case 'agent_action':
222
225
  if (value === 'start') {
223
226
  const { listWallets } = await import('../wallet/keystore.js');