okx-trade-cli 1.0.0 → 1.0.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/index.js CHANGED
@@ -2,10 +2,399 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { parseArgs } from "util";
5
- import { OkxRestClient, toToolErrorPayload } from "@okx-hub/core";
5
+
6
+ // node_modules/@okx-hub/core/dist/index.js
7
+ import { createHmac } from "crypto";
8
+ import { readFileSync, existsSync } from "fs";
9
+ import { join } from "path";
10
+ import { homedir } from "os";
11
+ import { parse } from "smol-toml";
12
+ function getNow() {
13
+ return (/* @__PURE__ */ new Date()).toISOString();
14
+ }
15
+ function signOkxPayload(payload, secretKey) {
16
+ return createHmac("sha256", secretKey).update(payload).digest("base64");
17
+ }
18
+ var OkxMcpError = class extends Error {
19
+ type;
20
+ code;
21
+ suggestion;
22
+ endpoint;
23
+ constructor(type, message, options) {
24
+ super(message, options?.cause ? { cause: options.cause } : void 0);
25
+ this.name = type;
26
+ this.type = type;
27
+ this.code = options?.code;
28
+ this.suggestion = options?.suggestion;
29
+ this.endpoint = options?.endpoint;
30
+ }
31
+ };
32
+ var ConfigError = class extends OkxMcpError {
33
+ constructor(message, suggestion) {
34
+ super("ConfigError", message, { suggestion });
35
+ }
36
+ };
37
+ var RateLimitError = class extends OkxMcpError {
38
+ constructor(message, suggestion, endpoint) {
39
+ super("RateLimitError", message, { suggestion, endpoint });
40
+ }
41
+ };
42
+ var AuthenticationError = class extends OkxMcpError {
43
+ constructor(message, suggestion, endpoint) {
44
+ super("AuthenticationError", message, { suggestion, endpoint });
45
+ }
46
+ };
47
+ var OkxApiError = class extends OkxMcpError {
48
+ constructor(message, options) {
49
+ super("OkxApiError", message, options);
50
+ }
51
+ };
52
+ var NetworkError = class extends OkxMcpError {
53
+ constructor(message, endpoint, cause) {
54
+ super("NetworkError", message, {
55
+ endpoint,
56
+ cause,
57
+ suggestion: "Please check network connectivity and retry the request in a few seconds."
58
+ });
59
+ }
60
+ };
61
+ function toToolErrorPayload(error, fallbackEndpoint) {
62
+ if (error instanceof OkxMcpError) {
63
+ return {
64
+ error: true,
65
+ type: error.type,
66
+ code: error.code,
67
+ message: error.message,
68
+ suggestion: error.suggestion,
69
+ endpoint: error.endpoint ?? fallbackEndpoint,
70
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
71
+ };
72
+ }
73
+ const message = error instanceof Error ? error.message : String(error);
74
+ return {
75
+ error: true,
76
+ type: "InternalError",
77
+ message,
78
+ suggestion: "Unexpected server error. Check tool arguments and retry. If it persists, inspect server logs.",
79
+ endpoint: fallbackEndpoint,
80
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
81
+ };
82
+ }
83
+ function sleep(ms) {
84
+ return new Promise((resolve) => {
85
+ setTimeout(resolve, ms);
86
+ });
87
+ }
88
+ var RateLimiter = class {
89
+ buckets = /* @__PURE__ */ new Map();
90
+ maxWaitMs;
91
+ constructor(maxWaitMs = 3e4) {
92
+ this.maxWaitMs = maxWaitMs;
93
+ }
94
+ async consume(config, amount = 1) {
95
+ const bucket = this.getBucket(config);
96
+ this.refill(bucket);
97
+ if (bucket.tokens >= amount) {
98
+ bucket.tokens -= amount;
99
+ return;
100
+ }
101
+ const missing = amount - bucket.tokens;
102
+ const secondsToWait = missing / bucket.refillPerSecond;
103
+ const waitMs = Math.ceil(secondsToWait * 1e3);
104
+ if (waitMs > this.maxWaitMs) {
105
+ throw new RateLimitError(
106
+ `Client-side rate limit reached for ${config.key}. Required wait ${waitMs}ms exceeds allowed max ${this.maxWaitMs}ms.`,
107
+ "Reduce tool call frequency or retry later."
108
+ );
109
+ }
110
+ await sleep(waitMs);
111
+ this.refill(bucket);
112
+ if (bucket.tokens < amount) {
113
+ throw new RateLimitError(
114
+ `Rate limiter failed to acquire enough tokens for ${config.key}.`
115
+ );
116
+ }
117
+ bucket.tokens -= amount;
118
+ }
119
+ getBucket(config) {
120
+ const existing = this.buckets.get(config.key);
121
+ if (existing) {
122
+ if (existing.capacity !== config.capacity || existing.refillPerSecond !== config.refillPerSecond) {
123
+ existing.capacity = config.capacity;
124
+ existing.refillPerSecond = config.refillPerSecond;
125
+ existing.tokens = Math.min(existing.tokens, config.capacity);
126
+ }
127
+ return existing;
128
+ }
129
+ const now = Date.now();
130
+ const created = {
131
+ tokens: config.capacity,
132
+ lastRefillMs: now,
133
+ capacity: config.capacity,
134
+ refillPerSecond: config.refillPerSecond
135
+ };
136
+ this.buckets.set(config.key, created);
137
+ return created;
138
+ }
139
+ refill(bucket) {
140
+ const now = Date.now();
141
+ const elapsedMs = now - bucket.lastRefillMs;
142
+ if (elapsedMs <= 0) {
143
+ return;
144
+ }
145
+ const refillTokens = elapsedMs / 1e3 * bucket.refillPerSecond;
146
+ bucket.tokens = Math.min(bucket.capacity, bucket.tokens + refillTokens);
147
+ bucket.lastRefillMs = now;
148
+ }
149
+ };
150
+ function isDefined(value) {
151
+ return value !== void 0 && value !== null;
152
+ }
153
+ function stringifyQueryValue(value) {
154
+ if (Array.isArray(value)) {
155
+ return value.map((item) => String(item)).join(",");
156
+ }
157
+ return String(value);
158
+ }
159
+ function buildQueryString(query) {
160
+ if (!query) {
161
+ return "";
162
+ }
163
+ const entries = Object.entries(query).filter(([, value]) => isDefined(value));
164
+ if (entries.length === 0) {
165
+ return "";
166
+ }
167
+ const params = new URLSearchParams();
168
+ for (const [key, value] of entries) {
169
+ params.set(key, stringifyQueryValue(value));
170
+ }
171
+ return params.toString();
172
+ }
173
+ var OkxRestClient = class {
174
+ config;
175
+ rateLimiter = new RateLimiter();
176
+ constructor(config) {
177
+ this.config = config;
178
+ }
179
+ async publicGet(path, query, rateLimit) {
180
+ return this.request({
181
+ method: "GET",
182
+ path,
183
+ auth: "public",
184
+ query,
185
+ rateLimit
186
+ });
187
+ }
188
+ async privateGet(path, query, rateLimit) {
189
+ return this.request({
190
+ method: "GET",
191
+ path,
192
+ auth: "private",
193
+ query,
194
+ rateLimit
195
+ });
196
+ }
197
+ async privatePost(path, body, rateLimit) {
198
+ return this.request({
199
+ method: "POST",
200
+ path,
201
+ auth: "private",
202
+ body,
203
+ rateLimit
204
+ });
205
+ }
206
+ async request(config) {
207
+ const queryString = buildQueryString(config.query);
208
+ const requestPath = queryString.length > 0 ? `${config.path}?${queryString}` : config.path;
209
+ const url = `${this.config.baseUrl}${requestPath}`;
210
+ const bodyJson = config.body ? JSON.stringify(config.body) : "";
211
+ const timestamp = getNow();
212
+ if (config.rateLimit) {
213
+ await this.rateLimiter.consume(config.rateLimit);
214
+ }
215
+ const headers = new Headers({
216
+ "Content-Type": "application/json",
217
+ Accept: "application/json"
218
+ });
219
+ if (config.auth === "private") {
220
+ if (!this.config.hasAuth) {
221
+ throw new ConfigError(
222
+ "Private endpoint requires API credentials.",
223
+ "Configure OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE."
224
+ );
225
+ }
226
+ if (!this.config.apiKey || !this.config.secretKey || !this.config.passphrase) {
227
+ throw new ConfigError(
228
+ "Invalid private API credentials state.",
229
+ "Ensure all OKX credentials are set."
230
+ );
231
+ }
232
+ const payload = `${timestamp}${config.method.toUpperCase()}${requestPath}${bodyJson}`;
233
+ const signature = signOkxPayload(payload, this.config.secretKey);
234
+ headers.set("OK-ACCESS-KEY", this.config.apiKey);
235
+ headers.set("OK-ACCESS-SIGN", signature);
236
+ headers.set("OK-ACCESS-PASSPHRASE", this.config.passphrase);
237
+ headers.set("OK-ACCESS-TIMESTAMP", timestamp);
238
+ }
239
+ if (this.config.demo) {
240
+ headers.set("x-simulated-trading", "1");
241
+ }
242
+ let response;
243
+ try {
244
+ response = await fetch(url, {
245
+ method: config.method,
246
+ headers,
247
+ body: config.method === "POST" ? bodyJson : void 0,
248
+ signal: AbortSignal.timeout(this.config.timeoutMs)
249
+ });
250
+ } catch (error) {
251
+ throw new NetworkError(
252
+ `Failed to call OKX endpoint ${config.method} ${requestPath}.`,
253
+ `${config.method} ${requestPath}`,
254
+ error
255
+ );
256
+ }
257
+ const rawText = await response.text();
258
+ let parsed;
259
+ try {
260
+ parsed = rawText ? JSON.parse(rawText) : {};
261
+ } catch (error) {
262
+ if (!response.ok) {
263
+ const messagePreview = rawText.slice(0, 160).replace(/\s+/g, " ").trim();
264
+ throw new OkxApiError(
265
+ `HTTP ${response.status} from OKX: ${messagePreview || "Non-JSON response body"}`,
266
+ {
267
+ code: String(response.status),
268
+ endpoint: `${config.method} ${config.path}`,
269
+ suggestion: "Verify endpoint path and request parameters."
270
+ }
271
+ );
272
+ }
273
+ throw new NetworkError(
274
+ `OKX returned non-JSON response for ${config.method} ${requestPath}.`,
275
+ `${config.method} ${requestPath}`,
276
+ error
277
+ );
278
+ }
279
+ if (!response.ok) {
280
+ throw new OkxApiError(
281
+ `HTTP ${response.status} from OKX: ${parsed.msg ?? "Unknown error"}`,
282
+ {
283
+ code: String(response.status),
284
+ endpoint: `${config.method} ${config.path}`,
285
+ suggestion: "Retry later or verify endpoint parameters."
286
+ }
287
+ );
288
+ }
289
+ const responseCode = parsed.code;
290
+ if (responseCode && responseCode !== "0") {
291
+ const message = parsed.msg ?? "OKX API request failed.";
292
+ if (responseCode === "50111" || responseCode === "50112" || responseCode === "50113") {
293
+ throw new AuthenticationError(
294
+ message,
295
+ "Check API key, secret, passphrase and permissions.",
296
+ `${config.method} ${config.path}`
297
+ );
298
+ }
299
+ throw new OkxApiError(message, {
300
+ code: responseCode,
301
+ endpoint: `${config.method} ${config.path}`
302
+ });
303
+ }
304
+ return {
305
+ endpoint: `${config.method} ${config.path}`,
306
+ requestTime: (/* @__PURE__ */ new Date()).toISOString(),
307
+ data: parsed.data ?? null,
308
+ raw: parsed
309
+ };
310
+ }
311
+ };
312
+ var OKX_API_BASE_URL = "https://www.okx.com";
313
+ var MODULES = [
314
+ "market",
315
+ "spot",
316
+ "swap",
317
+ "account"
318
+ ];
319
+ var DEFAULT_MODULES = ["spot", "swap", "account"];
320
+ function configFilePath() {
321
+ return join(homedir(), ".okx", "config.toml");
322
+ }
323
+ function readTomlProfile(profileName) {
324
+ const path = configFilePath();
325
+ if (!existsSync(path)) return {};
326
+ const raw = readFileSync(path, "utf-8");
327
+ const config = parse(raw);
328
+ const name = profileName ?? config.default_profile ?? "default";
329
+ return config.profiles?.[name] ?? {};
330
+ }
331
+ function parseModuleList(rawModules) {
332
+ if (!rawModules || rawModules.trim().length === 0) {
333
+ return [...DEFAULT_MODULES];
334
+ }
335
+ const trimmed = rawModules.trim().toLowerCase();
336
+ if (trimmed === "all") {
337
+ return [...MODULES];
338
+ }
339
+ const requested = trimmed.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
340
+ if (requested.length === 0) {
341
+ return [...DEFAULT_MODULES];
342
+ }
343
+ const deduped = /* @__PURE__ */ new Set();
344
+ for (const moduleId of requested) {
345
+ if (!MODULES.includes(moduleId)) {
346
+ throw new ConfigError(
347
+ `Unknown module "${moduleId}".`,
348
+ `Use one of: ${MODULES.join(", ")} or "all".`
349
+ );
350
+ }
351
+ deduped.add(moduleId);
352
+ }
353
+ return Array.from(deduped);
354
+ }
355
+ function loadConfig(cli) {
356
+ const toml = readTomlProfile(cli.profile);
357
+ const apiKey = process.env.OKX_API_KEY?.trim() ?? toml.api_key;
358
+ const secretKey = process.env.OKX_SECRET_KEY?.trim() ?? toml.secret_key;
359
+ const passphrase = process.env.OKX_PASSPHRASE?.trim() ?? toml.passphrase;
360
+ const hasAuth = Boolean(apiKey && secretKey && passphrase);
361
+ const partialAuth = Boolean(apiKey) || Boolean(secretKey) || Boolean(passphrase);
362
+ if (partialAuth && !hasAuth) {
363
+ throw new ConfigError(
364
+ "Partial API credentials detected.",
365
+ "Set OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE together (env vars or config.toml profile)."
366
+ );
367
+ }
368
+ const demo = cli.demo || process.env.OKX_DEMO === "1" || process.env.OKX_DEMO === "true" || (toml.demo ?? false);
369
+ const rawBaseUrl = process.env.OKX_API_BASE_URL?.trim() ?? toml.base_url ?? OKX_API_BASE_URL;
370
+ if (!rawBaseUrl.startsWith("http://") && !rawBaseUrl.startsWith("https://")) {
371
+ throw new ConfigError(
372
+ `Invalid base URL "${rawBaseUrl}".`,
373
+ "OKX_API_BASE_URL must start with http:// or https://"
374
+ );
375
+ }
376
+ const baseUrl = rawBaseUrl.replace(/\/+$/, "");
377
+ const rawTimeout = process.env.OKX_TIMEOUT_MS ? Number(process.env.OKX_TIMEOUT_MS) : toml.timeout_ms ?? 15e3;
378
+ if (!Number.isFinite(rawTimeout) || rawTimeout <= 0) {
379
+ throw new ConfigError(
380
+ `Invalid timeout value "${rawTimeout}".`,
381
+ "Set OKX_TIMEOUT_MS as a positive integer in milliseconds."
382
+ );
383
+ }
384
+ return {
385
+ apiKey,
386
+ secretKey,
387
+ passphrase,
388
+ hasAuth,
389
+ baseUrl,
390
+ timeoutMs: Math.floor(rawTimeout),
391
+ modules: parseModuleList(cli.modules),
392
+ readOnly: cli.readOnly,
393
+ demo
394
+ };
395
+ }
6
396
 
7
397
  // src/config/loader.ts
