black-edge-cli 1.0.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/README.md +178 -0
- package/index.js +425 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# ⚡ Black Edge CLI
|
|
2
|
+
|
|
3
|
+
> **Institutional-grade HFT terminal for prediction market arbitrage**
|
|
4
|
+
|
|
5
|
+
The command-line interface for Black Edge — stream real-time trading signals powered by a 5-agent AI Council directly to your terminal.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
█████╗ ██╗ █████╗ █████╗ ██╗ ██╗ ███████╗██████╗ ██████╗ ███████╗
|
|
9
|
+
██╔══██╗██║ ██╔══██╗██╔══██╗██║ ██╔╝ ██╔════╝██╔══██╗██╔════╝ ██╔════╝
|
|
10
|
+
███████║██║ ███████║██║ ╚═╝█████═╝ █████╗ ██║ ██║██║ ██╗ █████╗
|
|
11
|
+
██╔══██║██║ ██╔══██║██║ ██╗██╔═██╗ ██╔══╝ ██║ ██║██║ ╚██╗██╔══╝
|
|
12
|
+
██║ ██║███████╗██║ ██║╚█████╔╝██║ ╚██╗ ███████╗██████╔╝╚██████╔╝███████╗
|
|
13
|
+
╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚════╝ ╚═╝ ╚═╝ ╚══════╝╚═════╝ ╚═════╝ ╚══════╝
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🚀 Quick Start
|
|
19
|
+
|
|
20
|
+
### Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g black-edge-cli
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
black-edge start
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
On first run, you'll be guided through:
|
|
33
|
+
1. **API Key** — Enter your Black Edge API key (`be_live_***`)
|
|
34
|
+
2. **Credit Check** — Verify your remaining API credits
|
|
35
|
+
3. **Polymarket Keys** — Configure local trading credentials (optional)
|
|
36
|
+
4. **Strategy Selection** — Choose Oracle or Sniper mode
|
|
37
|
+
5. **Live Streaming** — Receive real-time signals as they're generated
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 📡 How It Works
|
|
42
|
+
|
|
43
|
+
Black Edge CLI connects to the **Black Edge API** and streams trading signals in real-time:
|
|
44
|
+
|
|
45
|
+
- **Web Terminal**: Trade directly in your browser at [blackedge.io](https://blackedge.io)
|
|
46
|
+
- **CLI Terminal**: Run the engine locally with your own keys
|
|
47
|
+
|
|
48
|
+
**Both clients consume the same centralized API credit pool.**
|
|
49
|
+
|
|
50
|
+
Each signal costs **1 credit**. Purchase credits at [blackedge.io/pricing](https://blackedge.io/pricing).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🔑 Get Your API Key
|
|
55
|
+
|
|
56
|
+
1. Sign up at **[blackedge.io](https://blackedge.io)**
|
|
57
|
+
2. Connect your wallet or OAuth (Google/Apple)
|
|
58
|
+
3. Go to **Account & API** panel
|
|
59
|
+
4. Copy your API key (`be_live_***`)
|
|
60
|
+
|
|
61
|
+
**⚠️ Keep your API key secret!** It authenticates both Web Terminal and CLI access.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 💳 Credit System
|
|
66
|
+
|
|
67
|
+
- **100 credits** — Free tier (demo)
|
|
68
|
+
- **10,000 credits** — Runner tier ($29/month)
|
|
69
|
+
- **100,000 credits** — Whale tier ($999/month)
|
|
70
|
+
|
|
71
|
+
When you run out of credits, the CLI will display:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
┌────────────────────────────────────────┐
|
|
75
|
+
│ ⚠️ NO API CREDITS REMAINING │
|
|
76
|
+
│ │
|
|
77
|
+
│ Purchase more at: │
|
|
78
|
+
│ https://blackedge.io/pricing │
|
|
79
|
+
└────────────────────────────────────────┘
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 🎯 Features
|
|
85
|
+
|
|
86
|
+
✅ **Real-time Signal Streaming** — Receive signals as they're generated
|
|
87
|
+
✅ **Credit Balance Tracking** — See remaining credits after each signal
|
|
88
|
+
✅ **5-Agent AI Council** — Powered by Sage, Prophet, Doomer, Sentinel, Arbiter
|
|
89
|
+
✅ **Polymarket Integration** — Execute trades locally with your own keys
|
|
90
|
+
✅ **Strategy Modes** — Oracle (sentiment) or Sniper (arbitrage)
|
|
91
|
+
✅ **Beautiful CLI** — Sleek terminal UI with color-coded output
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🛠️ Configuration
|
|
96
|
+
|
|
97
|
+
On first run, `black-edge start` creates `~/.blackedge/config.json`:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"apiKey": "be_live_***",
|
|
102
|
+
"polymarket": {
|
|
103
|
+
"proxyKey": "your-proxy-key",
|
|
104
|
+
"secret": "your-secret",
|
|
105
|
+
"passphrase": "your-passphrase",
|
|
106
|
+
"polygonPrivateKey": "your-polygon-pk"
|
|
107
|
+
},
|
|
108
|
+
"strategy": "oracle"
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**To reconfigure:** Delete `~/.blackedge/config.json` and run `black-edge start` again.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 📊 Example Output
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
[11:42:03] ✅ Connected to Black Edge API
|
|
120
|
+
[11:42:03] 💳 Credits remaining: 8,450 / 10,000
|
|
121
|
+
|
|
122
|
+
[11:42:15] 📡 NEW SIGNAL
|
|
123
|
+
Market: Bitcoin above $120K by End of 2025
|
|
124
|
+
Edge: +12.4%
|
|
125
|
+
Council Vote: 4/5 YES
|
|
126
|
+
Kelly: 8.2%
|
|
127
|
+
💳 Credits: 8,449
|
|
128
|
+
|
|
129
|
+
[11:42:47] 📡 NEW SIGNAL
|
|
130
|
+
Market: Ethereum ETF Approval 2025
|
|
131
|
+
Edge: +7.8%
|
|
132
|
+
Council Vote: 5/5 YES
|
|
133
|
+
Kelly: 6.1%
|
|
134
|
+
💳 Credits: 8,448
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🔒 Security
|
|
140
|
+
|
|
141
|
+
- **API keys are stored locally** in `~/.blackedge/config.json`
|
|
142
|
+
- **Never share your API key** — it grants full access to your account
|
|
143
|
+
- **Polymarket keys stay local** — they're never sent to Black Edge servers
|
|
144
|
+
- **All connections use TLS/SSL** encryption
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 📚 Documentation
|
|
149
|
+
|
|
150
|
+
- **Web Terminal**: [blackedge.io/terminal](https://blackedge.io/terminal)
|
|
151
|
+
- **API Docs**: [blackedge.io/api-docs](https://blackedge.io/api-docs)
|
|
152
|
+
- **Technical Paper**: [blackedge.io/technical-paper](https://blackedge.io/technical-paper)
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## ⚖️ Legal
|
|
157
|
+
|
|
158
|
+
- **Not financial advice** — All signals are for informational purposes only
|
|
159
|
+
- **Prediction markets** — Subject to local regulations
|
|
160
|
+
- **Risk disclosure** — Read [blackedge.io/risk-disclosure](https://blackedge.io/risk-disclosure)
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 🆘 Support
|
|
165
|
+
|
|
166
|
+
- **Issues**: [github.com/Monarch33/black-edge/issues](https://github.com/Monarch33/black-edge/issues)
|
|
167
|
+
- **Email**: support@blackedge.io
|
|
168
|
+
- **Discord**: [discord.gg/blackedge](https://discord.gg/blackedge)
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 📜 License
|
|
173
|
+
|
|
174
|
+
MIT © Black Edge
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
**Built with ⚡ by the Black Edge team**
|
package/index.js
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Black Edge CLI
|
|
5
|
+
* ==============
|
|
6
|
+
* Institutional-grade HFT terminal for prediction market arbitrage
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
const inquirer = require('inquirer');
|
|
13
|
+
const chalk = require('chalk');
|
|
14
|
+
const ora = require('ora');
|
|
15
|
+
const WebSocket = require('ws');
|
|
16
|
+
const axios = require('axios');
|
|
17
|
+
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Constants
|
|
20
|
+
// =============================================================================
|
|
21
|
+
|
|
22
|
+
const CONFIG_DIR = path.join(os.homedir(), '.blackedge');
|
|
23
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
24
|
+
const DEFAULT_API_URL = process.env.BLACK_EDGE_API || 'https://black-edge-backend-production-e616.up.railway.app';
|
|
25
|
+
const DEFAULT_WS_URL = process.env.BLACK_EDGE_WS || 'wss://black-edge-backend-production-e616.up.railway.app/ws/v2/stream';
|
|
26
|
+
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// ASCII Logo
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
const LOGO = chalk.green(`
|
|
32
|
+
╔════════════════════════════════════════════════════════════════════╗
|
|
33
|
+
║ ║
|
|
34
|
+
║ ██████╗ ██╗ █████╗ ██████╗██╗ ██╗ ║
|
|
35
|
+
║ ██╔══██╗██║ ██╔══██╗██╔════╝██║ ██╔╝ ║
|
|
36
|
+
║ ██████╔╝██║ ███████║██║ █████╔╝ ║
|
|
37
|
+
║ ██╔══██╗██║ ██╔══██║██║ ██╔═██╗ ║
|
|
38
|
+
║ ██████╔╝███████╗██║ ██║╚██████╗██║ ██╗ ║
|
|
39
|
+
║ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ║
|
|
40
|
+
║ ║
|
|
41
|
+
║ ███████╗██████╗ ██████╗ ███████╗ ║
|
|
42
|
+
║ ██╔════╝██╔══██╗██╔════╝ ██╔════╝ ║
|
|
43
|
+
║ █████╗ ██║ ██║██║ ███╗█████╗ ║
|
|
44
|
+
║ ██╔══╝ ██║ ██║██║ ██║██╔══╝ ║
|
|
45
|
+
║ ███████╗██████╔╝╚██████╔╝███████╗ ║
|
|
46
|
+
║ ╚══════╝╚═════╝ ╚═════╝ ╚══════╝ ║
|
|
47
|
+
║ ║
|
|
48
|
+
║ ${chalk.white('Institutional-Grade HFT Terminal')} ║
|
|
49
|
+
║ ${chalk.gray('Powered by 5-Agent AI Council')} ║
|
|
50
|
+
║ ║
|
|
51
|
+
╚════════════════════════════════════════════════════════════════════╝
|
|
52
|
+
`);
|
|
53
|
+
|
|
54
|
+
// =============================================================================
|
|
55
|
+
// Config Management
|
|
56
|
+
// =============================================================================
|
|
57
|
+
|
|
58
|
+
function ensureConfigDir() {
|
|
59
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
60
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function loadConfig() {
|
|
65
|
+
ensureConfigDir();
|
|
66
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
67
|
+
try {
|
|
68
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf8');
|
|
69
|
+
return JSON.parse(data);
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.error(chalk.red('Failed to load config:'), e.message);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function saveConfig(config) {
|
|
79
|
+
ensureConfigDir();
|
|
80
|
+
try {
|
|
81
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
82
|
+
return true;
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error(chalk.red('Failed to save config:'), e.message);
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// =============================================================================
|
|
90
|
+
// API Functions
|
|
91
|
+
// =============================================================================
|
|
92
|
+
|
|
93
|
+
async function validateApiKey(apiKey) {
|
|
94
|
+
try {
|
|
95
|
+
const response = await axios.get(`${DEFAULT_API_URL}/api/credits/balance`, {
|
|
96
|
+
headers: {
|
|
97
|
+
'Authorization': `Bearer ${apiKey}`
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return response.data;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error.response && error.response.status === 401) {
|
|
103
|
+
return { valid: false, error: 'Invalid API key' };
|
|
104
|
+
}
|
|
105
|
+
return { valid: false, error: error.message };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// =============================================================================
|
|
110
|
+
// Setup Flow
|
|
111
|
+
// =============================================================================
|
|
112
|
+
|
|
113
|
+
async function runSetup() {
|
|
114
|
+
console.clear();
|
|
115
|
+
console.log(LOGO);
|
|
116
|
+
console.log(chalk.cyan('Welcome to Black Edge CLI!\n'));
|
|
117
|
+
|
|
118
|
+
// Step 1: API Key
|
|
119
|
+
const { apiKey } = await inquirer.prompt([
|
|
120
|
+
{
|
|
121
|
+
type: 'password',
|
|
122
|
+
name: 'apiKey',
|
|
123
|
+
message: chalk.white('Enter your Black Edge API Key:'),
|
|
124
|
+
mask: '•',
|
|
125
|
+
validate: (input) => {
|
|
126
|
+
if (!input) return 'API key is required';
|
|
127
|
+
if (!input.startsWith('be_live_')) return 'API key must start with be_live_';
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
]);
|
|
132
|
+
|
|
133
|
+
// Step 2: Validate & Check Credits
|
|
134
|
+
const spinner = ora('Validating API key...').start();
|
|
135
|
+
|
|
136
|
+
const creditsData = await validateApiKey(apiKey);
|
|
137
|
+
|
|
138
|
+
if (creditsData.error || creditsData.valid === false) {
|
|
139
|
+
spinner.fail(chalk.red('Invalid API key!'));
|
|
140
|
+
console.log(chalk.yellow('\nGet your API key at: https://blackedge.io\n'));
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
spinner.succeed(chalk.green('API key validated!'));
|
|
145
|
+
|
|
146
|
+
// Display credit balance
|
|
147
|
+
const { credits, max_credits, percentage } = creditsData;
|
|
148
|
+
const creditBar = generateProgressBar(percentage);
|
|
149
|
+
|
|
150
|
+
console.log(chalk.white('\n💳 Credit Balance:'));
|
|
151
|
+
console.log(chalk.cyan(` ${creditBar} ${credits.toLocaleString()} / ${max_credits.toLocaleString()}`));
|
|
152
|
+
|
|
153
|
+
if (credits === 0) {
|
|
154
|
+
console.log(chalk.red('\n╔════════════════════════════════════════╗'));
|
|
155
|
+
console.log(chalk.red('║ ⚠️ NO API CREDITS REMAINING ║'));
|
|
156
|
+
console.log(chalk.red('║ ║'));
|
|
157
|
+
console.log(chalk.red('║ Purchase more at: ║'));
|
|
158
|
+
console.log(chalk.red('║ https://blackedge.io/pricing ║'));
|
|
159
|
+
console.log(chalk.red('╚════════════════════════════════════════╝\n'));
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (credits < 1000) {
|
|
164
|
+
console.log(chalk.yellow('\n⚠️ Warning: Low credits! Consider purchasing more.\n'));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Step 3-6: Polymarket Keys (Optional)
|
|
168
|
+
console.log(chalk.white('\n🔑 Polymarket Configuration (Optional):'));
|
|
169
|
+
console.log(chalk.gray('Leave blank to skip automated trading\n'));
|
|
170
|
+
|
|
171
|
+
const polymarketAnswers = await inquirer.prompt([
|
|
172
|
+
{
|
|
173
|
+
type: 'input',
|
|
174
|
+
name: 'proxyKey',
|
|
175
|
+
message: 'Polymarket Proxy Key (or press Enter to skip):',
|
|
176
|
+
default: ''
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'password',
|
|
180
|
+
name: 'secret',
|
|
181
|
+
message: 'Polymarket Secret (or press Enter to skip):',
|
|
182
|
+
mask: '•',
|
|
183
|
+
default: '',
|
|
184
|
+
when: (answers) => answers.proxyKey
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
type: 'password',
|
|
188
|
+
name: 'passphrase',
|
|
189
|
+
message: 'Polymarket Passphrase (or press Enter to skip):',
|
|
190
|
+
mask: '•',
|
|
191
|
+
default: '',
|
|
192
|
+
when: (answers) => answers.proxyKey
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
type: 'password',
|
|
196
|
+
name: 'polygonPrivateKey',
|
|
197
|
+
message: 'Polygon Private Key (or press Enter to skip):',
|
|
198
|
+
mask: '•',
|
|
199
|
+
default: '',
|
|
200
|
+
when: (answers) => answers.proxyKey
|
|
201
|
+
}
|
|
202
|
+
]);
|
|
203
|
+
|
|
204
|
+
// Step 7: Strategy Selection
|
|
205
|
+
const { strategy } = await inquirer.prompt([
|
|
206
|
+
{
|
|
207
|
+
type: 'list',
|
|
208
|
+
name: 'strategy',
|
|
209
|
+
message: 'Select trading strategy:',
|
|
210
|
+
choices: [
|
|
211
|
+
{ name: chalk.green('Oracle') + chalk.gray(' — Sentiment-driven signals'), value: 'oracle' },
|
|
212
|
+
{ name: chalk.green('Sniper') + chalk.gray(' — Arbitrage opportunities'), value: 'sniper' }
|
|
213
|
+
],
|
|
214
|
+
default: 'oracle'
|
|
215
|
+
}
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
// Save config
|
|
219
|
+
const config = {
|
|
220
|
+
apiKey,
|
|
221
|
+
apiUrl: DEFAULT_API_URL,
|
|
222
|
+
wsUrl: DEFAULT_WS_URL,
|
|
223
|
+
strategy,
|
|
224
|
+
polymarket: polymarketAnswers.proxyKey ? {
|
|
225
|
+
proxyKey: polymarketAnswers.proxyKey,
|
|
226
|
+
secret: polymarketAnswers.secret,
|
|
227
|
+
passphrase: polymarketAnswers.passphrase,
|
|
228
|
+
polygonPrivateKey: polymarketAnswers.polygonPrivateKey
|
|
229
|
+
} : null
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
if (!saveConfig(config)) {
|
|
233
|
+
console.log(chalk.red('\n❌ Failed to save configuration\n'));
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
console.log(chalk.green('\n✅ Configuration saved to ' + CONFIG_FILE + '\n'));
|
|
238
|
+
|
|
239
|
+
return config;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// =============================================================================
|
|
243
|
+
// WebSocket Stream
|
|
244
|
+
// =============================================================================
|
|
245
|
+
|
|
246
|
+
async function startStream(config) {
|
|
247
|
+
console.log(chalk.cyan('\n🚀 Initializing signal stream...\n'));
|
|
248
|
+
|
|
249
|
+
const wsUrl = `${config.wsUrl}?api_key=${config.apiKey}&client_type=cli`;
|
|
250
|
+
|
|
251
|
+
const ws = new WebSocket(wsUrl);
|
|
252
|
+
|
|
253
|
+
ws.on('open', () => {
|
|
254
|
+
console.log(chalk.green('✅ Connected to Black Edge API\n'));
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
ws.on('message', (data) => {
|
|
258
|
+
try {
|
|
259
|
+
const message = JSON.parse(data.toString());
|
|
260
|
+
handleMessage(message);
|
|
261
|
+
} catch (e) {
|
|
262
|
+
console.error(chalk.red('Failed to parse message:'), e.message);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
ws.on('error', (error) => {
|
|
267
|
+
console.error(chalk.red('WebSocket error:'), error.message);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
ws.on('close', () => {
|
|
271
|
+
console.log(chalk.yellow('\n⚠️ Disconnected from Black Edge API'));
|
|
272
|
+
console.log(chalk.gray('Reconnecting in 5 seconds...\n'));
|
|
273
|
+
setTimeout(() => startStream(config), 5000);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Send ping every 30 seconds
|
|
277
|
+
setInterval(() => {
|
|
278
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
279
|
+
ws.send(JSON.stringify({ type: 'ping' }));
|
|
280
|
+
}
|
|
281
|
+
}, 30000);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// =============================================================================
|
|
285
|
+
// Message Handlers
|
|
286
|
+
// =============================================================================
|
|
287
|
+
|
|
288
|
+
function handleMessage(message) {
|
|
289
|
+
const { type, data, credits_remaining } = message;
|
|
290
|
+
|
|
291
|
+
switch (type) {
|
|
292
|
+
case 'welcome':
|
|
293
|
+
console.log(chalk.green(`💳 Credits: ${data.credits.toLocaleString()} / ${data.max_credits.toLocaleString()}`));
|
|
294
|
+
console.log(chalk.gray(` Tier: ${data.tier.toUpperCase()}\n`));
|
|
295
|
+
break;
|
|
296
|
+
|
|
297
|
+
case 'signal':
|
|
298
|
+
handleSignal(data, credits_remaining);
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
case 'heartbeat':
|
|
302
|
+
// Silent heartbeat
|
|
303
|
+
break;
|
|
304
|
+
|
|
305
|
+
case 'error':
|
|
306
|
+
handleError(message);
|
|
307
|
+
break;
|
|
308
|
+
|
|
309
|
+
case 'pong':
|
|
310
|
+
// Silent pong
|
|
311
|
+
break;
|
|
312
|
+
|
|
313
|
+
default:
|
|
314
|
+
console.log(chalk.gray(`[${type}]`), message);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function handleSignal(signal, creditsRemaining) {
|
|
319
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
320
|
+
|
|
321
|
+
console.log(chalk.cyan(`\n[${timestamp}] 📡 NEW SIGNAL`));
|
|
322
|
+
console.log(chalk.white(` Market: ${signal.market || signal.name || 'Unknown'}`));
|
|
323
|
+
|
|
324
|
+
if (signal.edge) {
|
|
325
|
+
const edgeColor = signal.edge > 10 ? chalk.green : chalk.yellow;
|
|
326
|
+
console.log(edgeColor(` Edge: +${signal.edge}%`));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (signal.council_vote) {
|
|
330
|
+
console.log(chalk.white(` Council Vote: ${signal.council_vote}`));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (signal.kelly) {
|
|
334
|
+
console.log(chalk.white(` Kelly: ${signal.kelly}%`));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (signal.side) {
|
|
338
|
+
const sideColor = signal.side === 'YES' ? chalk.green : chalk.red;
|
|
339
|
+
console.log(sideColor(` Side: ${signal.side}`));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (creditsRemaining !== undefined) {
|
|
343
|
+
console.log(chalk.gray(` 💳 Credits: ${creditsRemaining.toLocaleString()}`));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function handleError(message) {
|
|
348
|
+
const { code, message: errorMessage } = message;
|
|
349
|
+
|
|
350
|
+
console.log(chalk.red('\n╔════════════════════════════════════════╗'));
|
|
351
|
+
console.log(chalk.red(`║ ⚠️ ${code || 'ERROR'} ║`));
|
|
352
|
+
console.log(chalk.red('║ ║'));
|
|
353
|
+
console.log(chalk.red(`║ ${errorMessage} ║`));
|
|
354
|
+
|
|
355
|
+
if (code === 'INSUFFICIENT_CREDITS') {
|
|
356
|
+
console.log(chalk.red('║ ║'));
|
|
357
|
+
console.log(chalk.red('║ Purchase more at: ║'));
|
|
358
|
+
console.log(chalk.red('║ https://blackedge.io/pricing ║'));
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
console.log(chalk.red('╚════════════════════════════════════════╝\n'));
|
|
362
|
+
|
|
363
|
+
if (code === 'INSUFFICIENT_CREDITS') {
|
|
364
|
+
process.exit(1);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// =============================================================================
|
|
369
|
+
// Utilities
|
|
370
|
+
// =============================================================================
|
|
371
|
+
|
|
372
|
+
function generateProgressBar(percentage, length = 12) {
|
|
373
|
+
const filled = Math.round((percentage / 100) * length);
|
|
374
|
+
const empty = length - filled;
|
|
375
|
+
|
|
376
|
+
let color = chalk.green;
|
|
377
|
+
if (percentage < 20) color = chalk.red;
|
|
378
|
+
else if (percentage < 50) color = chalk.yellow;
|
|
379
|
+
|
|
380
|
+
return color('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// =============================================================================
|
|
384
|
+
// Main
|
|
385
|
+
// =============================================================================
|
|
386
|
+
|
|
387
|
+
async function main() {
|
|
388
|
+
const args = process.argv.slice(2);
|
|
389
|
+
const command = args[0];
|
|
390
|
+
|
|
391
|
+
if (command === 'reset') {
|
|
392
|
+
// Delete config and restart
|
|
393
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
394
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
395
|
+
console.log(chalk.green('✅ Configuration reset\n'));
|
|
396
|
+
}
|
|
397
|
+
process.exit(0);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Load or create config
|
|
401
|
+
let config = loadConfig();
|
|
402
|
+
|
|
403
|
+
if (!config) {
|
|
404
|
+
config = await runSetup();
|
|
405
|
+
} else {
|
|
406
|
+
console.clear();
|
|
407
|
+
console.log(LOGO);
|
|
408
|
+
console.log(chalk.cyan('Welcome back to Black Edge CLI!\n'));
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Start streaming
|
|
412
|
+
await startStream(config);
|
|
413
|
+
|
|
414
|
+
// Keep process alive
|
|
415
|
+
process.on('SIGINT', () => {
|
|
416
|
+
console.log(chalk.yellow('\n\n👋 Goodbye!\n'));
|
|
417
|
+
process.exit(0);
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Run
|
|
422
|
+
main().catch(error => {
|
|
423
|
+
console.error(chalk.red('\n❌ Fatal error:'), error.message);
|
|
424
|
+
process.exit(1);
|
|
425
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "black-edge-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Institutional-grade HFT CLI for the Black Edge Dark Pool",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"black-edge": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node index.js",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"trading",
|
|
15
|
+
"crypto",
|
|
16
|
+
"polymarket",
|
|
17
|
+
"hft",
|
|
18
|
+
"cli",
|
|
19
|
+
"prediction-markets",
|
|
20
|
+
"arbitrage",
|
|
21
|
+
"ai",
|
|
22
|
+
"terminal",
|
|
23
|
+
"black-edge"
|
|
24
|
+
],
|
|
25
|
+
"author": "Black Edge <contact@blackedge.io>",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"homepage": "https://blackedge.io",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/Monarch33/black-edge.git",
|
|
31
|
+
"directory": "cli"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/Monarch33/black-edge/issues"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=16.0.0"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"axios": "^1.7.0",
|
|
41
|
+
"chalk": "^4.1.2",
|
|
42
|
+
"inquirer": "^8.2.6",
|
|
43
|
+
"ora": "^5.4.1",
|
|
44
|
+
"ws": "^8.18.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {}
|
|
47
|
+
}
|