perp-cli 0.4.2 → 0.4.8

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 (68) hide show
  1. package/README.md +2 -0
  2. package/dist/arb/sizing.d.ts +12 -1
  3. package/dist/arb/sizing.js +38 -5
  4. package/dist/arb/state.d.ts +6 -0
  5. package/dist/cli-spec.d.ts +0 -4
  6. package/dist/cli-spec.js +8 -1
  7. package/dist/commands/agent.js +7 -4
  8. package/dist/commands/arb-auto.js +643 -4
  9. package/dist/commands/dex.js +7 -1
  10. package/dist/commands/funding.d.ts +2 -1
  11. package/dist/commands/funding.js +211 -4
  12. package/dist/commands/manage.js +1 -1
  13. package/dist/commands/market.js +1 -1
  14. package/dist/commands/multileg.d.ts +16 -0
  15. package/dist/commands/multileg.js +174 -0
  16. package/dist/commands/pnl.d.ts +12 -0
  17. package/dist/commands/pnl.js +243 -0
  18. package/dist/commands/stream.js +132 -55
  19. package/dist/commands/trade.js +29 -8
  20. package/dist/commands/wallet.js +1 -1
  21. package/dist/config.d.ts +5 -0
  22. package/dist/config.js +12 -0
  23. package/dist/dashboard/ws-feeds.js +1 -1
  24. package/dist/equity-tracker.d.ts +57 -0
  25. package/dist/equity-tracker.js +209 -0
  26. package/dist/exchanges/hyperliquid-spot.d.ts +68 -0
  27. package/dist/exchanges/hyperliquid-spot.js +317 -0
  28. package/dist/exchanges/hyperliquid.d.ts +26 -5
  29. package/dist/exchanges/hyperliquid.js +171 -73
  30. package/dist/exchanges/interface.d.ts +1 -1
  31. package/dist/exchanges/lighter-spot.d.ts +55 -0
  32. package/dist/exchanges/lighter-spot.js +417 -0
  33. package/dist/exchanges/lighter.d.ts +10 -2
  34. package/dist/exchanges/lighter.js +128 -35
  35. package/dist/exchanges/pacifica.d.ts +11 -4
  36. package/dist/exchanges/pacifica.js +52 -37
  37. package/dist/exchanges/spot-interface.d.ts +45 -0
  38. package/dist/exchanges/spot-interface.js +22 -0
  39. package/dist/execution-log.d.ts +2 -2
  40. package/dist/funding/rates.d.ts +36 -0
  41. package/dist/funding/rates.js +146 -0
  42. package/dist/index.js +147 -98
  43. package/dist/liquidity.d.ts +12 -0
  44. package/dist/liquidity.js +43 -0
  45. package/dist/signer/evm-local.d.ts +12 -0
  46. package/dist/signer/evm-local.js +19 -0
  47. package/dist/signer/index.d.ts +3 -0
  48. package/dist/signer/index.js +2 -0
  49. package/dist/signer/interface.d.ts +31 -0
  50. package/dist/signer/interface.js +7 -0
  51. package/dist/signer/solana-local.d.ts +13 -0
  52. package/dist/signer/solana-local.js +19 -0
  53. package/dist/smart-order.js +14 -3
  54. package/dist/utils.js +7 -1
  55. package/dist/ws/market-feed.d.ts +74 -0
  56. package/dist/ws/market-feed.js +227 -0
  57. package/package.json +1 -1
  58. package/skills/perp-cli/SKILL.md +93 -4
  59. package/skills/perp-cli/references/commands.md +16 -1
  60. package/skills/perp-cli/references/strategies.md +1 -1
  61. package/skills/perp-cli/scripts/arb-monitor.sh +74 -0
  62. package/skills/perp-cli/scripts/funding-analysis.sh +85 -0
  63. package/skills/perp-cli/scripts/preflight.sh +98 -0
  64. package/skills/perp-cli/scripts/spot-perp-scan.sh +83 -0
  65. package/skills/perp-cli/scripts/validate-arb.sh +112 -0
  66. package/skills/perp-cli/templates/arb-scan.sh +0 -15
  67. package/skills/perp-cli/templates/open-position.sh +0 -38
  68. package/skills/perp-cli/templates/wallet-setup.sh +0 -17
package/README.md CHANGED
@@ -33,6 +33,8 @@ perp wallet show
33
33
 
34
34
  Same EVM key works for both Hyperliquid and Lighter.
35
35
 
36
+ > **Lighter API Key Index:** Indexes 0–3 are reserved by Lighter's frontend (web/mobile). perp-cli defaults to index `4`. Override with `LIGHTER_API_KEY_INDEX` env var or `--key-index` flag on `manage setup-api-key`. Valid range: 4–254.
37
+
36
38
  ## Core Commands