8
- import { loadConfig } from "@okx-hub/core";
9
398
  function loadProfileConfig(opts) {
10
399
  return loadConfig({
11
400
  profile: opts.profile,
@@ -456,37 +845,33 @@ async function cmdSwapSetLeverage(client, opts) {
456
845
  `);
457
846
  }
458
847
 
459
- // src/commands/config.ts
460
- import { configFilePath as configFilePath2 } from "@okx-hub/core";
461
-
462
848
  // src/config/toml.ts
463
- import { writeFileSync, mkdirSync, existsSync } from "fs";
849
+ import { writeFileSync, mkdirSync, existsSync as existsSync2 } from "fs";
464
850
  import { stringify } from "smol-toml";
465
- import { configFilePath } from "@okx-hub/core";
466
851
  function configDir() {
467
852
  return configFilePath().replace(/\/config\.toml$/, "");
468
853
  }
469
854
  function writeCliConfig(config) {
470
855
  const dir = configDir();
471
- if (!existsSync(dir)) {
856
+ if (!existsSync2(dir)) {
472
857
  mkdirSync(dir, { recursive: true });
473
858
  }
474
859
  writeFileSync(configFilePath(), stringify(config), "utf-8");
475
860
  }
476
861
 
477
862
  // src/commands/config.ts
478
- import { existsSync as existsSync2, readFileSync } from "fs";
479
- import { parse } from "smol-toml";
863
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
864
+ import { parse as parse2 } from "smol-toml";
480
865
  function readFullConfig() {
481
- const path = configFilePath2();
482
- if (!existsSync2(path)) return { profiles: {} };
483
- const raw = readFileSync(path, "utf-8");
484
- return parse(raw);
866
+ const path = configFilePath();
867
+ if (!existsSync3(path)) return { profiles: {} };
868
+ const raw = readFileSync2(path, "utf-8");
869
+ return parse2(raw);
485
870
  }
486
871
  function cmdConfigShow(json) {
487
872
  const config = readFullConfig();
488
873
  if (json) return printJson(config);
489
- process.stdout.write(`Config: ${configFilePath2()}
874
+ process.stdout.write(`Config: ${configFilePath()}
490
875
 
491
876
  `);
492
877
  process.stdout.write(`default_profile: ${config.default_profile ?? "(not set)"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config/loader.ts","../src/formatter.ts","../src/commands/market.ts","../src/commands/account.ts","../src/commands/spot.ts","../src/commands/swap.ts","../src/commands/config.ts","../src/config/toml.ts"],"sourcesContent":["import { parseArgs } from \"node:util\";\nimport { OkxRestClient, toToolErrorPayload } from \"@okx-hub/core\";\nimport { loadProfileConfig } from \"./config/loader.js\";\nimport {\n cmdMarketTicker,\n cmdMarketTickers,\n cmdMarketOrderbook,\n cmdMarketCandles,\n} from \"./commands/market.js\";\nimport { cmdAccountBalance } from \"./commands/account.js\";\nimport {\n cmdSpotOrders,\n cmdSpotPlace,\n cmdSpotCancel,\n cmdSpotFills,\n cmdSpotAlgoPlace,\n cmdSpotAlgoAmend,\n cmdSpotAlgoCancel,\n cmdSpotAlgoOrders,\n} from \"./commands/spot.js\";\nimport {\n cmdSwapPositions,\n cmdSwapOrders,\n cmdSwapPlace,\n cmdSwapCancel,\n cmdSwapSetLeverage,\n cmdSwapAlgoPlace,\n cmdSwapAlgoAmend,\n cmdSwapAlgoCancel,\n cmdSwapAlgoOrders,\n} from \"./commands/swap.js\";\nimport { cmdConfigShow, cmdConfigSet } from \"./commands/config.js\";\n\nfunction printHelp(): void {\n process.stdout.write(`\nUsage: okx [--profile <name>] [--json] <command> [args]\n\nGlobal Options:\n --profile <name> Use a named profile from ~/.okx/config.toml\n --json Output raw JSON\n --help Show this help\n\nCommands:\n market ticker <instId>\n market tickers <instType> (SPOT|SWAP|FUTURES|OPTION)\n market orderbook <instId> [--sz <n>]\n market candles <instId> [--bar <bar>] [--limit <n>]\n\n account balance [<ccy>]\n\n spot orders [--instId <id>] [--history]\n spot fills [--instId <id>] [--ordId <id>]\n spot place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--px <price>]\n spot cancel <instId> --ordId <id>\n spot algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]\n spot algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>]\n spot algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]\n spot algo cancel --instId <id> --algoId <id>\n\n swap positions [<instId>]\n swap orders [--instId <id>] [--history]\n swap place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--posSide <side>] [--px <price>] [--tdMode <cross|isolated>]\n swap cancel <instId> --ordId <id>\n swap leverage --instId <id> --lever <n> --mgnMode <cross|isolated> [--posSide <side>]\n swap algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]\n swap algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>]\n [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]\n swap algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]\n swap algo cancel --instId <id> --algoId <id>\n\n config show\n config set <key> <value>\n`);\n}\n\nasync function main(): Promise<void> {\n const { values, positionals } = parseArgs({\n args: process.argv.slice(2),\n options: {\n profile: { type: \"string\" },\n json: { type: \"boolean\", default: false },\n help: { type: \"boolean\", default: false },\n // market candles\n bar: { type: \"string\" },\n limit: { type: \"string\" },\n sz: { type: \"string\" },\n // orders\n instId: { type: \"string\" },\n history: { type: \"boolean\", default: false },\n ordId: { type: \"string\" },\n // trade\n side: { type: \"string\" },\n ordType: { type: \"string\" },\n px: { type: \"string\" },\n posSide: { type: \"string\" },\n tdMode: { type: \"string\" },\n // leverage\n lever: { type: \"string\" },\n mgnMode: { type: \"string\" },\n // algo orders\n tpTriggerPx: { type: \"string\" },\n tpOrdPx: { type: \"string\" },\n slTriggerPx: { type: \"string\" },\n slOrdPx: { type: \"string\" },\n algoId: { type: \"string\" },\n reduceOnly: { type: \"boolean\", default: false },\n // algo amend\n newSz: { type: \"string\" },\n newTpTriggerPx: { type: \"string\" },\n newTpOrdPx: { type: \"string\" },\n newSlTriggerPx: { type: \"string\" },\n newSlOrdPx: { type: \"string\" },\n },\n allowPositionals: true,\n });\n\n if (values.help || positionals.length === 0) {\n printHelp();\n return;\n }\n\n const [module, action, ...rest] = positionals;\n const json = values.json ?? false;\n\n // config commands don't need a client\n if (module === \"config\") {\n if (action === \"show\") return cmdConfigShow(json);\n if (action === \"set\") return cmdConfigSet(rest[0], rest[1]);\n process.stderr.write(`Unknown config command: ${action}\\n`);\n process.exitCode = 1;\n return;\n }\n\n const config = loadProfileConfig({ profile: values.profile });\n const client = new OkxRestClient(config);\n\n if (module === \"market\") {\n if (action === \"ticker\") return cmdMarketTicker(client, rest[0], json);\n if (action === \"tickers\") return cmdMarketTickers(client, rest[0], json);\n if (action === \"orderbook\")\n return cmdMarketOrderbook(client, rest[0], values.sz ? Number(values.sz) : undefined, json);\n if (action === \"candles\")\n return cmdMarketCandles(client, rest[0], {\n bar: values.bar,\n limit: values.limit ? Number(values.limit) : undefined,\n json,\n });\n }\n\n if (module === \"account\") {\n if (action === \"balance\") return cmdAccountBalance(client, rest[0], json);\n }\n\n if (module === \"spot\") {\n if (action === \"orders\")\n return cmdSpotOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"open\",\n json,\n });\n if (action === \"fills\")\n return cmdSpotFills(client, { instId: values.instId, ordId: values.ordId, json });\n if (action === \"place\")\n return cmdSpotPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType!,\n sz: values.sz!,\n px: values.px,\n json,\n });\n if (action === \"cancel\")\n return cmdSpotCancel(client, rest[0], values.ordId!, json);\n if (action === \"algo\") {\n const subAction = rest[0];\n if (subAction === \"place\")\n return cmdSpotAlgoPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType ?? \"conditional\",\n sz: values.sz!,\n tpTriggerPx: values.tpTriggerPx,\n tpOrdPx: values.tpOrdPx,\n slTriggerPx: values.slTriggerPx,\n slOrdPx: values.slOrdPx,\n json,\n });\n if (subAction === \"amend\")\n return cmdSpotAlgoAmend(client, {\n instId: values.instId!,\n algoId: values.algoId!,\n newSz: values.newSz,\n newTpTriggerPx: values.newTpTriggerPx,\n newTpOrdPx: values.newTpOrdPx,\n newSlTriggerPx: values.newSlTriggerPx,\n newSlOrdPx: values.newSlOrdPx,\n json,\n });\n if (subAction === \"cancel\")\n return cmdSpotAlgoCancel(client, values.instId!, values.algoId!, json);\n if (subAction === \"orders\")\n return cmdSpotAlgoOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"pending\",\n ordType: values.ordType,\n json,\n });\n }\n }\n\n if (module === \"swap\") {\n if (action === \"positions\")\n return cmdSwapPositions(client, rest[0] ?? values.instId, json);\n if (action === \"orders\")\n return cmdSwapOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"open\",\n json,\n });\n if (action === \"place\")\n return cmdSwapPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType!,\n sz: values.sz!,\n posSide: values.posSide,\n px: values.px,\n tdMode: values.tdMode ?? \"cross\",\n json,\n });\n if (action === \"cancel\")\n return cmdSwapCancel(client, rest[0], values.ordId!, json);\n if (action === \"leverage\")\n return cmdSwapSetLeverage(client, {\n instId: values.instId!,\n lever: values.lever!,\n mgnMode: values.mgnMode!,\n posSide: values.posSide,\n json,\n });\n if (action === \"algo\") {\n const subAction = rest[0];\n if (subAction === \"place\")\n return cmdSwapAlgoPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType ?? \"conditional\",\n sz: values.sz!,\n posSide: values.posSide,\n tdMode: values.tdMode ?? \"cross\",\n tpTriggerPx: values.tpTriggerPx,\n tpOrdPx: values.tpOrdPx,\n slTriggerPx: values.slTriggerPx,\n slOrdPx: values.slOrdPx,\n reduceOnly: values.reduceOnly,\n json,\n });\n if (subAction === \"amend\")\n return cmdSwapAlgoAmend(client, {\n instId: values.instId!,\n algoId: values.algoId!,\n newSz: values.newSz,\n newTpTriggerPx: values.newTpTriggerPx,\n newTpOrdPx: values.newTpOrdPx,\n newSlTriggerPx: values.newSlTriggerPx,\n newSlOrdPx: values.newSlOrdPx,\n json,\n });\n if (subAction === \"cancel\")\n return cmdSwapAlgoCancel(client, values.instId!, values.algoId!, json);\n if (subAction === \"orders\")\n return cmdSwapAlgoOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"pending\",\n ordType: values.ordType,\n json,\n });\n }\n }\n\n process.stderr.write(`Unknown command: ${module} ${action ?? \"\"}\\n`);\n process.exitCode = 1;\n}\n\nmain().catch((error: unknown) => {\n const payload = toToolErrorPayload(error);\n process.stderr.write(`Error: ${payload.message}\\n`);\n if (payload.suggestion) process.stderr.write(`Hint: ${payload.suggestion}\\n`);\n process.exitCode = 1;\n});\n","import type { OkxConfig } from \"@okx-hub/core\";\nimport { loadConfig } from \"@okx-hub/core\";\n\nexport interface LoadProfileOptions {\n profile?: string;\n modules?: string;\n readOnly?: boolean;\n demo?: boolean;\n}\n\n/**\n * Load config for CLI commands.\n * Delegates to core's loadConfig which handles the full priority chain:\n * env vars > ~/.okx/config.toml (selected profile) > defaults\n */\nexport function loadProfileConfig(opts: LoadProfileOptions): OkxConfig {\n return loadConfig({\n profile: opts.profile,\n modules: opts.modules,\n readOnly: opts.readOnly ?? false,\n demo: opts.demo ?? false,\n });\n}\n","export function printJson(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n}\n\nexport function printTable(rows: Record<string, unknown>[]): void {\n if (rows.length === 0) {\n process.stdout.write(\"(no data)\\n\");\n return;\n }\n const keys = Object.keys(rows[0]);\n const widths = keys.map((k) =>\n Math.max(k.length, ...rows.map((r) => String(r[k] ?? \"\").length)),\n );\n const header = keys.map((k, i) => k.padEnd(widths[i])).join(\" \");\n const divider = widths.map((w) => \"-\".repeat(w)).join(\" \");\n process.stdout.write(header + \"\\n\" + divider + \"\\n\");\n for (const row of rows) {\n process.stdout.write(\n keys.map((k, i) => String(row[k] ?? \"\").padEnd(widths[i])).join(\" \") + \"\\n\",\n );\n }\n}\n\nexport function printKv(obj: Record<string, unknown>, indent = 0): void {\n const pad = \" \".repeat(indent);\n for (const [k, v] of Object.entries(obj)) {\n if (v !== null && typeof v === \"object\" && !Array.isArray(v)) {\n process.stdout.write(`${pad}${k}:\\n`);\n printKv(v as Record<string, unknown>, indent + 2);\n } else {\n process.stdout.write(`${pad}${k.padEnd(20 - indent)} ${v}\\n`);\n }\n }\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printKv, printTable } from \"../formatter.js\";\n\nexport async function cmdMarketTicker(\n client: OkxRestClient,\n instId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.publicGet(\"/api/v5/market/ticker\", { instId });\n const items = res.data as Record<string, unknown>[];\n if (json) return printJson(items);\n if (!items?.length) { process.stdout.write(\"No data\\n\"); return; }\n const t = items[0];\n printKv({\n instId: t[\"instId\"],\n last: t[\"last\"],\n \"24h change %\": t[\"sodUtc8\"],\n \"24h high\": t[\"high24h\"],\n \"24h low\": t[\"low24h\"],\n \"24h vol\": t[\"vol24h\"],\n time: new Date(Number(t[\"ts\"])).toLocaleString(),\n });\n}\n\nexport async function cmdMarketTickers(\n client: OkxRestClient,\n instType: string,\n json: boolean,\n): Promise<void> {\n const res = await client.publicGet(\"/api/v5/market/tickers\", { instType });\n const items = res.data as Record<string, unknown>[];\n if (json) return printJson(items);\n printTable(\n (items ?? []).map((t) => ({\n instId: t[\"instId\"],\n last: t[\"last\"],\n \"24h high\": t[\"high24h\"],\n \"24h low\": t[\"low24h\"],\n \"24h vol\": t[\"vol24h\"],\n })),\n );\n}\n\nexport async function cmdMarketOrderbook(\n client: OkxRestClient,\n instId: string,\n sz: number | undefined,\n json: boolean,\n): Promise<void> {\n const params: Record<string, unknown> = { instId };\n if (sz !== undefined) params[\"sz\"] = String(sz);\n const res = await client.publicGet(\"/api/v5/market/books\", params);\n if (json) return printJson(res.data);\n const book = (res.data as Record<string, unknown>[])[0];\n if (!book) { process.stdout.write(\"No data\\n\"); return; }\n const asks = (book[\"asks\"] as string[][]).slice(0, 5);\n const bids = (book[\"bids\"] as string[][]).slice(0, 5);\n process.stdout.write(\"Asks (price / size):\\n\");\n for (const [p, s] of asks.reverse()) process.stdout.write(` ${p.padStart(16)} ${s}\\n`);\n process.stdout.write(\"Bids (price / size):\\n\");\n for (const [p, s] of bids) process.stdout.write(` ${p.padStart(16)} ${s}\\n`);\n}\n\nexport async function cmdMarketCandles(\n client: OkxRestClient,\n instId: string,\n opts: { bar?: string; limit?: number; json: boolean },\n): Promise<void> {\n const params: Record<string, unknown> = { instId };\n if (opts.bar) params[\"bar\"] = opts.bar;\n if (opts.limit) params[\"limit\"] = String(opts.limit);\n const res = await client.publicGet(\"/api/v5/market/candles\", params);\n const candles = res.data as string[][];\n if (opts.json) return printJson(candles);\n printTable(\n (candles ?? []).map(([ts, o, h, l, c, vol]) => ({\n time: new Date(Number(ts)).toLocaleString(),\n open: o, high: h, low: l, close: c, vol,\n })),\n );\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printTable } from \"../formatter.js\";\n\nexport async function cmdAccountBalance(\n client: OkxRestClient,\n ccy: string | undefined,\n json: boolean,\n): Promise<void> {\n const params: Record<string, unknown> = {};\n if (ccy) params[\"ccy\"] = ccy;\n const res = await client.privateGet(\"/api/v5/account/balance\", params);\n const data = res.data as Record<string, unknown>[];\n if (json) return printJson(data);\n const details = (data?.[0]?.[\"details\"] as Record<string, unknown>[]) ?? [];\n printTable(\n details\n .filter((d) => Number(d[\"eq\"]) > 0)\n .map((d) => ({\n currency: d[\"ccy\"],\n equity: d[\"eq\"],\n available: d[\"availEq\"],\n frozen: d[\"frozenBal\"],\n })),\n );\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printTable } from \"../formatter.js\";\n\nexport async function cmdSpotOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"open\" | \"history\"; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-history\"\n : \"/api/v5/trade/orders-pending\";\n const params: Record<string, unknown> = { instType: \"SPOT\" };\n if (opts.instId) params[\"instId\"] = opts.instId;\n const res = await client.privateGet(endpoint, params);\n const orders = res.data as Record<string, unknown>[];\n if (opts.json) return printJson(orders);\n printTable(\n (orders ?? []).map((o) => ({\n ordId: o[\"ordId\"],\n instId: o[\"instId\"],\n side: o[\"side\"],\n type: o[\"ordType\"],\n price: o[\"px\"],\n size: o[\"sz\"],\n filled: o[\"fillSz\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSpotPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n px?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: \"cash\",\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.px) body[\"px\"] = opts.px;\n const res = await client.privatePost(\"/api/v5/trade/order\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Order placed: ${order?.[\"ordId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSpotCancel(\n client: OkxRestClient,\n instId: string,\n ordId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-order\", { instId, ordId });\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Cancelled: ${r?.[\"ordId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSpotAlgoPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n tpTriggerPx?: string;\n tpOrdPx?: string;\n slTriggerPx?: string;\n slOrdPx?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: \"cash\",\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.tpTriggerPx) body[\"tpTriggerPx\"] = opts.tpTriggerPx;\n if (opts.tpOrdPx) body[\"tpOrdPx\"] = opts.tpOrdPx;\n if (opts.slTriggerPx) body[\"slTriggerPx\"] = opts.slTriggerPx;\n if (opts.slOrdPx) body[\"slOrdPx\"] = opts.slOrdPx;\n const res = await client.privatePost(\"/api/v5/trade/order-algo\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order placed: ${order?.[\"algoId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSpotAlgoAmend(\n client: OkxRestClient,\n opts: {\n instId: string;\n algoId: string;\n newSz?: string;\n newTpTriggerPx?: string;\n newTpOrdPx?: string;\n newSlTriggerPx?: string;\n newSlOrdPx?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n algoId: opts.algoId,\n };\n if (opts.newSz) body[\"newSz\"] = opts.newSz;\n if (opts.newTpTriggerPx) body[\"newTpTriggerPx\"] = opts.newTpTriggerPx;\n if (opts.newTpOrdPx) body[\"newTpOrdPx\"] = opts.newTpOrdPx;\n if (opts.newSlTriggerPx) body[\"newSlTriggerPx\"] = opts.newSlTriggerPx;\n if (opts.newSlOrdPx) body[\"newSlOrdPx\"] = opts.newSlOrdPx;\n const res = await client.privatePost(\"/api/v5/trade/amend-algos\", body);\n if (opts.json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order amended: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSpotAlgoCancel(\n client: OkxRestClient,\n instId: string,\n algoId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-algos\", [\n { algoId, instId },\n ]);\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order cancelled: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSpotAlgoOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"pending\" | \"history\"; ordType?: string; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-algo-history\"\n : \"/api/v5/trade/orders-algo-pending\";\n const baseParams: Record<string, unknown> = { instType: \"SPOT\" };\n if (opts.instId) baseParams[\"instId\"] = opts.instId;\n\n let orders: Record<string, unknown>[];\n if (opts.ordType) {\n const res = await client.privateGet(endpoint, { ...baseParams, ordType: opts.ordType });\n orders = (res.data as Record<string, unknown>[]) ?? [];\n } else {\n const [r1, r2] = await Promise.all([\n client.privateGet(endpoint, { ...baseParams, ordType: \"conditional\" }),\n client.privateGet(endpoint, { ...baseParams, ordType: \"oco\" }),\n ]);\n orders = [\n ...((r1.data as Record<string, unknown>[]) ?? []),\n ...((r2.data as Record<string, unknown>[]) ?? []),\n ];\n }\n\n if (opts.json) return printJson(orders);\n if (!(orders ?? []).length) { process.stdout.write(\"No algo orders\\n\"); return; }\n printTable(\n orders.map((o) => ({\n algoId: o[\"algoId\"],\n instId: o[\"instId\"],\n type: o[\"ordType\"],\n side: o[\"side\"],\n sz: o[\"sz\"],\n tpTrigger: o[\"tpTriggerPx\"],\n slTrigger: o[\"slTriggerPx\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSpotFills(\n client: OkxRestClient,\n opts: { instId?: string; ordId?: string; json: boolean },\n): Promise<void> {\n const params: Record<string, unknown> = { instType: \"SPOT\" };\n if (opts.instId) params[\"instId\"] = opts.instId;\n if (opts.ordId) params[\"ordId\"] = opts.ordId;\n const res = await client.privateGet(\"/api/v5/trade/fills\", params);\n const fills = res.data as Record<string, unknown>[];\n if (opts.json) return printJson(fills);\n printTable(\n (fills ?? []).map((f) => ({\n instId: f[\"instId\"],\n side: f[\"side\"],\n fillPx: f[\"fillPx\"],\n fillSz: f[\"fillSz\"],\n fee: f[\"fee\"],\n ts: new Date(Number(f[\"ts\"])).toLocaleString(),\n })),\n );\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printTable } from \"../formatter.js\";\n\nexport async function cmdSwapPositions(\n client: OkxRestClient,\n instId: string | undefined,\n json: boolean,\n): Promise<void> {\n const params: Record<string, unknown> = { instType: \"SWAP\" };\n if (instId) params[\"instId\"] = instId;\n const res = await client.privateGet(\"/api/v5/account/positions\", params);\n const positions = res.data as Record<string, unknown>[];\n if (json) return printJson(positions);\n const open = (positions ?? []).filter((p) => Number(p[\"pos\"]) !== 0);\n if (!open.length) { process.stdout.write(\"No open positions\\n\"); return; }\n printTable(\n open.map((p) => ({\n instId: p[\"instId\"],\n side: p[\"posSide\"],\n size: p[\"pos\"],\n avgPx: p[\"avgPx\"],\n upl: p[\"upl\"],\n uplRatio: p[\"uplRatio\"],\n lever: p[\"lever\"],\n })),\n );\n}\n\nexport async function cmdSwapOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"open\" | \"history\"; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-history\"\n : \"/api/v5/trade/orders-pending\";\n const params: Record<string, unknown> = { instType: \"SWAP\" };\n if (opts.instId) params[\"instId\"] = opts.instId;\n const res = await client.privateGet(endpoint, params);\n const orders = res.data as Record<string, unknown>[];\n if (opts.json) return printJson(orders);\n printTable(\n (orders ?? []).map((o) => ({\n ordId: o[\"ordId\"],\n instId: o[\"instId\"],\n side: o[\"side\"],\n posSide: o[\"posSide\"],\n type: o[\"ordType\"],\n price: o[\"px\"],\n size: o[\"sz\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSwapPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n posSide?: string;\n px?: string;\n tdMode: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: opts.tdMode,\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.posSide) body[\"posSide\"] = opts.posSide;\n if (opts.px) body[\"px\"] = opts.px;\n const res = await client.privatePost(\"/api/v5/trade/order\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Order placed: ${order?.[\"ordId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSwapCancel(\n client: OkxRestClient,\n instId: string,\n ordId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-order\", { instId, ordId });\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Cancelled: ${r?.[\"ordId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSwapAlgoPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n posSide?: string;\n tdMode: string;\n tpTriggerPx?: string;\n tpOrdPx?: string;\n slTriggerPx?: string;\n slOrdPx?: string;\n reduceOnly?: boolean;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: opts.tdMode,\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.posSide) body[\"posSide\"] = opts.posSide;\n if (opts.tpTriggerPx) body[\"tpTriggerPx\"] = opts.tpTriggerPx;\n if (opts.tpOrdPx) body[\"tpOrdPx\"] = opts.tpOrdPx;\n if (opts.slTriggerPx) body[\"slTriggerPx\"] = opts.slTriggerPx;\n if (opts.slOrdPx) body[\"slOrdPx\"] = opts.slOrdPx;\n if (opts.reduceOnly !== undefined) body[\"reduceOnly\"] = String(opts.reduceOnly);\n const res = await client.privatePost(\"/api/v5/trade/order-algo\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order placed: ${order?.[\"algoId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSwapAlgoAmend(\n client: OkxRestClient,\n opts: {\n instId: string;\n algoId: string;\n newSz?: string;\n newTpTriggerPx?: string;\n newTpOrdPx?: string;\n newSlTriggerPx?: string;\n newSlOrdPx?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n algoId: opts.algoId,\n };\n if (opts.newSz) body[\"newSz\"] = opts.newSz;\n if (opts.newTpTriggerPx) body[\"newTpTriggerPx\"] = opts.newTpTriggerPx;\n if (opts.newTpOrdPx) body[\"newTpOrdPx\"] = opts.newTpOrdPx;\n if (opts.newSlTriggerPx) body[\"newSlTriggerPx\"] = opts.newSlTriggerPx;\n if (opts.newSlOrdPx) body[\"newSlOrdPx\"] = opts.newSlOrdPx;\n const res = await client.privatePost(\"/api/v5/trade/amend-algos\", body);\n if (opts.json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order amended: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSwapAlgoCancel(\n client: OkxRestClient,\n instId: string,\n algoId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-algos\", [\n { algoId, instId },\n ]);\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order cancelled: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSwapAlgoOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"pending\" | \"history\"; ordType?: string; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-algo-history\"\n : \"/api/v5/trade/orders-algo-pending\";\n const baseParams: Record<string, unknown> = { instType: \"SWAP\" };\n if (opts.instId) baseParams[\"instId\"] = opts.instId;\n\n let orders: Record<string, unknown>[];\n if (opts.ordType) {\n const res = await client.privateGet(endpoint, { ...baseParams, ordType: opts.ordType });\n orders = (res.data as Record<string, unknown>[]) ?? [];\n } else {\n const [r1, r2] = await Promise.all([\n client.privateGet(endpoint, { ...baseParams, ordType: \"conditional\" }),\n client.privateGet(endpoint, { ...baseParams, ordType: \"oco\" }),\n ]);\n orders = [\n ...((r1.data as Record<string, unknown>[]) ?? []),\n ...((r2.data as Record<string, unknown>[]) ?? []),\n ];\n }\n\n if (opts.json) return printJson(orders);\n if (!(orders ?? []).length) { process.stdout.write(\"No algo orders\\n\"); return; }\n printTable(\n orders.map((o) => ({\n algoId: o[\"algoId\"],\n instId: o[\"instId\"],\n type: o[\"ordType\"],\n side: o[\"side\"],\n sz: o[\"sz\"],\n tpTrigger: o[\"tpTriggerPx\"],\n slTrigger: o[\"slTriggerPx\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSwapSetLeverage(\n client: OkxRestClient,\n opts: { instId: string; lever: string; mgnMode: string; posSide?: string; json: boolean },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n lever: opts.lever,\n mgnMode: opts.mgnMode,\n };\n if (opts.posSide) body[\"posSide\"] = opts.posSide;\n const res = await client.privatePost(\"/api/v5/account/set-leverage\", body);\n if (opts.json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Leverage set: ${r?.[\"lever\"]}x ${r?.[\"instId\"]}\\n`);\n}\n","import { readTomlProfile, configFilePath } from \"@okx-hub/core\";\nimport { writeCliConfig } from \"../config/toml.js\";\nimport { printJson, printKv } from \"../formatter.js\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { parse } from \"smol-toml\";\nimport type { OkxTomlConfig } from \"@okx-hub/core\";\n\nfunction readFullConfig(): OkxTomlConfig {\n const path = configFilePath();\n if (!existsSync(path)) return { profiles: {} };\n const raw = readFileSync(path, \"utf-8\");\n return parse(raw) as unknown as OkxTomlConfig;\n}\n\nexport function cmdConfigShow(json: boolean): void {\n const config = readFullConfig();\n if (json) return printJson(config);\n process.stdout.write(`Config: ${configFilePath()}\\n\\n`);\n process.stdout.write(`default_profile: ${config.default_profile ?? \"(not set)\"}\\n\\n`);\n for (const [name, profile] of Object.entries(config.profiles)) {\n process.stdout.write(`[${name}]\\n`);\n printKv({\n api_key: profile.api_key ? \"***\" + profile.api_key.slice(-4) : \"(not set)\",\n demo: profile.demo ?? false,\n base_url: profile.base_url ?? \"(default)\",\n }, 2);\n process.stdout.write(\"\\n\");\n }\n}\n\nexport function cmdConfigSet(key: string, value: string): void {\n const config = readFullConfig();\n if (key === \"default_profile\") {\n config.default_profile = value;\n writeCliConfig(config);\n process.stdout.write(`default_profile set to \"${value}\"\\n`);\n } else {\n process.stderr.write(`Unknown config key: ${key}\\n`);\n process.exitCode = 1;\n }\n}\n","import { writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { stringify } from \"smol-toml\";\nimport { configFilePath } from \"@okx-hub/core\";\nimport type { OkxTomlConfig } from \"@okx-hub/core\";\n\n// Re-export for backward compat within CLI\nexport type { OkxTomlConfig as CliConfig };\nexport { configFilePath as configPath };\n\nexport function configDir(): string {\n return configFilePath().replace(/\\/config\\.toml$/, \"\");\n}\n\nexport function writeCliConfig(config: OkxTomlConfig): void {\n const dir = configDir();\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(configFilePath(), stringify(config as unknown as Record<string, unknown>), \"utf-8\");\n}\n"],"mappings":"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","names":["configFilePath","existsSync","configFilePath"]}
