@onebullex-group/cli 1.3.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,6 +3,9 @@ import {
3
3
  effectiveFormat,
4
4
  render
5
5
  } from "./chunk-J3TAAD3Q.js";
6
+ import {
7
+ resolveBillNo
8
+ } from "./chunk-6DC55RF7.js";
6
9
  import {
7
10
  DEFAULT_CONFIG_PATH,
8
11
  checkConfigPermissions,
@@ -11,20 +14,23 @@ import {
11
14
  resolveConfig,
12
15
  writeConfigFile
13
16
  } from "./chunk-AKGCHJPQ.js";
17
+ import {
18
+ downloadToFile
19
+ } from "./chunk-SGLPG2FL.js";
14
20
  import {
15
21
  HttpClient
16
- } from "./chunk-NKWXNVLA.js";
22
+ } from "./chunk-YE5LER6U.js";
23
+ import "./chunk-LVNSFQXS.js";
24
+ import {
25
+ redactSecret
26
+ } from "./chunk-OOLZIYXS.js";
27
+ import "./chunk-ZYO5P4DH.js";
17
28
  import {
18
29
  ConfigError,
19
30
  DryRunInterception,
20
31
  EXIT,
21
32
  OneBullExError
22
33
  } from "./chunk-JRUFIHU7.js";
23
- import {
24
- redactSecret
25
- } from "./chunk-OOLZIYXS.js";
26
- import "./chunk-ZYO5P4DH.js";
27
- import "./chunk-LVNSFQXS.js";
28
34
 
29
35
  // src/index.ts
30
36
  import { Command } from "commander";
@@ -113,11 +119,11 @@ function prune(o) {
113
119
  return out;
114
120
  }