37
39
 
38
40
  ```bash
@@ -5,7 +5,18 @@ import type { ExchangeAdapter } from "../exchanges/interface.js";
5
5
  *
6
6
  * @returns size string that works for both exchanges, or null if not viable
7
7
  */
8
- export declare function computeMatchedSize(sizeUsd: number, price: number, longExchange: string, shortExchange: string): {
8
+ export declare function computeMatchedSize(sizeUsd: number, price: number, longExchange: string, shortExchange: string, opts?: {
9
+ longSizeDecimals?: number;
10
+ shortSizeDecimals?: number;
11
+ }): {
12
+ size: string;
13
+ notional: number;
14
+ } | null;
15
+ /**
16
+ * Compute matched size for spot-perp arb.
17
+ * Uses spot exchange's size decimals for the spot leg.
18
+ */
19
+ export declare function computeSpotPerpMatchedSize(sizeUsd: number, price: number, spotExchange: string, perpExchange: string, spotSizeDecimals?: number): {
9
20
  size: string;
10
21
  notional: number;
11
22
  } | null;
@@ -4,12 +4,12 @@
4
4
  *
5
5
  * @returns size string that works for both exchanges, or null if not viable
6
6
  */
7
- export function computeMatchedSize(sizeUsd, price, longExchange, shortExchange) {
7
+ export function computeMatchedSize(sizeUsd, price, longExchange, shortExchange, opts) {
8
8
  if (price <= 0)
9
9
  return null;
10
10
  const rawSize = sizeUsd / price;
11
- // Size decimals per exchange (conservative defaults)
12
- const szDecimals = Math.min(getSizeDecimals(longExchange), getSizeDecimals(shortExchange));
11
+ // Use explicitly provided decimals if available, else conservative defaults
12
+ const szDecimals = Math.min(opts?.longSizeDecimals ?? getSizeDecimals(longExchange), opts?.shortSizeDecimals ?? getSizeDecimals(shortExchange));
13
13
  // Round DOWN to the least precise exchange's decimals
14
14
  const factor = Math.pow(10, szDecimals);
15
15
  const roundedSize = Math.floor(rawSize * factor) / factor;
@@ -30,12 +30,15 @@ export function computeMatchedSize(sizeUsd, price, longExchange, shortExchange)
30
30
  }
31
31
  return { size: roundedSize.toFixed(szDecimals), notional };
32
32
  }
33
- /** Size decimal precision by exchange */
33
+ /** Size decimal precision by exchange (conservative fallbacks — prefer explicit decimals via opts) */
34
34
  function getSizeDecimals(exchange) {
35
35
  switch (exchange.toLowerCase()) {
36
- case "hyperliquid": return 1; // Most HL perps use 1 decimal
36
+ case "hyperliquid": return 2; // HL perps range 0-5; 2 is safe middle ground
37
37
  case "lighter": return 2;
38
38
  case "pacifica": return 4;
39
+ // Spot exchanges
40
+ case "spot:hyperliquid": return 2;
41
+ case "spot:lighter": return 2;
39
42
  default: return 2;
40
43
  }
41
44
  }
@@ -45,9 +48,39 @@ function getMinNotional(exchange) {
45
48
  case "hyperliquid": return 10;
46
49
  case "lighter": return 10;
47
50
  case "pacifica": return 1;
51
+ case "spot:hyperliquid": return 10;
52
+ case "spot:lighter": return 10;
48
53
  default: return 10;
49
54
  }
50
55
  }
56
+ /**
57
+ * Compute matched size for spot-perp arb.
58
+ * Uses spot exchange's size decimals for the spot leg.
59
+ */
60
+ export function computeSpotPerpMatchedSize(sizeUsd, price, spotExchange, perpExchange, spotSizeDecimals) {
61
+ if (price <= 0)
62
+ return null;
63
+ // If explicit spot decimals provided, use them; otherwise derive from exchange
64
+ const spotDec = spotSizeDecimals ?? getSizeDecimals(`spot:${spotExchange}`);
65
+ const perpDec = getSizeDecimals(perpExchange);
66
+ const szDecimals = Math.min(spotDec, perpDec);
67
+ const rawSize = sizeUsd / price;
68
+ const factor = Math.pow(10, szDecimals);
69
+ const roundedSize = Math.floor(rawSize * factor) / factor;
70
+ if (roundedSize <= 0)
71
+ return null;
72
+ const notional = roundedSize * price;
73
+ const minNotional = Math.max(getMinNotional(`spot:${spotExchange}`), getMinNotional(perpExchange));
74
+ if (notional < minNotional) {
75
+ const roundedUp = Math.ceil(rawSize * factor) / factor;
76
+ const notionalUp = roundedUp * price;
77
+ if (notionalUp <= sizeUsd * 1.2) {
78
+ return { size: roundedUp.toFixed(szDecimals), notional: notionalUp };
79
+ }
80
+ return null;
81
+ }
82
+ return { size: roundedSize.toFixed(szDecimals), notional };
83
+ }
51
84
  /**
52
85
  * After both legs are submitted, verify actual fills match.
53
86
  * If there's a size mismatch, place a correction order on the larger side.
@@ -13,6 +13,12 @@ export interface ArbPositionState {
13
13
  entryShortPrice: number;
14
14
  accumulatedFunding: number;
15
15
  lastCheckTime: string;
16
+ /** "perp-perp" (default) or "spot-perp" */
17
+ mode?: "perp-perp" | "spot-perp";
18
+ /** Spot leg exchange name (for spot-perp mode) */
19
+ spotExchange?: string;
20
+ /** Spot symbol, e.g. "ETH/USDC" (for spot-perp mode) */
21
+ spotSymbol?: string;
16
22
  }
17
23
  export interface ArbDaemonState {
18
24
  version: 1;
@@ -1,7 +1,3 @@
1
- /**
2
- * Generates a structured CLI spec from Commander's program tree.
3
- * Used by `perp api-spec` so agents can discover all commands programmatically.
4
- */
5
1
  import type { Command } from "commander";
6
2
  interface ArgSpec {
7
3
  name: string;
package/dist/cli-spec.js CHANGED
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Generates a structured CLI spec from Commander's program tree.
3
+ * Used by `perp api-spec` so agents can discover all commands programmatically.
4
+ */
5
+ import { createRequire } from "node:module";
6
+ const require = createRequire(import.meta.url);
7
+ const { version: pkgVersion } = require("../package.json");
1
8
  function extractCommand(cmd) {
2
9
  const args = cmd._args ?? [];
3
10
  const options = cmd.options.map((opt) => ({
@@ -27,7 +34,7 @@ export function getCliSpec(program) {
27
34
  }));
28
35
  return {
29
36
  name: "perp",
30
- version: "0.1.0",
37
+ version: pkgVersion,
31
38
  description: "Multi-DEX Perpetual Futures CLI (Pacifica, Hyperliquid, Lighter)",
32
39
  globalOptions,
33
40
  commands,
@@ -1,6 +1,9 @@
1
+ import { createRequire } from "node:module";
1
2
  import { printJson, jsonOk } from "../utils.js";
2
3
  import { ERROR_CODES } from "../errors.js";
3
4
  import chalk from "chalk";
5
+ const _require = createRequire(import.meta.url);
6
+ const _pkg = _require("../../package.json");
4
7
  /** Infer parameter type from commander flags/description */
5
8
  function inferType(flags, desc) {
6
9
  if (flags.includes("[boolean]") || !flags.includes("<") && !flags.includes("["))
@@ -72,7 +75,7 @@ export function registerAgentCommands(program, getAdapter, isJson) {
72
75
  }
73
76
  const envelope = {
74
77
  schemaVersion: "2.0",
75
- cliVersion: "0.1.0",
78
+ cliVersion: _pkg.version,
76
79
  generatedAt: new Date().toISOString(),
77
80
  exchanges: ["pacifica", "hyperliquid", "lighter"],
78
81
  errorCodes: errorCodeDocs,
@@ -93,7 +96,7 @@ export function registerAgentCommands(program, getAdapter, isJson) {
93
96
  }
94
97
  const envelope = {
95
98
  schemaVersion: "2.0",
96
- cliVersion: "0.1.0",
99
+ cliVersion: _pkg.version,
97
100
  generatedAt: new Date().toISOString(),
98
101
  exchanges: ["pacifica", "hyperliquid", "lighter"],
99
102
  errorCodes: errorCodeDocs,
@@ -110,7 +113,7 @@ export function registerAgentCommands(program, getAdapter, isJson) {
110
113
  .action(() => {
111
114
  printJson(jsonOk({
112
115
  name: "perp-cli",
113
- version: "0.1.0",
116
+ version: _pkg.version,
114
117
  description: "Multi-DEX Perpetual Futures CLI (Pacifica, Hyperliquid, Lighter) with HIP-3 deployed dex support",
115
118
  exchanges: ["pacifica", "hyperliquid", "lighter"],
116
119
  capabilities: [
@@ -276,7 +279,7 @@ export function registerAgentCommands(program, getAdapter, isJson) {
276
279
  .action(async () => {
277
280
  const results = {
278
281
  timestamp: new Date().toISOString(),
279
- cli_version: "0.1.0",
282
+ cli_version: _pkg.version,
280
283
  };
281
284
  // Check exchange APIs
282
285
  const { pingPacifica, pingHyperliquid } = await import("../shared-api.js");