1
+ {"version":3,"sources":["../src/index.ts","../node_modules/@okx-hub/core/src/utils/signature.ts","../node_modules/@okx-hub/core/src/utils/errors.ts","../node_modules/@okx-hub/core/src/utils/rate-limiter.ts","../node_modules/@okx-hub/core/src/client/rest-client.ts","../node_modules/@okx-hub/core/src/tools/helpers.ts","../node_modules/@okx-hub/core/src/tools/common.ts","../node_modules/@okx-hub/core/src/tools/account.ts","../node_modules/@okx-hub/core/src/tools/algo-trade.ts","../node_modules/@okx-hub/core/src/tools/market.ts","../node_modules/@okx-hub/core/src/tools/spot-trade.ts","../node_modules/@okx-hub/core/src/tools/swap-trade.ts","../node_modules/@okx-hub/core/src/tools/index.ts","../node_modules/@okx-hub/core/src/tools/types.ts","../node_modules/@okx-hub/core/src/constants.ts","../node_modules/@okx-hub/core/src/config/toml.ts","../node_modules/@okx-hub/core/src/config.ts","../src/config/loader.ts","../src/formatter.ts","../src/commands/market.ts","../src/commands/account.ts","../src/commands/spot.ts","../src/commands/swap.ts","../src/config/toml.ts","../src/commands/config.ts"],"sourcesContent":["import { parseArgs } from \"node:util\";\nimport { OkxRestClient, toToolErrorPayload } from \"@okx-hub/core\";\nimport { loadProfileConfig } from \"./config/loader.js\";\nimport {\n cmdMarketTicker,\n cmdMarketTickers,\n cmdMarketOrderbook,\n cmdMarketCandles,\n} from \"./commands/market.js\";\nimport { cmdAccountBalance } from \"./commands/account.js\";\nimport {\n cmdSpotOrders,\n cmdSpotPlace,\n cmdSpotCancel,\n cmdSpotFills,\n cmdSpotAlgoPlace,\n cmdSpotAlgoAmend,\n cmdSpotAlgoCancel,\n cmdSpotAlgoOrders,\n} from \"./commands/spot.js\";\nimport {\n cmdSwapPositions,\n cmdSwapOrders,\n cmdSwapPlace,\n cmdSwapCancel,\n cmdSwapSetLeverage,\n cmdSwapAlgoPlace,\n cmdSwapAlgoAmend,\n cmdSwapAlgoCancel,\n cmdSwapAlgoOrders,\n} from \"./commands/swap.js\";\nimport { cmdConfigShow, cmdConfigSet } from \"./commands/config.js\";\n\nfunction printHelp(): void {\n process.stdout.write(`\nUsage: okx [--profile <name>] [--json] <command> [args]\n\nGlobal Options:\n --profile <name> Use a named profile from ~/.okx/config.toml\n --json Output raw JSON\n --help Show this help\n\nCommands:\n market ticker <instId>\n market tickers <instType> (SPOT|SWAP|FUTURES|OPTION)\n market orderbook <instId> [--sz <n>]\n market candles <instId> [--bar <bar>] [--limit <n>]\n\n account balance [<ccy>]\n\n spot orders [--instId <id>] [--history]\n spot fills [--instId <id>] [--ordId <id>]\n spot place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--px <price>]\n spot cancel <instId> --ordId <id>\n spot algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]\n spot algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>]\n spot algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]\n spot algo cancel --instId <id> --algoId <id>\n\n swap positions [<instId>]\n swap orders [--instId <id>] [--history]\n swap place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--posSide <side>] [--px <price>] [--tdMode <cross|isolated>]\n swap cancel <instId> --ordId <id>\n swap leverage --instId <id> --lever <n> --mgnMode <cross|isolated> [--posSide <side>]\n swap algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]\n swap algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>]\n [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]\n swap algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]\n swap algo cancel --instId <id> --algoId <id>\n\n config show\n config set <key> <value>\n`);\n}\n\nasync function main(): Promise<void> {\n const { values, positionals } = parseArgs({\n args: process.argv.slice(2),\n options: {\n profile: { type: \"string\" },\n json: { type: \"boolean\", default: false },\n help: { type: \"boolean\", default: false },\n // market candles\n bar: { type: \"string\" },\n limit: { type: \"string\" },\n sz: { type: \"string\" },\n // orders\n instId: { type: \"string\" },\n history: { type: \"boolean\", default: false },\n ordId: { type: \"string\" },\n // trade\n side: { type: \"string\" },\n ordType: { type: \"string\" },\n px: { type: \"string\" },\n posSide: { type: \"string\" },\n tdMode: { type: \"string\" },\n // leverage\n lever: { type: \"string\" },\n mgnMode: { type: \"string\" },\n // algo orders\n tpTriggerPx: { type: \"string\" },\n tpOrdPx: { type: \"string\" },\n slTriggerPx: { type: \"string\" },\n slOrdPx: { type: \"string\" },\n algoId: { type: \"string\" },\n reduceOnly: { type: \"boolean\", default: false },\n // algo amend\n newSz: { type: \"string\" },\n newTpTriggerPx: { type: \"string\" },\n newTpOrdPx: { type: \"string\" },\n newSlTriggerPx: { type: \"string\" },\n newSlOrdPx: { type: \"string\" },\n },\n allowPositionals: true,\n });\n\n if (values.help || positionals.length === 0) {\n printHelp();\n return;\n }\n\n const [module, action, ...rest] = positionals;\n const json = values.json ?? false;\n\n // config commands don't need a client\n if (module === \"config\") {\n if (action === \"show\") return cmdConfigShow(json);\n if (action === \"set\") return cmdConfigSet(rest[0], rest[1]);\n process.stderr.write(`Unknown config command: ${action}\\n`);\n process.exitCode = 1;\n return;\n }\n\n const config = loadProfileConfig({ profile: values.profile });\n const client = new OkxRestClient(config);\n\n if (module === \"market\") {\n if (action === \"ticker\") return cmdMarketTicker(client, rest[0], json);\n if (action === \"tickers\") return cmdMarketTickers(client, rest[0], json);\n if (action === \"orderbook\")\n return cmdMarketOrderbook(client, rest[0], values.sz ? Number(values.sz) : undefined, json);\n if (action === \"candles\")\n return cmdMarketCandles(client, rest[0], {\n bar: values.bar,\n limit: values.limit ? Number(values.limit) : undefined,\n json,\n });\n }\n\n if (module === \"account\") {\n if (action === \"balance\") return cmdAccountBalance(client, rest[0], json);\n }\n\n if (module === \"spot\") {\n if (action === \"orders\")\n return cmdSpotOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"open\",\n json,\n });\n if (action === \"fills\")\n return cmdSpotFills(client, { instId: values.instId, ordId: values.ordId, json });\n if (action === \"place\")\n return cmdSpotPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType!,\n sz: values.sz!,\n px: values.px,\n json,\n });\n if (action === \"cancel\")\n return cmdSpotCancel(client, rest[0], values.ordId!, json);\n if (action === \"algo\") {\n const subAction = rest[0];\n if (subAction === \"place\")\n return cmdSpotAlgoPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType ?? \"conditional\",\n sz: values.sz!,\n tpTriggerPx: values.tpTriggerPx,\n tpOrdPx: values.tpOrdPx,\n slTriggerPx: values.slTriggerPx,\n slOrdPx: values.slOrdPx,\n json,\n });\n if (subAction === \"amend\")\n return cmdSpotAlgoAmend(client, {\n instId: values.instId!,\n algoId: values.algoId!,\n newSz: values.newSz,\n newTpTriggerPx: values.newTpTriggerPx,\n newTpOrdPx: values.newTpOrdPx,\n newSlTriggerPx: values.newSlTriggerPx,\n newSlOrdPx: values.newSlOrdPx,\n json,\n });\n if (subAction === \"cancel\")\n return cmdSpotAlgoCancel(client, values.instId!, values.algoId!, json);\n if (subAction === \"orders\")\n return cmdSpotAlgoOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"pending\",\n ordType: values.ordType,\n json,\n });\n }\n }\n\n if (module === \"swap\") {\n if (action === \"positions\")\n return cmdSwapPositions(client, rest[0] ?? values.instId, json);\n if (action === \"orders\")\n return cmdSwapOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"open\",\n json,\n });\n if (action === \"place\")\n return cmdSwapPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType!,\n sz: values.sz!,\n posSide: values.posSide,\n px: values.px,\n tdMode: values.tdMode ?? \"cross\",\n json,\n });\n if (action === \"cancel\")\n return cmdSwapCancel(client, rest[0], values.ordId!, json);\n if (action === \"leverage\")\n return cmdSwapSetLeverage(client, {\n instId: values.instId!,\n lever: values.lever!,\n mgnMode: values.mgnMode!,\n posSide: values.posSide,\n json,\n });\n if (action === \"algo\") {\n const subAction = rest[0];\n if (subAction === \"place\")\n return cmdSwapAlgoPlace(client, {\n instId: values.instId!,\n side: values.side!,\n ordType: values.ordType ?? \"conditional\",\n sz: values.sz!,\n posSide: values.posSide,\n tdMode: values.tdMode ?? \"cross\",\n tpTriggerPx: values.tpTriggerPx,\n tpOrdPx: values.tpOrdPx,\n slTriggerPx: values.slTriggerPx,\n slOrdPx: values.slOrdPx,\n reduceOnly: values.reduceOnly,\n json,\n });\n if (subAction === \"amend\")\n return cmdSwapAlgoAmend(client, {\n instId: values.instId!,\n algoId: values.algoId!,\n newSz: values.newSz,\n newTpTriggerPx: values.newTpTriggerPx,\n newTpOrdPx: values.newTpOrdPx,\n newSlTriggerPx: values.newSlTriggerPx,\n newSlOrdPx: values.newSlOrdPx,\n json,\n });\n if (subAction === \"cancel\")\n return cmdSwapAlgoCancel(client, values.instId!, values.algoId!, json);\n if (subAction === \"orders\")\n return cmdSwapAlgoOrders(client, {\n instId: values.instId,\n status: values.history ? \"history\" : \"pending\",\n ordType: values.ordType,\n json,\n });\n }\n }\n\n process.stderr.write(`Unknown command: ${module} ${action ?? \"\"}\\n`);\n process.exitCode = 1;\n}\n\nmain().catch((error: unknown) => {\n const payload = toToolErrorPayload(error);\n process.stderr.write(`Error: ${payload.message}\\n`);\n if (payload.suggestion) process.stderr.write(`Hint: ${payload.suggestion}\\n`);\n process.exitCode = 1;\n});\n","import { createHmac } from \"node:crypto\";\n\nexport function getNow(): string {\n return new Date().toISOString();\n}\n\nexport function signOkxPayload(payload: string, secretKey: string): string {\n return createHmac(\"sha256\", secretKey).update(payload).digest(\"base64\");\n}\n","export type ErrorType =\n | \"ConfigError\"\n | \"AuthenticationError\"\n | \"RateLimitError\"\n | \"ValidationError\"\n | \"OkxApiError\"\n | \"NetworkError\"\n | \"InternalError\";\n\nexport interface ToolErrorPayload {\n error: true;\n type: ErrorType;\n code?: string;\n message: string;\n suggestion?: string;\n endpoint?: string;\n timestamp: string;\n}\n\nexport class OkxMcpError extends Error {\n public readonly type: ErrorType;\n public readonly code?: string;\n public readonly suggestion?: string;\n public readonly endpoint?: string;\n\n public constructor(\n type: ErrorType,\n message: string,\n options?: {\n code?: string;\n suggestion?: string;\n endpoint?: string;\n cause?: unknown;\n },\n ) {\n super(message, options?.cause ? { cause: options.cause } : undefined);\n this.name = type;\n this.type = type;\n this.code = options?.code;\n this.suggestion = options?.suggestion;\n this.endpoint = options?.endpoint;\n }\n}\n\nexport class ConfigError extends OkxMcpError {\n public constructor(message: string, suggestion?: string) {\n super(\"ConfigError\", message, { suggestion });\n }\n}\n\nexport class ValidationError extends OkxMcpError {\n public constructor(message: string, suggestion?: string) {\n super(\"ValidationError\", message, { suggestion });\n }\n}\n\nexport class RateLimitError extends OkxMcpError {\n public constructor(message: string, suggestion?: string, endpoint?: string) {\n super(\"RateLimitError\", message, { suggestion, endpoint });\n }\n}\n\nexport class AuthenticationError extends OkxMcpError {\n public constructor(message: string, suggestion?: string, endpoint?: string) {\n super(\"AuthenticationError\", message, { suggestion, endpoint });\n }\n}\n\nexport class OkxApiError extends OkxMcpError {\n public constructor(\n message: string,\n options?: {\n code?: string;\n suggestion?: string;\n endpoint?: string;\n cause?: unknown;\n },\n ) {\n super(\"OkxApiError\", message, options);\n }\n}\n\nexport class NetworkError extends OkxMcpError {\n public constructor(message: string, endpoint?: string, cause?: unknown) {\n super(\"NetworkError\", message, {\n endpoint,\n cause,\n suggestion:\n \"Please check network connectivity and retry the request in a few seconds.\",\n });\n }\n}\n\nexport function toToolErrorPayload(\n error: unknown,\n fallbackEndpoint?: string,\n): ToolErrorPayload {\n if (error instanceof OkxMcpError) {\n return {\n error: true,\n type: error.type,\n code: error.code,\n message: error.message,\n suggestion: error.suggestion,\n endpoint: error.endpoint ?? fallbackEndpoint,\n timestamp: new Date().toISOString(),\n };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n\n return {\n error: true,\n type: \"InternalError\",\n message,\n suggestion:\n \"Unexpected server error. Check tool arguments and retry. If it persists, inspect server logs.\",\n endpoint: fallbackEndpoint,\n timestamp: new Date().toISOString(),\n };\n}\n","import { RateLimitError } from \"./errors.js\";\n\ntype Bucket = {\n tokens: number;\n lastRefillMs: number;\n capacity: number;\n refillPerSecond: number;\n};\n\nexport type RateLimitConfig = {\n key: string;\n capacity: number;\n refillPerSecond: number;\n};\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport class RateLimiter {\n private readonly buckets = new Map<string, Bucket>();\n private readonly maxWaitMs: number;\n\n public constructor(maxWaitMs = 30_000) {\n this.maxWaitMs = maxWaitMs;\n }\n\n public async consume(config: RateLimitConfig, amount = 1): Promise<void> {\n const bucket = this.getBucket(config);\n this.refill(bucket);\n\n if (bucket.tokens >= amount) {\n bucket.tokens -= amount;\n return;\n }\n\n const missing = amount - bucket.tokens;\n const secondsToWait = missing / bucket.refillPerSecond;\n const waitMs = Math.ceil(secondsToWait * 1000);\n\n if (waitMs > this.maxWaitMs) {\n throw new RateLimitError(\n `Client-side rate limit reached for ${config.key}. Required wait ${waitMs}ms exceeds allowed max ${this.maxWaitMs}ms.`,\n \"Reduce tool call frequency or retry later.\",\n );\n }\n\n await sleep(waitMs);\n this.refill(bucket);\n\n if (bucket.tokens < amount) {\n throw new RateLimitError(\n `Rate limiter failed to acquire enough tokens for ${config.key}.`,\n );\n }\n\n bucket.tokens -= amount;\n }\n\n private getBucket(config: RateLimitConfig): Bucket {\n const existing = this.buckets.get(config.key);\n if (existing) {\n if (\n existing.capacity !== config.capacity ||\n existing.refillPerSecond !== config.refillPerSecond\n ) {\n existing.capacity = config.capacity;\n existing.refillPerSecond = config.refillPerSecond;\n existing.tokens = Math.min(existing.tokens, config.capacity);\n }\n return existing;\n }\n\n const now = Date.now();\n const created: Bucket = {\n tokens: config.capacity,\n lastRefillMs: now,\n capacity: config.capacity,\n refillPerSecond: config.refillPerSecond,\n };\n this.buckets.set(config.key, created);\n return created;\n }\n\n private refill(bucket: Bucket): void {\n const now = Date.now();\n const elapsedMs = now - bucket.lastRefillMs;\n if (elapsedMs <= 0) {\n return;\n }\n\n const refillTokens = (elapsedMs / 1000) * bucket.refillPerSecond;\n bucket.tokens = Math.min(bucket.capacity, bucket.tokens + refillTokens);\n bucket.lastRefillMs = now;\n }\n}\n","import { getNow, signOkxPayload } from \"../utils/signature.js\";\nimport {\n AuthenticationError,\n ConfigError,\n NetworkError,\n OkxApiError,\n} from \"../utils/errors.js\";\nimport { RateLimiter } from \"../utils/rate-limiter.js\";\nimport type { OkxConfig } from \"../config.js\";\nimport type {\n OkxApiResponse,\n QueryParams,\n QueryValue,\n RequestConfig,\n RequestResult,\n} from \"./types.js\";\n\nfunction isDefined(value: unknown): boolean {\n return value !== undefined && value !== null;\n}\n\nfunction stringifyQueryValue(value: QueryValue): string {\n if (Array.isArray(value)) {\n return value.map((item) => String(item)).join(\",\");\n }\n return String(value);\n}\n\nfunction buildQueryString(query?: QueryParams): string {\n if (!query) {\n return \"\";\n }\n\n const entries = Object.entries(query).filter(([, value]) => isDefined(value));\n if (entries.length === 0) {\n return \"\";\n }\n\n const params = new URLSearchParams();\n for (const [key, value] of entries) {\n params.set(key, stringifyQueryValue(value));\n }\n return params.toString();\n}\n\nexport class OkxRestClient {\n private readonly config: OkxConfig;\n private readonly rateLimiter = new RateLimiter();\n\n public constructor(config: OkxConfig) {\n this.config = config;\n }\n\n public async publicGet<TData = unknown>(\n path: string,\n query?: QueryParams,\n rateLimit?: RequestConfig[\"rateLimit\"],\n ): Promise<RequestResult<TData>> {\n return this.request<TData>({\n method: \"GET\",\n path,\n auth: \"public\",\n query,\n rateLimit,\n });\n }\n\n public async privateGet<TData = unknown>(\n path: string,\n query?: QueryParams,\n rateLimit?: RequestConfig[\"rateLimit\"],\n ): Promise<RequestResult<TData>> {\n return this.request<TData>({\n method: \"GET\",\n path,\n auth: \"private\",\n query,\n rateLimit,\n });\n }\n\n public async privatePost<TData = unknown>(\n path: string,\n body?: RequestConfig[\"body\"],\n rateLimit?: RequestConfig[\"rateLimit\"],\n ): Promise<RequestResult<TData>> {\n return this.request<TData>({\n method: \"POST\",\n path,\n auth: \"private\",\n body,\n rateLimit,\n });\n }\n\n private async request<TData = unknown>(\n config: RequestConfig,\n ): Promise<RequestResult<TData>> {\n const queryString = buildQueryString(config.query);\n const requestPath = queryString.length > 0 ? `${config.path}?${queryString}` : config.path;\n const url = `${this.config.baseUrl}${requestPath}`;\n const bodyJson = config.body ? JSON.stringify(config.body) : \"\";\n const timestamp = getNow();\n\n if (config.rateLimit) {\n await this.rateLimiter.consume(config.rateLimit);\n }\n\n const headers = new Headers({\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n });\n\n if (config.auth === \"private\") {\n if (!this.config.hasAuth) {\n throw new ConfigError(\n \"Private endpoint requires API credentials.\",\n \"Configure OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE.\",\n );\n }\n\n if (!this.config.apiKey || !this.config.secretKey || !this.config.passphrase) {\n throw new ConfigError(\n \"Invalid private API credentials state.\",\n \"Ensure all OKX credentials are set.\",\n );\n }\n\n // OKX signature: timestamp + METHOD + requestPath + body\n const payload = `${timestamp}${config.method.toUpperCase()}${requestPath}${bodyJson}`;\n const signature = signOkxPayload(payload, this.config.secretKey);\n headers.set(\"OK-ACCESS-KEY\", this.config.apiKey);\n headers.set(\"OK-ACCESS-SIGN\", signature);\n headers.set(\"OK-ACCESS-PASSPHRASE\", this.config.passphrase);\n headers.set(\"OK-ACCESS-TIMESTAMP\", timestamp);\n }\n\n if (this.config.demo) {\n headers.set(\"x-simulated-trading\", \"1\");\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: config.method,\n headers,\n body: config.method === \"POST\" ? bodyJson : undefined,\n signal: AbortSignal.timeout(this.config.timeoutMs),\n });\n } catch (error) {\n throw new NetworkError(\n `Failed to call OKX endpoint ${config.method} ${requestPath}.`,\n `${config.method} ${requestPath}`,\n error,\n );\n }\n\n const rawText = await response.text();\n let parsed: OkxApiResponse<TData>;\n try {\n parsed = (rawText ? JSON.parse(rawText) : {}) as OkxApiResponse<TData>;\n } catch (error) {\n if (!response.ok) {\n const messagePreview = rawText.slice(0, 160).replace(/\\s+/g, \" \").trim();\n throw new OkxApiError(\n `HTTP ${response.status} from OKX: ${messagePreview || \"Non-JSON response body\"}`,\n {\n code: String(response.status),\n endpoint: `${config.method} ${config.path}`,\n suggestion: \"Verify endpoint path and request parameters.\",\n },\n );\n }\n throw new NetworkError(\n `OKX returned non-JSON response for ${config.method} ${requestPath}.`,\n `${config.method} ${requestPath}`,\n error,\n );\n }\n\n if (!response.ok) {\n throw new OkxApiError(\n `HTTP ${response.status} from OKX: ${parsed.msg ?? \"Unknown error\"}`,\n {\n code: String(response.status),\n endpoint: `${config.method} ${config.path}`,\n suggestion: \"Retry later or verify endpoint parameters.\",\n },\n );\n }\n\n const responseCode = parsed.code;\n if (responseCode && responseCode !== \"0\") {\n const message = parsed.msg ?? \"OKX API request failed.\";\n if (\n responseCode === \"50111\" ||\n responseCode === \"50112\" ||\n responseCode === \"50113\"\n ) {\n throw new AuthenticationError(\n message,\n \"Check API key, secret, passphrase and permissions.\",\n `${config.method} ${config.path}`,\n );\n }\n\n throw new OkxApiError(message, {\n code: responseCode,\n endpoint: `${config.method} ${config.path}`,\n });\n }\n\n return {\n endpoint: `${config.method} ${config.path}`,\n requestTime: new Date().toISOString(),\n data: (parsed.data ?? null) as TData,\n raw: parsed,\n };\n }\n}\n","import { ValidationError } from \"../utils/errors.js\";\n\nexport function asRecord(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return {};\n }\n return value as Record<string, unknown>;\n}\n\nexport function readString(\n args: Record<string, unknown>,\n key: string,\n): string | undefined {\n const value = args[key];\n if (value === undefined || value === null) {\n return undefined;\n }\n if (typeof value !== \"string\") {\n throw new ValidationError(`Parameter \"${key}\" must be a string.`);\n }\n return value;\n}\n\nexport function readNumber(\n args: Record<string, unknown>,\n key: string,\n): number | undefined {\n const value = args[key];\n if (value === undefined || value === null) {\n return undefined;\n }\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n throw new ValidationError(`Parameter \"${key}\" must be a number.`);\n }\n return value;\n}\n\nexport function readBoolean(\n args: Record<string, unknown>,\n key: string,\n): boolean | undefined {\n const value = args[key];\n if (value === undefined || value === null) {\n return undefined;\n }\n if (typeof value !== \"boolean\") {\n throw new ValidationError(`Parameter \"${key}\" must be a boolean.`);\n }\n return value;\n}\n\nexport function readStringArray(\n args: Record<string, unknown>,\n key: string,\n): string[] | undefined {\n const value = args[key];\n if (value === undefined || value === null) {\n return undefined;\n }\n if (!Array.isArray(value) || value.some((item) => typeof item !== \"string\")) {\n throw new ValidationError(`Parameter \"${key}\" must be an array of strings.`);\n }\n return value;\n}\n\nexport function requireString(\n args: Record<string, unknown>,\n key: string,\n): string {\n const value = readString(args, key);\n if (!value || value.length === 0) {\n throw new ValidationError(`Missing required parameter \"${key}\".`);\n }\n return value;\n}\n\nexport function assertEnum(\n value: string | undefined,\n key: string,\n values: readonly string[],\n): void {\n if (value === undefined) {\n return;\n }\n if (!values.includes(value)) {\n throw new ValidationError(\n `Parameter \"${key}\" must be one of: ${values.join(\", \")}.`,\n );\n }\n}\n\nexport function compactObject(\n object: Record<string, unknown>,\n): Record<string, unknown> {\n const next: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(object)) {\n if (value !== undefined && value !== null) {\n next[key] = value;\n }\n }\n return next;\n}\n","import type { RateLimitConfig } from \"../utils/rate-limiter.js\";\n\nexport const OKX_CANDLE_BARS = [\n \"1m\", \"3m\", \"5m\", \"15m\", \"30m\",\n \"1H\", \"2H\", \"4H\", \"6H\", \"12H\",\n \"1D\", \"2D\", \"3D\", \"1W\", \"1M\", \"3M\",\n] as const;\n\nexport const OKX_INST_TYPES = [\n \"SPOT\", \"SWAP\", \"FUTURES\", \"OPTION\", \"MARGIN\",\n] as const;\n\nexport function publicRateLimit(key: string, rps = 20): RateLimitConfig {\n return {\n key: `public:${key}`,\n capacity: rps,\n refillPerSecond: rps,\n };\n}\n\nexport function privateRateLimit(key: string, rps = 10): RateLimitConfig {\n return {\n key: `private:${key}`,\n capacity: rps,\n refillPerSecond: rps,\n };\n}\n","import type { ToolSpec } from \"./types.js\";\nimport {\n asRecord,\n compactObject,\n readString,\n requireString,\n} from \"./helpers.js\";\nimport { privateRateLimit } from \"./common.js\";\n\nfunction normalize(response: {\n endpoint: string;\n requestTime: string;\n data: unknown;\n}): Record<string, unknown> {\n return {\n endpoint: response.endpoint,\n requestTime: response.requestTime,\n data: response.data,\n };\n}\n\nexport function registerAccountTools(): ToolSpec[] {\n return [\n {\n name: \"account_get_balance\",\n module: \"account\",\n description:\n \"Get account balance for trading account. Returns balances for all currencies or a specific one. Private endpoint. Rate limit: 10 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n ccy: {\n type: \"string\",\n description:\n \"Currency, e.g. BTC. Comma-separated for multiple, e.g. BTC,ETH. Omit for all.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privateGet(\n \"/api/v5/account/balance\",\n compactObject({ ccy: readString(args, \"ccy\") }),\n privateRateLimit(\"account_get_balance\", 10),\n );\n return normalize(response);\n },\n },\n {\n name: \"account_transfer\",\n module: \"account\",\n description:\n \"Transfer funds between accounts (trading, funding, etc.). [CAUTION] Moves real funds. Private endpoint. Rate limit: 2 req/s.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n ccy: {\n type: \"string\",\n description: \"Currency to transfer, e.g. USDT.\",\n },\n amt: {\n type: \"string\",\n description: \"Transfer amount.\",\n },\n from: {\n type: \"string\",\n description:\n \"Transfer source account type. 6=funding, 18=trading (unified).\",\n },\n to: {\n type: \"string\",\n description:\n \"Transfer destination account type. 6=funding, 18=trading (unified).\",\n },\n type: {\n type: \"string\",\n description:\n \"Transfer type. 0=master account transfer (default), 1=master to sub-account, 2=sub-account to master, 3=sub-account to sub-account.\",\n },\n subAcct: {\n type: \"string\",\n description: \"Sub-account name. Required when type is 1, 2, or 3.\",\n },\n clientId: {\n type: \"string\",\n description: \"Client-supplied ID. Up to 32 characters.\",\n },\n },\n required: [\"ccy\", \"amt\", \"from\", \"to\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/asset/transfer\",\n compactObject({\n ccy: requireString(args, \"ccy\"),\n amt: requireString(args, \"amt\"),\n from: requireString(args, \"from\"),\n to: requireString(args, \"to\"),\n type: readString(args, \"type\"),\n subAcct: readString(args, \"subAcct\"),\n clientId: readString(args, \"clientId\"),\n }),\n privateRateLimit(\"account_transfer\", 2),\n );\n return normalize(response);\n },\n },\n ];\n}\n","import type { ToolSpec } from \"./types.js\";\nimport {\n asRecord,\n compactObject,\n readNumber,\n readString,\n requireString,\n} from \"./helpers.js\";\nimport { privateRateLimit } from \"./common.js\";\n\nfunction normalize(response: {\n endpoint: string;\n requestTime: string;\n data: unknown;\n}): Record<string, unknown> {\n return {\n endpoint: response.endpoint,\n requestTime: response.requestTime,\n data: response.data,\n };\n}\n\nexport function registerAlgoTradeTools(): ToolSpec[] {\n return [\n {\n name: \"swap_place_algo_order\",\n module: \"swap\",\n description:\n \"Place a SWAP/FUTURES take-profit or stop-loss algo order. [CAUTION] Executes real trades. \" +\n \"Use ordType='conditional' for a single TP, single SL, or combined TP+SL on one order. \" +\n \"Use ordType='oco' (one-cancels-other) to place TP and SL simultaneously — whichever triggers first cancels the other. \" +\n \"Set tpOrdPx='-1' or slOrdPx='-1' to execute the closing leg as a market order. \" +\n \"Private endpoint. Rate limit: 20 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT-SWAP.\",\n },\n tdMode: {\n type: \"string\",\n enum: [\"cross\", \"isolated\"],\n description: \"Trade mode: cross or isolated margin.\",\n },\n side: {\n type: \"string\",\n enum: [\"buy\", \"sell\"],\n description:\n \"Closing side: use 'sell' to close a long position, 'buy' to close a short position.\",\n },\n posSide: {\n type: \"string\",\n enum: [\"long\", \"short\", \"net\"],\n description:\n \"Position side. Use 'net' for one-way mode (default for most accounts). Use 'long' or 'short' only in hedge mode.\",\n },\n ordType: {\n type: \"string\",\n enum: [\"conditional\", \"oco\"],\n description:\n \"Algo order type. 'conditional': set TP only, SL only, or both TP+SL together. 'oco': set TP and SL as a pair — the first to trigger cancels the other.\",\n },\n sz: {\n type: \"string\",\n description:\n \"Number of contracts to close (e.g. '1'). Should match your open position size.\",\n },\n tpTriggerPx: {\n type: \"string\",\n description:\n \"Take-profit trigger price. When market reaches this price, the TP order is submitted. Required if setting a take-profit.\",\n },\n tpOrdPx: {\n type: \"string\",\n description:\n \"Take-profit order price. Set to '-1' for a market order when triggered. Required if tpTriggerPx is set.\",\n },\n tpTriggerPxType: {\n type: \"string\",\n enum: [\"last\", \"index\", \"mark\"],\n description:\n \"Price type for tpTriggerPx. 'last': last traded price (default). 'index': index price. 'mark': mark price.\",\n },\n slTriggerPx: {\n type: \"string\",\n description:\n \"Stop-loss trigger price. When market reaches this price, the SL order is submitted. Required if setting a stop-loss.\",\n },\n slOrdPx: {\n type: \"string\",\n description:\n \"Stop-loss order price. Set to '-1' for a market order when triggered (recommended to ensure execution). Required if slTriggerPx is set.\",\n },\n slTriggerPxType: {\n type: \"string\",\n enum: [\"last\", \"index\", \"mark\"],\n description:\n \"Price type for slTriggerPx. 'last': last traded price (default). 'index': index price. 'mark': mark price.\",\n },\n reduceOnly: {\n type: \"boolean\",\n description:\n \"Set true to ensure this order only reduces an existing position. Recommended for TP/SL orders.\",\n },\n clOrdId: {\n type: \"string\",\n description: \"Client-supplied order ID. Up to 32 characters.\",\n },\n },\n required: [\"instId\", \"tdMode\", \"side\", \"ordType\", \"sz\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const reduceOnly = args.reduceOnly;\n const response = await context.client.privatePost(\n \"/api/v5/trade/order-algo\",\n compactObject({\n instId: requireString(args, \"instId\"),\n tdMode: requireString(args, \"tdMode\"),\n side: requireString(args, \"side\"),\n posSide: readString(args, \"posSide\"),\n ordType: requireString(args, \"ordType\"),\n sz: requireString(args, \"sz\"),\n tpTriggerPx: readString(args, \"tpTriggerPx\"),\n tpOrdPx: readString(args, \"tpOrdPx\"),\n tpTriggerPxType: readString(args, \"tpTriggerPxType\"),\n slTriggerPx: readString(args, \"slTriggerPx\"),\n slOrdPx: readString(args, \"slOrdPx\"),\n slTriggerPxType: readString(args, \"slTriggerPxType\"),\n reduceOnly:\n typeof reduceOnly === \"boolean\" ? String(reduceOnly) : undefined,\n clOrdId: readString(args, \"clOrdId\"),\n }),\n privateRateLimit(\"swap_place_algo_order\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_cancel_algo_orders\",\n module: \"swap\",\n description:\n \"Cancel one or more pending SWAP/FUTURES algo orders (TP/SL). \" +\n \"Accepts a list of {algoId, instId} objects. Private endpoint. Rate limit: 20 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n orders: {\n type: \"array\",\n description:\n \"List of algo orders to cancel. Each item must have algoId and instId.\",\n items: {\n type: \"object\",\n properties: {\n algoId: {\n type: \"string\",\n description: \"Algo order ID to cancel.\",\n },\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT-SWAP.\",\n },\n },\n required: [\"algoId\", \"instId\"],\n },\n },\n },\n required: [\"orders\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const orders = args.orders;\n if (!Array.isArray(orders) || orders.length === 0) {\n throw new Error(\"orders must be a non-empty array.\");\n }\n const response = await context.client.privatePost(\n \"/api/v5/trade/cancel-algos\",\n orders,\n privateRateLimit(\"swap_cancel_algo_orders\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_get_algo_orders\",\n module: \"swap\",\n description:\n \"Query pending or completed SWAP/FUTURES algo orders (TP/SL, OCO). Private endpoint. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n status: {\n type: \"string\",\n enum: [\"pending\", \"history\"],\n description:\n \"Query pending (active) algo orders or completed history. Default: 'pending'.\",\n },\n ordType: {\n type: \"string\",\n enum: [\"conditional\", \"oco\"],\n description: \"Filter by algo order type.\",\n },\n instId: {\n type: \"string\",\n description: \"Instrument ID filter, e.g. BTC-USDT-SWAP.\",\n },\n algoId: {\n type: \"string\",\n description: \"Filter by specific algo order ID.\",\n },\n after: {\n type: \"string\",\n description: \"Pagination: orders earlier than this algo order ID.\",\n },\n before: {\n type: \"string\",\n description: \"Pagination: orders newer than this algo order ID.\",\n },\n limit: {\n type: \"number\",\n description: \"Number of results, default 100, max 100.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const status = readString(args, \"status\") ?? \"pending\";\n const path =\n status === \"history\"\n ? \"/api/v5/trade/orders-algo-history\"\n : \"/api/v5/trade/orders-algo-pending\";\n const response = await context.client.privateGet(\n path,\n compactObject({\n instType: \"SWAP\",\n ordType: readString(args, \"ordType\"),\n instId: readString(args, \"instId\"),\n algoId: readString(args, \"algoId\"),\n after: readString(args, \"after\"),\n before: readString(args, \"before\"),\n limit: readNumber(args, \"limit\"),\n }),\n privateRateLimit(\"swap_get_algo_orders\", 20),\n );\n return normalize(response);\n },\n },\n ];\n}\n","import type { ToolSpec } from \"./types.js\";\nimport { asRecord, compactObject, readNumber, readString, requireString } from \"./helpers.js\";\nimport { publicRateLimit, OKX_CANDLE_BARS, OKX_INST_TYPES } from \"./common.js\";\n\nfunction normalize(response: {\n endpoint: string;\n requestTime: string;\n data: unknown;\n}): Record<string, unknown> {\n return {\n endpoint: response.endpoint,\n requestTime: response.requestTime,\n data: response.data,\n };\n}\n\nexport function registerMarketTools(): ToolSpec[] {\n return [\n {\n name: \"market_get_ticker\",\n module: \"market\",\n description:\n \"Get ticker data for a single instrument. Public endpoint, no authentication required. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT, BTC-USDT-SWAP.\",\n },\n },\n required: [\"instId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.publicGet(\n \"/api/v5/market/ticker\",\n { instId: requireString(args, \"instId\") },\n publicRateLimit(\"market_get_ticker\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"market_get_tickers\",\n module: \"market\",\n description:\n \"Get ticker data for all instruments of a given type. Public endpoint, no authentication required. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n instType: {\n type: \"string\",\n enum: [...OKX_INST_TYPES],\n description: \"Instrument type: SPOT, SWAP, FUTURES, OPTION, MARGIN.\",\n },\n uly: {\n type: \"string\",\n description: \"Underlying, e.g. BTC-USD. Required for OPTION.\",\n },\n instFamily: {\n type: \"string\",\n description: \"Instrument family, e.g. BTC-USD.\",\n },\n },\n required: [\"instType\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.publicGet(\n \"/api/v5/market/tickers\",\n compactObject({\n instType: requireString(args, \"instType\"),\n uly: readString(args, \"uly\"),\n instFamily: readString(args, \"instFamily\"),\n }),\n publicRateLimit(\"market_get_tickers\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"market_get_orderbook\",\n module: \"market\",\n description:\n \"Get the order book (bids/asks) for an instrument. Public endpoint, no authentication required. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT.\",\n },\n sz: {\n type: \"number\",\n description: \"Order book depth per side. Default 1, max 400.\",\n },\n },\n required: [\"instId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.publicGet(\n \"/api/v5/market/books\",\n compactObject({\n instId: requireString(args, \"instId\"),\n sz: readNumber(args, \"sz\"),\n }),\n publicRateLimit(\"market_get_orderbook\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"market_get_candles\",\n module: \"market\",\n description:\n \"Get candlestick (OHLCV) data for an instrument. Public endpoint, no authentication required. Rate limit: 40 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT.\",\n },\n bar: {\n type: \"string\",\n enum: [...OKX_CANDLE_BARS],\n description: \"Bar size. Default 1m.\",\n },\n after: {\n type: \"string\",\n description: \"Pagination: return records earlier than this timestamp (ms).\",\n },\n before: {\n type: \"string\",\n description: \"Pagination: return records newer than this timestamp (ms).\",\n },\n limit: {\n type: \"number\",\n description: \"Number of results, default 100, max 300.\",\n },\n },\n required: [\"instId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.publicGet(\n \"/api/v5/market/candles\",\n compactObject({\n instId: requireString(args, \"instId\"),\n bar: readString(args, \"bar\"),\n after: readString(args, \"after\"),\n before: readString(args, \"before\"),\n limit: readNumber(args, \"limit\"),\n }),\n publicRateLimit(\"market_get_candles\", 40),\n );\n return normalize(response);\n },\n },\n ];\n}\n","import type { ToolSpec } from \"./types.js\";\nimport {\n asRecord,\n compactObject,\n readNumber,\n readString,\n requireString,\n} from \"./helpers.js\";\nimport { privateRateLimit } from \"./common.js\";\n\nfunction normalize(response: {\n endpoint: string;\n requestTime: string;\n data: unknown;\n}): Record<string, unknown> {\n return {\n endpoint: response.endpoint,\n requestTime: response.requestTime,\n data: response.data,\n };\n}\n\nexport function registerSpotTradeTools(): ToolSpec[] {\n return [\n {\n name: \"spot_place_order\",\n module: \"spot\",\n description:\n \"Place a spot order. Optionally attach take-profit/stop-loss via tpTriggerPx/slTriggerPx (assembled into attachAlgoOrds automatically). [CAUTION] Executes real trades. Private endpoint. Rate limit: 60 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT.\",\n },\n tdMode: {\n type: \"string\",\n enum: [\"cash\", \"cross\", \"isolated\"],\n description:\n \"Trade mode. Use 'cash' for regular spot trading. Use 'cross' or 'isolated' only for margin trading.\",\n },\n side: {\n type: \"string\",\n enum: [\"buy\", \"sell\"],\n description: \"Order side: 'buy' to purchase, 'sell' to sell.\",\n },\n ordType: {\n type: \"string\",\n enum: [\"market\", \"limit\", \"post_only\", \"fok\", \"ioc\"],\n description:\n \"Order type. 'market': execute immediately at market price, no px needed. 'limit': execute at px or better, px required. 'post_only': maker-only limit order, px required. 'fok': fill entire order immediately or cancel, px required. 'ioc': fill as much as possible immediately, cancel rest, px required.\",\n },\n sz: {\n type: \"string\",\n description:\n \"Quantity. For market BUY: amount in quote currency (e.g. '100' means spend 100 USDT). For all other order types: amount in base currency (e.g. '0.001' means 0.001 BTC). For limit orders, always use base currency.\",\n },\n px: {\n type: \"string\",\n description:\n \"Order price in quote currency. Required for limit, post_only, fok, ioc orders. Omit for market orders.\",\n },\n clOrdId: {\n type: \"string\",\n description: \"Client-supplied order ID. Up to 32 characters.\",\n },\n tag: {\n type: \"string\",\n description: \"Order tag.\",\n },\n tpTriggerPx: {\n type: \"string\",\n description:\n \"Take-profit trigger price. When triggered, places a TP order at tpOrdPx. Assembled into attachAlgoOrds automatically.\",\n },\n tpOrdPx: {\n type: \"string\",\n description:\n \"Take-profit order price. Use '-1' for market order. Required when tpTriggerPx is set.\",\n },\n slTriggerPx: {\n type: \"string\",\n description:\n \"Stop-loss trigger price. When triggered, places a SL order at slOrdPx. Assembled into attachAlgoOrds automatically.\",\n },\n slOrdPx: {\n type: \"string\",\n description:\n \"Stop-loss order price. Use '-1' for market order. Required when slTriggerPx is set.\",\n },\n },\n required: [\"instId\", \"tdMode\", \"side\", \"ordType\", \"sz\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const tpTriggerPx = readString(args, \"tpTriggerPx\");\n const tpOrdPx = readString(args, \"tpOrdPx\");\n const slTriggerPx = readString(args, \"slTriggerPx\");\n const slOrdPx = readString(args, \"slOrdPx\");\n const algoEntry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });\n const attachAlgoOrds = Object.keys(algoEntry).length > 0 ? [algoEntry] : undefined;\n const response = await context.client.privatePost(\n \"/api/v5/trade/order\",\n compactObject({\n instId: requireString(args, \"instId\"),\n tdMode: requireString(args, \"tdMode\"),\n side: requireString(args, \"side\"),\n ordType: requireString(args, \"ordType\"),\n sz: requireString(args, \"sz\"),\n px: readString(args, \"px\"),\n clOrdId: readString(args, \"clOrdId\"),\n tag: readString(args, \"tag\"),\n attachAlgoOrds,\n }),\n privateRateLimit(\"spot_place_order\", 60),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_cancel_order\",\n module: \"spot\",\n description:\n \"Cancel an unfilled spot order by order ID or client order ID. Private endpoint. Rate limit: 60 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT.\",\n },\n ordId: {\n type: \"string\",\n description: \"Order ID.\",\n },\n clOrdId: {\n type: \"string\",\n description: \"Client-supplied order ID.\",\n },\n },\n required: [\"instId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/trade/cancel-order\",\n compactObject({\n instId: requireString(args, \"instId\"),\n ordId: readString(args, \"ordId\"),\n clOrdId: readString(args, \"clOrdId\"),\n }),\n privateRateLimit(\"spot_cancel_order\", 60),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_amend_order\",\n module: \"spot\",\n description:\n \"Amend an unfilled spot order (modify price or size). Private endpoint. Rate limit: 60 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT.\",\n },\n ordId: {\n type: \"string\",\n description: \"Order ID.\",\n },\n clOrdId: {\n type: \"string\",\n description: \"Client-supplied order ID.\",\n },\n newSz: {\n type: \"string\",\n description: \"New quantity.\",\n },\n newPx: {\n type: \"string\",\n description: \"New price.\",\n },\n newClOrdId: {\n type: \"string\",\n description: \"New client order ID after amendment.\",\n },\n },\n required: [\"instId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/trade/amend-order\",\n compactObject({\n instId: requireString(args, \"instId\"),\n ordId: readString(args, \"ordId\"),\n clOrdId: readString(args, \"clOrdId\"),\n newSz: readString(args, \"newSz\"),\n newPx: readString(args, \"newPx\"),\n newClOrdId: readString(args, \"newClOrdId\"),\n }),\n privateRateLimit(\"spot_amend_order\", 60),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_get_orders\",\n module: \"spot\",\n description:\n \"Query spot open orders or order history. Private endpoint. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n status: {\n type: \"string\",\n enum: [\"open\", \"history\"],\n description: \"Query open orders (default) or history.\",\n },\n instId: {\n type: \"string\",\n description: \"Instrument ID filter, e.g. BTC-USDT.\",\n },\n ordType: {\n type: \"string\",\n description: \"Order type filter.\",\n },\n state: {\n type: \"string\",\n description: \"Order state filter (for history): canceled, filled.\",\n },\n after: {\n type: \"string\",\n description: \"Pagination cursor: orders earlier than this order ID.\",\n },\n before: {\n type: \"string\",\n description: \"Pagination cursor: orders newer than this order ID.\",\n },\n begin: {\n type: \"string\",\n description: \"Start time filter in milliseconds.\",\n },\n end: {\n type: \"string\",\n description: \"End time filter in milliseconds.\",\n },\n limit: {\n type: \"number\",\n description: \"Number of results, default 100, max 100.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const status = readString(args, \"status\") ?? \"open\";\n const path =\n status === \"history\"\n ? \"/api/v5/trade/orders-history\"\n : \"/api/v5/trade/orders-pending\";\n const response = await context.client.privateGet(\n path,\n compactObject({\n instType: \"SPOT\",\n instId: readString(args, \"instId\"),\n ordType: readString(args, \"ordType\"),\n state: readString(args, \"state\"),\n after: readString(args, \"after\"),\n before: readString(args, \"before\"),\n begin: readString(args, \"begin\"),\n end: readString(args, \"end\"),\n limit: readNumber(args, \"limit\"),\n }),\n privateRateLimit(\"spot_get_orders\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_place_algo_order\",\n module: \"spot\",\n description:\n \"Place a spot algo order with take-profit and/or stop-loss. [CAUTION] Executes real trades. Private endpoint. Rate limit: 20 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT.\",\n },\n side: {\n type: \"string\",\n enum: [\"buy\", \"sell\"],\n description: \"Order side.\",\n },\n ordType: {\n type: \"string\",\n enum: [\"conditional\", \"oco\"],\n description:\n \"'conditional': single TP or SL. 'oco': both TP and SL in one order (one-cancels-the-other).\",\n },\n sz: {\n type: \"string\",\n description: \"Quantity in base currency, e.g. '0.001' for 0.001 BTC.\",\n },\n tpTriggerPx: {\n type: \"string\",\n description: \"Take-profit trigger price.\",\n },\n tpOrdPx: {\n type: \"string\",\n description: \"Take-profit order price. Use '-1' for market order.\",\n },\n slTriggerPx: {\n type: \"string\",\n description: \"Stop-loss trigger price.\",\n },\n slOrdPx: {\n type: \"string\",\n description: \"Stop-loss order price. Use '-1' for market order.\",\n },\n },\n required: [\"instId\", \"side\", \"ordType\", \"sz\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/trade/order-algo\",\n compactObject({\n instId: requireString(args, \"instId\"),\n tdMode: \"cash\",\n side: requireString(args, \"side\"),\n ordType: requireString(args, \"ordType\"),\n sz: requireString(args, \"sz\"),\n tpTriggerPx: readString(args, \"tpTriggerPx\"),\n tpOrdPx: readString(args, \"tpOrdPx\"),\n slTriggerPx: readString(args, \"slTriggerPx\"),\n slOrdPx: readString(args, \"slOrdPx\"),\n }),\n privateRateLimit(\"spot_place_algo_order\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_amend_algo_order\",\n module: \"spot\",\n description:\n \"Amend a pending spot algo order (modify TP/SL prices or size). Private endpoint. Rate limit: 20 req/s.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: { type: \"string\", description: \"Instrument ID, e.g. BTC-USDT.\" },\n algoId: { type: \"string\", description: \"Algo order ID to amend.\" },\n newSz: { type: \"string\", description: \"New quantity in base currency.\" },\n newTpTriggerPx: { type: \"string\", description: \"New take-profit trigger price.\" },\n newTpOrdPx: { type: \"string\", description: \"New take-profit order price. Use '-1' for market.\" },\n newSlTriggerPx: { type: \"string\", description: \"New stop-loss trigger price.\" },\n newSlOrdPx: { type: \"string\", description: \"New stop-loss order price. Use '-1' for market.\" },\n },\n required: [\"instId\", \"algoId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/trade/amend-algos\",\n compactObject({\n instId: requireString(args, \"instId\"),\n algoId: requireString(args, \"algoId\"),\n newSz: readString(args, \"newSz\"),\n newTpTriggerPx: readString(args, \"newTpTriggerPx\"),\n newTpOrdPx: readString(args, \"newTpOrdPx\"),\n newSlTriggerPx: readString(args, \"newSlTriggerPx\"),\n newSlOrdPx: readString(args, \"newSlOrdPx\"),\n }),\n privateRateLimit(\"spot_amend_algo_order\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_cancel_algo_order\",\n module: \"spot\",\n description:\n \"Cancel a spot algo order (TP/SL). Private endpoint. Rate limit: 20 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT.\",\n },\n algoId: {\n type: \"string\",\n description: \"Algo order ID.\",\n },\n },\n required: [\"instId\", \"algoId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/trade/cancel-algos\",\n [\n {\n instId: requireString(args, \"instId\"),\n algoId: requireString(args, \"algoId\"),\n },\n ],\n privateRateLimit(\"spot_cancel_algo_order\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_get_algo_orders\",\n module: \"spot\",\n description:\n \"Query spot algo orders (TP/SL) — pending or history. Private endpoint. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n status: {\n type: \"string\",\n enum: [\"pending\", \"history\"],\n description: \"Query pending algo orders (default) or history.\",\n },\n instId: {\n type: \"string\",\n description: \"Instrument ID filter, e.g. BTC-USDT.\",\n },\n ordType: {\n type: \"string\",\n enum: [\"conditional\", \"oco\"],\n description: \"Filter by algo order type.\",\n },\n after: {\n type: \"string\",\n description: \"Pagination cursor: orders earlier than this algo ID.\",\n },\n before: {\n type: \"string\",\n description: \"Pagination cursor: orders newer than this algo ID.\",\n },\n limit: {\n type: \"number\",\n description: \"Number of results, default 100, max 100.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const status = readString(args, \"status\") ?? \"pending\";\n const path =\n status === \"history\"\n ? \"/api/v5/trade/orders-algo-history\"\n : \"/api/v5/trade/orders-algo-pending\";\n const response = await context.client.privateGet(\n path,\n compactObject({\n instType: \"SPOT\",\n instId: readString(args, \"instId\"),\n ordType: readString(args, \"ordType\"),\n after: readString(args, \"after\"),\n before: readString(args, \"before\"),\n limit: readNumber(args, \"limit\"),\n }),\n privateRateLimit(\"spot_get_algo_orders\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"spot_get_fills\",\n module: \"spot\",\n description:\n \"Get spot transaction fill details. Private endpoint. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID filter, e.g. BTC-USDT.\",\n },\n ordId: {\n type: \"string\",\n description: \"Order ID filter.\",\n },\n after: {\n type: \"string\",\n description: \"Pagination cursor: fills earlier than this bill ID.\",\n },\n before: {\n type: \"string\",\n description: \"Pagination cursor: fills newer than this bill ID.\",\n },\n begin: {\n type: \"string\",\n description: \"Start time filter in milliseconds.\",\n },\n end: {\n type: \"string\",\n description: \"End time filter in milliseconds.\",\n },\n limit: {\n type: \"number\",\n description: \"Number of results, default 100, max 100.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privateGet(\n \"/api/v5/trade/fills\",\n compactObject({\n instType: \"SPOT\",\n instId: readString(args, \"instId\"),\n ordId: readString(args, \"ordId\"),\n after: readString(args, \"after\"),\n before: readString(args, \"before\"),\n begin: readString(args, \"begin\"),\n end: readString(args, \"end\"),\n limit: readNumber(args, \"limit\"),\n }),\n privateRateLimit(\"spot_get_fills\", 20),\n );\n return normalize(response);\n },\n },\n ];\n}\n","import type { ToolSpec } from \"./types.js\";\nimport {\n asRecord,\n assertEnum,\n compactObject,\n readNumber,\n readString,\n requireString,\n} from \"./helpers.js\";\nimport { privateRateLimit } from \"./common.js\";\n\nconst SWAP_INST_TYPES = [\"SWAP\", \"FUTURES\"] as const;\n\nfunction normalize(response: {\n endpoint: string;\n requestTime: string;\n data: unknown;\n}): Record<string, unknown> {\n return {\n endpoint: response.endpoint,\n requestTime: response.requestTime,\n data: response.data,\n };\n}\n\nexport function registerSwapTradeTools(): ToolSpec[] {\n return [\n {\n name: \"swap_place_order\",\n module: \"swap\",\n description:\n \"Place a SWAP or FUTURES perpetual/delivery contract order. Optionally attach take-profit/stop-loss via tpTriggerPx/slTriggerPx (assembled into attachAlgoOrds automatically). [CAUTION] Executes real trades. Private endpoint. Rate limit: 60 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description:\n \"Instrument ID, e.g. BTC-USDT-SWAP for perpetual, BTC-USD-240329 for delivery futures.\",\n },\n tdMode: {\n type: \"string\",\n enum: [\"cross\", \"isolated\"],\n description: \"Trade mode: cross or isolated margin.\",\n },\n side: {\n type: \"string\",\n enum: [\"buy\", \"sell\"],\n description:\n \"Order side. In one-way mode: buy=open/add long, sell=open/add short. To close: sell with reduceOnly=true (long) or buy with reduceOnly=true (short). In hedge mode: buy+long=open long, sell+long=close long, sell+short=open short, buy+short=close short.\",\n },\n posSide: {\n type: \"string\",\n enum: [\"long\", \"short\", \"net\"],\n description:\n \"Position side. IMPORTANT: Most OKX accounts use one-way mode — use 'net' in that case. Only use 'long' or 'short' if your account is configured for hedge mode (双向持仓). If you get an error like 'posSide is not valid', switch to 'net'.\",\n },\n ordType: {\n type: \"string\",\n enum: [\"market\", \"limit\", \"post_only\", \"fok\", \"ioc\"],\n description:\n \"Order type. 'market': execute immediately at market price, no px needed. 'limit': execute at px or better, px required. 'post_only': maker-only limit order, px required. 'fok': fill entire order immediately or cancel, px required. 'ioc': fill as much as possible immediately, cancel rest, px required.\",\n },\n sz: {\n type: \"string\",\n description:\n \"Quantity in number of contracts (e.g. '1' = 1 contract). For BTC-USDT-SWAP, 1 contract = 0.01 BTC.\",\n },\n px: {\n type: \"string\",\n description:\n \"Order price. Required for limit, post_only, fok, ioc orders. Omit for market orders.\",\n },\n reduceOnly: {\n type: \"boolean\",\n description:\n \"Set true to close/reduce an existing position without opening a new one. Use this in one-way mode to close positions instead of posSide.\",\n },\n clOrdId: {\n type: \"string\",\n description: \"Client-supplied order ID. Up to 32 characters.\",\n },\n tag: {\n type: \"string\",\n description: \"Order tag.\",\n },\n tpTriggerPx: {\n type: \"string\",\n description:\n \"Take-profit trigger price. When triggered, places a TP order at tpOrdPx. Assembled into attachAlgoOrds automatically.\",\n },\n tpOrdPx: {\n type: \"string\",\n description:\n \"Take-profit order price. Use '-1' for market order. Required when tpTriggerPx is set.\",\n },\n slTriggerPx: {\n type: \"string\",\n description:\n \"Stop-loss trigger price. When triggered, places a SL order at slOrdPx. Assembled into attachAlgoOrds automatically.\",\n },\n slOrdPx: {\n type: \"string\",\n description:\n \"Stop-loss order price. Use '-1' for market order. Required when slTriggerPx is set.\",\n },\n },\n required: [\"instId\", \"tdMode\", \"side\", \"ordType\", \"sz\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const reduceOnly = args.reduceOnly;\n const tpTriggerPx = readString(args, \"tpTriggerPx\");\n const tpOrdPx = readString(args, \"tpOrdPx\");\n const slTriggerPx = readString(args, \"slTriggerPx\");\n const slOrdPx = readString(args, \"slOrdPx\");\n const algoEntry = compactObject({ tpTriggerPx, tpOrdPx, slTriggerPx, slOrdPx });\n const attachAlgoOrds = Object.keys(algoEntry).length > 0 ? [algoEntry] : undefined;\n const response = await context.client.privatePost(\n \"/api/v5/trade/order\",\n compactObject({\n instId: requireString(args, \"instId\"),\n tdMode: requireString(args, \"tdMode\"),\n side: requireString(args, \"side\"),\n posSide: readString(args, \"posSide\"),\n ordType: requireString(args, \"ordType\"),\n sz: requireString(args, \"sz\"),\n px: readString(args, \"px\"),\n reduceOnly: typeof reduceOnly === \"boolean\" ? String(reduceOnly) : undefined,\n clOrdId: readString(args, \"clOrdId\"),\n tag: readString(args, \"tag\"),\n attachAlgoOrds,\n }),\n privateRateLimit(\"swap_place_order\", 60),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_cancel_order\",\n module: \"swap\",\n description:\n \"Cancel an unfilled SWAP or FUTURES order. Private endpoint. Rate limit: 60 req/s per UID.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT-SWAP.\",\n },\n ordId: {\n type: \"string\",\n description: \"Order ID.\",\n },\n clOrdId: {\n type: \"string\",\n description: \"Client-supplied order ID.\",\n },\n },\n required: [\"instId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/trade/cancel-order\",\n compactObject({\n instId: requireString(args, \"instId\"),\n ordId: readString(args, \"ordId\"),\n clOrdId: readString(args, \"clOrdId\"),\n }),\n privateRateLimit(\"swap_cancel_order\", 60),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_get_orders\",\n module: \"swap\",\n description:\n \"Query SWAP or FUTURES open orders or order history. Private endpoint. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n status: {\n type: \"string\",\n enum: [\"open\", \"history\"],\n description: \"Query open orders (default) or history.\",\n },\n instType: {\n type: \"string\",\n enum: [...SWAP_INST_TYPES],\n description: \"Instrument type: SWAP (default) or FUTURES.\",\n },\n instId: {\n type: \"string\",\n description: \"Instrument ID filter.\",\n },\n ordType: {\n type: \"string\",\n description: \"Order type filter.\",\n },\n state: {\n type: \"string\",\n description: \"Order state filter (for history): canceled, filled.\",\n },\n after: {\n type: \"string\",\n description: \"Pagination cursor: orders earlier than this order ID.\",\n },\n before: {\n type: \"string\",\n description: \"Pagination cursor: orders newer than this order ID.\",\n },\n begin: {\n type: \"string\",\n description: \"Start time filter in milliseconds.\",\n },\n end: {\n type: \"string\",\n description: \"End time filter in milliseconds.\",\n },\n limit: {\n type: \"number\",\n description: \"Number of results, default 100, max 100.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const status = readString(args, \"status\") ?? \"open\";\n const instType = readString(args, \"instType\") ?? \"SWAP\";\n assertEnum(instType, \"instType\", SWAP_INST_TYPES);\n const path =\n status === \"history\"\n ? \"/api/v5/trade/orders-history\"\n : \"/api/v5/trade/orders-pending\";\n const response = await context.client.privateGet(\n path,\n compactObject({\n instType,\n instId: readString(args, \"instId\"),\n ordType: readString(args, \"ordType\"),\n state: readString(args, \"state\"),\n after: readString(args, \"after\"),\n before: readString(args, \"before\"),\n begin: readString(args, \"begin\"),\n end: readString(args, \"end\"),\n limit: readNumber(args, \"limit\"),\n }),\n privateRateLimit(\"swap_get_orders\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_get_positions\",\n module: \"swap\",\n description:\n \"Get current SWAP or FUTURES positions. Private endpoint. Rate limit: 10 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n instType: {\n type: \"string\",\n enum: [...SWAP_INST_TYPES],\n description: \"Instrument type: SWAP (default) or FUTURES.\",\n },\n instId: {\n type: \"string\",\n description: \"Instrument ID filter, e.g. BTC-USDT-SWAP.\",\n },\n posId: {\n type: \"string\",\n description: \"Position ID filter.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const instType = readString(args, \"instType\") ?? \"SWAP\";\n assertEnum(instType, \"instType\", SWAP_INST_TYPES);\n const response = await context.client.privateGet(\n \"/api/v5/account/positions\",\n compactObject({\n instType,\n instId: readString(args, \"instId\"),\n posId: readString(args, \"posId\"),\n }),\n privateRateLimit(\"swap_get_positions\", 10),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_set_leverage\",\n module: \"swap\",\n description:\n \"Set leverage for a SWAP or FUTURES instrument or position. [CAUTION] Changes risk parameters. Private endpoint. Rate limit: 20 req/s.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: {\n type: \"string\",\n description: \"Instrument ID, e.g. BTC-USDT-SWAP.\",\n },\n lever: {\n type: \"string\",\n description: \"Leverage value, e.g. '10'.\",\n },\n mgnMode: {\n type: \"string\",\n enum: [\"cross\", \"isolated\"],\n description: \"Margin mode.\",\n },\n posSide: {\n type: \"string\",\n enum: [\"long\", \"short\", \"net\"],\n description:\n \"Position side. Required for isolated margin in hedge mode.\",\n },\n },\n required: [\"instId\", \"lever\", \"mgnMode\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/account/set-leverage\",\n compactObject({\n instId: requireString(args, \"instId\"),\n lever: requireString(args, \"lever\"),\n mgnMode: requireString(args, \"mgnMode\"),\n posSide: readString(args, \"posSide\"),\n }),\n privateRateLimit(\"swap_set_leverage\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_amend_algo_order\",\n module: \"swap\",\n description:\n \"Amend a pending SWAP/FUTURES algo order (modify TP/SL prices or size). Private endpoint. Rate limit: 20 req/s.\",\n isWrite: true,\n inputSchema: {\n type: \"object\",\n properties: {\n instId: { type: \"string\", description: \"Instrument ID, e.g. BTC-USDT-SWAP.\" },\n algoId: { type: \"string\", description: \"Algo order ID to amend.\" },\n newSz: { type: \"string\", description: \"New quantity in number of contracts.\" },\n newTpTriggerPx: { type: \"string\", description: \"New take-profit trigger price.\" },\n newTpOrdPx: { type: \"string\", description: \"New take-profit order price. Use '-1' for market.\" },\n newSlTriggerPx: { type: \"string\", description: \"New stop-loss trigger price.\" },\n newSlOrdPx: { type: \"string\", description: \"New stop-loss order price. Use '-1' for market.\" },\n },\n required: [\"instId\", \"algoId\"],\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const response = await context.client.privatePost(\n \"/api/v5/trade/amend-algos\",\n compactObject({\n instId: requireString(args, \"instId\"),\n algoId: requireString(args, \"algoId\"),\n newSz: readString(args, \"newSz\"),\n newTpTriggerPx: readString(args, \"newTpTriggerPx\"),\n newTpOrdPx: readString(args, \"newTpOrdPx\"),\n newSlTriggerPx: readString(args, \"newSlTriggerPx\"),\n newSlOrdPx: readString(args, \"newSlOrdPx\"),\n }),\n privateRateLimit(\"swap_amend_algo_order\", 20),\n );\n return normalize(response);\n },\n },\n {\n name: \"swap_get_fills\",\n module: \"swap\",\n description:\n \"Get SWAP or FUTURES transaction fill details. Private endpoint. Rate limit: 20 req/s.\",\n isWrite: false,\n inputSchema: {\n type: \"object\",\n properties: {\n instType: {\n type: \"string\",\n enum: [...SWAP_INST_TYPES],\n description: \"Instrument type: SWAP (default) or FUTURES.\",\n },\n instId: {\n type: \"string\",\n description: \"Instrument ID filter.\",\n },\n ordId: {\n type: \"string\",\n description: \"Order ID filter.\",\n },\n after: {\n type: \"string\",\n description: \"Pagination cursor: fills earlier than this bill ID.\",\n },\n before: {\n type: \"string\",\n description: \"Pagination cursor: fills newer than this bill ID.\",\n },\n begin: {\n type: \"string\",\n description: \"Start time filter in milliseconds.\",\n },\n end: {\n type: \"string\",\n description: \"End time filter in milliseconds.\",\n },\n limit: {\n type: \"number\",\n description: \"Number of results, default 100, max 100.\",\n },\n },\n },\n handler: async (rawArgs, context) => {\n const args = asRecord(rawArgs);\n const instType = readString(args, \"instType\") ?? \"SWAP\";\n assertEnum(instType, \"instType\", SWAP_INST_TYPES);\n const response = await context.client.privateGet(\n \"/api/v5/trade/fills\",\n compactObject({\n instType,\n instId: readString(args, \"instId\"),\n ordId: readString(args, \"ordId\"),\n after: readString(args, \"after\"),\n before: readString(args, \"before\"),\n begin: readString(args, \"begin\"),\n end: readString(args, \"end\"),\n limit: readNumber(args, \"limit\"),\n }),\n privateRateLimit(\"swap_get_fills\", 20),\n );\n return normalize(response);\n },\n },\n ];\n}\n","import type { OkxConfig } from \"../config.js\";\nimport { registerAccountTools } from \"./account.js\";\nimport { registerAlgoTradeTools } from \"./algo-trade.js\";\nimport { registerMarketTools } from \"./market.js\";\nimport { registerSpotTradeTools } from \"./spot-trade.js\";\nimport { registerSwapTradeTools } from \"./swap-trade.js\";\nimport type { ToolSpec } from \"./types.js\";\n\nfunction allToolSpecs(): ToolSpec[] {\n return [\n ...registerMarketTools(),\n ...registerSpotTradeTools(),\n ...registerSwapTradeTools(),\n ...registerAlgoTradeTools(),\n ...registerAccountTools(),\n ];\n}\n\nexport function buildTools(config: OkxConfig): ToolSpec[] {\n const enabledModules = new Set(config.modules);\n const tools = allToolSpecs().filter((tool) => enabledModules.has(tool.module));\n if (!config.readOnly) {\n return tools;\n }\n return tools.filter((tool) => !tool.isWrite);\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { OkxRestClient } from \"../client/rest-client.js\";\nimport type { OkxConfig } from \"../config.js\";\nimport type { ModuleId } from \"../constants.js\";\n\nexport type ToolArgs = Record<string, unknown>;\n\nexport type JsonSchema = Tool[\"inputSchema\"];\n\nexport interface ToolContext {\n config: OkxConfig;\n client: OkxRestClient;\n}\n\nexport interface ToolSpec {\n name: string;\n module: ModuleId;\n description: string;\n inputSchema: JsonSchema;\n isWrite: boolean;\n handler: (args: ToolArgs, context: ToolContext) => Promise<unknown>;\n}\n\nexport function toMcpTool(tool: ToolSpec): Tool {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n annotations: {\n readOnlyHint: !tool.isWrite,\n destructiveHint: tool.isWrite,\n idempotentHint: !tool.isWrite,\n openWorldHint: true,\n },\n };\n}\n","export const OKX_API_BASE_URL = \"https://www.okx.com\";\n\nexport const MODULES = [\n \"market\",\n \"spot\",\n \"swap\",\n \"account\",\n] as const;\n\nexport type ModuleId = (typeof MODULES)[number];\n\nexport const DEFAULT_MODULES: ModuleId[] = [\"spot\", \"swap\", \"account\"];\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { parse } from \"smol-toml\";\n\nexport interface OkxProfile {\n api_key?: string;\n secret_key?: string;\n passphrase?: string;\n base_url?: string;\n timeout_ms?: number;\n demo?: boolean;\n}\n\nexport interface OkxTomlConfig {\n default_profile?: string;\n profiles: Record<string, OkxProfile>;\n}\n\nexport function configFilePath(): string {\n return join(homedir(), \".okx\", \"config.toml\");\n}\n\n/**\n * Read a profile from ~/.okx/config.toml.\n * Returns an empty object if the file does not exist or the profile is not found.\n */\nexport function readTomlProfile(profileName?: string): OkxProfile {\n const path = configFilePath();\n if (!existsSync(path)) return {};\n\n const raw = readFileSync(path, \"utf-8\");\n const config = parse(raw) as unknown as OkxTomlConfig;\n\n const name = profileName ?? config.default_profile ?? \"default\";\n return config.profiles?.[name] ?? {};\n}\n","import { DEFAULT_MODULES, MODULES, OKX_API_BASE_URL, type ModuleId } from \"./constants.js\";\nimport { ConfigError } from \"./utils/errors.js\";\nimport { readTomlProfile } from \"./config/toml.js\";\n\nexport interface CliOptions {\n modules?: string;\n readOnly: boolean;\n demo: boolean;\n profile?: string;\n}\n\nexport interface OkxConfig {\n apiKey?: string;\n secretKey?: string;\n passphrase?: string;\n hasAuth: boolean;\n baseUrl: string;\n timeoutMs: number;\n modules: ModuleId[];\n readOnly: boolean;\n demo: boolean;\n}\n\nfunction parseModuleList(rawModules?: string): ModuleId[] {\n if (!rawModules || rawModules.trim().length === 0) {\n return [...DEFAULT_MODULES];\n }\n\n const trimmed = rawModules.trim().toLowerCase();\n if (trimmed === \"all\") {\n return [...MODULES];\n }\n\n const requested = trimmed\n .split(\",\")\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n\n if (requested.length === 0) {\n return [...DEFAULT_MODULES];\n }\n\n const deduped = new Set<ModuleId>();\n for (const moduleId of requested) {\n if (!MODULES.includes(moduleId as ModuleId)) {\n throw new ConfigError(\n `Unknown module \"${moduleId}\".`,\n `Use one of: ${MODULES.join(\", \")} or \"all\".`,\n );\n }\n deduped.add(moduleId as ModuleId);\n }\n\n return Array.from(deduped);\n}\n\n/**\n * Credential priority (highest to lowest):\n * 1. Environment variables (OKX_API_KEY / OKX_SECRET_KEY / OKX_PASSPHRASE)\n * 2. ~/.okx/config.toml — profile selected by cli.profile or default_profile\n */\nexport function loadConfig(cli: CliOptions): OkxConfig {\n // Read toml profile as fallback\n const toml = readTomlProfile(cli.profile);\n\n const apiKey = process.env.OKX_API_KEY?.trim() ?? toml.api_key;\n const secretKey = process.env.OKX_SECRET_KEY?.trim() ?? toml.secret_key;\n const passphrase = process.env.OKX_PASSPHRASE?.trim() ?? toml.passphrase;\n\n const hasAuth = Boolean(apiKey && secretKey && passphrase);\n const partialAuth = Boolean(apiKey) || Boolean(secretKey) || Boolean(passphrase);\n\n if (partialAuth && !hasAuth) {\n throw new ConfigError(\n \"Partial API credentials detected.\",\n \"Set OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE together (env vars or config.toml profile).\",\n );\n }\n\n // demo flag: cli arg > env var > toml profile\n const demo =\n cli.demo ||\n process.env.OKX_DEMO === \"1\" ||\n process.env.OKX_DEMO === \"true\" ||\n (toml.demo ?? false);\n\n // base url: env var > toml profile > default\n const rawBaseUrl =\n process.env.OKX_API_BASE_URL?.trim() ?? toml.base_url ?? OKX_API_BASE_URL;\n if (!rawBaseUrl.startsWith(\"http://\") && !rawBaseUrl.startsWith(\"https://\")) {\n throw new ConfigError(\n `Invalid base URL \"${rawBaseUrl}\".`,\n \"OKX_API_BASE_URL must start with http:// or https://\",\n );\n }\n const baseUrl = rawBaseUrl.replace(/\\/+$/, \"\");\n\n // timeout: env var > toml profile > default\n const rawTimeout = process.env.OKX_TIMEOUT_MS\n ? Number(process.env.OKX_TIMEOUT_MS)\n : (toml.timeout_ms ?? 15_000);\n if (!Number.isFinite(rawTimeout) || rawTimeout <= 0) {\n throw new ConfigError(\n `Invalid timeout value \"${rawTimeout}\".`,\n \"Set OKX_TIMEOUT_MS as a positive integer in milliseconds.\",\n );\n }\n\n return {\n apiKey,\n secretKey,\n passphrase,\n hasAuth,\n baseUrl,\n timeoutMs: Math.floor(rawTimeout),\n modules: parseModuleList(cli.modules),\n readOnly: cli.readOnly,\n demo,\n };\n}\n","import type { OkxConfig } from \"@okx-hub/core\";\nimport { loadConfig } from \"@okx-hub/core\";\n\nexport interface LoadProfileOptions {\n profile?: string;\n modules?: string;\n readOnly?: boolean;\n demo?: boolean;\n}\n\n/**\n * Load config for CLI commands.\n * Delegates to core's loadConfig which handles the full priority chain:\n * env vars > ~/.okx/config.toml (selected profile) > defaults\n */\nexport function loadProfileConfig(opts: LoadProfileOptions): OkxConfig {\n return loadConfig({\n profile: opts.profile,\n modules: opts.modules,\n readOnly: opts.readOnly ?? false,\n demo: opts.demo ?? false,\n });\n}\n","export function printJson(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n}\n\nexport function printTable(rows: Record<string, unknown>[]): void {\n if (rows.length === 0) {\n process.stdout.write(\"(no data)\\n\");\n return;\n }\n const keys = Object.keys(rows[0]);\n const widths = keys.map((k) =>\n Math.max(k.length, ...rows.map((r) => String(r[k] ?? \"\").length)),\n );\n const header = keys.map((k, i) => k.padEnd(widths[i])).join(\" \");\n const divider = widths.map((w) => \"-\".repeat(w)).join(\" \");\n process.stdout.write(header + \"\\n\" + divider + \"\\n\");\n for (const row of rows) {\n process.stdout.write(\n keys.map((k, i) => String(row[k] ?? \"\").padEnd(widths[i])).join(\" \") + \"\\n\",\n );\n }\n}\n\nexport function printKv(obj: Record<string, unknown>, indent = 0): void {\n const pad = \" \".repeat(indent);\n for (const [k, v] of Object.entries(obj)) {\n if (v !== null && typeof v === \"object\" && !Array.isArray(v)) {\n process.stdout.write(`${pad}${k}:\\n`);\n printKv(v as Record<string, unknown>, indent + 2);\n } else {\n process.stdout.write(`${pad}${k.padEnd(20 - indent)} ${v}\\n`);\n }\n }\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printKv, printTable } from \"../formatter.js\";\n\nexport async function cmdMarketTicker(\n client: OkxRestClient,\n instId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.publicGet(\"/api/v5/market/ticker\", { instId });\n const items = res.data as Record<string, unknown>[];\n if (json) return printJson(items);\n if (!items?.length) { process.stdout.write(\"No data\\n\"); return; }\n const t = items[0];\n printKv({\n instId: t[\"instId\"],\n last: t[\"last\"],\n \"24h change %\": t[\"sodUtc8\"],\n \"24h high\": t[\"high24h\"],\n \"24h low\": t[\"low24h\"],\n \"24h vol\": t[\"vol24h\"],\n time: new Date(Number(t[\"ts\"])).toLocaleString(),\n });\n}\n\nexport async function cmdMarketTickers(\n client: OkxRestClient,\n instType: string,\n json: boolean,\n): Promise<void> {\n const res = await client.publicGet(\"/api/v5/market/tickers\", { instType });\n const items = res.data as Record<string, unknown>[];\n if (json) return printJson(items);\n printTable(\n (items ?? []).map((t) => ({\n instId: t[\"instId\"],\n last: t[\"last\"],\n \"24h high\": t[\"high24h\"],\n \"24h low\": t[\"low24h\"],\n \"24h vol\": t[\"vol24h\"],\n })),\n );\n}\n\nexport async function cmdMarketOrderbook(\n client: OkxRestClient,\n instId: string,\n sz: number | undefined,\n json: boolean,\n): Promise<void> {\n const params: Record<string, unknown> = { instId };\n if (sz !== undefined) params[\"sz\"] = String(sz);\n const res = await client.publicGet(\"/api/v5/market/books\", params);\n if (json) return printJson(res.data);\n const book = (res.data as Record<string, unknown>[])[0];\n if (!book) { process.stdout.write(\"No data\\n\"); return; }\n const asks = (book[\"asks\"] as string[][]).slice(0, 5);\n const bids = (book[\"bids\"] as string[][]).slice(0, 5);\n process.stdout.write(\"Asks (price / size):\\n\");\n for (const [p, s] of asks.reverse()) process.stdout.write(` ${p.padStart(16)} ${s}\\n`);\n process.stdout.write(\"Bids (price / size):\\n\");\n for (const [p, s] of bids) process.stdout.write(` ${p.padStart(16)} ${s}\\n`);\n}\n\nexport async function cmdMarketCandles(\n client: OkxRestClient,\n instId: string,\n opts: { bar?: string; limit?: number; json: boolean },\n): Promise<void> {\n const params: Record<string, unknown> = { instId };\n if (opts.bar) params[\"bar\"] = opts.bar;\n if (opts.limit) params[\"limit\"] = String(opts.limit);\n const res = await client.publicGet(\"/api/v5/market/candles\", params);\n const candles = res.data as string[][];\n if (opts.json) return printJson(candles);\n printTable(\n (candles ?? []).map(([ts, o, h, l, c, vol]) => ({\n time: new Date(Number(ts)).toLocaleString(),\n open: o, high: h, low: l, close: c, vol,\n })),\n );\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printTable } from \"../formatter.js\";\n\nexport async function cmdAccountBalance(\n client: OkxRestClient,\n ccy: string | undefined,\n json: boolean,\n): Promise<void> {\n const params: Record<string, unknown> = {};\n if (ccy) params[\"ccy\"] = ccy;\n const res = await client.privateGet(\"/api/v5/account/balance\", params);\n const data = res.data as Record<string, unknown>[];\n if (json) return printJson(data);\n const details = (data?.[0]?.[\"details\"] as Record<string, unknown>[]) ?? [];\n printTable(\n details\n .filter((d) => Number(d[\"eq\"]) > 0)\n .map((d) => ({\n currency: d[\"ccy\"],\n equity: d[\"eq\"],\n available: d[\"availEq\"],\n frozen: d[\"frozenBal\"],\n })),\n );\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printTable } from \"../formatter.js\";\n\nexport async function cmdSpotOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"open\" | \"history\"; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-history\"\n : \"/api/v5/trade/orders-pending\";\n const params: Record<string, unknown> = { instType: \"SPOT\" };\n if (opts.instId) params[\"instId\"] = opts.instId;\n const res = await client.privateGet(endpoint, params);\n const orders = res.data as Record<string, unknown>[];\n if (opts.json) return printJson(orders);\n printTable(\n (orders ?? []).map((o) => ({\n ordId: o[\"ordId\"],\n instId: o[\"instId\"],\n side: o[\"side\"],\n type: o[\"ordType\"],\n price: o[\"px\"],\n size: o[\"sz\"],\n filled: o[\"fillSz\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSpotPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n px?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: \"cash\",\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.px) body[\"px\"] = opts.px;\n const res = await client.privatePost(\"/api/v5/trade/order\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Order placed: ${order?.[\"ordId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSpotCancel(\n client: OkxRestClient,\n instId: string,\n ordId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-order\", { instId, ordId });\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Cancelled: ${r?.[\"ordId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSpotAlgoPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n tpTriggerPx?: string;\n tpOrdPx?: string;\n slTriggerPx?: string;\n slOrdPx?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: \"cash\",\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.tpTriggerPx) body[\"tpTriggerPx\"] = opts.tpTriggerPx;\n if (opts.tpOrdPx) body[\"tpOrdPx\"] = opts.tpOrdPx;\n if (opts.slTriggerPx) body[\"slTriggerPx\"] = opts.slTriggerPx;\n if (opts.slOrdPx) body[\"slOrdPx\"] = opts.slOrdPx;\n const res = await client.privatePost(\"/api/v5/trade/order-algo\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order placed: ${order?.[\"algoId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSpotAlgoAmend(\n client: OkxRestClient,\n opts: {\n instId: string;\n algoId: string;\n newSz?: string;\n newTpTriggerPx?: string;\n newTpOrdPx?: string;\n newSlTriggerPx?: string;\n newSlOrdPx?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n algoId: opts.algoId,\n };\n if (opts.newSz) body[\"newSz\"] = opts.newSz;\n if (opts.newTpTriggerPx) body[\"newTpTriggerPx\"] = opts.newTpTriggerPx;\n if (opts.newTpOrdPx) body[\"newTpOrdPx\"] = opts.newTpOrdPx;\n if (opts.newSlTriggerPx) body[\"newSlTriggerPx\"] = opts.newSlTriggerPx;\n if (opts.newSlOrdPx) body[\"newSlOrdPx\"] = opts.newSlOrdPx;\n const res = await client.privatePost(\"/api/v5/trade/amend-algos\", body);\n if (opts.json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order amended: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSpotAlgoCancel(\n client: OkxRestClient,\n instId: string,\n algoId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-algos\", [\n { algoId, instId },\n ]);\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order cancelled: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSpotAlgoOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"pending\" | \"history\"; ordType?: string; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-algo-history\"\n : \"/api/v5/trade/orders-algo-pending\";\n const baseParams: Record<string, unknown> = { instType: \"SPOT\" };\n if (opts.instId) baseParams[\"instId\"] = opts.instId;\n\n let orders: Record<string, unknown>[];\n if (opts.ordType) {\n const res = await client.privateGet(endpoint, { ...baseParams, ordType: opts.ordType });\n orders = (res.data as Record<string, unknown>[]) ?? [];\n } else {\n const [r1, r2] = await Promise.all([\n client.privateGet(endpoint, { ...baseParams, ordType: \"conditional\" }),\n client.privateGet(endpoint, { ...baseParams, ordType: \"oco\" }),\n ]);\n orders = [\n ...((r1.data as Record<string, unknown>[]) ?? []),\n ...((r2.data as Record<string, unknown>[]) ?? []),\n ];\n }\n\n if (opts.json) return printJson(orders);\n if (!(orders ?? []).length) { process.stdout.write(\"No algo orders\\n\"); return; }\n printTable(\n orders.map((o) => ({\n algoId: o[\"algoId\"],\n instId: o[\"instId\"],\n type: o[\"ordType\"],\n side: o[\"side\"],\n sz: o[\"sz\"],\n tpTrigger: o[\"tpTriggerPx\"],\n slTrigger: o[\"slTriggerPx\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSpotFills(\n client: OkxRestClient,\n opts: { instId?: string; ordId?: string; json: boolean },\n): Promise<void> {\n const params: Record<string, unknown> = { instType: \"SPOT\" };\n if (opts.instId) params[\"instId\"] = opts.instId;\n if (opts.ordId) params[\"ordId\"] = opts.ordId;\n const res = await client.privateGet(\"/api/v5/trade/fills\", params);\n const fills = res.data as Record<string, unknown>[];\n if (opts.json) return printJson(fills);\n printTable(\n (fills ?? []).map((f) => ({\n instId: f[\"instId\"],\n side: f[\"side\"],\n fillPx: f[\"fillPx\"],\n fillSz: f[\"fillSz\"],\n fee: f[\"fee\"],\n ts: new Date(Number(f[\"ts\"])).toLocaleString(),\n })),\n );\n}\n","import type { OkxRestClient } from \"@okx-hub/core\";\nimport { printJson, printTable } from \"../formatter.js\";\n\nexport async function cmdSwapPositions(\n client: OkxRestClient,\n instId: string | undefined,\n json: boolean,\n): Promise<void> {\n const params: Record<string, unknown> = { instType: \"SWAP\" };\n if (instId) params[\"instId\"] = instId;\n const res = await client.privateGet(\"/api/v5/account/positions\", params);\n const positions = res.data as Record<string, unknown>[];\n if (json) return printJson(positions);\n const open = (positions ?? []).filter((p) => Number(p[\"pos\"]) !== 0);\n if (!open.length) { process.stdout.write(\"No open positions\\n\"); return; }\n printTable(\n open.map((p) => ({\n instId: p[\"instId\"],\n side: p[\"posSide\"],\n size: p[\"pos\"],\n avgPx: p[\"avgPx\"],\n upl: p[\"upl\"],\n uplRatio: p[\"uplRatio\"],\n lever: p[\"lever\"],\n })),\n );\n}\n\nexport async function cmdSwapOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"open\" | \"history\"; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-history\"\n : \"/api/v5/trade/orders-pending\";\n const params: Record<string, unknown> = { instType: \"SWAP\" };\n if (opts.instId) params[\"instId\"] = opts.instId;\n const res = await client.privateGet(endpoint, params);\n const orders = res.data as Record<string, unknown>[];\n if (opts.json) return printJson(orders);\n printTable(\n (orders ?? []).map((o) => ({\n ordId: o[\"ordId\"],\n instId: o[\"instId\"],\n side: o[\"side\"],\n posSide: o[\"posSide\"],\n type: o[\"ordType\"],\n price: o[\"px\"],\n size: o[\"sz\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSwapPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n posSide?: string;\n px?: string;\n tdMode: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: opts.tdMode,\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.posSide) body[\"posSide\"] = opts.posSide;\n if (opts.px) body[\"px\"] = opts.px;\n const res = await client.privatePost(\"/api/v5/trade/order\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Order placed: ${order?.[\"ordId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSwapCancel(\n client: OkxRestClient,\n instId: string,\n ordId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-order\", { instId, ordId });\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Cancelled: ${r?.[\"ordId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`);\n}\n\nexport async function cmdSwapAlgoPlace(\n client: OkxRestClient,\n opts: {\n instId: string;\n side: string;\n ordType: string;\n sz: string;\n posSide?: string;\n tdMode: string;\n tpTriggerPx?: string;\n tpOrdPx?: string;\n slTriggerPx?: string;\n slOrdPx?: string;\n reduceOnly?: boolean;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n tdMode: opts.tdMode,\n side: opts.side,\n ordType: opts.ordType,\n sz: opts.sz,\n };\n if (opts.posSide) body[\"posSide\"] = opts.posSide;\n if (opts.tpTriggerPx) body[\"tpTriggerPx\"] = opts.tpTriggerPx;\n if (opts.tpOrdPx) body[\"tpOrdPx\"] = opts.tpOrdPx;\n if (opts.slTriggerPx) body[\"slTriggerPx\"] = opts.slTriggerPx;\n if (opts.slOrdPx) body[\"slOrdPx\"] = opts.slOrdPx;\n if (opts.reduceOnly !== undefined) body[\"reduceOnly\"] = String(opts.reduceOnly);\n const res = await client.privatePost(\"/api/v5/trade/order-algo\", body);\n if (opts.json) return printJson(res.data);\n const order = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order placed: ${order?.[\"algoId\"]} (${order?.[\"sCode\"] === \"0\" ? \"OK\" : order?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSwapAlgoAmend(\n client: OkxRestClient,\n opts: {\n instId: string;\n algoId: string;\n newSz?: string;\n newTpTriggerPx?: string;\n newTpOrdPx?: string;\n newSlTriggerPx?: string;\n newSlOrdPx?: string;\n json: boolean;\n },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n algoId: opts.algoId,\n };\n if (opts.newSz) body[\"newSz\"] = opts.newSz;\n if (opts.newTpTriggerPx) body[\"newTpTriggerPx\"] = opts.newTpTriggerPx;\n if (opts.newTpOrdPx) body[\"newTpOrdPx\"] = opts.newTpOrdPx;\n if (opts.newSlTriggerPx) body[\"newSlTriggerPx\"] = opts.newSlTriggerPx;\n if (opts.newSlOrdPx) body[\"newSlOrdPx\"] = opts.newSlOrdPx;\n const res = await client.privatePost(\"/api/v5/trade/amend-algos\", body);\n if (opts.json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order amended: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSwapAlgoCancel(\n client: OkxRestClient,\n instId: string,\n algoId: string,\n json: boolean,\n): Promise<void> {\n const res = await client.privatePost(\"/api/v5/trade/cancel-algos\", [\n { algoId, instId },\n ]);\n if (json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(\n `Algo order cancelled: ${r?.[\"algoId\"]} (${r?.[\"sCode\"] === \"0\" ? \"OK\" : r?.[\"sMsg\"]})\\n`,\n );\n}\n\nexport async function cmdSwapAlgoOrders(\n client: OkxRestClient,\n opts: { instId?: string; status: \"pending\" | \"history\"; ordType?: string; json: boolean },\n): Promise<void> {\n const endpoint =\n opts.status === \"history\"\n ? \"/api/v5/trade/orders-algo-history\"\n : \"/api/v5/trade/orders-algo-pending\";\n const baseParams: Record<string, unknown> = { instType: \"SWAP\" };\n if (opts.instId) baseParams[\"instId\"] = opts.instId;\n\n let orders: Record<string, unknown>[];\n if (opts.ordType) {\n const res = await client.privateGet(endpoint, { ...baseParams, ordType: opts.ordType });\n orders = (res.data as Record<string, unknown>[]) ?? [];\n } else {\n const [r1, r2] = await Promise.all([\n client.privateGet(endpoint, { ...baseParams, ordType: \"conditional\" }),\n client.privateGet(endpoint, { ...baseParams, ordType: \"oco\" }),\n ]);\n orders = [\n ...((r1.data as Record<string, unknown>[]) ?? []),\n ...((r2.data as Record<string, unknown>[]) ?? []),\n ];\n }\n\n if (opts.json) return printJson(orders);\n if (!(orders ?? []).length) { process.stdout.write(\"No algo orders\\n\"); return; }\n printTable(\n orders.map((o) => ({\n algoId: o[\"algoId\"],\n instId: o[\"instId\"],\n type: o[\"ordType\"],\n side: o[\"side\"],\n sz: o[\"sz\"],\n tpTrigger: o[\"tpTriggerPx\"],\n slTrigger: o[\"slTriggerPx\"],\n state: o[\"state\"],\n })),\n );\n}\n\nexport async function cmdSwapSetLeverage(\n client: OkxRestClient,\n opts: { instId: string; lever: string; mgnMode: string; posSide?: string; json: boolean },\n): Promise<void> {\n const body: Record<string, unknown> = {\n instId: opts.instId,\n lever: opts.lever,\n mgnMode: opts.mgnMode,\n };\n if (opts.posSide) body[\"posSide\"] = opts.posSide;\n const res = await client.privatePost(\"/api/v5/account/set-leverage\", body);\n if (opts.json) return printJson(res.data);\n const r = (res.data as Record<string, unknown>[])[0];\n process.stdout.write(`Leverage set: ${r?.[\"lever\"]}x ${r?.[\"instId\"]}\\n`);\n}\n","import { writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { stringify } from \"smol-toml\";\nimport { configFilePath } from \"@okx-hub/core\";\nimport type { OkxTomlConfig } from \"@okx-hub/core\";\n\n// Re-export for backward compat within CLI\nexport type { OkxTomlConfig as CliConfig };\nexport { configFilePath as configPath };\n\nexport function configDir(): string {\n return configFilePath().replace(/\\/config\\.toml$/, \"\");\n}\n\nexport function writeCliConfig(config: OkxTomlConfig): void {\n const dir = configDir();\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(configFilePath(), stringify(config as unknown as Record<string, unknown>), \"utf-8\");\n}\n","import { readTomlProfile, configFilePath } from \"@okx-hub/core\";\nimport { writeCliConfig } from \"../config/toml.js\";\nimport { printJson, printKv } from \"../formatter.js\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { parse } from \"smol-toml\";\nimport type { OkxTomlConfig } from \"@okx-hub/core\";\n\nfunction readFullConfig(): OkxTomlConfig {\n const path = configFilePath();\n if (!existsSync(path)) return { profiles: {} };\n const raw = readFileSync(path, \"utf-8\");\n return parse(raw) as unknown as OkxTomlConfig;\n}\n\nexport function cmdConfigShow(json: boolean): void {\n const config = readFullConfig();\n if (json) return printJson(config);\n process.stdout.write(`Config: ${configFilePath()}\\n\\n`);\n process.stdout.write(`default_profile: ${config.default_profile ?? \"(not set)\"}\\n\\n`);\n for (const [name, profile] of Object.entries(config.profiles)) {\n process.stdout.write(`[${name}]\\n`);\n printKv({\n api_key: profile.api_key ? \"***\" + profile.api_key.slice(-4) : \"(not set)\",\n demo: profile.demo ?? false,\n base_url: profile.base_url ?? \"(default)\",\n }, 2);\n process.stdout.write(\"\\n\");\n }\n}\n\nexport function cmdConfigSet(key: string, value: string): void {\n const config = readFullConfig();\n if (key === \"default_profile\") {\n config.default_profile = value;\n writeCliConfig(config);\n process.stdout.write(`default_profile set to \"${value}\"\\n`);\n } else {\n process.stderr.write(`Unknown config key: ${key}\\n`);\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":["existsSync","existsSync","existsSync","readFileSync","parse"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okx-trade-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "OKX CLI - Command line tool for OKX exchange",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,13 +24,13 @@
24
24
  "trading"
25
25
  ],
26
26
  "dependencies": {
27
- "smol-toml": "^1.3.4",
28
- "@okx-hub/core": "1.0.0"
27
+ "smol-toml": "^1.3.4"
29
28
  },
30
29
  "devDependencies": {
31
30
  "@types/node": "^25.2.2",
32
31
  "tsup": "^8.5.1",
33
- "typescript": "^5.9.3"
32
+ "typescript": "^5.9.3",
33
+ "@okx-hub/core": "1.0.0"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "tsup",