115
121
  function registerTickerGet(parent, ctx) {
116
- parent.command("get <symbol>").description("Get ticker for a symbol (GET /v2/public/q/ticker)").option("--time-range <type>", "time range type").action(async (symbol, opts) => {
122
+ parent.command("get <symbol>").description("Get ticker for a symbol (GET /v2/public/q/ticker)").requiredOption("--time-range-type <type>", "H24, or calendar-day window UTC_P_0..UTC_P_12 / UTC_N_1..UTC_N_12 (e.g. UTC_P_8)").action(async (symbol, opts) => {
117
123
  const c = ctx.http({ requireAuth: false });
118
124
  const data = await c.getPublic(
119
125
  "/v2/public/q/ticker",
120
- prune({ symbol, timeRangeType: opts.timeRange })
126
+ prune({ symbol, timeRangeType: opts.timeRangeType })
121
127
  );
122
128
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
123
129
  ctx.stdout(
@@ -138,11 +144,11 @@ function prune2(o) {
138
144
  return out;
139
145
  }
140
146
  function registerTickerList(parent, ctx) {
141
- parent.command("list").description("List all tickers (GET /v2/public/q/tickers)").requiredOption("--time-range <type>", "time range type").action(async (opts) => {
147
+ parent.command("list").description("List all tickers (GET /v2/public/q/tickers)").requiredOption("--time-range-type <type>", "H24, or calendar-day window UTC_P_0..UTC_P_12 / UTC_N_1..UTC_N_12 (e.g. UTC_P_8)").action(async (opts) => {
142
148
  const c = ctx.http({ requireAuth: false });
143
149
  const data = await c.getPublic(
144
150
  "/v2/public/q/tickers",
145
- prune2({ timeRangeType: opts.timeRange })
151
+ prune2({ timeRangeType: opts.timeRangeType })
146
152
  );
147
153
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
148
154
  ctx.stdout(
@@ -163,11 +169,11 @@ function prune3(o) {
163
169
  return out;
164
170
  }
165
171
  function registerTickerAgg(parent, ctx) {
166
- parent.command("agg <symbol>").description("Get aggregated ticker for a symbol (GET /v2/public/q/agg-ticker)").option("--time-range <type>", "time range type").action(async (symbol, opts) => {
172
+ parent.command("agg <symbol>").description("Get aggregated ticker for a symbol (GET /v2/public/q/agg-ticker)").requiredOption("--time-range-type <type>", "H24, or calendar-day window UTC_P_0..UTC_P_12 / UTC_N_1..UTC_N_12 (e.g. UTC_P_8)").action(async (symbol, opts) => {
167
173
  const c = ctx.http({ requireAuth: false });
168
174
  const data = await c.getPublic(
169
175
  "/v2/public/q/agg-ticker",
170
- prune3({ symbol, timeRangeType: opts.timeRange })
176
+ prune3({ symbol, timeRangeType: opts.timeRangeType })
171
177
  );
172
178
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
173
179
  ctx.stdout(
@@ -188,11 +194,11 @@ function prune4(o) {
188
194
  return out;
189
195
  }
190
196
  function registerTickerAggList(parent, ctx) {
191
- parent.command("agg-list").description("List all aggregated tickers (GET /v2/public/q/agg-tickers)").requiredOption("--time-range <type>", "time range type").action(async (opts) => {
197
+ parent.command("agg-list").description("List all aggregated tickers (GET /v2/public/q/agg-tickers)").requiredOption("--time-range-type <type>", "H24, or calendar-day window UTC_P_0..UTC_P_12 / UTC_N_1..UTC_N_12 (e.g. UTC_P_8)").action(async (opts) => {
192
198
  const c = ctx.http({ requireAuth: false });
193
199
  const data = await c.getPublic(
194
200
  "/v2/public/q/agg-tickers",
195
- prune4({ timeRangeType: opts.timeRange })
201
+ prune4({ timeRangeType: opts.timeRangeType })
196
202
  );
197
203
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
198
204
  ctx.stdout(
@@ -213,7 +219,7 @@ function prune5(o) {
213
219
  return out;
214
220
  }
215
221
  function registerDepthGet(parent, ctx) {
216
- parent.command("get <symbol>").description("Get order book depth (GET /v2/public/q/depth)").option("--level <level>", "depth level", parseInt).action(async (symbol, opts) => {
222
+ parent.command("get <symbol>").description("Get order book depth (GET /v2/public/q/depth)").requiredOption("--level <level>", "depth levels, 1-50", parseInt).action(async (symbol, opts) => {
217
223
  const c = ctx.http({ requireAuth: false });
218
224
  const data = await c.getPublic(
219
225
  "/v2/public/q/depth",
@@ -355,8 +361,8 @@ function registerIndexPriceList(parent, ctx) {
355
361
  // src/commands/index-price/get.ts
356
362
  function registerIndexPriceGet(parent, ctx) {
357
363
  parent.command("get <symbol>").description("Get index price for a symbol (GET /v2/public/q/symbol-index-price)").action(async (symbol) => {
358
- const c = ctx.http({ requireAuth: true });
359
- const data = await c.getPrivate("/v2/public/q/symbol-index-price", { symbol });
364
+ const c = ctx.http({ requireAuth: false });
365
+ const data = await c.getPublic("/v2/public/q/symbol-index-price", { symbol });
360
366
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
361
367
  ctx.stdout(
362
368
  render2(data, {
@@ -545,18 +551,22 @@ function prune12(o) {
545
551
  return out;
546
552
  }
547
553
  function registerBalanceBills(parent, ctx) {
548
- parent.command("bills").description("List balance bill records (GET /v2/balance/bills)").option("--coin <coin>", "filter by coin").option("--type <type>", "bill type").option("--start-time <ms>", "start time in milliseconds", parseInt).option("--end-time <ms>", "end time in milliseconds", parseInt).option("--page <page>", "page number", parseInt).option("--size <size>", "page size", parseInt).action(
554
+ parent.command("bills").description(
555
+ "List balance bill records, cursor-paginated (GET /v2/balance/bills). Pass the last item id as --id with --direction NEXT for the next page."
556
+ ).option("--coin <coin>", "filter by coin").option("--symbol <symbol>", "filter by trading pair").option("--type <type>", "bill type, e.g. EXCHANGE / FEE / FUND / CLOSE_POSITION").option("--start-time <ms>", "start time in milliseconds", parseInt).option("--end-time <ms>", "end time in milliseconds", parseInt).option("--id <id>", "cursor: bill id to page from").option("--direction <direction>", "cursor direction: NEXT | PREV (API default NEXT)").option("--limit <limit>", "records per page (API default 10)", parseInt).action(
549
557
  async (opts) => {
550
558
  const c = ctx.http({ requireAuth: true });
551
559
  const data = await c.getPrivate(
552
560
  "/v2/balance/bills",
553
561
  prune12({
554
562
  coin: opts.coin,
563
+ symbol: opts.symbol,
555
564
  type: opts.type,
556
565
  startTime: opts.startTime,
557
566
  endTime: opts.endTime,
558
- page: opts.page,
559
- size: opts.size
567
+ id: opts.id,
568
+ direction: opts.direction,
569
+ limit: opts.limit
560
570
  })
561
571
  );
562
572
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
@@ -570,6 +580,106 @@ function registerBalanceBills(parent, ctx) {
570
580
  );
571
581
  }
572
582
 
583
+ // src/commands/balance/funding.ts
584
+ function registerBalanceFunding(parent, ctx) {
585
+ parent.command("funding").description("Get funding account (USDT) balance (GET /v2/balance/funding)").action(async () => {
586
+ const c = ctx.http({ requireAuth: true });
587
+ const data = await c.getPrivate("/v2/balance/funding", {});
588
+ const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
589
+ ctx.stdout(
590
+ render2(data, {
591
+ format: effectiveFormat2(ctx.outputFormat, ctx.isTTY),
592
+ isTTY: ctx.isTTY
593
+ })
594
+ );
595
+ });
596
+ }
597
+
598
+ // src/core/dry-run.ts
599
+ function renderDryRun(p) {
600
+ const lines = [
601
+ "--- DRY RUN (no request sent) ---",
602
+ `${p.method} ${p.url}`
603
+ ];
604
+ if (p.body !== void 0) {
605
+ lines.push("Body:");
606
+ lines.push(JSON.stringify(p.body, null, 2));
607
+ }
608
+ lines.push("");
609
+ lines.push("To execute, re-run with --confirm.");
610
+ return lines.join("\n");
611
+ }
612
+
613
+ // src/core/execute-write.ts
614
+ async function executeWrite(opts) {
615
+ if (!opts.confirm) {
616
+ const url = `${opts.config?.baseUrl ?? ""}${opts.path}`;
617
+ const preview = renderDryRun({ method: opts.method, url, body: opts.body });
618
+ throw new DryRunInterception(preview);
619
+ }
620
+ return opts.send();
621
+ }
622
+
623
+ // src/commands/_write/_helpers.ts
624
+ function pruneEmpty(o) {
625
+ const out = {};
626
+ for (const [k, v] of Object.entries(o)) {
627
+ if (v != null && v !== "") out[k] = v;
628
+ }
629
+ return out;
630
+ }
631
+ async function runWrite(ctx, path, body) {
632
+ const cfg = ctx.resolveConfig({ requireAuth: true });
633
+ const c = ctx.http({ requireAuth: true });
634
+ const data = await executeWrite({
635
+ confirm: ctx.confirm ?? false,
636
+ method: "POST",
637
+ path,
638
+ body,
639
+ send: () => c.postPrivate(path, body),
640
+ config: cfg
641
+ });
642
+ ctx.stdout(
643
+ render(data, {
644
+ format: effectiveFormat(ctx.outputFormat, ctx.isTTY),
645
+ isTTY: ctx.isTTY
646
+ })
647
+ );
648
+ }
649
+
650
+ // src/commands/balance/transfer.ts
651
+ function registerBalanceTransfer(parent, ctx) {
652
+ parent.command("transfer").description("Transfer funds between accounts (POST /v2/balance/transfer)").requiredOption("--from <account>", "source account: FUNDING | CONTRACT").requiredOption("--to <account>", "destination account: FUNDING | CONTRACT").requiredOption("--amount <amount>", "transfer amount, must be greater than 0").option("--bill-no <id>", "idempotency key; auto-generated when omitted").option("--remark <text>", "optional note").action(
653
+ async (opts) => {
654
+ if (opts.from === opts.to) {
655
+ throw new Error("--from and --to must differ (the API rejects identical accounts)");
656
+ }
657
+ await runWrite(ctx, "/v2/balance/transfer", {
658
+ billNo: resolveBillNo(opts.billNo),
659
+ from: opts.from,
660
+ to: opts.to,
661
+ amount: opts.amount,
662
+ ...opts.remark != null && opts.remark !== "" ? { remark: opts.remark } : {}
663
+ });
664
+ }
665
+ );
666
+ }
667
+
668
+ // src/commands/bot/redeeming-info.ts
669
+ function registerBotRedeemingInfo(parent, ctx) {
670
+ parent.command("redeeming-info").description("Get bot redemption queue summary (GET /v2/bot/redeeming-info)").action(async () => {
671
+ const c = ctx.http({ requireAuth: true });
672
+ const data = await c.getPrivate("/v2/bot/redeeming-info", {});
673
+ const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
674
+ ctx.stdout(
675
+ render2(data, {
676
+ format: effectiveFormat2(ctx.outputFormat, ctx.isTTY),
677
+ isTTY: ctx.isTTY
678
+ })
679
+ );
680
+ });
681
+ }
682
+
573
683
  // src/commands/order/list-unfinished.ts
574
684
  function prune13(o) {
575
685
  const out = {};
@@ -579,7 +689,7 @@ function prune13(o) {
579
689
  return out;
580
690
  }
581
691
  function registerOrderListUnfinished(parent, ctx) {
582
- parent.command("list-unfinished <symbol>").description("List unfinished orders for a symbol (GET /v2/order/listUnfinished)").option("--direction <direction>", "order direction").action(async (symbol, opts) => {
692
+ parent.command("list-unfinished <symbol>").description("List unfinished orders for a symbol (GET /v2/order/listUnfinished)").requiredOption("--direction <direction>", "order side: BUY | SELL").action(async (symbol, opts) => {
583
693
  const c = ctx.http({ requireAuth: true });
584
694
  const data = await c.getPrivate(
585
695
  "/v2/order/listUnfinished",
@@ -666,7 +776,7 @@ function prune15(o) {
666
776
  return out;
667
777
  }
668
778
  function registerOrderListHistory(parent, ctx) {
669
- parent.command("list-history").description("List order history (GET /v2/order/list-history)").option("--symbol <symbol>", "filter by symbol").option("--start-time <ms>", "start time in milliseconds", parseInt).option("--end-time <ms>", "end time in milliseconds", parseInt).option("--id <id>", "order ID cursor").option("--direction <direction>", "order direction").option("--limit <limit>", "number of records", parseInt).option("--force-close", "filter force-close orders").action(
779
+ parent.command("list-history").description("List order history (GET /v2/order/list-history)").option("--symbol <symbol>", "filter by symbol").option("--start-time <ms>", "start time in milliseconds", parseInt).option("--end-time <ms>", "end time in milliseconds", parseInt).option("--id <id>", "order ID cursor").option("--direction <direction>", "cursor direction: NEXT | PREV (API default NEXT)").option("--limit <limit>", "number of records", parseInt).option("--force-close", "filter force-close orders").action(
670
780
  async (opts) => {
671
781
  const c = ctx.http({ requireAuth: true });
672
782
  const data = await c.getPrivate(
@@ -775,7 +885,7 @@ function prune18(o) {
775
885
  return out;
776
886
  }
777
887
  function registerEntrustPlanHistory(parent, ctx) {
778
- parent.command("plan-history").description("List plan entrust history (GET /v2/entrust/plan-list-history)").option("--symbol <symbol>", "filter by symbol").option("--start-time <ms>", "start time in milliseconds", parseInt).option("--end-time <ms>", "end time in milliseconds", parseInt).option("--id <id>", "cursor ID").option("--direction <direction>", "order direction").option("--limit <limit>", "number of records", parseInt).action(
888
+ parent.command("plan-history").description("List plan entrust history (GET /v2/entrust/plan-list-history)").option("--symbol <symbol>", "filter by symbol").option("--start-time <ms>", "start time in milliseconds", parseInt).option("--end-time <ms>", "end time in milliseconds", parseInt).option("--id <id>", "cursor ID").option("--direction <direction>", "cursor direction: NEXT | PREV (API default NEXT)").option("--limit <limit>", "number of records", parseInt).action(
779
889
  async (opts) => {
780
890
  const c = ctx.http({ requireAuth: true });
781
891
  const data = await c.getPrivate(
@@ -802,7 +912,9 @@ function registerEntrustPlanHistory(parent, ctx) {
802
912
 
803
913
  // src/commands/entrust/plan-get.ts
804
914
  function registerEntrustPlanGet(parent, ctx) {
805
- parent.command("plan-get <id>").description("Get plan entrust detail (GET /v2/entrust/plan-detail)").action(async (id) => {
915
+ parent.command("plan-get <id>").description(
916
+ "Get plan entrust detail (GET /v2/entrust/plan-detail). Positional <id> is sent as entrustId."
917
+ ).action(async (id) => {
806
918
  const c = ctx.http({ requireAuth: true });
807
919
  const data = await c.getPrivate("/v2/entrust/plan-detail", { entrustId: id });
808
920
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
@@ -842,7 +954,9 @@ function registerEntrustProfitList(parent, ctx) {
842
954
 
843
955
  // src/commands/entrust/profit-get.ts
844
956
  function registerEntrustProfitGet(parent, ctx) {
845
- parent.command("profit-get <id>").description("Get TP/SL entrust detail (GET /v2/entrust/profit-detail)").action(async (id) => {
957
+ parent.command("profit-get <id>").description(
958
+ "Get TP/SL entrust detail (GET /v2/entrust/profit-detail). Positional <id> is sent as profitId."
959
+ ).action(async (id) => {
846
960
  const c = ctx.http({ requireAuth: true });
847
961
  const data = await c.getPrivate("/v2/entrust/profit-detail", { profitId: id });
848
962
  const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
@@ -954,7 +1068,9 @@ async function prompt(rl, q, def) {
954
1068
  return ans.length === 0 && def !== void 0 ? def : ans;
955
1069
  }
956
1070
  function registerConfigInit(parent, ctx) {
957
- parent.command("init").description("Initialize a new profile (interactive)").option("--name <name>", "profile name (skip prompt)").option("--env <env>", "environment: test | prod").option("--base-url <url>", "override base url").option("--api-key <key>", "API key (only allowed with --yes; prefer interactive)").option("--secret <secret>", "API secret (only allowed with --yes; prefer interactive)").option("--identify <id>", "sub-account identify header (optional)").option("--set-default", "mark this profile as default-profile", true).option("--yes", "non-interactive mode (use provided flags only)").action(async (flags) => {
1071
+ parent.command("init").description("Initialize a new profile (interactive)").option("--name <name>", "profile name (skip prompt)").option("--env <env>", "environment: test | prod").option("--base-url <url>", "override base url").option("--api-key <key>", "API key (only allowed with --yes; prefer interactive)").option("--secret <secret>", "API secret (only allowed with --yes; prefer interactive)").option("--identify <id>", "sub-account identify header (optional)").option("--set-default", "mark this profile as default-profile (default)", true).option("--no-set-default", "add the profile without changing default-profile").option("--yes", "non-interactive mode (use provided flags only)").action(async (subFlags, cmd) => {
1072
+ const flags = cmd.optsWithGlobals();
1073
+ flags.setDefault = subFlags.setDefault;
958
1074
  const path = ctx.getConfigPath();
959
1075
  let existing = null;
960
1076
  try {
@@ -1172,61 +1288,9 @@ function registerConfigRemove(parent, ctx) {
1172
1288
  });
1173
1289
  }
1174
1290
 
1175
- // src/core/dry-run.ts
1176
- function renderDryRun(p) {
1177
- const lines = [
1178
- "--- DRY RUN (no request sent) ---",
1179
- `${p.method} ${p.url}`
1180
- ];
1181
- if (p.body !== void 0) {
1182
- lines.push("Body:");
1183
- lines.push(JSON.stringify(p.body, null, 2));
1184
- }
1185
- lines.push("");
1186
- lines.push("To execute, re-run with --confirm.");
1187
- return lines.join("\n");
1188
- }
1189
-
1190
- // src/core/execute-write.ts
1191
- async function executeWrite(opts) {
1192
- if (!opts.confirm) {
1193
- const url = `${opts.config?.baseUrl ?? ""}${opts.path}`;
1194
- const preview = renderDryRun({ method: opts.method, url, body: opts.body });
1195
- throw new DryRunInterception(preview);
1196
- }
1197
- return opts.send();
1198
- }
1199
-
1200
- // src/commands/_write/_helpers.ts
1201
- function pruneEmpty(o) {
1202
- const out = {};
1203
- for (const [k, v] of Object.entries(o)) {
1204
- if (v != null && v !== "") out[k] = v;
1205
- }
1206
- return out;
1207
- }
1208
- async function runWrite(ctx, path, body) {
1209
- const cfg = ctx.resolveConfig({ requireAuth: true });
1210
- const c = ctx.http({ requireAuth: true });
1211
- const data = await executeWrite({
1212
- confirm: ctx.confirm ?? false,
1213
- method: "POST",
1214
- path,
1215
- body,
1216
- send: () => c.postPrivate(path, body),
1217
- config: cfg
1218
- });
1219
- ctx.stdout(
1220
- render(data, {
1221
- format: effectiveFormat(ctx.outputFormat, ctx.isTTY),
1222
- isTTY: ctx.isTTY
1223
- })
1224
- );
1225
- }
1226
-
1227
1291
  // src/commands/order/create.ts
1228
1292
  function registerOrderCreate(parent, ctx) {
1229
- parent.command("create").description("Place a new order (POST /v2/order/create)").requiredOption("--symbol <symbol>", "trading pair, e.g. btc_usdt").requiredOption("--order-type <type>", "LIMIT | MARKET | STOP_LIMIT | etc.").requiredOption("--order-side <side>", "BUY | SELL").requiredOption("--position-side <side>", "LONG | SHORT | NET").requiredOption("--orig-qty <qty>", "order quantity (string, decimal-safe)").option("--price <price>", "limit price (string)").option("--time-in-force <tif>", "GTC | IOC | FOK | GTX").option("--reduce-only <bool>", "true | false").option("--client-order-id <id>", "client-supplied order id").option("--position-id <id>", "existing position id (for hedge mode)").option("--leverage <lv>", "override leverage").option("--trigger-profit-price <price>", "TP trigger price").option("--trigger-stop-price <price>", "SL trigger price").option("--profit-order-type <type>", "TP child order type").option("--stop-order-type <type>", "SL child order type").option("--profit-order-price <price>", "TP child order price").option("--stop-order-price <price>", "SL child order price").option("--market-order-level <lv>", "market order depth level").action(
1293
+ parent.command("create").description("Place a new order (POST /v2/order/create)").requiredOption("--symbol <symbol>", "trading pair, e.g. btc_usdt").requiredOption("--order-type <type>", "LIMIT | MARKET").requiredOption("--order-side <side>", "BUY | SELL").requiredOption("--position-side <side>", "LONG | SHORT").requiredOption("--orig-qty <qty>", "integer contracts (string)").option("--price <price>", "required when --order-type LIMIT; ignored for MARKET").option("--time-in-force <tif>", "GTC | IOC | FOK | GTX (MARKET defaults IOC, LIMIT defaults GTC; MARKET only allows IOC/FOK)").option("--reduce-only <bool>", "true | false").option("--client-order-id <id>", "client-supplied order id").option("--position-id <id>", "existing position id (for hedge mode)").option("--leverage <lv>", "override leverage").option("--trigger-profit-price <price>", "TP trigger price").option("--trigger-stop-price <price>", "SL trigger price").option("--profit-order-type <type>", "TP child order type").option("--stop-order-type <type>", "SL child order type").option("--profit-order-price <price>", "TP child order price").option("--stop-order-price <price>", "SL child order price").option("--market-order-level <lv>", "market order depth level").action(
1230
1294
  async (opts) => {
1231
1295
  const body = pruneEmpty({
1232
1296
  symbol: opts.symbol,
@@ -1289,7 +1353,7 @@ function registerOrderCancelAll(parent, ctx) {
1289
1353
 
1290
1354
  // src/commands/entrust/create-plan.ts
1291
1355
  function registerEntrustCreatePlan(parent, ctx) {
1292
- parent.command("create-plan").description("Create a plan entrust (POST /v2/entrust/create-plan)").requiredOption("--symbol <symbol>", "trading pair").requiredOption("--order-side <side>", "BUY | SELL").requiredOption("--position-side <side>", "LONG | SHORT | NET").requiredOption("--entrust-type <type>", "plan entrust type").requiredOption("--time-in-force <tif>", "time-in-force, e.g. GTC").requiredOption("--trigger-price-type <type>", "INDEX | MARK | LATEST").requiredOption("--orig-qty <qty>", "order quantity (string)").option("--stop-price <price>", "stop price").option("--price <price>", "limit price").option("--position-id <id>", "existing position id").option("--market-order-level <lv>", "market order depth level").option("--expire-time <ms>", "expiration time in ms").action(
1356
+ parent.command("create-plan").description("Create a plan entrust (POST /v2/entrust/create-plan)").requiredOption("--symbol <symbol>", "trading pair").requiredOption("--order-side <side>", "BUY | SELL").requiredOption("--position-side <side>", "LONG | SHORT").requiredOption("--entrust-type <type>", "STOP | STOP_MARKET").requiredOption("--time-in-force <tif>", "GTC | IOC | FOK | GTX").requiredOption("--trigger-price-type <type>", "MARK_PRICE | LATEST_PRICE").requiredOption("--orig-qty <qty>", "integer contracts (string)").requiredOption("--stop-price <price>", "trigger price (server-required despite the doc marking it conditional)").option("--price <price>", "limit price").option("--position-id <id>", "existing position id").option("--market-order-level <lv>", "market order depth level").option("--expire-time <ms>", "expiration time in ms").action(
1293
1357
  async (opts) => {
1294
1358
  const body = pruneEmpty({
1295
1359
  symbol: opts.symbol,
@@ -1312,7 +1376,7 @@ function registerEntrustCreatePlan(parent, ctx) {
1312
1376
 
1313
1377
  // src/commands/entrust/create-profit.ts
1314
1378
  function registerEntrustCreateProfit(parent, ctx) {
1315
- parent.command("create-profit").description("Create a TP/SL entrust (POST /v2/entrust/create-profit)").requiredOption("--symbol <symbol>", "trading pair").requiredOption("--orig-qty <qty>", "order quantity (string)").option("--position-side <side>", "LONG | SHORT | NET").option("--order-side <side>", "BUY | SELL").option("--trigger-price-type <type>", "INDEX | MARK | LATEST").option("--trigger-profit-price <price>", "TP trigger price").option("--trigger-stop-price <price>", "SL trigger price").option("--profit-order-type <type>", "TP child order type").option("--stop-order-type <type>", "SL child order type").option("--profit-order-price <price>", "TP child order price").option("--stop-order-price <price>", "SL child order price").option("--position-id <id>", "existing position id").option("--reduce-only <bool>", "true | false").option("--profit-flag <flag>", "profit flag").option("--expire-time <ms>", "expiration time in ms").action(
1379
+ parent.command("create-profit").description("Create a TP/SL entrust (POST /v2/entrust/create-profit)").requiredOption("--symbol <symbol>", "trading pair").requiredOption("--orig-qty <qty>", "order quantity (string)").option("--position-side <side>", "LONG | SHORT (required when --position-id is omitted)").option("--order-side <side>", "BUY | SELL (required when --position-id is omitted)").option("--trigger-price-type <type>", "MARK_PRICE | LATEST_PRICE (API default LATEST_PRICE)").option("--trigger-profit-price <price>", "TP trigger price").option("--trigger-stop-price <price>", "SL trigger price").option("--profit-order-type <type>", "TP child order type").option("--stop-order-type <type>", "SL child order type").option("--profit-order-price <price>", "TP child order price").option("--stop-order-price <price>", "SL child order price").option("--position-id <id>", "existing position id").option("--reduce-only <bool>", "true | false").option("--profit-flag <flag>", "profit flag").option("--expire-time <ms>", "expiration time in ms").action(
1316
1380
  async (opts) => {
1317
1381
  const body = pruneEmpty({
1318
1382
  symbol: opts.symbol,
@@ -1471,6 +1535,68 @@ function registerPositionChangeType(parent, ctx) {
1471
1535
  );
1472
1536
  }
1473
1537
 
1538
+ // src/commands/position/history-async.ts
1539
+ var MAX_RANGE_MS = 366 * 24 * 60 * 60 * 1e3;
1540
+ function registerPositionHistoryAsync(parent, ctx) {
1541
+ parent.command("history-async").description(
1542
+ "Create an async position-history export task (GET /v2/position/history/async). Max 1-year range; at most 5 tasks per account per month. Download the result with `system download <downloadId>`."
1543
+ ).requiredOption("--start-time <ms>", "start time in milliseconds", parseInt).requiredOption("--end-time <ms>", "end time in milliseconds", parseInt).action(async (opts) => {
1544
+ if (!Number.isFinite(opts.startTime) || !Number.isFinite(opts.endTime)) {
1545
+ throw new Error("--start-time and --end-time must be millisecond timestamps");
1546
+ }
1547
+ if (opts.endTime < opts.startTime) {
1548
+ throw new Error("--end-time must not be earlier than --start-time");
1549
+ }
1550
+ if (opts.endTime - opts.startTime > MAX_RANGE_MS) {
1551
+ throw new Error("time range must not exceed 1 year (API limit)");
1552
+ }
1553
+ const c = ctx.http({ requireAuth: true });
1554
+ const data = await c.getPrivate("/v2/position/history/async", {
1555
+ startTime: opts.startTime,
1556
+ endTime: opts.endTime
1557
+ });
1558
+ const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
1559
+ ctx.stdout(
1560
+ render2(data, {
1561
+ format: effectiveFormat2(ctx.outputFormat, ctx.isTTY),
1562
+ isTTY: ctx.isTTY
1563
+ })
1564
+ );
1565
+ });
1566
+ }
1567
+
1568
+ // src/commands/system/user-info.ts
1569
+ function registerSystemUserInfo(parent, ctx) {
1570
+ parent.command("user-info").description("Get the user bound to the current API key (GET /v2/system/user/info)").action(async () => {
1571
+ const c = ctx.http({ requireAuth: true });
1572
+ const data = await c.getPrivate("/v2/system/user/info", {});
1573
+ const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
1574
+ ctx.stdout(
1575
+ render2(data, {
1576
+ format: effectiveFormat2(ctx.outputFormat, ctx.isTTY),
1577
+ isTTY: ctx.isTTY
1578
+ })
1579
+ );
1580
+ });
1581
+ }
1582
+
1583
+ // src/commands/system/download.ts
1584
+ function registerSystemDownload(parent, ctx) {
1585
+ parent.command("download <downloadId>").description(
1586
+ "Download an async export file (GET /v2/system/download). Saves to ~/.onebullex/downloads/ unless --out is given. Each success counts toward the 5-per-hour limit for that downloadId."
1587
+ ).option("--out <path>", 'target file, or an existing directory / path ending in "/"').action(async (downloadId, opts) => {
1588
+ const c = ctx.http({ requireAuth: true });
1589
+ const result = await downloadToFile({ client: c, downloadId, out: opts.out, cwd: ctx.cwd });
1590
+ const { render: render2, effectiveFormat: effectiveFormat2 } = await import("./output-UIZGG7EU.js");
1591
+ ctx.stdout(
1592
+ render2(result, {
1593
+ format: effectiveFormat2(ctx.outputFormat, ctx.isTTY),
1594
+ isTTY: ctx.isTTY
1595
+ })
1596
+ );
1597
+ });
1598
+ }
1599
+
1474
1600
  // src/index.ts
1475
1601
  function buildProgram(opts) {
1476
1602
  const stdoutFn = opts?.stdout ?? ((s) => process.stdout.write(s + "\n"));
@@ -1512,7 +1638,7 @@ function buildProgram(opts) {
1512
1638
  return new HttpClient(cfg, opts?.fetch);
1513
1639
  }
1514
1640
  };
1515
- const program = new Command("onebullex").version(true ? "1.3.1" : "0.0.0-dev").description("OneBullEx exchange CLI").option("-p, --profile <name>", "config profile to use").option("-o, --output <format>", "output format: table | json").option("--debug", "enable debug logging").option("--timeout <ms>", "request timeout in milliseconds", parseInt).option("--confirm", "confirm write operations (required for non-dry-run writes)").option("--base-url <url>", "override base URL").option("--api-key <key>", "override api key (env: ONEBULLEX_API_KEY)").option("--secret <s>", "override secret (env: ONEBULLEX_SECRET; CLI flag discouraged for security)").exitOverride();
1641
+ const program = new Command("onebullex").version(true ? "1.5.0" : "0.0.0-dev").description("OneBullEx exchange CLI").option("-p, --profile <name>", "config profile to use").option("-o, --output <format>", "output format: table | json").option("--debug", "enable debug logging").option("--timeout <ms>", "request timeout in milliseconds", parseInt).option("--confirm", "confirm write operations (required for non-dry-run writes)").option("--base-url <url>", "override base URL").option("--api-key <key>", "override api key (env: ONEBULLEX_API_KEY)").option("--secret <s>", "override secret (env: ONEBULLEX_SECRET; CLI flag discouraged for security)").exitOverride();
1516
1642
  program.hook("preAction", (thisCommand, _actionCommand) => {
1517
1643
  const flags = thisCommand.opts();
1518
1644
  if (flags.output === "table" || flags.output === "json") {
@@ -1569,6 +1695,10 @@ function buildProgram(opts) {
1569
1695
  registerBalanceList(balance, ctx);
1570
1696
  registerBalanceGet(balance, ctx);
1571
1697
  registerBalanceBills(balance, ctx);
1698
+ registerBalanceFunding(balance, ctx);
1699
+ registerBalanceTransfer(balance, ctx);
1700
+ const bot = program.command("bot").description("Bot redemption queue");
1701
+ registerBotRedeemingInfo(bot, ctx);
1572
1702
  const order = program.command("order").description("Orders");
1573
1703
  registerOrderListUnfinished(order, ctx);
1574
1704
  registerOrderListUnfinishedMulti(order, ctx);
@@ -1603,12 +1733,16 @@ function buildProgram(opts) {
1603
1733
  registerPositionList(position, ctx);
1604
1734
  registerPositionConfs(position, ctx);
1605
1735
  registerPositionHistory(position, ctx);
1736
+ registerPositionHistoryAsync(position, ctx);
1606
1737
  registerPositionAdjustLeverage(position, ctx);
1607
1738
  registerPositionMargin(position, ctx);
1608
1739
  registerPositionAutoMargin(position, ctx);
1609
1740
  registerPositionCloseAll(position, ctx);
1610
1741
  registerPositionMerge(position, ctx);
1611
1742
  registerPositionChangeType(position, ctx);
1743
+ const system = program.command("system").description("Account identity and async export downloads");
1744
+ registerSystemUserInfo(system, ctx);
1745
+ registerSystemDownload(system, ctx);
1612
1746
  const config = program.command("config").description("Manage CLI configuration");
1613
1747
  registerConfigInit(config, ctx);
1614
1748
  registerConfigSet(config, ctx);
@@ -1656,7 +1790,7 @@ async function main(argv) {
1656
1790
  return EXIT.GENERIC;
1657
1791
  }
1658
1792
  }
1659
- var isEntry = process.argv[1] && (process.argv[1].endsWith("/index.ts") || process.argv[1].endsWith("/index.js") || process.argv[1].endsWith("\\index.ts") || process.argv[1].endsWith("\\index.js"));
1793
+ var isEntry = process.argv[1] && (process.argv[1].endsWith("/index.ts") || process.argv[1].endsWith("/index.js") || process.argv[1].endsWith("\\index.ts") || process.argv[1].endsWith("\\index.js") || process.argv[1].endsWith("/onebullex") || process.argv[1].endsWith("\\onebullex"));
1660
1794
  if (isEntry) {
1661
1795
  void main(process.argv).then((code) => process.exit(code));
1662
1796
  }
@@ -25,7 +25,7 @@ declare function diffEndpoints(doc: readonly Endpoint[], cli: readonly Endpoint[
25
25
  * - GET / query table: 5 columns `参数 | 位置 | 类型 | 必填 | 说明`
26
26
  * - POST body table: 4 columns `字段 | 类型 | 必填 | 说明`
27
27
  */
28
- declare function parseDocParams(md: string, path: string): DocParam[];
28
+ declare function parseDocParams(rawMd: string, path: string): DocParam[];
29
29
  /**
30
30
  * Parses a TS source string and returns commander positional/option flags as
31
31
  * `(name, required)` pairs. Positional `<x>` → required, `[x]` → optional;
package/dist/lint-api.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  REGISTRY
4
- } from "./chunk-PEVZEMJG.js";
4
+ } from "./chunk-NMW73ILO.js";
5
5
 
6
6
  // scripts/check-cli-coverage.ts
7
7
  import { readFileSync } from "fs";
@@ -37,7 +37,8 @@ function diffEndpoints(doc, cli) {
37
37
  function escapeRegex(s) {
38
38
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
39
39
  }
40
- function parseDocParams(md, path) {
40
+ function parseDocParams(rawMd, path) {
41
+ const md = rawMd.replace(/\r\n/g, "\n");
41
42
  const headingRe = new RegExp(
42
43
  `####\\s+(?:GET|POST)\\s+${escapeRegex(path)}\\b`,
43
44
  "m"
@@ -130,20 +131,40 @@ var GLOBAL_FLAGS = /* @__PURE__ */ new Set([
130
131
  function normalize(name) {
131
132
  return name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/_/g, "-").toLowerCase();
132
133
  }
134
+ var CLI_DEFAULTED_PARAMS = /* @__PURE__ */ new Map([
135
+ // billNo is an idempotency key; cli/src/core/bill-no.ts generates one when
136
+ // the caller omits it.
137
+ ["POST /v2/balance/transfer", /* @__PURE__ */ new Set(["bill-no"])]
138
+ ]);
139
+ var CLI_ONLY_PARAMS = /* @__PURE__ */ new Map([
140
+ // where to save the downloaded file; the API only sees downloadId
141
+ ["GET /v2/system/download", /* @__PURE__ */ new Set(["out"])]
142
+ ]);
143
+ var CLI_POSITIONAL_ALIASES = /* @__PURE__ */ new Map([
144
+ ["GET /v2/entrust/plan-detail", /* @__PURE__ */ new Map([["id", "entrust-id"]])],
145
+ ["GET /v2/entrust/profit-detail", /* @__PURE__ */ new Map([["id", "profit-id"]])]
146
+ ]);
133
147
  function diffParams(endpoint, docParams, cliParams) {
134
148
  const errors = [];
149
+ const key = `${endpoint.method} ${endpoint.path}`;
150
+ const defaulted = CLI_DEFAULTED_PARAMS.get(key) ?? /* @__PURE__ */ new Set();
151
+ const cliOnly = CLI_ONLY_PARAMS.get(key) ?? /* @__PURE__ */ new Set();
152
+ const aliases = CLI_POSITIONAL_ALIASES.get(key) ?? /* @__PURE__ */ new Map();
135
153
  const docMap = new Map(
136
154
  docParams.map((p) => [normalize(p.name), p])
137
155
  );
138
- const cliMap = new Map(
139
- cliParams.filter((p) => !GLOBAL_FLAGS.has(p.name)).map((p) => [normalize(p.name), p])
140
- );
156
+ const cliMap = /* @__PURE__ */ new Map();
157
+ for (const p of cliParams) {
158
+ if (GLOBAL_FLAGS.has(p.name) || cliOnly.has(p.name)) continue;
159
+ const mapped = aliases.get(p.name) ?? normalize(p.name);
160
+ cliMap.set(mapped, { name: mapped, required: p.required });
161
+ }
141
162
  for (const [k, dp] of docMap.entries()) {
142
163
  if (dp.required) {
143
164
  const cp = cliMap.get(k);
144
165
  if (!cp) {
145
166
  errors.push(`${endpoint.method} ${endpoint.path}: missing required CLI option --${k}`);
146
- } else if (!cp.required) {
167
+ } else if (!cp.required && !defaulted.has(k)) {
147
168
  errors.push(
148
169
  `${endpoint.method} ${endpoint.path}: --${k} should be requiredOption (doc says \u5FC5\u586B=\u662F)`
149
170
  );
package/dist/registry.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  REGISTRY
4
- } from "./chunk-PEVZEMJG.js";
4
+ } from "./chunk-NMW73ILO.js";
5
5
  export {
6
6
  REGISTRY
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onebullex-group/cli",
3
- "version": "1.3.1",
3
+ "version": "1.5.0",
4
4
  "description": "OneBullEx Open API V2 command-line interface",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -16,6 +16,8 @@
16
16
  "./core/errors": "./dist/core/errors.js",
17
17
  "./core/signature": "./dist/core/signature.js",
18
18
  "./core/types": "./dist/core/types.js",
19
+ "./core/bill-no": "./dist/core/bill-no.js",
20
+ "./core/download": "./dist/core/download.js",
19
21
  "./core/redact": "./dist/core/redact.js"
20
22
  },
21
23
  "files": [