@raintree-technology/perps 0.1.2 → 0.1.4

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/README.md +42 -4
  3. package/dist/adapters/aevo.d.ts +1 -6
  4. package/dist/adapters/aevo.js +0 -21
  5. package/dist/adapters/certification.js +55 -9
  6. package/dist/adapters/decibel/order-manager.d.ts +41 -0
  7. package/dist/adapters/decibel/order-manager.js +216 -0
  8. package/dist/adapters/decibel/rest-client.d.ts +21 -0
  9. package/dist/adapters/decibel/rest-client.js +15 -8
  10. package/dist/adapters/decibel/ws-feed.js +19 -4
  11. package/dist/adapters/decibel.d.ts +15 -10
  12. package/dist/adapters/decibel.js +371 -50
  13. package/dist/adapters/hyperliquid.d.ts +1 -6
  14. package/dist/adapters/hyperliquid.js +0 -18
  15. package/dist/adapters/interface.d.ts +15 -14
  16. package/dist/adapters/orderly.d.ts +1 -9
  17. package/dist/adapters/orderly.js +0 -33
  18. package/dist/adapters/paradex.d.ts +1 -9
  19. package/dist/adapters/paradex.js +1 -34
  20. package/dist/cli/experience.js +0 -1
  21. package/dist/cli/program.js +28 -5
  22. package/dist/commands/arb/alert.d.ts +0 -4
  23. package/dist/commands/arb/alert.js +4 -14
  24. package/dist/commands/markets/index.js +2 -0
  25. package/dist/commands/markets/read-simple.d.ts +2 -0
  26. package/dist/commands/markets/read-simple.js +130 -0
  27. package/dist/commands/order/advanced-simple.d.ts +2 -0
  28. package/dist/commands/order/advanced-simple.js +820 -0
  29. package/dist/commands/order/index.js +2 -0
  30. package/dist/index.js +35 -1
  31. package/dist/lib/exit-codes.js +5 -1
  32. package/dist/lib/prompts.d.ts +0 -18
  33. package/dist/lib/prompts.js +1 -22
  34. package/dist/lib/schema.d.ts +8 -8
  35. package/dist/lib/schema.js +47 -8
  36. package/package.json +5 -2
