@okx_ai/okx-trade-cli 1.2.4-beta.0 → 1.2.4-beta.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 +822 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1284,7 +1284,8 @@ var BOT_SUB_MODULE_IDS = [
|
|
|
1284
1284
|
var BOT_DEFAULT_SUB_MODULES = ["bot.grid"];
|
|
1285
1285
|
var EARN_SUB_MODULE_IDS = [
|
|
1286
1286
|
"earn.savings",
|
|
1287
|
-
"earn.onchain"
|
|
1287
|
+
"earn.onchain",
|
|
1288
|
+
"earn.dcd"
|
|
1288
1289
|
];
|
|
1289
1290
|
var MODULES = [
|
|
1290
1291
|
"market",
|
|
@@ -3428,10 +3429,286 @@ function registerOnchainEarnTools() {
|
|
|
3428
3429
|
}
|
|
3429
3430
|
];
|
|
3430
3431
|
}
|
|
3432
|
+
var DCD_CODE_BEHAVIORS = {
|
|
3433
|
+
"50001": { retry: true, suggestion: "DCD service is down. Retry in a few minutes." },
|
|
3434
|
+
"50002": { retry: false, suggestion: "Invalid JSON in request body. This is likely a bug \u2014 check request parameters." },
|
|
3435
|
+
"50014": { retry: false, suggestion: "Missing required parameter. Check that all required fields are provided." },
|
|
3436
|
+
"50016": { retry: false, suggestion: "notionalCcy does not match productId option type. Use baseCcy for CALL, quoteCcy for PUT." },
|
|
3437
|
+
"50026": { retry: true, suggestion: "DCD system error. Retry in a few minutes." },
|
|
3438
|
+
"50030": { retry: false, suggestion: "Account not authorized for DCD (earn-auth check failed). Complete required verification in the OKX app first." },
|
|
3439
|
+
"50038": { retry: false, suggestion: "DCD Open API feature is disabled for this account. Contact OKX support to enable it." },
|
|
3440
|
+
"50051": { retry: false, suggestion: "This currency pair is restricted for your country or account type. Do not retry." },
|
|
3441
|
+
"51000": { retry: false, suggestion: "Invalid parameter value or format. Check ordId, quoteId, or clOrdId." },
|
|
3442
|
+
"51728": { retry: false, suggestion: "Available quota exceeded. Reduce the amount and retry." },
|
|
3443
|
+
"51736": { retry: false, suggestion: "Insufficient balance. Top up your account before retrying." },
|
|
3444
|
+
"52905": { retry: false, suggestion: "Quote has expired or was not found. Request a new quote." },
|
|
3445
|
+
"52909": { retry: false, suggestion: "Duplicate client order ID. Use a different clOrdId." },
|
|
3446
|
+
"52917": { retry: false, suggestion: "Amount is below the minimum trade size. Increase the amount." },
|
|
3447
|
+
"52918": { retry: false, suggestion: "Amount exceeds the maximum trade size. Reduce the amount." },
|
|
3448
|
+
"52921": { retry: false, suggestion: "Quote has already been used by another trade." },
|
|
3449
|
+
"52927": { retry: true, suggestion: "No quote returned by liquidity provider. Retry the quote request." },
|
|
3450
|
+
"52928": { retry: false, suggestion: "Amount is not divisible by the required step size. Adjust the amount." },
|
|
3451
|
+
"58004": { retry: false, suggestion: "Account is frozen or blocked. Contact OKX support. Do not retry." },
|
|
3452
|
+
"58102": { retry: true, suggestion: "DCD rate limit exceeded. Back off and retry after a short delay." }
|
|
3453
|
+
};
|
|
3454
|
+
async function withDcdErrors(fn) {
|
|
3455
|
+
try {
|
|
3456
|
+
return await fn();
|
|
3457
|
+
} catch (error) {
|
|
3458
|
+
if (error instanceof OkxApiError && error.code) {
|
|
3459
|
+
const behavior = DCD_CODE_BEHAVIORS[error.code];
|
|
3460
|
+
if (behavior) {
|
|
3461
|
+
if (behavior.retry) {
|
|
3462
|
+
throw new RateLimitError(error.message, behavior.suggestion, error.endpoint, error.traceId);
|
|
3463
|
+
}
|
|
3464
|
+
throw new OkxApiError(error.message, {
|
|
3465
|
+
code: error.code,
|
|
3466
|
+
suggestion: behavior.suggestion,
|
|
3467
|
+
endpoint: error.endpoint,
|
|
3468
|
+
traceId: error.traceId
|
|
3469
|
+
});
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
throw error;
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3475
|
+
function registerDcdTools() {
|
|
3476
|
+
return [
|
|
3477
|
+
{
|
|
3478
|
+
name: "dcd_get_currency_pairs",
|
|
3479
|
+
module: "earn.dcd",
|
|
3480
|
+
description: "Get available DCD (Dual Currency Deposit) currency pairs. Private endpoint. Rate limit: 5 req/s.",
|
|
3481
|
+
isWrite: false,
|
|
3482
|
+
inputSchema: { type: "object", properties: {} },
|
|
3483
|
+
handler: async (_rawArgs, context) => {
|
|
3484
|
+
return withDcdErrors(async () => {
|
|
3485
|
+
const response = await context.client.privateGet(
|
|
3486
|
+
"/api/v5/finance/sfp/dcd/currency-pair",
|
|
3487
|
+
void 0,
|
|
3488
|
+
privateRateLimit("dcd_get_currency_pairs", 5)
|
|
3489
|
+
);
|
|
3490
|
+
return normalizeResponse(response);
|
|
3491
|
+
});
|
|
3492
|
+
}
|
|
3493
|
+
},
|
|
3494
|
+
{
|
|
3495
|
+
name: "dcd_get_products",
|
|
3496
|
+
module: "earn.dcd",
|
|
3497
|
+
description: "Get active DCD products with yield, trade size, quota, and VIP yield tier information. baseCcy, quoteCcy, and optType are all required. Private endpoint. Rate limit: 5 req/s.",
|
|
3498
|
+
isWrite: false,
|
|
3499
|
+
inputSchema: {
|
|
3500
|
+
type: "object",
|
|
3501
|
+
properties: {
|
|
3502
|
+
baseCcy: { type: "string", description: "Base currency, e.g. BTC" },
|
|
3503
|
+
quoteCcy: { type: "string", description: "Quote currency, e.g. USDT" },
|
|
3504
|
+
optType: { type: "string", description: "Option type: C (Call/\u9AD8\u5356) or P (Put/\u4F4E\u4E70)" }
|
|
3505
|
+
},
|
|
3506
|
+
required: ["baseCcy", "quoteCcy", "optType"]
|
|
3507
|
+
},
|
|
3508
|
+
handler: async (rawArgs, context) => {
|
|
3509
|
+
const args = asRecord(rawArgs);
|
|
3510
|
+
return withDcdErrors(async () => {
|
|
3511
|
+
const response = await context.client.privateGet(
|
|
3512
|
+
"/api/v5/finance/sfp/dcd/products",
|
|
3513
|
+
{
|
|
3514
|
+
baseCcy: requireString(args, "baseCcy"),
|
|
3515
|
+
quoteCcy: requireString(args, "quoteCcy"),
|
|
3516
|
+
optType: requireString(args, "optType")
|
|
3517
|
+
},
|
|
3518
|
+
privateRateLimit("dcd_get_products", 5)
|
|
3519
|
+
);
|
|
3520
|
+
return normalizeResponse(response);
|
|
3521
|
+
});
|
|
3522
|
+
}
|
|
3523
|
+
},
|
|
3524
|
+
{
|
|
3525
|
+
name: "dcd_request_quote",
|
|
3526
|
+
module: "earn.dcd",
|
|
3527
|
+
description: "Request a real-time quote for a DCD product. Check validUntil for expiry time \u2014 execute before expiry. Yield reflects the user's actual VIP tier rate. Private endpoint. Rate limit: 5 req/s.",
|
|
3528
|
+
isWrite: false,
|
|
3529
|
+
// POST for payload, no state change
|
|
3530
|
+
inputSchema: {
|
|
3531
|
+
type: "object",
|
|
3532
|
+
properties: {
|
|
3533
|
+
productId: { type: "string", description: "Product ID, e.g. BTC-USDT-260327-77000-C" },
|
|
3534
|
+
notionalSz: { type: "string", description: "Investment amount" },
|
|
3535
|
+
notionalCcy: { type: "string", description: "Investment currency: baseCcy for CALL (C), quoteCcy for PUT (P)" }
|
|
3536
|
+
},
|
|
3537
|
+
required: ["productId", "notionalSz", "notionalCcy"]
|
|
3538
|
+
},
|
|
3539
|
+
handler: async (rawArgs, context) => {
|
|
3540
|
+
const args = asRecord(rawArgs);
|
|
3541
|
+
return withDcdErrors(async () => {
|
|
3542
|
+
const response = await context.client.privatePost(
|
|
3543
|
+
"/api/v5/finance/sfp/dcd/quote",
|
|
3544
|
+
{
|
|
3545
|
+
productId: requireString(args, "productId"),
|
|
3546
|
+
notionalSz: requireString(args, "notionalSz"),
|
|
3547
|
+
notionalCcy: requireString(args, "notionalCcy")
|
|
3548
|
+
},
|
|
3549
|
+
privateRateLimit("dcd_request_quote", 5)
|
|
3550
|
+
);
|
|
3551
|
+
return normalizeResponse(response);
|
|
3552
|
+
});
|
|
3553
|
+
}
|
|
3554
|
+
},
|
|
3555
|
+
{
|
|
3556
|
+
name: "dcd_execute_quote",
|
|
3557
|
+
module: "earn.dcd",
|
|
3558
|
+
description: "Execute a DCD quote to place a trade. [CAUTION] Moves real funds into DCD product. Quote expires \u2014 call immediately after dcd_request_quote. Not supported in demo/simulated trading mode. Private endpoint. Rate limit: 5 req/s.",
|
|
3559
|
+
isWrite: true,
|
|
3560
|
+
inputSchema: {
|
|
3561
|
+
type: "object",
|
|
3562
|
+
properties: {
|
|
3563
|
+
quoteId: { type: "string", description: "Quote ID from dcd_request_quote" },
|
|
3564
|
+
clOrdId: { type: "string", description: "Client order ID for idempotency (optional)" }
|
|
3565
|
+
},
|
|
3566
|
+
required: ["quoteId"]
|
|
3567
|
+
},
|
|
3568
|
+
handler: async (rawArgs, context) => {
|
|
3569
|
+
assertNotDemo(context.config, "dcd_execute_quote");
|
|
3570
|
+
const args = asRecord(rawArgs);
|
|
3571
|
+
return withDcdErrors(async () => {
|
|
3572
|
+
const response = await context.client.privatePost(
|
|
3573
|
+
"/api/v5/finance/sfp/dcd/trade",
|
|
3574
|
+
compactObject({
|
|
3575
|
+
quoteId: requireString(args, "quoteId"),
|
|
3576
|
+
clOrdId: readString(args, "clOrdId")
|
|
3577
|
+
}),
|
|
3578
|
+
privateRateLimit("dcd_execute_quote", 5)
|
|
3579
|
+
);
|
|
3580
|
+
return normalizeResponse(response);
|
|
3581
|
+
});
|
|
3582
|
+
}
|
|
3583
|
+
},
|
|
3584
|
+
{
|
|
3585
|
+
name: "dcd_request_redeem_quote",
|
|
3586
|
+
module: "earn.dcd",
|
|
3587
|
+
description: "Request an early redemption quote for a live DCD order. Check validUntil for expiry. Private endpoint. Rate limit: 5 req/s.",
|
|
3588
|
+
isWrite: false,
|
|
3589
|
+
inputSchema: {
|
|
3590
|
+
type: "object",
|
|
3591
|
+
properties: {
|
|
3592
|
+
ordId: { type: "string", description: "Order ID to redeem early" }
|
|
3593
|
+
},
|
|
3594
|
+
required: ["ordId"]
|
|
3595
|
+
},
|
|
3596
|
+
handler: async (rawArgs, context) => {
|
|
3597
|
+
const args = asRecord(rawArgs);
|
|
3598
|
+
return withDcdErrors(async () => {
|
|
3599
|
+
const response = await context.client.privatePost(
|
|
3600
|
+
"/api/v5/finance/sfp/dcd/redeem-quote",
|
|
3601
|
+
{ ordId: requireString(args, "ordId") },
|
|
3602
|
+
privateRateLimit("dcd_request_redeem_quote", 5)
|
|
3603
|
+
);
|
|
3604
|
+
return normalizeResponse(response);
|
|
3605
|
+
});
|
|
3606
|
+
}
|
|
3607
|
+
},
|
|
3608
|
+
{
|
|
3609
|
+
name: "dcd_execute_redeem",
|
|
3610
|
+
module: "earn.dcd",
|
|
3611
|
+
description: "Execute an early redemption using a valid redeem quote. [CAUTION] Initiates early redemption of a DCD position. Not supported in demo/simulated trading mode. Private endpoint. Rate limit: 5 req/s.",
|
|
3612
|
+
isWrite: true,
|
|
3613
|
+
inputSchema: {
|
|
3614
|
+
type: "object",
|
|
3615
|
+
properties: {
|
|
3616
|
+
ordId: { type: "string", description: "Order ID" },
|
|
3617
|
+
quoteId: { type: "string", description: "Redeem quote ID from dcd_request_redeem_quote" }
|
|
3618
|
+
},
|
|
3619
|
+
required: ["ordId", "quoteId"]
|
|
3620
|
+
},
|
|
3621
|
+
handler: async (rawArgs, context) => {
|
|
3622
|
+
assertNotDemo(context.config, "dcd_execute_redeem");
|
|
3623
|
+
const args = asRecord(rawArgs);
|
|
3624
|
+
return withDcdErrors(async () => {
|
|
3625
|
+
const response = await context.client.privatePost(
|
|
3626
|
+
"/api/v5/finance/sfp/dcd/redeem",
|
|
3627
|
+
{
|
|
3628
|
+
ordId: requireString(args, "ordId"),
|
|
3629
|
+
quoteId: requireString(args, "quoteId")
|
|
3630
|
+
},
|
|
3631
|
+
privateRateLimit("dcd_execute_redeem", 5)
|
|
3632
|
+
);
|
|
3633
|
+
return normalizeResponse(response);
|
|
3634
|
+
});
|
|
3635
|
+
}
|
|
3636
|
+
},
|
|
3637
|
+
{
|
|
3638
|
+
name: "dcd_get_order_state",
|
|
3639
|
+
module: "earn.dcd",
|
|
3640
|
+
description: "Query DCD order state by order ID. Private endpoint. Rate limit: 5 req/s.",
|
|
3641
|
+
isWrite: false,
|
|
3642
|
+
inputSchema: {
|
|
3643
|
+
type: "object",
|
|
3644
|
+
properties: {
|
|
3645
|
+
ordId: { type: "string", description: "Order ID" }
|
|
3646
|
+
},
|
|
3647
|
+
required: ["ordId"]
|
|
3648
|
+
},
|
|
3649
|
+
handler: async (rawArgs, context) => {
|
|
3650
|
+
const args = asRecord(rawArgs);
|
|
3651
|
+
return withDcdErrors(async () => {
|
|
3652
|
+
const response = await context.client.privateGet(
|
|
3653
|
+
"/api/v5/finance/sfp/dcd/order-status",
|
|
3654
|
+
{ ordId: requireString(args, "ordId") },
|
|
3655
|
+
privateRateLimit("dcd_get_order_state", 5)
|
|
3656
|
+
);
|
|
3657
|
+
return normalizeResponse(response);
|
|
3658
|
+
});
|
|
3659
|
+
}
|
|
3660
|
+
},
|
|
3661
|
+
{
|
|
3662
|
+
name: "dcd_get_orders",
|
|
3663
|
+
module: "earn.dcd",
|
|
3664
|
+
description: "Get DCD order history with optional filters. Returns up to 100 records per request. Private endpoint. Rate limit: 5 req/s.",
|
|
3665
|
+
isWrite: false,
|
|
3666
|
+
inputSchema: {
|
|
3667
|
+
type: "object",
|
|
3668
|
+
properties: {
|
|
3669
|
+
ordId: { type: "string", description: "Filter by specific order ID (ignores other filters when provided)" },
|
|
3670
|
+
productId: { type: "string", description: "Filter by product ID, e.g. BTC-USDT-260327-77000-C" },
|
|
3671
|
+
uly: { type: "string", description: "Filter by underlying index, e.g. BTC-USD" },
|
|
3672
|
+
state: {
|
|
3673
|
+
type: "string",
|
|
3674
|
+
description: "Filter by state: initial | live | pending_settle | settled | pending_redeem | redeemed | rejected"
|
|
3675
|
+
},
|
|
3676
|
+
beginId: { type: "string", description: "Return records newer than this order ID (pagination)" },
|
|
3677
|
+
endId: { type: "string", description: "Return records older than this order ID (pagination)" },
|
|
3678
|
+
begin: { type: "string", description: "Begin timestamp filter, Unix ms" },
|
|
3679
|
+
end: { type: "string", description: "End timestamp filter, Unix ms" },
|
|
3680
|
+
limit: { type: "number", description: "Results per request, max 100 (default 100)" }
|
|
3681
|
+
}
|
|
3682
|
+
},
|
|
3683
|
+
handler: async (rawArgs, context) => {
|
|
3684
|
+
const args = asRecord(rawArgs);
|
|
3685
|
+
return withDcdErrors(async () => {
|
|
3686
|
+
const response = await context.client.privateGet(
|
|
3687
|
+
"/api/v5/finance/sfp/dcd/order-history",
|
|
3688
|
+
compactObject({
|
|
3689
|
+
ordId: readString(args, "ordId"),
|
|
3690
|
+
productId: readString(args, "productId"),
|
|
3691
|
+
uly: readString(args, "uly"),
|
|
3692
|
+
state: readString(args, "state"),
|
|
3693
|
+
beginId: readString(args, "beginId"),
|
|
3694
|
+
endId: readString(args, "endId"),
|
|
3695
|
+
begin: readString(args, "begin"),
|
|
3696
|
+
end: readString(args, "end"),
|
|
3697
|
+
limit: readNumber(args, "limit")
|
|
3698
|
+
}),
|
|
3699
|
+
privateRateLimit("dcd_get_orders", 5)
|
|
3700
|
+
);
|
|
3701
|
+
return normalizeResponse(response);
|
|
3702
|
+
});
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
];
|
|
3706
|
+
}
|
|
3431
3707
|
function registerAllEarnTools() {
|
|
3432
3708
|
return [
|
|
3433
3709
|
...registerEarnTools(),
|
|
3434
|
-
...registerOnchainEarnTools()
|
|
3710
|
+
...registerOnchainEarnTools(),
|
|
3711
|
+
...registerDcdTools()
|
|
3435
3712
|
];
|
|
3436
3713
|
}
|
|
3437
3714
|
var FUTURES_INST_TYPES = ["FUTURES", "SWAP"];
|
|
@@ -4276,6 +4553,40 @@ function registerMarketTools() {
|
|
|
4276
4553
|
);
|
|
4277
4554
|
return normalize6(response);
|
|
4278
4555
|
}
|
|
4556
|
+
},
|
|
4557
|
+
{
|
|
4558
|
+
name: "market_get_stock_tokens",
|
|
4559
|
+
module: "market",
|
|
4560
|
+
description: "Get all stock token instruments (instCategory=3). Stock tokens track real-world stock prices on OKX (e.g. AAPL-USDT-SWAP, TSLA-USDT-SWAP). Fetches all instruments of the given type and filters client-side by instCategory=3. Public endpoint. Rate limit: 20 req/s.",
|
|
4561
|
+
isWrite: false,
|
|
4562
|
+
inputSchema: {
|
|
4563
|
+
type: "object",
|
|
4564
|
+
properties: {
|
|
4565
|
+
instType: {
|
|
4566
|
+
type: "string",
|
|
4567
|
+
enum: ["SPOT", "SWAP"],
|
|
4568
|
+
description: "Instrument type. Default: SWAP"
|
|
4569
|
+
},
|
|
4570
|
+
instId: {
|
|
4571
|
+
type: "string",
|
|
4572
|
+
description: "Optional: filter by specific instrument ID, e.g. AAPL-USDT-SWAP"
|
|
4573
|
+
}
|
|
4574
|
+
},
|
|
4575
|
+
required: []
|
|
4576
|
+
},
|
|
4577
|
+
handler: async (rawArgs, context) => {
|
|
4578
|
+
const args = asRecord(rawArgs);
|
|
4579
|
+
const instType = readString(args, "instType") ?? "SWAP";
|
|
4580
|
+
const instId = readString(args, "instId");
|
|
4581
|
+
const response = await context.client.publicGet(
|
|
4582
|
+
"/api/v5/public/instruments",
|
|
4583
|
+
compactObject({ instType, instId }),
|
|
4584
|
+
publicRateLimit("market_get_stock_tokens", 20)
|
|
4585
|
+
);
|
|
4586
|
+
const data = response.data;
|
|
4587
|
+
const filtered = Array.isArray(data) ? data.filter((item) => item.instCategory === "3") : data;
|
|
4588
|
+
return normalize6({ ...response, data: filtered });
|
|
4589
|
+
}
|
|
4279
4590
|
}
|
|
4280
4591
|
];
|
|
4281
4592
|
}
|
|
@@ -6380,7 +6691,7 @@ function readCliVersion() {
|
|
|
6380
6691
|
return "0.0.0";
|
|
6381
6692
|
}
|
|
6382
6693
|
var CLI_VERSION = readCliVersion();
|
|
6383
|
-
var GIT_HASH = true ? "
|
|
6694
|
+
var GIT_HASH = true ? "1df90cc" : "dev";
|
|
6384
6695
|
var Report = class {
|
|
6385
6696
|
lines = [];
|
|
6386
6697
|
add(key, value) {
|
|
@@ -6607,18 +6918,19 @@ async function checkNetwork(config, client, report) {
|
|
|
6607
6918
|
}
|
|
6608
6919
|
return passed;
|
|
6609
6920
|
}
|
|
6610
|
-
function getAuthHints(msg) {
|
|
6921
|
+
function getAuthHints(msg, baseUrl) {
|
|
6922
|
+
const accountUrl = baseUrl.replace(/\/+$/, "") + "/account/my-api";
|
|
6611
6923
|
if (msg.includes("50111") || msg.includes("Invalid OK-ACCESS-KEY")) {
|
|
6612
|
-
return ["API key is invalid or expired",
|
|
6924
|
+
return ["API key is invalid or expired", `Regenerate at ${accountUrl}`];
|
|
6613
6925
|
}
|
|
6614
6926
|
if (msg.includes("50112") || msg.includes("Invalid Sign")) {
|
|
6615
|
-
return ["Secret key or passphrase may be wrong",
|
|
6927
|
+
return ["Secret key or passphrase may be wrong", `Regenerate API key at ${accountUrl}`];
|
|
6616
6928
|
}
|
|
6617
6929
|
if (msg.includes("50113")) {
|
|
6618
6930
|
return ["Passphrase is incorrect"];
|
|
6619
6931
|
}
|
|
6620
6932
|
if (msg.includes("50100")) {
|
|
6621
|
-
return ["API key lacks required permissions",
|
|
6933
|
+
return ["API key lacks required permissions", `Update permissions at ${accountUrl}`];
|
|
6622
6934
|
}
|
|
6623
6935
|
return ["Check API credentials and permissions"];
|
|
6624
6936
|
}
|
|
@@ -6641,7 +6953,7 @@ async function checkAuth(client, config, report) {
|
|
|
6641
6953
|
} catch (e) {
|
|
6642
6954
|
const ms = Date.now() - t1;
|
|
6643
6955
|
const msg = e instanceof Error ? e.message : String(e);
|
|
6644
|
-
const hints = getAuthHints(msg);
|
|
6956
|
+
const hints = getAuthHints(msg, config.baseUrl);
|
|
6645
6957
|
fail("Account balance", msg, hints);
|
|
6646
6958
|
passed = false;
|
|
6647
6959
|
report.add("auth_api", `FAIL /account/balance ${msg} (${ms}ms)`);
|
|
@@ -6763,6 +7075,10 @@ var HELP_TREE = {
|
|
|
6763
7075
|
"open-interest": {
|
|
6764
7076
|
usage: "okx market open-interest --instType <SWAP|FUTURES|OPTION> [--instId <id>]",
|
|
6765
7077
|
description: "Get open interest for instruments"
|
|
7078
|
+
},
|
|
7079
|
+
"stock-tokens": {
|
|
7080
|
+
usage: "okx market stock-tokens [--instType <SPOT|SWAP>] [--instId <id>]",
|
|
7081
|
+
description: "List all stock token instruments (instCategory=3, e.g. AAPL-USDT-SWAP)"
|
|
6766
7082
|
}
|
|
6767
7083
|
}
|
|
6768
7084
|
},
|
|
@@ -7030,7 +7346,7 @@ var HELP_TREE = {
|
|
|
7030
7346
|
}
|
|
7031
7347
|
},
|
|
7032
7348
|
earn: {
|
|
7033
|
-
description: "Earn products \u2014 Simple Earn
|
|
7349
|
+
description: "Earn products \u2014 Simple Earn, On-chain Earn, and DCD (Dual Currency Deposit)",
|
|
7034
7350
|
subgroups: {
|
|
7035
7351
|
savings: {
|
|
7036
7352
|
description: "Simple Earn \u2014 flexible savings and lending",
|
|
@@ -7093,6 +7409,51 @@ var HELP_TREE = {
|
|
|
7093
7409
|
description: "Get on-chain earn order history"
|
|
7094
7410
|
}
|
|
7095
7411
|
}
|
|
7412
|
+
},
|
|
7413
|
+
dcd: {
|
|
7414
|
+
description: "DCD (Dual Currency Deposit) \u2014 structured products with fixed yield",
|
|
7415
|
+
commands: {
|
|
7416
|
+
pairs: {
|
|
7417
|
+
usage: "okx earn dcd pairs",
|
|
7418
|
+
description: "List available DCD currency pairs"
|
|
7419
|
+
},
|
|
7420
|
+
products: {
|
|
7421
|
+
usage: "okx earn dcd products --baseCcy <ccy> --quoteCcy <ccy> --optType <C|P>\n [--minYield <n>] [--strikeNear <price>]\n [--termDays <n>] [--minTermDays <n>] [--maxTermDays <n>]\n [--expDate <YYYY-MM-DD|YYYY-MM-DDTHH:mm>]",
|
|
7422
|
+
description: "List active DCD products (baseCcy, quoteCcy, optType required). Client-side filters: minYield (e.g. 0.05=5%), strikeNear (\xB110%), term range, expDate"
|
|
7423
|
+
},
|
|
7424
|
+
quote: {
|
|
7425
|
+
usage: "okx earn dcd quote --productId <id> --sz <n> --notionalCcy <ccy>",
|
|
7426
|
+
description: "Request a real-time DCD quote (TTL: 30 seconds)"
|
|
7427
|
+
},
|
|
7428
|
+
buy: {
|
|
7429
|
+
usage: "okx earn dcd buy --quoteId <id> [--clOrdId <id>]",
|
|
7430
|
+
description: "[CAUTION] Execute a DCD quote to place a trade. Auto-queries order state after placement"
|
|
7431
|
+
},
|
|
7432
|
+
"quote-and-buy": {
|
|
7433
|
+
usage: "okx earn dcd quote-and-buy --productId <id> --sz <n> --notionalCcy <ccy> [--clOrdId <id>]",
|
|
7434
|
+
description: "[CAUTION] Request quote and execute immediately in one step (no confirmation \u2014 for AI agent use)"
|
|
7435
|
+
},
|
|
7436
|
+
"redeem-quote": {
|
|
7437
|
+
usage: "okx earn dcd redeem-quote --ordId <id>",
|
|
7438
|
+
description: "Request an early redemption quote for a live DCD order (TTL: 15 seconds)"
|
|
7439
|
+
},
|
|
7440
|
+
redeem: {
|
|
7441
|
+
usage: "okx earn dcd redeem --ordId <id> --quoteId <id>",
|
|
7442
|
+
description: "[CAUTION] Execute early redemption of a DCD position"
|
|
7443
|
+
},
|
|
7444
|
+
"redeem-execute": {
|
|
7445
|
+
usage: "okx earn dcd redeem-execute --ordId <id>",
|
|
7446
|
+
description: "[CAUTION] Re-quote and execute early redemption in one step (recommended for AI agent use)"
|
|
7447
|
+
},
|
|
7448
|
+
order: {
|
|
7449
|
+
usage: "okx earn dcd order --ordId <id>",
|
|
7450
|
+
description: "Query current state of a DCD order"
|
|
7451
|
+
},
|
|
7452
|
+
orders: {
|
|
7453
|
+
usage: "okx earn dcd orders [--ordId <id>] [--productId <id>] [--uly <uly>] [--state <state>] [--limit <n>]",
|
|
7454
|
+
description: "Get DCD order history. State: initial|live|pending_settle|settled|pending_redeem|redeemed|rejected"
|
|
7455
|
+
}
|
|
7456
|
+
}
|
|
7096
7457
|
}
|
|
7097
7458
|
}
|
|
7098
7459
|
},
|
|
@@ -7415,6 +7776,21 @@ var CLI_OPTIONS = {
|
|
|
7415
7776
|
tag: { type: "string" },
|
|
7416
7777
|
allowEarlyRedeem: { type: "boolean", default: false },
|
|
7417
7778
|
state: { type: "string" },
|
|
7779
|
+
// dcd
|
|
7780
|
+
quoteId: { type: "string" },
|
|
7781
|
+
notionalCcy: { type: "string" },
|
|
7782
|
+
optType: { type: "string" },
|
|
7783
|
+
baseCcy: { type: "string" },
|
|
7784
|
+
beginId: { type: "string" },
|
|
7785
|
+
endId: { type: "string" },
|
|
7786
|
+
begin: { type: "string" },
|
|
7787
|
+
end: { type: "string" },
|
|
7788
|
+
minYield: { type: "string" },
|
|
7789
|
+
strikeNear: { type: "string" },
|
|
7790
|
+
termDays: { type: "string" },
|
|
7791
|
+
minTermDays: { type: "string" },
|
|
7792
|
+
maxTermDays: { type: "string" },
|
|
7793
|
+
expDate: { type: "string" },
|
|
7418
7794
|
// diagnostics
|
|
7419
7795
|
verbose: { type: "boolean", default: false }
|
|
7420
7796
|
};
|
|
@@ -7674,6 +8050,22 @@ async function cmdMarketCandles(run, instId, opts) {
|
|
|
7674
8050
|
}))
|
|
7675
8051
|
);
|
|
7676
8052
|
}
|
|
8053
|
+
async function cmdMarketStockTokens(run, opts) {
|
|
8054
|
+
const result = await run("market_get_stock_tokens", { instType: opts.instType, instId: opts.instId });
|
|
8055
|
+
const items = getData(result);
|
|
8056
|
+
if (opts.json) return printJson(items);
|
|
8057
|
+
printTable(
|
|
8058
|
+
(items ?? []).slice(0, 50).map((t) => ({
|
|
8059
|
+
instId: t["instId"],
|
|
8060
|
+
instCategory: t["instCategory"],
|
|
8061
|
+
ctVal: t["ctVal"],
|
|
8062
|
+
lotSz: t["lotSz"],
|
|
8063
|
+
minSz: t["minSz"],
|
|
8064
|
+
tickSz: t["tickSz"],
|
|
8065
|
+
state: t["state"]
|
|
8066
|
+
}))
|
|
8067
|
+
);
|
|
8068
|
+
}
|
|
7677
8069
|
|
|
7678
8070
|
// src/commands/account.ts
|
|
7679
8071
|
import * as fs4 from "fs";
|
|
@@ -9421,10 +9813,362 @@ function cmdOnchainEarnOrderHistory(run, v) {
|
|
|
9421
9813
|
});
|
|
9422
9814
|
}
|
|
9423
9815
|
|
|
9816
|
+
// src/commands/dcd.ts
|
|
9817
|
+
function extractArray(result) {
|
|
9818
|
+
if (result && typeof result === "object") {
|
|
9819
|
+
const data = result["data"];
|
|
9820
|
+
if (Array.isArray(data)) return data;
|
|
9821
|
+
}
|
|
9822
|
+
return [];
|
|
9823
|
+
}
|
|
9824
|
+
function extractProducts(result) {
|
|
9825
|
+
if (result && typeof result === "object") {
|
|
9826
|
+
const data = result["data"];
|
|
9827
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
9828
|
+
const products = data["products"];
|
|
9829
|
+
if (Array.isArray(products)) return products;
|
|
9830
|
+
}
|
|
9831
|
+
}
|
|
9832
|
+
return [];
|
|
9833
|
+
}
|
|
9834
|
+
async function cmdDcdPairs(run, json) {
|
|
9835
|
+
const result = await run("dcd_get_currency_pairs", {});
|
|
9836
|
+
const data = extractArray(result);
|
|
9837
|
+
if (json) {
|
|
9838
|
+
printJson(data);
|
|
9839
|
+
return;
|
|
9840
|
+
}
|
|
9841
|
+
if (!data.length) {
|
|
9842
|
+
process.stdout.write("No currency pairs available\n");
|
|
9843
|
+
return;
|
|
9844
|
+
}
|
|
9845
|
+
printTable(data.map((r) => ({
|
|
9846
|
+
baseCcy: r["baseCcy"],
|
|
9847
|
+
quoteCcy: r["quoteCcy"],
|
|
9848
|
+
optType: r["optType"]
|
|
9849
|
+
})));
|
|
9850
|
+
}
|
|
9851
|
+
function filterByYield(data, minYield) {
|
|
9852
|
+
return data.filter((r) => {
|
|
9853
|
+
const y = parseFloat(r["annualizedYield"]);
|
|
9854
|
+
return !isNaN(y) && y >= minYield;
|
|
9855
|
+
});
|
|
9856
|
+
}
|
|
9857
|
+
function filterByStrike(data, ref) {
|
|
9858
|
+
return data.filter((r) => {
|
|
9859
|
+
const strike = parseFloat(r["strike"]);
|
|
9860
|
+
return !isNaN(strike) && Math.abs(strike - ref) / ref <= 0.1;
|
|
9861
|
+
});
|
|
9862
|
+
}
|
|
9863
|
+
function filterByTerm(data, termDays, minTermDays, maxTermDays) {
|
|
9864
|
+
const MS_PER_DAY = 864e5;
|
|
9865
|
+
return data.filter((r) => {
|
|
9866
|
+
const exp = Number(r["expTime"]);
|
|
9867
|
+
const start = Number(r["interestAccrualTime"]);
|
|
9868
|
+
if (!exp || !start) return false;
|
|
9869
|
+
const days = Math.round((exp - start) / MS_PER_DAY);
|
|
9870
|
+
if (termDays !== void 0 && days !== termDays) return false;
|
|
9871
|
+
if (minTermDays !== void 0 && days < minTermDays) return false;
|
|
9872
|
+
if (maxTermDays !== void 0 && days > maxTermDays) return false;
|
|
9873
|
+
return true;
|
|
9874
|
+
});
|
|
9875
|
+
}
|
|
9876
|
+
function filterByExpDate(data, expDate) {
|
|
9877
|
+
const hasTime = expDate.includes("T") || expDate.includes(" ");
|
|
9878
|
+
const precision = hasTime ? 13 : 10;
|
|
9879
|
+
const target = new Date(expDate).toISOString().slice(0, precision);
|
|
9880
|
+
return data.filter((r) => {
|
|
9881
|
+
const exp = Number(r["expTime"]);
|
|
9882
|
+
if (!exp) return false;
|
|
9883
|
+
return new Date(exp).toISOString().slice(0, precision) === target;
|
|
9884
|
+
});
|
|
9885
|
+
}
|
|
9886
|
+
function applyProductFilters(data, opts) {
|
|
9887
|
+
if (opts.minYield !== void 0) data = filterByYield(data, opts.minYield);
|
|
9888
|
+
if (opts.strikeNear !== void 0) data = filterByStrike(data, opts.strikeNear);
|
|
9889
|
+
if (opts.termDays !== void 0 || opts.minTermDays !== void 0 || opts.maxTermDays !== void 0) {
|
|
9890
|
+
data = filterByTerm(data, opts.termDays, opts.minTermDays, opts.maxTermDays);
|
|
9891
|
+
}
|
|
9892
|
+
if (opts.expDate !== void 0) data = filterByExpDate(data, opts.expDate);
|
|
9893
|
+
return data;
|
|
9894
|
+
}
|
|
9895
|
+
async function cmdDcdProducts(run, opts) {
|
|
9896
|
+
const result = await run("dcd_get_products", {
|
|
9897
|
+
baseCcy: opts.baseCcy,
|
|
9898
|
+
quoteCcy: opts.quoteCcy,
|
|
9899
|
+
optType: opts.optType
|
|
9900
|
+
});
|
|
9901
|
+
const data = applyProductFilters(extractProducts(result), opts);
|
|
9902
|
+
if (opts.json) {
|
|
9903
|
+
printJson(data);
|
|
9904
|
+
return;
|
|
9905
|
+
}
|
|
9906
|
+
if (!data.length) {
|
|
9907
|
+
process.stdout.write("No products matched\n");
|
|
9908
|
+
return;
|
|
9909
|
+
}
|
|
9910
|
+
printTable(data.map((r) => ({
|
|
9911
|
+
productId: r["productId"],
|
|
9912
|
+
baseCcy: r["baseCcy"],
|
|
9913
|
+
quoteCcy: r["quoteCcy"],
|
|
9914
|
+
optType: r["optType"],
|
|
9915
|
+
strike: r["strike"],
|
|
9916
|
+
// products endpoint returns decimal (e.g. 0.3423 = 34.23%) — multiply by 100
|
|
9917
|
+
annualizedYield: r["annualizedYield"] ? `${(parseFloat(r["annualizedYield"]) * 100).toFixed(2)}%` : "\u2014",
|
|
9918
|
+
minSize: r["minSize"],
|
|
9919
|
+
expTime: r["expTime"] ? new Date(Number(r["expTime"])).toLocaleDateString() : ""
|
|
9920
|
+
})));
|
|
9921
|
+
}
|
|
9922
|
+
async function cmdDcdQuote(run, opts) {
|
|
9923
|
+
const result = await run("dcd_request_quote", {
|
|
9924
|
+
productId: opts.productId,
|
|
9925
|
+
notionalSz: opts.notionalSz,
|
|
9926
|
+
notionalCcy: opts.notionalCcy
|
|
9927
|
+
});
|
|
9928
|
+
const data = extractArray(result);
|
|
9929
|
+
if (opts.json) {
|
|
9930
|
+
printJson(data);
|
|
9931
|
+
return;
|
|
9932
|
+
}
|
|
9933
|
+
const r = data[0];
|
|
9934
|
+
if (!r) {
|
|
9935
|
+
process.stdout.write("No quote returned\n");
|
|
9936
|
+
return;
|
|
9937
|
+
}
|
|
9938
|
+
printKv({
|
|
9939
|
+
quoteId: r["quoteId"],
|
|
9940
|
+
productId: r["productId"],
|
|
9941
|
+
notionalSz: r["notionalSz"],
|
|
9942
|
+
notionalCcy: r["notionalCcy"],
|
|
9943
|
+
// quote endpoint returns percentage directly (e.g. 18.34 = 18.34%) — no ×100 needed
|
|
9944
|
+
annualizedYield: r["annualizedYield"] ? `${r["annualizedYield"]}%` : "\u2014",
|
|
9945
|
+
absYield: r["absYield"],
|
|
9946
|
+
idxPx: r["idxPx"],
|
|
9947
|
+
validUntil: r["validUntil"] ? new Date(Number(r["validUntil"])).toLocaleString() : "\u2014"
|
|
9948
|
+
});
|
|
9949
|
+
process.stdout.write("\nQuote expires soon. Use 'earn dcd buy --quoteId <id>' to execute.\n");
|
|
9950
|
+
}
|
|
9951
|
+
async function cmdDcdBuy(run, opts) {
|
|
9952
|
+
const result = await run("dcd_execute_quote", {
|
|
9953
|
+
quoteId: opts.quoteId,
|
|
9954
|
+
clOrdId: opts.clOrdId
|
|
9955
|
+
});
|
|
9956
|
+
const data = extractArray(result);
|
|
9957
|
+
const r = data[0];
|
|
9958
|
+
if (!r) {
|
|
9959
|
+
process.stdout.write("No response data\n");
|
|
9960
|
+
return;
|
|
9961
|
+
}
|
|
9962
|
+
const ordId = r["ordId"];
|
|
9963
|
+
let stateRow;
|
|
9964
|
+
if (ordId) {
|
|
9965
|
+
try {
|
|
9966
|
+
const stateResult = await run("dcd_get_order_state", { ordId });
|
|
9967
|
+
stateRow = extractArray(stateResult)[0];
|
|
9968
|
+
} catch {
|
|
9969
|
+
}
|
|
9970
|
+
}
|
|
9971
|
+
if (opts.json) {
|
|
9972
|
+
printJson({ order: r, state: stateRow ?? null });
|
|
9973
|
+
return;
|
|
9974
|
+
}
|
|
9975
|
+
process.stdout.write("Order placed:\n");
|
|
9976
|
+
printKv({ ordId: r["ordId"], quoteId: r["quoteId"], state: r["state"] });
|
|
9977
|
+
if (stateRow) {
|
|
9978
|
+
process.stdout.write("\nOrder state:\n");
|
|
9979
|
+
printKv({
|
|
9980
|
+
ordId: stateRow["ordId"],
|
|
9981
|
+
state: stateRow["state"]
|
|
9982
|
+
});
|
|
9983
|
+
}
|
|
9984
|
+
}
|
|
9985
|
+
async function cmdDcdRedeemQuote(run, opts) {
|
|
9986
|
+
const result = await run("dcd_request_redeem_quote", { ordId: opts.ordId });
|
|
9987
|
+
const data = extractArray(result);
|
|
9988
|
+
if (opts.json) {
|
|
9989
|
+
printJson(data);
|
|
9990
|
+
return;
|
|
9991
|
+
}
|
|
9992
|
+
const r = data[0];
|
|
9993
|
+
if (!r) {
|
|
9994
|
+
process.stdout.write("No redeem quote returned\n");
|
|
9995
|
+
return;
|
|
9996
|
+
}
|
|
9997
|
+
const redeemSzRaw = r["redeemSz"];
|
|
9998
|
+
const redeemSzDisplay = redeemSzRaw ? `${parseFloat(redeemSzRaw).toFixed(8)} ${r["redeemCcy"]}` : "\u2014";
|
|
9999
|
+
const termRateRaw = r["termRate"];
|
|
10000
|
+
const termRateDisplay = termRateRaw ? `${termRateRaw}%` : "\u2014";
|
|
10001
|
+
const validUntil = r["validUntil"] ? new Date(Number(r["validUntil"])).toLocaleString() : "\u2014";
|
|
10002
|
+
printKv({
|
|
10003
|
+
ordId: r["ordId"],
|
|
10004
|
+
quoteId: r["quoteId"],
|
|
10005
|
+
redeemSz: redeemSzDisplay,
|
|
10006
|
+
termRate: termRateDisplay,
|
|
10007
|
+
validUntil
|
|
10008
|
+
});
|
|
10009
|
+
process.stdout.write("\nQuote expires soon. Use 'earn dcd redeem-execute --ordId <id>' to execute.\n");
|
|
10010
|
+
}
|
|
10011
|
+
async function cmdDcdRedeem(run, opts) {
|
|
10012
|
+
const result = await run("dcd_execute_redeem", { ordId: opts.ordId, quoteId: opts.quoteId });
|
|
10013
|
+
const data = extractArray(result);
|
|
10014
|
+
if (opts.json) {
|
|
10015
|
+
printJson(data);
|
|
10016
|
+
return;
|
|
10017
|
+
}
|
|
10018
|
+
const r = data[0];
|
|
10019
|
+
if (!r) {
|
|
10020
|
+
process.stdout.write("No response data\n");
|
|
10021
|
+
return;
|
|
10022
|
+
}
|
|
10023
|
+
printKv({ ordId: r["ordId"], state: r["state"] });
|
|
10024
|
+
}
|
|
10025
|
+
async function cmdDcdRedeemExecute(run, opts) {
|
|
10026
|
+
const quoteResult = await run("dcd_request_redeem_quote", { ordId: opts.ordId });
|
|
10027
|
+
const quoteData = extractArray(quoteResult);
|
|
10028
|
+
const q = quoteData[0];
|
|
10029
|
+
if (!q) {
|
|
10030
|
+
process.stdout.write("Failed to get redeem quote\n");
|
|
10031
|
+
return;
|
|
10032
|
+
}
|
|
10033
|
+
const redeemResult = await run("dcd_execute_redeem", {
|
|
10034
|
+
ordId: opts.ordId,
|
|
10035
|
+
quoteId: q["quoteId"]
|
|
10036
|
+
});
|
|
10037
|
+
const redeemData = extractArray(redeemResult);
|
|
10038
|
+
const r = redeemData[0];
|
|
10039
|
+
if (!r) {
|
|
10040
|
+
process.stdout.write("No response data\n");
|
|
10041
|
+
return;
|
|
10042
|
+
}
|
|
10043
|
+
if (opts.json) {
|
|
10044
|
+
printJson({ quote: q, redeem: r });
|
|
10045
|
+
return;
|
|
10046
|
+
}
|
|
10047
|
+
printKv({
|
|
10048
|
+
ordId: r["ordId"],
|
|
10049
|
+
state: r["state"],
|
|
10050
|
+
redeemSz: q["redeemSz"] ? `${parseFloat(q["redeemSz"]).toFixed(8)} ${q["redeemCcy"]}` : "\u2014",
|
|
10051
|
+
termRate: q["termRate"] ? `${q["termRate"]}%` : "\u2014",
|
|
10052
|
+
validUntil: q["validUntil"] ? new Date(Number(q["validUntil"])).toLocaleString() : "\u2014"
|
|
10053
|
+
});
|
|
10054
|
+
}
|
|
10055
|
+
async function cmdDcdOrderState(run, opts) {
|
|
10056
|
+
const result = await run("dcd_get_order_state", { ordId: opts.ordId });
|
|
10057
|
+
const data = extractArray(result);
|
|
10058
|
+
if (opts.json) {
|
|
10059
|
+
printJson(data);
|
|
10060
|
+
return;
|
|
10061
|
+
}
|
|
10062
|
+
const r = data[0];
|
|
10063
|
+
if (!r) {
|
|
10064
|
+
process.stdout.write("Order not found\n");
|
|
10065
|
+
return;
|
|
10066
|
+
}
|
|
10067
|
+
printKv({
|
|
10068
|
+
ordId: r["ordId"],
|
|
10069
|
+
state: r["state"],
|
|
10070
|
+
productId: r["productId"],
|
|
10071
|
+
strike: r["strike"],
|
|
10072
|
+
notionalSz: r["notionalSz"],
|
|
10073
|
+
settleTime: r["settleTime"] ? new Date(Number(r["settleTime"])).toLocaleDateString() : ""
|
|
10074
|
+
});
|
|
10075
|
+
}
|
|
10076
|
+
async function cmdDcdOrders(run, opts) {
|
|
10077
|
+
const result = await run("dcd_get_orders", {
|
|
10078
|
+
ordId: opts.ordId,
|
|
10079
|
+
productId: opts.productId,
|
|
10080
|
+
uly: opts.uly,
|
|
10081
|
+
state: opts.state,
|
|
10082
|
+
beginId: opts.beginId,
|
|
10083
|
+
endId: opts.endId,
|
|
10084
|
+
begin: opts.begin,
|
|
10085
|
+
end: opts.end,
|
|
10086
|
+
limit: opts.limit
|
|
10087
|
+
});
|
|
10088
|
+
const data = extractArray(result);
|
|
10089
|
+
if (opts.json) {
|
|
10090
|
+
printJson(data);
|
|
10091
|
+
return;
|
|
10092
|
+
}
|
|
10093
|
+
if (!data.length) {
|
|
10094
|
+
process.stdout.write("No orders found\n");
|
|
10095
|
+
return;
|
|
10096
|
+
}
|
|
10097
|
+
printTable(data.map((r) => ({
|
|
10098
|
+
ordId: r["ordId"],
|
|
10099
|
+
productId: r["productId"],
|
|
10100
|
+
state: r["state"],
|
|
10101
|
+
baseCcy: r["baseCcy"],
|
|
10102
|
+
quoteCcy: r["quoteCcy"],
|
|
10103
|
+
strike: r["strike"],
|
|
10104
|
+
notionalSz: r["notionalSz"],
|
|
10105
|
+
annualizedYield: r["annualizedYield"],
|
|
10106
|
+
yieldSz: r["yieldSz"],
|
|
10107
|
+
settleTime: r["settleTime"] ? new Date(Number(r["settleTime"])).toLocaleDateString() : "",
|
|
10108
|
+
// scheduled settlement time
|
|
10109
|
+
settledTime: r["settledTime"] ? new Date(Number(r["settledTime"])).toLocaleDateString() : ""
|
|
10110
|
+
// actual settled time (non-empty only after settlement)
|
|
10111
|
+
})));
|
|
10112
|
+
}
|
|
10113
|
+
async function cmdDcdQuoteAndBuy(run, opts) {
|
|
10114
|
+
const quoteResult = await run("dcd_request_quote", {
|
|
10115
|
+
productId: opts.productId,
|
|
10116
|
+
notionalSz: opts.notionalSz,
|
|
10117
|
+
notionalCcy: opts.notionalCcy
|
|
10118
|
+
});
|
|
10119
|
+
const quoteData = extractArray(quoteResult);
|
|
10120
|
+
const q = quoteData[0];
|
|
10121
|
+
if (!q) {
|
|
10122
|
+
process.stdout.write("No quote returned\n");
|
|
10123
|
+
return;
|
|
10124
|
+
}
|
|
10125
|
+
const buyResult = await run("dcd_execute_quote", {
|
|
10126
|
+
quoteId: q["quoteId"],
|
|
10127
|
+
clOrdId: opts.clOrdId
|
|
10128
|
+
});
|
|
10129
|
+
const buyData = extractArray(buyResult);
|
|
10130
|
+
const r = buyData[0];
|
|
10131
|
+
if (!r) {
|
|
10132
|
+
process.stdout.write("No order response\n");
|
|
10133
|
+
return;
|
|
10134
|
+
}
|
|
10135
|
+
const ordId = r["ordId"];
|
|
10136
|
+
let stateRow;
|
|
10137
|
+
if (ordId) {
|
|
10138
|
+
try {
|
|
10139
|
+
const stateResult = await run("dcd_get_order_state", { ordId });
|
|
10140
|
+
stateRow = extractArray(stateResult)[0];
|
|
10141
|
+
} catch {
|
|
10142
|
+
}
|
|
10143
|
+
}
|
|
10144
|
+
if (opts.json) {
|
|
10145
|
+
printJson({ quote: q, order: r, state: stateRow ?? null });
|
|
10146
|
+
return;
|
|
10147
|
+
}
|
|
10148
|
+
process.stdout.write("Quote:\n");
|
|
10149
|
+
printKv({
|
|
10150
|
+
quoteId: q["quoteId"],
|
|
10151
|
+
// quote endpoint returns percentage directly (e.g. 18.34 = 18.34%) — no ×100 needed
|
|
10152
|
+
annualizedYield: q["annualizedYield"] ? `${q["annualizedYield"]}%` : "\u2014",
|
|
10153
|
+
absYield: q["absYield"],
|
|
10154
|
+
notionalSz: q["notionalSz"],
|
|
10155
|
+
notionalCcy: q["notionalCcy"]
|
|
10156
|
+
});
|
|
10157
|
+
process.stdout.write("\nOrder placed:\n");
|
|
10158
|
+
printKv({ ordId: r["ordId"], quoteId: r["quoteId"], state: r["state"] ?? r["status"] });
|
|
10159
|
+
if (stateRow) {
|
|
10160
|
+
process.stdout.write("\nOrder state:\n");
|
|
10161
|
+
printKv({
|
|
10162
|
+
ordId: stateRow["ordId"],
|
|
10163
|
+
state: stateRow["state"]
|
|
10164
|
+
});
|
|
10165
|
+
}
|
|
10166
|
+
}
|
|
10167
|
+
|
|
9424
10168
|
// src/index.ts
|
|
9425
10169
|
var _require2 = createRequire2(import.meta.url);
|
|
9426
10170
|
var CLI_VERSION2 = _require2("../package.json").version;
|
|
9427
|
-
var GIT_HASH2 = true ? "
|
|
10171
|
+
var GIT_HASH2 = true ? "1df90cc" : "dev";
|
|
9428
10172
|
function handleConfigCommand(action, rest, json, lang, force) {
|
|
9429
10173
|
if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
|
|
9430
10174
|
if (action === "show") return cmdConfigShow(json);
|
|
@@ -9469,6 +10213,8 @@ function handleMarketPublicCommand(run, action, rest, v, json) {
|
|
|
9469
10213
|
if (action === "price-limit") return cmdMarketPriceLimit(run, rest[0], json);
|
|
9470
10214
|
if (action === "open-interest")
|
|
9471
10215
|
return cmdMarketOpenInterest(run, { instType: v.instType, instId: v.instId, json });
|
|
10216
|
+
if (action === "stock-tokens")
|
|
10217
|
+
return cmdMarketStockTokens(run, { instType: v.instType, instId: v.instId, json });
|
|
9472
10218
|
}
|
|
9473
10219
|
function handleMarketDataCommand(run, action, rest, v, json) {
|
|
9474
10220
|
const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
|
|
@@ -9891,8 +10637,9 @@ function handleEarnCommand(run, submodule, rest, v, json) {
|
|
|
9891
10637
|
const innerRest = rest.slice(1);
|
|
9892
10638
|
if (submodule === "savings") return handleEarnSavingsCommand(run, action, innerRest, v, json);
|
|
9893
10639
|
if (submodule === "onchain") return handleEarnOnchainCommand(run, action, v, json);
|
|
10640
|
+
if (submodule === "dcd") return handleEarnDcdCommand(run, action, v, json);
|
|
9894
10641
|
process.stderr.write(`Unknown earn sub-module: ${submodule}
|
|
9895
|
-
Valid: savings, onchain
|
|
10642
|
+
Valid: savings, onchain, dcd
|
|
9896
10643
|
`);
|
|
9897
10644
|
process.exitCode = 1;
|
|
9898
10645
|
}
|
|
@@ -9920,6 +10667,70 @@ function handleEarnOnchainCommand(run, action, v, json) {
|
|
|
9920
10667
|
`);
|
|
9921
10668
|
process.exitCode = 1;
|
|
9922
10669
|
}
|
|
10670
|
+
function parseDcdOpts(v) {
|
|
10671
|
+
return {
|
|
10672
|
+
limit: v.limit !== void 0 ? Number(v.limit) : void 0,
|
|
10673
|
+
minYield: v.minYield !== void 0 ? parseFloat(v.minYield) : void 0,
|
|
10674
|
+
strikeNear: v.strikeNear !== void 0 ? parseFloat(v.strikeNear) : void 0,
|
|
10675
|
+
termDays: v.termDays !== void 0 ? parseInt(v.termDays, 10) : void 0,
|
|
10676
|
+
minTermDays: v.minTermDays !== void 0 ? parseInt(v.minTermDays, 10) : void 0,
|
|
10677
|
+
maxTermDays: v.maxTermDays !== void 0 ? parseInt(v.maxTermDays, 10) : void 0
|
|
10678
|
+
};
|
|
10679
|
+
}
|
|
10680
|
+
function handleEarnDcdCommand(run, action, v, json) {
|
|
10681
|
+
const { limit, minYield, strikeNear, termDays, minTermDays, maxTermDays } = parseDcdOpts(v);
|
|
10682
|
+
if (action === "pairs") return cmdDcdPairs(run, json);
|
|
10683
|
+
if (action === "products")
|
|
10684
|
+
return cmdDcdProducts(run, {
|
|
10685
|
+
baseCcy: v.baseCcy,
|
|
10686
|
+
quoteCcy: v.quoteCcy,
|
|
10687
|
+
optType: v.optType,
|
|
10688
|
+
minYield,
|
|
10689
|
+
strikeNear,
|
|
10690
|
+
termDays,
|
|
10691
|
+
minTermDays,
|
|
10692
|
+
maxTermDays,
|
|
10693
|
+
expDate: v.expDate,
|
|
10694
|
+
json
|
|
10695
|
+
});
|
|
10696
|
+
if (action === "quote")
|
|
10697
|
+
return cmdDcdQuote(run, { productId: v.productId, notionalSz: v.sz, notionalCcy: v.notionalCcy, json });
|
|
10698
|
+
if (action === "buy")
|
|
10699
|
+
return cmdDcdBuy(run, { quoteId: v.quoteId, clOrdId: v.clOrdId, json });
|
|
10700
|
+
if (action === "quote-and-buy")
|
|
10701
|
+
return cmdDcdQuoteAndBuy(run, {
|
|
10702
|
+
productId: v.productId,
|
|
10703
|
+
notionalSz: v.sz,
|
|
10704
|
+
notionalCcy: v.notionalCcy,
|
|
10705
|
+
clOrdId: v.clOrdId,
|
|
10706
|
+
json
|
|
10707
|
+
});
|
|
10708
|
+
if (action === "redeem-quote")
|
|
10709
|
+
return cmdDcdRedeemQuote(run, { ordId: v.ordId, json });
|
|
10710
|
+
if (action === "redeem")
|
|
10711
|
+
return cmdDcdRedeem(run, { ordId: v.ordId, quoteId: v.quoteId, json });
|
|
10712
|
+
if (action === "redeem-execute")
|
|
10713
|
+
return cmdDcdRedeemExecute(run, { ordId: v.ordId, json });
|
|
10714
|
+
if (action === "order")
|
|
10715
|
+
return cmdDcdOrderState(run, { ordId: v.ordId, json });
|
|
10716
|
+
if (action === "orders")
|
|
10717
|
+
return cmdDcdOrders(run, {
|
|
10718
|
+
ordId: v.ordId,
|
|
10719
|
+
productId: v.productId,
|
|
10720
|
+
uly: v.uly,
|
|
10721
|
+
state: v.state,
|
|
10722
|
+
beginId: v.beginId,
|
|
10723
|
+
endId: v.endId,
|
|
10724
|
+
begin: v.begin,
|
|
10725
|
+
end: v.end,
|
|
10726
|
+
limit,
|
|
10727
|
+
json
|
|
10728
|
+
});
|
|
10729
|
+
process.stderr.write(`Unknown earn dcd command: ${action}
|
|
10730
|
+
Valid: pairs, products, quote, buy, quote-and-buy, redeem-quote, redeem, redeem-execute, order, orders
|
|
10731
|
+
`);
|
|
10732
|
+
process.exitCode = 1;
|
|
10733
|
+
}
|
|
9923
10734
|
function outputResult(result, json) {
|
|
9924
10735
|
if (json) {
|
|
9925
10736
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|