@darksol/terminal 0.2.0 → 0.2.1

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.2.0",
3
+ "version": "0.2.1",
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/skill/SKILL.md ADDED
@@ -0,0 +1,177 @@
1
+ ---
2
+ name: darksol-terminal
3
+ description: "DARKSOL Terminal — unified CLI for trading, wallets, execution scripts, AI-powered market analysis, secure agent signing, and all DARKSOL services. Use when: (1) swapping/sniping tokens on Base/Ethereum/L2s, (2) managing encrypted wallets, (3) running automated trading scripts, (4) DCA strategies, (5) market intel lookups, (6) on-chain oracle/casino/cards, (7) natural language trading via LLM, (8) signing transactions securely for x402/contracts without exposing private keys."
4
+ ---
5
+
6
+ # DARKSOL Terminal
7
+
8
+ **All DARKSOL services. One terminal. Zero trust required. 🌑**
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install -g @darksol/terminal
14
+ ```
15
+
16
+ ## Quick Reference
17
+
18
+ ### Wallet Management
19
+ ```bash
20
+ darksol wallet create <name> # Create new wallet (AES-256-GCM encrypted)
21
+ darksol wallet import <name> # Import from private key
22
+ darksol wallet list # List all wallets
23
+ darksol wallet balance [name] # Check ETH + USDC balance
24
+ darksol wallet use <name> # Set active wallet
25
+ darksol wallet export [name] # Export details (password required for PK)
26
+ ```
27
+
28
+ ### Trading
29
+ ```bash
30
+ darksol trade swap -i ETH -o USDC -a 0.1 # Swap via Uniswap V3
31
+ darksol trade snipe <token> -a 0.05 # Fast buy with gas boost
32
+ darksol trade snipe <token> -a 0.05 -g 2.0 # Snipe with 2x gas priority
33
+ darksol trade watch # Monitor new pairs
34
+ ```
35
+
36
+ ### DCA (Dollar-Cost Averaging)
37
+ ```bash
38
+ darksol dca create # Interactive DCA order creation
39
+ darksol dca list # List active DCA orders
40
+ darksol dca run # Execute pending orders
41
+ darksol dca cancel <id> # Cancel an order
42
+ ```
43
+
44
+ ### AI Trading Assistant
45
+ ```bash
46
+ darksol ai chat # Interactive AI trading chat
47
+ darksol ai ask "buy 0.5 ETH of AERO" # Parse natural language trade intent
48
+ darksol ai strategy VIRTUAL -b 500 # DCA strategy recommendation
49
+ darksol ai analyze AERO # AI-powered token analysis
50
+ ```
51
+
52
+ ### Execution Scripts
53
+ ```bash
54
+ darksol script templates # List available templates
55
+ darksol script create # Create from template (buy, sell, limit-buy, stop-loss, etc.)
56
+ darksol script list # List saved scripts
57
+ darksol script run <name> # Execute (requires wallet password)
58
+ darksol script run <name> -p "pw" -y # Non-interactive (for automation/cron)
59
+ darksol script show <name> # View code + params
60
+ darksol script edit <name> # Edit params/wallet/chain
61
+ darksol script clone <name> <new> # Clone a script
62
+ darksol script delete <name> # Delete a script
63
+ ```
64
+
65
+ Script templates: `buy-token`, `sell-token`, `limit-buy`, `stop-loss`, `multi-buy`, `transfer`, `empty` (custom)
66
+
67
+ ### Market Intel
68
+ ```bash
69
+ darksol market top # Top movers on Base
70
+ darksol market top -c ethereum # Top movers on Ethereum
71
+ darksol market token VIRTUAL # Full token detail
72
+ darksol market compare ETH AERO VIRTUAL # Side-by-side comparison
73
+ ```
74
+
75
+ ### Secure Agent Signer (for OpenClaw / AI agents)
76
+ ```bash
77
+ darksol agent start <wallet> # Start signing proxy
78
+ darksol agent start <wallet> --max-value 0.5 --daily-limit 2.0
79
+ darksol agent docs # Full security documentation
80
+ ```
81
+
82
+ The agent signer creates a local HTTP server at `127.0.0.1:18790` that signs transactions without exposing the private key. AI agents authenticate with a one-time bearer token.
83
+
84
+ **Endpoints:**
85
+ - `GET /address` — wallet address
86
+ - `GET /balance` — ETH balance
87
+ - `POST /send` — sign + broadcast transaction
88
+ - `POST /sign-message` — sign EIP-191 message (x402)
89
+ - `POST /sign-typed-data` — sign EIP-712 typed data (x402)
90
+ - `GET /policy` — spending limits
91
+ - `GET /audit` — operation log
92
+
93
+ ### Oracle
94
+ ```bash
95
+ darksol oracle flip # Coin flip
96
+ darksol oracle dice 20 # Roll d20
97
+ darksol oracle number 1 100 # Random 1-100
98
+ darksol oracle shuffle a b c d # Shuffle list
99
+ ```
100
+
101
+ ### Casino
102
+ ```bash
103
+ darksol casino bet coin-flip heads # Place a bet
104
+ darksol casino tables # View games
105
+ darksol casino stats # House stats
106
+ darksol casino receipt <id> # Verify on-chain
107
+ ```
108
+
109
+ ### Prepaid Cards
110
+ ```bash
111
+ darksol cards catalog # Available providers
112
+ darksol cards order -p swype -a 50 # Order a card
113
+ darksol cards status <id> # Check order
114
+ ```
115
+
116
+ ### Builder Index
117
+ ```bash
118
+ darksol builders leaderboard # ERC-8021 builder rankings
119
+ darksol builders lookup <code> # Builder profile
120
+ darksol builders feed # Recent transactions
121
+ ```
122
+
123
+ ### Facilitator
124
+ ```bash
125
+ darksol facilitator health # Status
126
+ darksol facilitator verify <payment> # Verify off-chain
127
+ darksol facilitator settle <payment> # Settle on-chain (free)
128
+ ```
129
+
130
+ ### API Keys
131
+ ```bash
132
+ darksol keys list # Show all services + status
133
+ darksol keys add openai # Add OpenAI key
134
+ darksol keys add coingecko # Add CoinGecko Pro key
135
+ darksol keys add alchemy # Add Alchemy RPC key
136
+ darksol keys remove <service> # Remove a key
137
+ ```
138
+
139
+ Supported: `openai`, `anthropic`, `openrouter`, `ollama`, `coingecko`, `dexscreener`, `alchemy`, `infura`, `quicknode`, `oneinch`, `paraswap`
140
+
141
+ ### Configuration
142
+ ```bash
143
+ darksol config show # View all settings
144
+ darksol config set chain base # Set active chain
145
+ darksol config set slippage 1.0 # Set slippage %
146
+ darksol config rpc base https://... # Custom RPC endpoint
147
+ ```
148
+
149
+ ### Reference
150
+ ```bash
151
+ darksol tips # Trading + scripting tips
152
+ darksol tips --trading # Trading tips only
153
+ darksol networks # Chain reference table
154
+ darksol quickstart # Getting started guide
155
+ darksol lookup 0x... # Look up address on-chain
156
+ ```
157
+
158
+ ## Supported Chains
159
+ - **Base** (default) — chain ID 8453
160
+ - **Ethereum** — chain ID 1
161
+ - **Polygon** — chain ID 137
162
+ - **Arbitrum** — chain ID 42161
163
+ - **Optimism** — chain ID 10
164
+
165
+ ## Agent Integration Notes
166
+
167
+ - All commands work non-interactively with flags (`-p`, `-y`, `--key`, etc.)
168
+ - Set `darksol config set output json` for programmatic JSON responses
169
+ - Scripts can be executed via cron: `darksol script run my-dca -p "pass" -y`
170
+ - The agent signer is the recommended way to give AI agents wallet access
171
+ - Helper functions available at `@darksol/terminal/src/utils/helpers.js`
172
+
173
+ ## Security
174
+ - Private keys encrypted with AES-256-GCM + scrypt KDF
175
+ - Agent signer: PK never exposed, loopback-only, bearer auth, spending limits
176
+ - Dangerous contract calls (transferOwnership, selfdestruct) blocked by default
177
+ - Full audit logging on all signing operations
package/src/cli.js CHANGED
@@ -18,6 +18,7 @@ import { showTradingTips, showScriptTips, showNetworkReference, showQuickStart,
18
18
  import { addKey, removeKey, listKeys } from './config/keys.js';
19
19
  import { parseIntent, startChat, adviseStrategy, analyzeToken } from './llm/intent.js';
20
20
  import { startAgentSigner, showAgentDocs } from './wallet/agent-signer.js';
21
+ import { listSkills, installSkill, skillInfo, uninstallSkill } from './services/skills.js';
21
22
 
22
23
  export function cli(argv) {
23
24
  const program = new Command();
@@ -385,6 +386,33 @@ export function cli(argv) {
385
386
  .description('Show agent signer security documentation')
386
387
  .action(() => showAgentDocs());
387
388
 
389
+ // ═══════════════════════════════════════
390
+ // SKILLS COMMANDS
391
+ // ═══════════════════════════════════════
392
+ const skills = program
393
+ .command('skills')
394
+ .description('DARKSOL skills directory — install agent skills');
395
+
396
+ skills
397
+ .command('list')
398
+ .description('List all available DARKSOL skills')
399
+ .action(() => listSkills());
400
+
401
+ skills
402
+ .command('install <name>')
403
+ .description('Install a skill to OpenClaw')
404
+ .action((name) => installSkill(name));
405
+
406
+ skills
407
+ .command('info <name>')
408
+ .description('Show skill details')
409
+ .action((name) => skillInfo(name));
410
+
411
+ skills
412
+ .command('uninstall <name>')
413
+ .description('Uninstall a skill')
414
+ .action((name) => uninstallSkill(name));
415
+
388
416
  // ═══════════════════════════════════════
389
417
  // TIPS & REFERENCE COMMANDS
390
418
  // ═══════════════════════════════════════
@@ -572,6 +600,7 @@ export function cli(argv) {
572
600
  ['cards', 'Prepaid Visa/MC cards'],
573
601
  ['builders', 'ERC-8021 builder index'],
574
602
  ['facilitator', 'x402 payment facilitator'],
603
+ ['skills', 'Agent skill directory & install'],
575
604
  ['config', 'Terminal configuration'],
576
605
  ['tips', 'Trading & scripting tips'],
577
606
  ['networks', 'Chain reference & explorers'],
@@ -0,0 +1,229 @@
1
+ import fetch from 'node-fetch';
2
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, cpSync } from 'fs';
3
+ import { join, dirname } from 'path';
4
+ import { homedir } from 'os';
5
+ import { fileURLToPath } from 'url';
6
+ import { theme } from '../ui/theme.js';
7
+ import { spinner, kvDisplay, success, error, warn, info, table } from '../ui/components.js';
8
+ import { showSection } from '../ui/banner.js';
9
+
10
+ const OPENCLAW_SKILLS_DIR = join(homedir(), '.openclaw', 'skills');
11
+
12
+ // ──────────────────────────────────────────────────
13
+ // DARKSOL SKILL CATALOG
14
+ // ──────────────────────────────────────────────────
15
+
16
+ const SKILL_CATALOG = [
17
+ {
18
+ name: 'darksol-terminal',
19
+ description: 'DARKSOL Terminal — unified CLI for trading, wallets, scripts, AI assistant, agent signing',
20
+ version: '0.2.0',
21
+ source: 'local', // bundled with the package
22
+ category: 'trading',
23
+ installed: () => existsSync(join(OPENCLAW_SKILLS_DIR, 'darksol-terminal', 'SKILL.md')),
24
+ },
25
+ {
26
+ name: 'darksol-facilitator',
27
+ description: 'Free on-chain x402 payment facilitator — verify and settle micropayments',
28
+ version: '1.0.0',
29
+ source: 'url',
30
+ url: 'https://facilitator.darksol.net/skill/SKILL.md',
31
+ category: 'payments',
32
+ installed: () => existsSync(join(OPENCLAW_SKILLS_DIR, 'darksol-facilitator', 'SKILL.md')),
33
+ },
34
+ {
35
+ name: 'darksol-prepaid-cards',
36
+ description: 'Crypto → prepaid Visa/MC cards, no KYC, agent-native REST API',
37
+ version: '1.0.0',
38
+ source: 'url',
39
+ url: 'https://acp.darksol.net/dist/darksol-prepaid-cards.skill',
40
+ skillMdUrl: 'https://acp.darksol.net/cards/skill/SKILL.md',
41
+ category: 'payments',
42
+ installed: () => existsSync(join(OPENCLAW_SKILLS_DIR, 'darksol-prepaid-cards', 'SKILL.md')),
43
+ },
44
+ {
45
+ name: 'random-oracle',
46
+ description: 'On-chain random oracle — verifiable randomness via x402',
47
+ version: '1.0.0',
48
+ source: 'url',
49
+ url: 'https://acp.darksol.net/oracle/skill/SKILL.md',
50
+ category: 'oracle',
51
+ installed: () => existsSync(join(OPENCLAW_SKILLS_DIR, 'random-oracle', 'SKILL.md')),
52
+ },
53
+ {
54
+ name: 'the-clawsino',
55
+ description: 'On-chain agent casino — coin flip, dice, hi-lo, slots via x402',
56
+ version: '1.0.0',
57
+ source: 'url',
58
+ url: 'https://casino.darksol.net/skill/SKILL.md',
59
+ category: 'gaming',
60
+ installed: () => existsSync(join(OPENCLAW_SKILLS_DIR, 'the-clawsino', 'SKILL.md')),
61
+ },
62
+ ];
63
+
64
+ // ──────────────────────────────────────────────────
65
+ // LIST SKILLS
66
+ // ──────────────────────────────────────────────────
67
+
68
+ export function listSkills() {
69
+ showSection('DARKSOL SKILLS DIRECTORY');
70
+
71
+ const rows = SKILL_CATALOG.map(s => {
72
+ const isInstalled = s.installed();
73
+ return [
74
+ isInstalled ? theme.success('● ') + theme.gold(s.name) : theme.dim('○ ') + s.name,
75
+ s.description.slice(0, 55) + (s.description.length > 55 ? '...' : ''),
76
+ s.version,
77
+ isInstalled ? theme.success('Installed') : theme.dim('Available'),
78
+ ];
79
+ });
80
+
81
+ table(['Skill', 'Description', 'Version', 'Status'], rows);
82
+
83
+ console.log('');
84
+ info('Install: darksol skills install <name>');
85
+ info('Info: darksol skills info <name>');
86
+ info('Skills install to: ' + OPENCLAW_SKILLS_DIR);
87
+ }
88
+
89
+ // ──────────────────────────────────────────────────
90
+ // INSTALL SKILL
91
+ // ──────────────────────────────────────────────────
92
+
93
+ export async function installSkill(name) {
94
+ const skill = SKILL_CATALOG.find(s => s.name === name);
95
+
96
+ if (!skill) {
97
+ error(`Unknown skill: ${name}`);
98
+ info('Available: ' + SKILL_CATALOG.map(s => s.name).join(', '));
99
+ return;
100
+ }
101
+
102
+ if (skill.installed()) {
103
+ warn(`${name} is already installed`);
104
+ const inquirer = (await import('inquirer')).default;
105
+ const { reinstall } = await inquirer.prompt([{
106
+ type: 'confirm',
107
+ name: 'reinstall',
108
+ message: theme.gold('Reinstall / update?'),
109
+ default: false,
110
+ }]);
111
+ if (!reinstall) return;
112
+ }
113
+
114
+ const spin = spinner(`Installing ${name}...`).start();
115
+
116
+ try {
117
+ const targetDir = join(OPENCLAW_SKILLS_DIR, name);
118
+ mkdirSync(targetDir, { recursive: true });
119
+
120
+ if (skill.source === 'local') {
121
+ // Copy from the npm package's bundled skill directory
122
+ const __dirname = dirname(fileURLToPath(import.meta.url));
123
+ const bundledSkillDir = join(__dirname, '..', '..', 'skill');
124
+
125
+ if (existsSync(join(bundledSkillDir, 'SKILL.md'))) {
126
+ const skillContent = readFileSync(join(bundledSkillDir, 'SKILL.md'), 'utf8');
127
+ writeFileSync(join(targetDir, 'SKILL.md'), skillContent);
128
+ } else {
129
+ throw new Error('Bundled SKILL.md not found in package');
130
+ }
131
+ } else if (skill.source === 'url') {
132
+ // Fetch from remote
133
+ const url = skill.skillMdUrl || skill.url;
134
+ const resp = await fetch(url);
135
+ if (!resp.ok) throw new Error(`Failed to fetch: ${resp.status}`);
136
+ const content = await resp.text();
137
+
138
+ // Handle .skill files (may be a zip or just SKILL.md content)
139
+ if (url.endsWith('.skill')) {
140
+ // .skill files are typically just the SKILL.md content
141
+ writeFileSync(join(targetDir, 'SKILL.md'), content);
142
+ } else {
143
+ writeFileSync(join(targetDir, 'SKILL.md'), content);
144
+ }
145
+ }
146
+
147
+ spin.succeed(`${name} installed`);
148
+
149
+ showSection(`INSTALLED: ${name}`);
150
+ kvDisplay([
151
+ ['Name', name],
152
+ ['Version', skill.version],
153
+ ['Category', skill.category],
154
+ ['Location', targetDir],
155
+ ]);
156
+ console.log('');
157
+ success('Skill is now available to OpenClaw and other agents');
158
+
159
+ } catch (err) {
160
+ spin.fail(`Failed to install ${name}`);
161
+ error(err.message);
162
+ }
163
+ }
164
+
165
+ // ──────────────────────────────────────────────────
166
+ // SKILL INFO
167
+ // ──────────────────────────────────────────────────
168
+
169
+ export async function skillInfo(name) {
170
+ const skill = SKILL_CATALOG.find(s => s.name === name);
171
+
172
+ if (!skill) {
173
+ error(`Unknown skill: ${name}`);
174
+ return;
175
+ }
176
+
177
+ const isInstalled = skill.installed();
178
+
179
+ showSection(`SKILL: ${name}`);
180
+ kvDisplay([
181
+ ['Name', skill.name],
182
+ ['Description', skill.description],
183
+ ['Version', skill.version],
184
+ ['Category', skill.category],
185
+ ['Status', isInstalled ? theme.success('Installed') : theme.dim('Not installed')],
186
+ ['Source', skill.source === 'local' ? 'Bundled with @darksol/terminal' : skill.url || 'Remote'],
187
+ ]);
188
+
189
+ if (isInstalled) {
190
+ const skillPath = join(OPENCLAW_SKILLS_DIR, name, 'SKILL.md');
191
+ console.log('');
192
+ console.log(theme.dim(` Location: ${skillPath}`));
193
+ }
194
+
195
+ console.log('');
196
+ if (!isInstalled) {
197
+ info(`Install: darksol skills install ${name}`);
198
+ }
199
+ }
200
+
201
+ // ──────────────────────────────────────────────────
202
+ // UNINSTALL SKILL
203
+ // ──────────────────────────────────────────────────
204
+
205
+ export async function uninstallSkill(name) {
206
+ const skill = SKILL_CATALOG.find(s => s.name === name);
207
+ const skillDir = join(OPENCLAW_SKILLS_DIR, name);
208
+
209
+ if (!existsSync(skillDir)) {
210
+ error(`${name} is not installed`);
211
+ return;
212
+ }
213
+
214
+ const inquirer = (await import('inquirer')).default;
215
+ const { confirm } = await inquirer.prompt([{
216
+ type: 'confirm',
217
+ name: 'confirm',
218
+ message: theme.accent(`Uninstall ${name}?`),
219
+ default: false,
220
+ }]);
221
+
222
+ if (!confirm) return;
223
+
224
+ const { rmSync } = await import('fs');
225
+ rmSync(skillDir, { recursive: true, force: true });
226
+ success(`${name} uninstalled`);
227
+ }
228
+
229
+ export { SKILL_CATALOG, OPENCLAW_SKILLS_DIR };
package/src/ui/banner.js CHANGED
@@ -26,7 +26,7 @@ export function showBanner(opts = {}) {
26
26
  );
27
27
  console.log(
28
28
  theme.dim(' ║ ') +
29
- theme.subtle(' v0.2.0') +
29
+ theme.subtle(' v0.2.1') +
30
30
  theme.dim(' ') +
31
31
  theme.gold('🌑') +
32
32
  theme.dim(' ║')
@@ -44,7 +44,7 @@ export function showBanner(opts = {}) {
44
44
 
45
45
  export function showMiniBanner() {
46
46
  console.log('');
47
- console.log(theme.gold.bold(' 🌑 DARKSOL TERMINAL') + theme.dim(' v0.2.0'));
47
+ console.log(theme.gold.bold(' 🌑 DARKSOL TERMINAL') + theme.dim(' v0.2.1'));
48
48
  console.log(theme.dim(' ─────────────────────────────'));
49
49
  console.log('');
50
50
  }
@@ -60,3 +60,4 @@ export function showDivider() {
60
60
  }
61
61
 
62
62
 
63
+