@@ -192,6 +192,7 @@ export interface ExchangeCredentials {
192
192
  accountAddress?: string;
193
193
  subaccountAddress?: string;
194
194
  packageAddress?: string;
195
+ usdcAddress?: string;
195
196
  restUrl?: string;
196
197
  wsUrl?: string;
197
198
  fullnodeUrl?: string;
@@ -286,20 +287,20 @@ export interface PerpDEXAdapter {
286
287
  cancelAllOrders(market?: string): Promise<number>;
287
288
  setLeverage(market: string, leverage: number): Promise<void>;
288
289
  setMarginType(market: string, type: MarginType): Promise<void>;
289
- modifyOrder(params: ModifyOrderParams): Promise<Order>;
290
- batchPlaceOrders(paramsList: OrderParams[]): Promise<Order[]>;
291
- batchCancelOrders(paramsList: CancelOrderParams[]): Promise<boolean[]>;
292
- cancelAllAfter(timeoutMs: number): Promise<void>;
293
- getOrderHistory(market?: string, limit?: number): Promise<Order[]>;
294
- getFundingHistory(market?: string, limit?: number): Promise<FundingPayment[]>;
295
- getPublicTrades(market: string, limit?: number): Promise<PublicTrade[]>;
296
- setMMP(config: MMPConfig): Promise<void>;
297
- getMMP(market: string): Promise<MMPStatus>;
298
- resetMMP(market: string): Promise<void>;
299
- placeTWAP(params: TWAPParams): Promise<TWAPStatus>;
300
- cancelTWAP(twapId: string): Promise<boolean>;
301
- getTWAPStatus(twapId: string): Promise<TWAPStatus | null>;
302
- updateIsolatedMargin(market: string, amount: string): Promise<void>;
290
+ modifyOrder?: (params: ModifyOrderParams) => Promise<Order>;
291
+ batchPlaceOrders?: (paramsList: OrderParams[]) => Promise<Order[]>;
292
+ batchCancelOrders?: (paramsList: CancelOrderParams[]) => Promise<boolean[]>;
293
+ cancelAllAfter?: (timeoutMs: number) => Promise<void>;
294
+ getOrderHistory?: (market?: string, limit?: number) => Promise<Order[]>;
295
+ getFundingHistory?: (market?: string, limit?: number) => Promise<FundingPayment[]>;
296
+ getPublicTrades?: (market: string, limit?: number) => Promise<PublicTrade[]>;
297
+ setMMP?: (config: MMPConfig) => Promise<void>;
298
+ getMMP?: (market: string) => Promise<MMPStatus>;
299
+ resetMMP?: (market: string) => Promise<void>;
300
+ placeTWAP?: (params: TWAPParams) => Promise<TWAPStatus>;
301
+ cancelTWAP?: (twapId: string) => Promise<boolean>;
302
+ getTWAPStatus?: (twapId: string) => Promise<TWAPStatus | null>;
303
+ updateIsolatedMargin?: (market: string, amount: string) => Promise<void>;
303
304
  subscribe(callbacks: SubscriptionCallbacks): Unsubscribe;
304
305
  subscribeOrderBook(market: string, callback: (book: OrderBook) => void): Unsubscribe;
305
306
  subscribeTicker(market: string, callback: (ticker: Ticker) => void): Unsubscribe;
@@ -5,7 +5,7 @@
5
5
  * API Docs: https://orderly.network/docs
6
6
  * Base URL: https://api-evm.orderly.org/v1
7
7
  */
8
- import { type PerpDEXAdapter, type ExchangeInfo, type ExchangeConfig, type Market, type Ticker, type OrderBook, type FundingRate, type Position, type Order, type Balance, type Trade, type OrderParams, type CancelOrderParams, type ModifyOrderParams, type FundingPayment, type PublicTrade, type SubscriptionCallbacks, type Unsubscribe, type MarginType, type MMPConfig, type MMPStatus, type TWAPParams, type TWAPStatus } from "./interface.js";
8
+ import { type PerpDEXAdapter, type ExchangeInfo, type ExchangeConfig, type Market, type Ticker, type OrderBook, type FundingRate, type Position, type Order, type Balance, type Trade, type OrderParams, type CancelOrderParams, type FundingPayment, type PublicTrade, type SubscriptionCallbacks, type Unsubscribe, type MarginType } from "./interface.js";
9
9
  export declare class OrderlyAdapter implements PerpDEXAdapter {
10
10
  readonly info: ExchangeInfo;
11
11
  private baseUrl;
@@ -43,20 +43,12 @@ export declare class OrderlyAdapter implements PerpDEXAdapter {
43
43
  cancelAllOrders(market?: string): Promise<number>;
44
44
  setLeverage(_market: string, leverage: number): Promise<void>;
45
45
  setMarginType(_market: string, type: MarginType): Promise<void>;
46
- modifyOrder(_params: ModifyOrderParams): Promise<Order>;
47
46
  batchPlaceOrders(paramsList: OrderParams[]): Promise<Order[]>;
48
47
  batchCancelOrders(paramsList: CancelOrderParams[]): Promise<boolean[]>;
49
48
  cancelAllAfter(timeoutMs: number): Promise<void>;
50
49
  getOrderHistory(market?: string, limit?: number): Promise<Order[]>;
51
50
  getFundingHistory(market?: string, limit?: number): Promise<FundingPayment[]>;
52
51
  getPublicTrades(market: string, limit?: number): Promise<PublicTrade[]>;
53
- setMMP(_config: MMPConfig): Promise<void>;
54
- getMMP(_market: string): Promise<MMPStatus>;
55
- resetMMP(_market: string): Promise<void>;
56
- placeTWAP(_params: TWAPParams): Promise<TWAPStatus>;
57
- cancelTWAP(_twapId: string): Promise<boolean>;
58
- getTWAPStatus(_twapId: string): Promise<TWAPStatus | null>;
59
- updateIsolatedMargin(_market: string, _amount: string): Promise<void>;
60
52
  subscribe(callbacks: SubscriptionCallbacks): Unsubscribe;
61
53
  subscribeOrderBook(market: string, callback: (book: OrderBook) => void): Unsubscribe;
62
54
  subscribeTicker(market: string, callback: (ticker: Ticker) => void): Unsubscribe;
@@ -660,9 +660,6 @@ export class OrderlyAdapter {
660
660
  // --------------------------------------------------------------------------
661
661
  // Advanced Trading
662
662
  // --------------------------------------------------------------------------
663
- async modifyOrder(_params) {
664
- throw new Error("Orderly does not support order modification. Cancel and replace instead.");
665
- }
666
663
  async batchPlaceOrders(paramsList) {
667
664
  // Orderly has batch create order endpoint
668
665
  const results = [];
@@ -741,36 +738,6 @@ export class OrderlyAdapter {
741
738
  }));
742
739
  }
743
740
  // --------------------------------------------------------------------------
744
- // Market Maker Protection
745
- // --------------------------------------------------------------------------
746
- async setMMP(_config) {
747
- throw new Error("Orderly does not support Market Maker Protection (MMP)");
748
- }
749
- async getMMP(_market) {
750
- throw new Error("Orderly does not support Market Maker Protection (MMP)");
751
- }
752
- async resetMMP(_market) {
753
- throw new Error("Orderly does not support Market Maker Protection (MMP)");
754
- }
755
- // --------------------------------------------------------------------------
756
- // TWAP Orders
757
- // --------------------------------------------------------------------------
758
- async placeTWAP(_params) {
759
- throw new Error("Orderly does not support TWAP orders");
760
- }
761
- async cancelTWAP(_twapId) {
762
- throw new Error("Orderly does not support TWAP orders");
763
- }
764
- async getTWAPStatus(_twapId) {
765
- throw new Error("Orderly does not support TWAP orders");
766
- }
767
- // --------------------------------------------------------------------------
768
- // Margin Management
769
- // --------------------------------------------------------------------------
770
- async updateIsolatedMargin(_market, _amount) {
771
- throw new Error("Orderly does not support isolated margin adjustment");
772
- }
773
- // --------------------------------------------------------------------------
774
741
  // Subscriptions (polling)
775
742
  // --------------------------------------------------------------------------
776
743
  subscribe(callbacks) {
@@ -5,7 +5,7 @@
5
5
  * API Docs: https://docs.paradex.trade/
6
6
  * Base URL: https://api.prod.paradex.trade/v1
7
7
  */
8
- import { type PerpDEXAdapter, type ExchangeInfo, type ExchangeConfig, type Market, type Ticker, type OrderBook, type FundingRate, type Position, type Order, type Balance, type Trade, type OrderParams, type CancelOrderParams, type SubscriptionCallbacks, type Unsubscribe, type MarginType, type ModifyOrderParams, type FundingPayment, type PublicTrade, type MMPConfig, type MMPStatus, type TWAPParams, type TWAPStatus } from "./interface.js";
8
+ import { type PerpDEXAdapter, type ExchangeInfo, type ExchangeConfig, type Market, type Ticker, type OrderBook, type FundingRate, type Position, type Order, type Balance, type Trade, type OrderParams, type CancelOrderParams, type SubscriptionCallbacks, type Unsubscribe, type MarginType, type ModifyOrderParams, type FundingPayment, type PublicTrade } from "./interface.js";
9
9
  export declare class ParadexAdapter implements PerpDEXAdapter {
10
10
  readonly info: ExchangeInfo;
11
11
  private baseUrl;
@@ -46,17 +46,9 @@ export declare class ParadexAdapter implements PerpDEXAdapter {
46
46
  modifyOrder(params: ModifyOrderParams): Promise<Order>;
47
47
  batchPlaceOrders(paramsList: OrderParams[]): Promise<Order[]>;
48
48
  batchCancelOrders(paramsList: CancelOrderParams[]): Promise<boolean[]>;
49
- cancelAllAfter(_timeoutMs: number): Promise<void>;
50
49
  getOrderHistory(market?: string, limit?: number): Promise<Order[]>;
51
50
  getFundingHistory(market?: string, limit?: number): Promise<FundingPayment[]>;
52
51
  getPublicTrades(market: string, limit?: number): Promise<PublicTrade[]>;
53
- setMMP(_config: MMPConfig): Promise<void>;
54
- getMMP(_market: string): Promise<MMPStatus>;
55
- resetMMP(_market: string): Promise<void>;
56
- placeTWAP(_params: TWAPParams): Promise<TWAPStatus>;
57
- cancelTWAP(_twapId: string): Promise<boolean>;
58
- getTWAPStatus(_twapId: string): Promise<TWAPStatus | null>;
59
- updateIsolatedMargin(_market: string, _amount: string): Promise<void>;
60
52
  subscribe(callbacks: SubscriptionCallbacks): Unsubscribe;
61
53
  subscribeOrderBook(market: string, callback: (book: OrderBook) => void): Unsubscribe;
62
54
  subscribeTicker(market: string, callback: (ticker: Ticker) => void): Unsubscribe;
@@ -24,7 +24,7 @@ export class ParadexAdapter {
24
24
  perp: true,
25
25
  margin: true,
26
26
  crossMargin: true,
27
- isolatedMargin: true,
27
+ isolatedMargin: false,
28
28
  stopOrders: true,
29
29
  takeProfitOrders: true,
30
30
  postOnly: true,
@@ -635,9 +635,6 @@ export class ParadexAdapter {
635
635
  }
636
636
  return results;
637
637
  }
638
- async cancelAllAfter(_timeoutMs) {
639
- throw new Error("Paradex does not support cancelAllAfter (dead man's switch)");
640
- }
641
638
  async getOrderHistory(market, limit = 100) {
642
639
  const params = new URLSearchParams();
643
640
  if (market)
@@ -674,36 +671,6 @@ export class ParadexAdapter {
674
671
  }));
675
672
  }
676
673
  // --------------------------------------------------------------------------
677
- // Market Maker Protection
678
- // --------------------------------------------------------------------------
679
- async setMMP(_config) {
680
- throw new Error("Paradex does not support Market Maker Protection (MMP)");
681
- }
682
- async getMMP(_market) {
683
- throw new Error("Paradex does not support Market Maker Protection (MMP)");
684
- }
685
- async resetMMP(_market) {
686
- throw new Error("Paradex does not support Market Maker Protection (MMP)");
687
- }
688
- // --------------------------------------------------------------------------
689
- // TWAP Orders
690
- // --------------------------------------------------------------------------
691
- async placeTWAP(_params) {
692
- throw new Error("Paradex does not support TWAP orders");
693
- }
694
- async cancelTWAP(_twapId) {
695
- throw new Error("Paradex does not support TWAP orders");
696
- }
697
- async getTWAPStatus(_twapId) {
698
- throw new Error("Paradex does not support TWAP orders");
699
- }
700
- // --------------------------------------------------------------------------
701
- // Margin Management
702
- // --------------------------------------------------------------------------
703
- async updateIsolatedMargin(_market, _amount) {
704
- throw new Error("Paradex does not support isolated margin adjustment");
705
- }
706
- // --------------------------------------------------------------------------
707
674
  // Subscriptions (polling)
708
675
  // --------------------------------------------------------------------------
709
676
  subscribe(callbacks) {
@@ -107,7 +107,6 @@ export function printSessionBanner(args) {
107
107
  for (const line of getPerpsAsciiMark()) {
108
108
  console.log(highlighter.brand(line));
109
109
  }
110
- console.log(highlighter.dim("by Raintree Technology"));
111
110
  console.log("");
112
111
  console.log(`${highlighter.dim("mode")} ${networkTag} ${highlighter.dim("exchange")} ${exchangeTag}`);
113
112
  console.log(`${highlighter.dim("command")} ${commandTag} ${highlighter.dim("version")} ${highlighter.dim(`v${args.version}`)}`);
@@ -8,6 +8,8 @@ import { createContext } from "./context.js";
8
8
  import { highlighter, printCommandCompletion, printSessionBanner } from "./experience.js";
9
9
  import { commandPathFromCommand, resolveTestnetMode } from "./network-defaults.js";
10
10
  import { outputError } from "./output.js";
11
+ import { inferExitCode } from "../lib/exit-codes.js";
12
+ import { withJsonContract } from "../lib/contracts.js";
11
13
  const require = createRequire(import.meta.url);
12
14
  const pkg = require("../../package.json");
13
15
  const commandMeta = new WeakMap();
@@ -30,6 +32,7 @@ export function createProgram() {
30
32
  .description("Universal CLI for perpetual DEXes")
31
33
  .showSuggestionAfterError(true)
32
34
  .showHelpAfterError()
35
+ .exitOverride()
33
36
  .version(pkg.version)
34
37
  .option("--json", "Output in JSON format", false)
35
38
  .option("--human", "Enable human-first output UX (banner, timing, rich formatting)", false)
@@ -62,17 +65,37 @@ Examples:
62
65
  setExchange(opts.exchange);
63
66
  }
64
67
  catch (err) {
65
- outputError(err instanceof Error ? err.message : String(err));
66
- console.error(highlighter.dim(`Available exchanges: ${getAvailableExchanges().join(", ")}`));
67
- process.exit(1);
68
+ const message = err instanceof Error ? err.message : String(err);
69
+ const exitCode = inferExitCode(err);
70
+ if (opts.json) {
71
+ console.error(JSON.stringify(withJsonContract("perps.error", {
72
+ status: "error",
73
+ error: { message, exitCode },
74
+ }), null, 2));
75
+ }
76
+ else {
77
+ outputError(message);
78
+ console.error(highlighter.dim(`Available exchanges: ${getAvailableExchanges().join(", ")}`));
79
+ }
80
+ process.exit(exitCode);
68
81
  }
69
82
  let config;
70
83
  try {
71
84
  config = loadConfig(isTestnet, opts.exchange);
72
85
  }
73
86
  catch (err) {
74
- outputError(err instanceof Error ? err.message : String(err));
75
- process.exit(1);
87
+ const message = err instanceof Error ? err.message : String(err);
88
+ const exitCode = inferExitCode(err);
89
+ if (opts.json) {
90
+ console.error(JSON.stringify(withJsonContract("perps.error", {
91
+ status: "error",
92
+ error: { message, exitCode },
93
+ }), null, 2));
94
+ }
95
+ else {
96
+ outputError(message);
97
+ }
98
+ process.exit(exitCode);
76
99
  }
77
100
  const context = createContext(config);
78
101
  // Store metadata on the root command
@@ -1,6 +1,2 @@
1
- /**
2
- * Arb Alert Command
3
- * Set up alerts for funding rate arbitrage opportunities
4
- */
5
1
  import { Command } from "commander";
6
2
  export declare function registerArbAlertCommand(arb: Command): void;
@@ -1,12 +1,8 @@
1
- /**
2
- * Arb Alert Command
3
- * Set up alerts for funding rate arbitrage opportunities
4
- */
5
1
  import { getContext } from "../../cli/program.js";
6
- import { pollFundingRates } from "../../lib/funding-tracker.js";
2
+ import { COMMON_ASSETS, DEFAULT_ALERT_INTERVAL_MS, MIN_PROFITABLE_SPREAD_PCT, } from "../../lib/constants.js";
7
3
  import { getAvailableExchanges } from "../../lib/exchange.js";
8
- import { COMMON_ASSETS, MIN_PROFITABLE_SPREAD_PCT, DEFAULT_ALERT_INTERVAL_MS } from "../../lib/constants.js";
9
- import { parseAssetList, parsePositiveNumber, parsePositiveInt } from "../../lib/validate.js";
4
+ import { pollFundingRates } from "../../lib/funding-tracker.js";
5
+ import { parseAssetList, parsePositiveInt, parsePositiveNumber } from "../../lib/validate.js";
10
6
  export function registerArbAlertCommand(arb) {
11
7
  arb
12
8
  .command("alert")
@@ -31,19 +27,15 @@ export function registerArbAlertCommand(arb) {
31
27
  console.log(` Exchanges: ${exchanges.join(", ")}`);
32
28
  console.log("\n Monitoring... (Ctrl+C to stop)\n");
33
29
  console.log(" " + "─".repeat(60));
34
- // Check immediately
35
30
  await checkAndAlert(config.assets, exchanges, config.threshold, isTestnet);
36
- // Then check on interval
37
31
  const interval = setInterval(async () => {
38
32
  await checkAndAlert(config.assets, exchanges, config.threshold, isTestnet);
39
33
  }, config.intervalMin * 60 * 1000);
40
- // Handle Ctrl+C
41
34
  process.once("SIGINT", () => {
42
35
  clearInterval(interval);
43
36
  console.log("\n\n Alert monitor stopped.\n");
44
37
  process.exit(0);
45
38
  });
46
- // Keep running
47
39
  await new Promise(() => { });
48
40
  });
49
41
  }
@@ -51,7 +43,6 @@ async function checkAndAlert(assets, exchanges, threshold, isTestnet) {
51
43
  try {
52
44
  const records = await pollFundingRates(assets, exchanges, undefined, isTestnet);
53
45
  const now = new Date().toLocaleTimeString();
54
- // Group by asset and find opportunities
55
46
  const byAsset = new Map();
56
47
  for (const r of records) {
57
48
  const asset = r.market.replace("-PERP", "");
@@ -71,11 +62,10 @@ async function checkAndAlert(assets, exchanges, threshold, isTestnet) {
71
62
  if (annualized >= threshold) {
72
63
  foundAny = true;
73
64
  const dailyOn10k = spread * 24 * 10000;
74
- console.log(`\n \x1b[32m🔔 ${now} - ${asset} OPPORTUNITY\x1b[0m`);
65
+ console.log(`\n \x1b[32m${now} - ${asset} OPPORTUNITY\x1b[0m`);
75
66
  console.log(` Short ${high.exchange} (${(high.rate * 100).toFixed(4)}%)`);
76
67
  console.log(` Long ${low.exchange} (${(low.rate * 100).toFixed(4)}%)`);
77
68
  console.log(` Spread: \x1b[32m${annualized.toFixed(1)}%\x1b[0m annualized (~$${dailyOn10k.toFixed(2)}/day on $10k)`);
78
- // Could add external notifications here (Discord, Telegram, etc.)
79
69
  }
80
70
  }
81
71
  if (!foundAny) {
@@ -1,5 +1,7 @@
1
1
  import { registerMarketsLsSimpleCommand } from "./ls-simple.js";
2
+ import { registerMarketsReadSimpleCommands } from "./read-simple.js";
2
3
  export function registerMarketsCommands(program) {
3
4
  const markets = program.command("markets").description("Market information");
4
5
  registerMarketsLsSimpleCommand(markets);
6
+ registerMarketsReadSimpleCommands(markets);
5
7
  }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerMarketsReadSimpleCommands(markets: Command): void;
@@ -0,0 +1,130 @@
1
+ import { getContext, getOutputOptions } from "../../cli/program.js";
2
+ import { output, outputError, outputSuccess } from "../../cli/output.js";
3
+ import { getExchangeAdapter } from "../../lib/exchange.js";
4
+ import { getExchangeCredentials } from "../../lib/config.js";
5
+ import { normalizeMarket } from "../order/shared.js";
6
+ function parseMarketSymbol(symbol) {
7
+ return normalizeMarket(symbol);
8
+ }
9
+ async function withConnectedMarketAdapter(command, action) {
10
+ const ctx = getContext(command);
11
+ const outputOpts = getOutputOptions(command);
12
+ const adapter = getExchangeAdapter();
13
+ let connected = false;
14
+ try {
15
+ const credentials = getExchangeCredentials(ctx.config, adapter.info.id);
16
+ await adapter.connect({
17
+ testnet: ctx.config.testnet,
18
+ rpcUrl: credentials.fullnodeUrl,
19
+ wsUrl: credentials.wsUrl,
20
+ credentials,
21
+ });
22
+ connected = true;
23
+ await action(adapter, outputOpts);
24
+ }
25
+ catch (err) {
26
+ outputError(err instanceof Error ? err.message : String(err));
27
+ process.exitCode = 1;
28
+ }
29
+ finally {
30
+ if (connected) {
31
+ await adapter.disconnect().catch(() => undefined);
32
+ }
33
+ }
34
+ }
35
+ export function registerMarketsReadSimpleCommands(markets) {
36
+ markets
37
+ .command("get <symbol>")
38
+ .description("Show market details for one symbol")
39
+ .action(async function (symbol) {
40
+ const market = parseMarketSymbol(symbol);
41
+ await withConnectedMarketAdapter(this, async (adapter, outputOpts) => {
42
+ const row = await adapter.getMarket(market);
43
+ if (outputOpts.json) {
44
+ output({ market: row }, outputOpts);
45
+ return;
46
+ }
47
+ if (!row) {
48
+ outputError(`Market ${market} not found`);
49
+ return;
50
+ }
51
+ outputSuccess(`Market ${row.symbol}`);
52
+ console.log(` Base: ${row.baseAsset}`);
53
+ console.log(` Quote: ${row.quoteAsset}`);
54
+ console.log(` Type: ${row.type}`);
55
+ console.log(` MaxLeverage: ${row.maxLeverage}x`);
56
+ console.log(` TickSize: ${row.tickSize}`);
57
+ console.log("");
58
+ });
59
+ });
60
+ markets
61
+ .command("ticker <symbol>")
62
+ .description("Show ticker for one symbol")
63
+ .action(async function (symbol) {
64
+ const market = parseMarketSymbol(symbol);
65
+ await withConnectedMarketAdapter(this, async (adapter, outputOpts) => {
66
+ const ticker = await adapter.getTicker(market);
67
+ if (outputOpts.json) {
68
+ output({ ticker }, outputOpts);
69
+ return;
70
+ }
71
+ outputSuccess(`Ticker ${ticker.market}`);
72
+ console.log(` Last: ${ticker.lastPrice}`);
73
+ console.log(` Mark: ${ticker.markPrice}`);
74
+ console.log(` FundingRate: ${ticker.fundingRate}`);
75
+ console.log(` OpenInterest: ${ticker.openInterest}`);
76
+ console.log("");
77
+ });
78
+ });
79
+ markets
80
+ .command("tickers")
81
+ .description("Show all tickers")
82
+ .action(async function () {
83
+ await withConnectedMarketAdapter(this, async (adapter, outputOpts) => {
84
+ const tickers = await adapter.getTickers();
85
+ if (outputOpts.json) {
86
+ output({ tickers }, outputOpts);
87
+ return;
88
+ }
89
+ outputSuccess(`Fetched ${tickers.length} tickers`);
90
+ for (const row of tickers) {
91
+ console.log(` ${row.market.padEnd(10)} last=${row.lastPrice} funding=${row.fundingRate} oi=${row.openInterest}`);
92
+ }
93
+ console.log("");
94
+ });
95
+ });
96
+ markets
97
+ .command("funding-rate <symbol>")
98
+ .description("Show funding rate for one symbol")
99
+ .action(async function (symbol) {
100
+ const market = parseMarketSymbol(symbol);
101
+ await withConnectedMarketAdapter(this, async (adapter, outputOpts) => {
102
+ const rate = await adapter.getFundingRate(market);
103
+ if (outputOpts.json) {
104
+ output({ fundingRate: rate }, outputOpts);
105
+ return;
106
+ }
107
+ outputSuccess(`Funding rate ${rate.market}`);
108
+ console.log(` Rate: ${rate.rate}`);
109
+ console.log(` NextFunding: ${new Date(rate.nextFundingTime).toISOString()}`);
110
+ console.log("");
111
+ });
112
+ });
113
+ markets
114
+ .command("funding-rates")
115
+ .description("Show funding rates for all markets")
116
+ .action(async function () {
117
+ await withConnectedMarketAdapter(this, async (adapter, outputOpts) => {
118
+ const rates = await adapter.getFundingRates();
119
+ if (outputOpts.json) {
120
+ output({ fundingRates: rates }, outputOpts);
121
+ return;
122
+ }
123
+ outputSuccess(`Fetched ${rates.length} funding rates`);
124
+ for (const row of rates) {
125
+ console.log(` ${row.market.padEnd(10)} rate=${row.rate}`);
126
+ }
127
+ console.log("");
128
+ });
129
+ });
130
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerAdvancedOrderSimpleCommands(order: Command): void;