omnitrade-mcp 0.4.0 → 0.4.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/dist/cli.js +130 -198
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,82 +5,71 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
|
5
5
|
import { homedir } from "os";
|
|
6
6
|
import { join } from "path";
|
|
7
7
|
import * as readline from "readline";
|
|
8
|
-
var VERSION = "0.4.
|
|
8
|
+
var VERSION = "0.4.1";
|
|
9
9
|
var CONFIG_PATH = join(homedir(), ".omnitrade", "config.json");
|
|
10
10
|
var c = {
|
|
11
11
|
reset: "\x1B[0m",
|
|
12
12
|
bold: "\x1B[1m",
|
|
13
13
|
dim: "\x1B[2m",
|
|
14
|
-
italic: "\x1B[3m",
|
|
15
|
-
// Subtle colors
|
|
16
14
|
white: "\x1B[97m",
|
|
17
15
|
gray: "\x1B[90m",
|
|
18
|
-
blue: "\x1B[38;5;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// Soft yellow
|
|
26
|
-
purple: "\x1B[38;5;141m",
|
|
27
|
-
// Soft purple
|
|
28
|
-
orange: "\x1B[38;5;215m",
|
|
29
|
-
// Soft orange
|
|
30
|
-
red: "\x1B[38;5;203m"
|
|
31
|
-
// Soft red
|
|
16
|
+
blue: "\x1B[38;5;39m",
|
|
17
|
+
cyan: "\x1B[38;5;51m",
|
|
18
|
+
green: "\x1B[38;5;46m",
|
|
19
|
+
yellow: "\x1B[38;5;226m",
|
|
20
|
+
purple: "\x1B[38;5;165m",
|
|
21
|
+
orange: "\x1B[38;5;208m",
|
|
22
|
+
red: "\x1B[38;5;196m"
|
|
32
23
|
};
|
|
33
24
|
function printLogo() {
|
|
34
25
|
console.log(`
|
|
35
|
-
${c.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
\
|
|
47
|
-
|
|
48
|
-
\
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F
|
|
26
|
+
${c.cyan}
|
|
27
|
+
\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584\u2584
|
|
28
|
+
\u2588${c.reset} ${c.cyan}\u2588
|
|
29
|
+
\u2588${c.reset} ${c.white}${c.bold} \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588${c.purple}\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588${c.white}\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 ${c.reset}${c.cyan} \u2588
|
|
30
|
+
\u2588${c.reset} ${c.white}${c.bold}\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588${c.purple} \u2588\u2588 ${c.white}\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ${c.reset}${c.cyan} \u2588
|
|
31
|
+
\u2588${c.reset} ${c.white}${c.bold}\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588${c.purple} \u2588\u2588 ${c.white}\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 ${c.reset}${c.cyan} \u2588
|
|
32
|
+
\u2588${c.reset} ${c.white}${c.bold}\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588${c.purple} \u2588\u2588 ${c.white}\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ${c.reset}${c.cyan} \u2588
|
|
33
|
+
\u2588${c.reset} ${c.white}${c.bold} \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588${c.purple} \u2588\u2588 ${c.white}\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 ${c.reset}${c.cyan} \u2588
|
|
34
|
+
\u2588${c.reset} ${c.cyan}\u2588
|
|
35
|
+
\u2588${c.gray} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.cyan}\u2588
|
|
36
|
+
\u2588${c.reset} ${c.cyan}\u2588
|
|
37
|
+
\u2588${c.reset} ${c.white}One AI. ${c.cyan}107 Exchanges. ${c.purple}Natural Language Trading.${c.reset} ${c.cyan}\u2588
|
|
38
|
+
\u2588${c.reset} ${c.cyan}\u2588
|
|
39
|
+
\u2588${c.reset} ${c.gray}v${VERSION}${c.reset} ${c.gray}by Connectry Labs${c.reset} ${c.cyan}\u2588
|
|
40
|
+
\u2588${c.reset} ${c.cyan}\u2588
|
|
41
|
+
\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580
|
|
52
42
|
${c.reset}`);
|
|
53
43
|
}
|
|
54
44
|
function printCompactLogo() {
|
|
55
45
|
console.log(`
|
|
56
|
-
${c.
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
${c.cyan}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}
|
|
47
|
+
${c.white}${c.bold}OMNITRADE${c.purple} MCP${c.reset} ${c.gray}\u2022 One AI. 107 Exchanges.${c.reset}
|
|
48
|
+
${c.cyan}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}
|
|
59
49
|
`);
|
|
60
50
|
}
|
|
61
51
|
function printHelp() {
|
|
62
52
|
printLogo();
|
|
63
53
|
console.log(`
|
|
64
|
-
${c.white}${c.bold}
|
|
65
|
-
${c.gray}
|
|
54
|
+
${c.white}${c.bold}COMMANDS${c.reset}
|
|
55
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
66
56
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
57
|
+
${c.green}${c.bold}setup${c.reset} Guided setup wizard ${c.dim}(start here!)${c.reset}
|
|
58
|
+
${c.cyan}start${c.reset} Start MCP server for Claude Desktop
|
|
59
|
+
${c.cyan}test${c.reset} Test your exchange connections
|
|
60
|
+
${c.cyan}config${c.reset} View current configuration
|
|
61
|
+
${c.cyan}exchanges${c.reset} List all 107 supported exchanges
|
|
62
|
+
${c.cyan}help${c.reset} Show this help
|
|
73
63
|
|
|
74
|
-
${c.white}${c.bold}
|
|
75
|
-
${c.gray}
|
|
64
|
+
${c.white}${c.bold}GET STARTED${c.reset}
|
|
65
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
76
66
|
|
|
77
|
-
|
|
67
|
+
${c.yellow}$${c.reset} ${c.green}omnitrade setup${c.reset}
|
|
78
68
|
|
|
79
|
-
${c.white}${c.bold}
|
|
80
|
-
${c.gray}
|
|
69
|
+
${c.white}${c.bold}DOCUMENTATION${c.reset}
|
|
70
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
81
71
|
|
|
82
|
-
|
|
83
|
-
${c.dim}Issues${c.reset} ${c.blue}https://github.com/Connectry-io/omnitrade-mcp/issues${c.reset}
|
|
72
|
+
${c.blue}https://github.com/Connectry-io/omnitrade-mcp${c.reset}
|
|
84
73
|
|
|
85
74
|
`);
|
|
86
75
|
}
|
|
@@ -91,40 +80,35 @@ async function runSetupWizard() {
|
|
|
91
80
|
output: process.stdout
|
|
92
81
|
});
|
|
93
82
|
const question = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
94
|
-
const clear = () => console.log("\x1B[2J\x1B[H");
|
|
95
83
|
console.log(`
|
|
96
|
-
${c.white}${c.bold}
|
|
97
|
-
${c.gray}
|
|
84
|
+
${c.white}${c.bold}WELCOME TO OMNITRADE${c.reset}
|
|
85
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
98
86
|
|
|
99
|
-
|
|
100
|
-
|
|
87
|
+
Let's connect your first crypto exchange to Claude.
|
|
88
|
+
This takes about ${c.green}2 minutes${c.reset}.
|
|
101
89
|
|
|
102
|
-
${c.white}${c.bold}
|
|
103
|
-
${c.gray} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
90
|
+
${c.white}${c.bold}WHAT YOU NEED${c.reset}
|
|
104
91
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
92
|
+
${c.cyan}1.${c.reset} A crypto exchange account ${c.dim}(Binance, Coinbase, etc.)${c.reset}
|
|
93
|
+
${c.cyan}2.${c.reset} API keys from that exchange
|
|
94
|
+
${c.cyan}3.${c.reset} Claude Desktop installed
|
|
108
95
|
|
|
109
|
-
${c.gray} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
110
96
|
`);
|
|
111
97
|
await question(` ${c.dim}Press Enter to continue...${c.reset}`);
|
|
112
98
|
console.log(`
|
|
113
|
-
${c.white}${c.bold}
|
|
114
|
-
${c.gray}
|
|
99
|
+
${c.white}${c.bold}STEP 1/4 \u2014 CHOOSE EXCHANGE${c.reset}
|
|
100
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
115
101
|
|
|
116
|
-
${c.dim}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
${c.cyan}[6]${c.reset} KuCoin ${c.dim}Altcoin variety${c.reset}
|
|
124
|
-
${c.cyan}[7]${c.reset} Other ${c.dim}Enter exchange name manually${c.reset}
|
|
102
|
+
${c.cyan}[1]${c.reset} Binance ${c.dim}Largest global exchange${c.reset}
|
|
103
|
+
${c.cyan}[2]${c.reset} Coinbase ${c.dim}US-based, beginner friendly${c.reset}
|
|
104
|
+
${c.cyan}[3]${c.reset} Kraken ${c.dim}Security focused${c.reset}
|
|
105
|
+
${c.cyan}[4]${c.reset} Bybit ${c.dim}Derivatives trading${c.reset}
|
|
106
|
+
${c.cyan}[5]${c.reset} OKX ${c.dim}Full-featured${c.reset}
|
|
107
|
+
${c.cyan}[6]${c.reset} KuCoin ${c.dim}Altcoin variety${c.reset}
|
|
108
|
+
${c.cyan}[7]${c.reset} Other ${c.dim}Enter name manually${c.reset}
|
|
125
109
|
|
|
126
110
|
`);
|
|
127
|
-
const exchangeChoice = await question(` ${c.yellow}?${c.reset} Select
|
|
111
|
+
const exchangeChoice = await question(` ${c.yellow}?${c.reset} Select [1-7]: `);
|
|
128
112
|
const exchangeMap = {
|
|
129
113
|
"1": "binance",
|
|
130
114
|
"2": "coinbase",
|
|
@@ -135,65 +119,55 @@ ${c.gray} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2
|
|
|
135
119
|
};
|
|
136
120
|
let exchange = exchangeMap[exchangeChoice.trim()];
|
|
137
121
|
if (!exchange) {
|
|
138
|
-
exchange = await question(` ${c.yellow}?${c.reset}
|
|
122
|
+
exchange = await question(` ${c.yellow}?${c.reset} Exchange name: `);
|
|
139
123
|
}
|
|
140
124
|
exchange = exchange.toLowerCase().trim();
|
|
141
125
|
console.log(`
|
|
142
|
-
${c.white}${c.bold}
|
|
143
|
-
${c.gray}
|
|
126
|
+
${c.white}${c.bold}STEP 2/4 \u2014 GET API KEYS${c.reset}
|
|
127
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
144
128
|
|
|
145
|
-
|
|
129
|
+
Create API keys on ${c.white}${c.bold}${exchange.toUpperCase()}${c.reset}:
|
|
146
130
|
`);
|
|
147
131
|
if (exchange === "binance") {
|
|
148
132
|
console.log(`
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
${c.cyan}4.${c.reset} Copy the ${c.white}API Key${c.reset} and ${c.white}Secret Key${c.reset}
|
|
133
|
+
${c.cyan}1.${c.reset} Go to ${c.blue}https://testnet.binance.vision${c.reset} ${c.dim}(testnet)${c.reset}
|
|
134
|
+
${c.cyan}2.${c.reset} Click ${c.white}"Generate HMAC_SHA256 Key"${c.reset}
|
|
135
|
+
${c.cyan}3.${c.reset} Permissions: ${c.green}\u2713 Read${c.reset} ${c.green}\u2713 Trade${c.reset} ${c.red}\u2717 Withdraw${c.reset}
|
|
136
|
+
${c.cyan}4.${c.reset} Copy ${c.white}API Key${c.reset} and ${c.white}Secret Key${c.reset}
|
|
154
137
|
`);
|
|
155
138
|
} else if (exchange === "coinbase") {
|
|
156
139
|
console.log(`
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
`);
|
|
162
|
-
} else if (exchange === "kraken") {
|
|
163
|
-
console.log(`
|
|
164
|
-
${c.cyan}1.${c.reset} Go to ${c.blue}https://www.kraken.com/u/security/api${c.reset}
|
|
165
|
-
${c.cyan}2.${c.reset} Click "Generate new key"
|
|
166
|
-
${c.cyan}3.${c.reset} Enable: ${c.green}\u2713 Query${c.reset} ${c.green}\u2713 Trade${c.reset} ${c.red}\u2717 Withdraw${c.reset}
|
|
167
|
-
${c.cyan}4.${c.reset} Copy the ${c.white}API Key${c.reset} and ${c.white}Private Key${c.reset}
|
|
140
|
+
${c.cyan}1.${c.reset} Go to ${c.blue}https://portal.cdp.coinbase.com${c.reset}
|
|
141
|
+
${c.cyan}2.${c.reset} Create a new project
|
|
142
|
+
${c.cyan}3.${c.reset} Generate API credentials
|
|
143
|
+
${c.cyan}4.${c.reset} Copy ${c.white}API Key${c.reset}, ${c.white}Secret${c.reset}, and ${c.white}Passphrase${c.reset}
|
|
168
144
|
`);
|
|
169
145
|
} else {
|
|
170
146
|
console.log(`
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
${c.cyan}5.${c.reset} Copy the ${c.white}API Key${c.reset} and ${c.white}Secret${c.reset}
|
|
147
|
+
${c.cyan}1.${c.reset} Log into ${c.white}${exchange}${c.reset}
|
|
148
|
+
${c.cyan}2.${c.reset} Go to API settings
|
|
149
|
+
${c.cyan}3.${c.reset} Create new API key
|
|
150
|
+
${c.cyan}4.${c.reset} Enable: ${c.green}\u2713 Read${c.reset} ${c.green}\u2713 Trade${c.reset} ${c.red}\u2717 Withdraw${c.reset}
|
|
176
151
|
`);
|
|
177
152
|
}
|
|
178
|
-
console.log(`
|
|
179
|
-
${c.orange} \u26A0 SECURITY TIP: Never enable withdrawal permissions!${c.reset}
|
|
153
|
+
console.log(` ${c.orange}\u26A0 Never enable withdrawal permissions!${c.reset}
|
|
180
154
|
`);
|
|
181
|
-
await question(` ${c.dim}Press Enter when you have your
|
|
155
|
+
await question(` ${c.dim}Press Enter when you have your keys...${c.reset}`);
|
|
182
156
|
console.log(`
|
|
183
|
-
${c.white}${c.bold}
|
|
184
|
-
${c.gray}
|
|
157
|
+
${c.white}${c.bold}STEP 3/4 \u2014 ENTER API KEYS${c.reset}
|
|
158
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
185
159
|
|
|
186
|
-
${c.dim}
|
|
160
|
+
${c.dim}Keys are stored locally at ~/.omnitrade/config.json${c.reset}
|
|
187
161
|
${c.dim}They never leave your machine.${c.reset}
|
|
188
162
|
|
|
189
163
|
`);
|
|
190
164
|
const apiKey = await question(` ${c.yellow}?${c.reset} API Key: `);
|
|
191
|
-
const secret = await question(` ${c.yellow}?${c.reset} Secret
|
|
165
|
+
const secret = await question(` ${c.yellow}?${c.reset} Secret: `);
|
|
192
166
|
let password = "";
|
|
193
167
|
if (["coinbase", "kucoin", "okx"].includes(exchange)) {
|
|
194
|
-
password = await question(` ${c.yellow}?${c.reset} Passphrase
|
|
168
|
+
password = await question(` ${c.yellow}?${c.reset} Passphrase: `);
|
|
195
169
|
}
|
|
196
|
-
const testnetAnswer = await question(` ${c.yellow}?${c.reset} Use testnet
|
|
170
|
+
const testnetAnswer = await question(` ${c.yellow}?${c.reset} Use testnet? ${c.dim}(Y/n)${c.reset}: `);
|
|
197
171
|
const testnet = testnetAnswer.toLowerCase() !== "n";
|
|
198
172
|
rl.close();
|
|
199
173
|
const config = {
|
|
@@ -221,44 +195,41 @@ ${c.gray} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2
|
|
|
221
195
|
} catch {
|
|
222
196
|
}
|
|
223
197
|
console.log(`
|
|
224
|
-
${c.green}${c.bold}
|
|
198
|
+
${c.green}${c.bold}\u2713 SAVED${c.reset}
|
|
225
199
|
|
|
226
|
-
${c.white}${c.bold}
|
|
227
|
-
${c.gray}
|
|
200
|
+
${c.white}${c.bold}STEP 4/4 \u2014 CONNECT TO CLAUDE${c.reset}
|
|
201
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
228
202
|
|
|
229
|
-
${c.
|
|
203
|
+
${c.cyan}1.${c.reset} Open Claude Desktop config:
|
|
230
204
|
|
|
231
|
-
|
|
232
|
-
|
|
205
|
+
${c.dim}macOS:${c.reset} ${c.blue}~/Library/Application Support/Claude/claude_desktop_config.json${c.reset}
|
|
206
|
+
${c.dim}Windows:${c.reset} ${c.blue}%APPDATA%\\Claude\\claude_desktop_config.json${c.reset}
|
|
233
207
|
|
|
234
|
-
|
|
208
|
+
${c.cyan}2.${c.reset} Add this:
|
|
235
209
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
210
|
+
${c.gray}{
|
|
211
|
+
"mcpServers": {
|
|
212
|
+
"omnitrade": {
|
|
213
|
+
"command": "omnitrade",
|
|
214
|
+
"args": ["start"]
|
|
242
215
|
}
|
|
243
|
-
}
|
|
216
|
+
}
|
|
217
|
+
}${c.reset}
|
|
244
218
|
|
|
245
|
-
|
|
219
|
+
${c.cyan}3.${c.reset} ${c.white}Restart Claude Desktop${c.reset}
|
|
246
220
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
${c.dim}"Show me the price of Bitcoin"${c.reset}
|
|
250
|
-
${c.dim}"Buy $10 of ETH"${c.reset}
|
|
221
|
+
${c.cyan}4.${c.reset} Try asking Claude:
|
|
222
|
+
${c.dim}"What's my balance on ${exchange}?"${c.reset}
|
|
251
223
|
|
|
252
|
-
${c.gray}
|
|
224
|
+
${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}
|
|
253
225
|
|
|
254
|
-
${c.white}${c.bold}
|
|
226
|
+
${c.white}${c.bold}USEFUL COMMANDS${c.reset}
|
|
255
227
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
${c.cyan}\u2022${c.reset} Get help: ${c.yellow}omnitrade help${c.reset}
|
|
228
|
+
${c.cyan}omnitrade test${c.reset} Test your connection
|
|
229
|
+
${c.cyan}omnitrade config${c.reset} View configuration
|
|
230
|
+
${c.cyan}omnitrade setup${c.reset} Add another exchange
|
|
260
231
|
|
|
261
|
-
${c.green}${c.bold}
|
|
232
|
+
${c.green}${c.bold}\u2713 Setup complete!${c.reset}
|
|
262
233
|
|
|
263
234
|
`);
|
|
264
235
|
}
|
|
@@ -266,55 +237,31 @@ async function showExchanges() {
|
|
|
266
237
|
printCompactLogo();
|
|
267
238
|
const ccxt = await import("ccxt");
|
|
268
239
|
const exchanges = ccxt.default.exchanges;
|
|
269
|
-
console.log(
|
|
240
|
+
console.log(` ${c.white}${c.bold}SUPPORTED EXCHANGES${c.reset} ${c.dim}(${exchanges.length})${c.reset}
|
|
270
241
|
`);
|
|
271
|
-
const tier1 = ["binance", "bybit", "okx", "gate", "kucoin", "bitget", "htx", "mexc", "cryptocom", "bitmex"
|
|
272
|
-
const tier2 = ["coinbase", "kraken", "bitstamp", "gemini", "bitfinex", "poloniex", "deribit", "upbit", "bithumb", "bitvavo"
|
|
273
|
-
console.log(` ${c.green}\u2605 TIER 1
|
|
274
|
-
console.log(` ${c.
|
|
275
|
-
console.log(`
|
|
276
|
-
${c.yellow}\u2605 TIER 2 - MAJOR${c.reset}`);
|
|
277
|
-
console.log(` ${c.dim}${tier2.filter((e) => exchanges.includes(e)).join(", ")}${c.reset}`);
|
|
242
|
+
const tier1 = ["binance", "bybit", "okx", "gate", "kucoin", "bitget", "htx", "mexc", "cryptocom", "bitmex"];
|
|
243
|
+
const tier2 = ["coinbase", "kraken", "bitstamp", "gemini", "bitfinex", "poloniex", "deribit", "upbit", "bithumb", "bitvavo"];
|
|
244
|
+
console.log(` ${c.green}\u2605 TIER 1${c.reset} ${c.dim}${tier1.join(", ")}${c.reset}`);
|
|
245
|
+
console.log(` ${c.yellow}\u2605 TIER 2${c.reset} ${c.dim}${tier2.join(", ")}${c.reset}`);
|
|
278
246
|
const others = exchanges.filter((e) => !tier1.includes(e) && !tier2.includes(e));
|
|
279
|
-
console.log(`
|
|
280
|
-
|
|
281
|
-
const cols = 8;
|
|
282
|
-
for (let i = 0; i < others.length; i += cols) {
|
|
283
|
-
const row = others.slice(i, i + cols);
|
|
284
|
-
console.log(` ${c.dim}${row.map((e) => e.padEnd(12)).join("")}${c.reset}`);
|
|
285
|
-
}
|
|
286
|
-
console.log("");
|
|
247
|
+
console.log(` ${c.gray}+ ${others.length} more...${c.reset}
|
|
248
|
+
`);
|
|
287
249
|
}
|
|
288
250
|
async function showConfig() {
|
|
289
251
|
printCompactLogo();
|
|
290
|
-
console.log(`${c.white}${c.bold} CONFIGURATION${c.reset}
|
|
291
|
-
`);
|
|
292
|
-
console.log(` ${c.dim}Location:${c.reset} ${c.blue}${CONFIG_PATH}${c.reset}
|
|
293
|
-
`);
|
|
294
252
|
if (!existsSync(CONFIG_PATH)) {
|
|
295
|
-
console.log(` ${c.red}\u2717 No configuration
|
|
296
|
-
|
|
297
|
-
Run ${c.cyan}omnitrade setup${c.reset} to get started.
|
|
253
|
+
console.log(` ${c.red}\u2717 No configuration${c.reset}
|
|
254
|
+
Run ${c.cyan}omnitrade setup${c.reset}
|
|
298
255
|
`);
|
|
299
256
|
return;
|
|
300
257
|
}
|
|
301
258
|
try {
|
|
302
259
|
const config = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
303
|
-
|
|
304
|
-
console.log(` ${c.green}\u2713 Config loaded${c.reset}
|
|
260
|
+
console.log(` ${c.green}\u2713 Config loaded${c.reset} ${c.dim}${CONFIG_PATH}${c.reset}
|
|
305
261
|
`);
|
|
306
|
-
|
|
307
|
-
for (const ex of exchanges) {
|
|
308
|
-
const cfg = config.exchanges[ex];
|
|
262
|
+
for (const [ex, cfg] of Object.entries(config.exchanges || {})) {
|
|
309
263
|
const mode = cfg.testnet ? `${c.yellow}testnet${c.reset}` : `${c.green}live${c.reset}`;
|
|
310
|
-
console.log(`
|
|
311
|
-
}
|
|
312
|
-
if (config.security) {
|
|
313
|
-
console.log(`
|
|
314
|
-
${c.white}${c.bold}Security:${c.reset}`);
|
|
315
|
-
if (config.security.maxOrderSize) {
|
|
316
|
-
console.log(` ${c.cyan}\u2022${c.reset} Max order: $${config.security.maxOrderSize}`);
|
|
317
|
-
}
|
|
264
|
+
console.log(` ${c.cyan}\u2022${c.reset} ${ex} (${mode})`);
|
|
318
265
|
}
|
|
319
266
|
console.log("");
|
|
320
267
|
} catch (error) {
|
|
@@ -324,44 +271,32 @@ async function showConfig() {
|
|
|
324
271
|
}
|
|
325
272
|
async function testConnections() {
|
|
326
273
|
printCompactLogo();
|
|
327
|
-
console.log(`${c.white}${c.bold} TESTING CONNECTIONS${c.reset}
|
|
328
|
-
`);
|
|
329
274
|
if (!existsSync(CONFIG_PATH)) {
|
|
330
|
-
console.log(` ${c.red}\u2717 No configuration
|
|
331
|
-
|
|
332
|
-
Run ${c.cyan}omnitrade setup${c.reset} to get started.
|
|
275
|
+
console.log(` ${c.red}\u2717 No configuration${c.reset}
|
|
276
|
+
Run ${c.cyan}omnitrade setup${c.reset}
|
|
333
277
|
`);
|
|
334
278
|
return;
|
|
335
279
|
}
|
|
280
|
+
console.log(` ${c.white}${c.bold}TESTING${c.reset}
|
|
281
|
+
`);
|
|
336
282
|
const ccxt = await import("ccxt");
|
|
337
283
|
const config = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
process.stdout.write(` Testing ${c.cyan}${name}${c.reset}... `);
|
|
284
|
+
for (const [name, cfg] of Object.entries(config.exchanges || {})) {
|
|
285
|
+
process.stdout.write(` ${c.cyan}${name}${c.reset} ... `);
|
|
341
286
|
try {
|
|
342
287
|
const ExchangeClass = ccxt.default[name];
|
|
343
|
-
if (!ExchangeClass) {
|
|
344
|
-
console.log(`${c.red}\u2717 Unknown exchange${c.reset}`);
|
|
345
|
-
continue;
|
|
346
|
-
}
|
|
347
288
|
const ex = new ExchangeClass({
|
|
348
289
|
apiKey: cfg.apiKey,
|
|
349
290
|
secret: cfg.secret,
|
|
350
291
|
password: cfg.password,
|
|
351
292
|
enableRateLimit: true
|
|
352
293
|
});
|
|
353
|
-
if (cfg.testnet)
|
|
354
|
-
ex.setSandboxMode(true);
|
|
355
|
-
}
|
|
294
|
+
if (cfg.testnet) ex.setSandboxMode(true);
|
|
356
295
|
const balance = await ex.fetchBalance();
|
|
357
|
-
const assets = Object.entries(balance.total).filter(([_, v]) => v > 0).slice(0, 3).map(([k, v]) => `${k}
|
|
358
|
-
|
|
359
|
-
console.log(`${c.green}\u2713${c.reset} Connected (${mode})`);
|
|
360
|
-
if (assets) {
|
|
361
|
-
console.log(` ${c.dim}Balances: ${assets}${c.reset}`);
|
|
362
|
-
}
|
|
296
|
+
const assets = Object.entries(balance.total).filter(([_, v]) => v > 0).slice(0, 3).map(([k, v]) => `${k}:${v}`).join(" ");
|
|
297
|
+
console.log(`${c.green}\u2713${c.reset} ${c.dim}${assets || "connected"}${c.reset}`);
|
|
363
298
|
} catch (error) {
|
|
364
|
-
console.log(`${c.red}\u2717 ${error.message.
|
|
299
|
+
console.log(`${c.red}\u2717${c.reset} ${c.dim}${error.message.slice(0, 40)}${c.reset}`);
|
|
365
300
|
}
|
|
366
301
|
}
|
|
367
302
|
console.log("");
|
|
@@ -372,7 +307,6 @@ async function main() {
|
|
|
372
307
|
switch (command) {
|
|
373
308
|
case "setup":
|
|
374
309
|
case "init":
|
|
375
|
-
case "configure":
|
|
376
310
|
await runSetupWizard();
|
|
377
311
|
break;
|
|
378
312
|
case "help":
|
|
@@ -390,7 +324,6 @@ async function main() {
|
|
|
390
324
|
await showExchanges();
|
|
391
325
|
break;
|
|
392
326
|
case "config":
|
|
393
|
-
case "status":
|
|
394
327
|
await showConfig();
|
|
395
328
|
break;
|
|
396
329
|
case "test":
|
|
@@ -398,12 +331,11 @@ async function main() {
|
|
|
398
331
|
break;
|
|
399
332
|
case "start":
|
|
400
333
|
case "serve":
|
|
401
|
-
case "run":
|
|
402
334
|
await import("./index.js");
|
|
403
335
|
break;
|
|
404
336
|
default:
|
|
405
|
-
console.log(`${c.red}Unknown
|
|
406
|
-
|
|
337
|
+
console.log(`${c.red}Unknown: ${command}${c.reset}
|
|
338
|
+
Run ${c.cyan}omnitrade help${c.reset}
|
|
407
339
|
`);
|
|
408
340
|
process.exit(1);
|
|
409
341
|
}
|
package/dist/index.js
CHANGED
|
@@ -911,7 +911,7 @@ function registerArbitrageTools(server, exchangeManager) {
|
|
|
911
911
|
}
|
|
912
912
|
|
|
913
913
|
// src/index.ts
|
|
914
|
-
var VERSION = "0.4.
|
|
914
|
+
var VERSION = "0.4.1";
|
|
915
915
|
function showBanner() {
|
|
916
916
|
console.error(`
|
|
917
917
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|