@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/CHANGELOG.md +123 -61
- package/README.md +304 -243
- package/dist/chunk-6DC55RF7.js +16 -0
- package/dist/{chunk-PEVZEMJG.js → chunk-NMW73ILO.js} +49 -1
- package/dist/chunk-SGLPG2FL.js +39 -0
- package/dist/{chunk-NKWXNVLA.js → chunk-YE5LER6U.js} +86 -19
- package/dist/core/bill-no.d.ts +19 -0
- package/dist/core/bill-no.js +9 -0
- package/dist/core/download.d.ts +41 -0
- package/dist/core/download.js +15 -0
- package/dist/core/http-client.d.ts +32 -1
- package/dist/core/http-client.js +9 -5
- package/dist/index.js +217 -83
- package/dist/lint-api.d.ts +1 -1
- package/dist/lint-api.js +27 -6
- package/dist/registry.js +1 -1
- package/package.json +3 -1
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-
|
|
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)").
|
|
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.
|
|
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>", "
|
|
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.
|
|
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)").
|
|
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.
|
|
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>", "
|
|
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.
|
|
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)").
|
|
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:
|
|
359
|
-
const data = await c.
|
|
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(
|
|
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
|
-
|
|
559
|
-
|
|
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)").
|
|
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>", "
|
|
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>", "
|
|
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(
|
|
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(
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
}
|
package/dist/lint-api.d.ts
CHANGED
|
@@ -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(
|
|
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-
|
|
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(
|
|
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
|
-
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onebullex-group/cli",
|
|
3
|
-
"version": "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": [
|