perp-cli 0.3.10 → 0.3.12

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.
@@ -70,12 +70,16 @@ export class LighterAdapter {
70
70
  : json.accounts[0].account_index;
71
71
  }
72
72
  // Auto-generate API key if we have PK but no API key and account exists
73
+ let signerReady = false;
73
74
  if (!this._apiKey && this._accountIndex >= 0) {
74
75
  try {
75
76
  const autoKeyIndex = 2; // default for auto-setup
76
77
  const { privateKey: apiKey } = await this.setupApiKey(autoKeyIndex);
77
78
  this._apiKey = apiKey;
78
79
  this._apiKeyIndex = autoKeyIndex;
80
+ // setupApiKey already configured the static WASM client — reuse it
81
+ this._signer = LighterAdapter._wasmClient;
82
+ signerReady = true;
79
83
  // Save to .env for future use
80
84
  try {
81
85
  const { setEnvVar } = await import("../commands/init.js");
@@ -91,18 +95,19 @@ export class LighterAdapter {
91
95
  console.error(`[lighter] API key auto-setup failed: ${msg}. Trading will be read-only. Run 'perp -e lighter manage setup-api-key' to retry.`);
92
96
  }
93
97
  }
94
- // Initialize signer for trading if we have an API key
95
- if (this._apiKey) {
96
- const { WasmSignerClient } = await import("lighter-ts-sdk");
97
- this._signer = new WasmSignerClient({});
98
- await this._signer.initialize();
99
- await this._signer.createClient({
98
+ // Initialize signer for trading if we have an API key (reuse singleton WASM client)
99
+ if (this._apiKey && !signerReady) {
100
+ const client = await LighterAdapter.getWasmClient();
101
+ await client.createClient({
100
102
  url: this._baseUrl,
101
103
  privateKey: this._apiKey,
102
104
  chainId: this._chainId,
103
105
  apiKeyIndex: this._apiKeyIndex,
104
106
  accountIndex: this._accountIndex,
105
107
  });
108
+ this._signer = client;
109
+ }
110
+ if (this._apiKey) {
106
111
  this._readOnly = false;
107
112
  }
108
113
  // Build symbol → marketIndex map + decimals from orderBookDetails
@@ -768,11 +773,22 @@ export class LighterAdapter {
768
773
  static async getWasmClient() {
769
774
  if (LighterAdapter._wasmClient)
770
775
  return LighterAdapter._wasmClient;
771
- const { WasmSignerClient } = await import("lighter-ts-sdk");
772
- const client = new WasmSignerClient({});
773
- await client.initialize();
774
- LighterAdapter._wasmClient = client;
775
- return client;
776
+ // Prevent Go WASM runtime from killing the process on panic
777
+ const origExit = process.exit;
778
+ process.exit = ((code) => {
779
+ process.exit = origExit; // restore immediately
780
+ throw new Error(`Lighter WASM runtime exited with code ${code}`);
781
+ });
782
+ try {
783
+ const { WasmSignerClient } = await import("lighter-ts-sdk");
784
+ const client = new WasmSignerClient({});
785
+ await client.initialize();
786
+ LighterAdapter._wasmClient = client;
787
+ return client;
788
+ }
789
+ finally {
790
+ process.exit = origExit;
791
+ }
776
792
  }
777
793
  /**
778
794
  * Generate a new Lighter API key pair using the WASM signer.
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { config } from "dotenv";
3
3
  import { resolve } from "path";
4
+ import { createRequire } from "node:module";
4
5
  // Load ~/.perp/.env first (global), then CWD .env (overrides)
5
6
  config({ path: resolve(process.env.HOME || "~", ".perp", ".env") });
6
7
  config();
@@ -41,6 +42,8 @@ import { registerInitCommand, EXCHANGE_ENV_MAP, validateKey } from "./commands/i
41
42
  import { registerEnvCommands } from "./commands/env.js";
42
43
  import { loadSettings, saveSettings } from "./settings.js";
43
44
  import { setSharedApiNetwork } from "./shared-api.js";
45
+ const _require = createRequire(import.meta.url);
46
+ const _pkg = _require("../package.json");
44
47
  const program = new Command();
45
48
  // Resolve default exchange from settings (fallback: "pacifica")
46
49
  const _settings = loadSettings();
@@ -48,7 +51,7 @@ const _defaultExchange = _settings.defaultExchange || "pacifica";
48
51
  program
49
52
  .name("perp")
50
53
  .description("Multi-DEX Perpetual Futures CLI (Pacifica, Hyperliquid, Lighter)")
51
- .version("0.3.7")
54
+ .version(_pkg.version)
52
55
  .option("-e, --exchange <exchange>", `Exchange: pacifica, hyperliquid, lighter (default: ${_defaultExchange})`, _defaultExchange)
53
56
  .option("-n, --network <network>", "Network: mainnet or testnet", "mainnet")
54
57
  .option("-k, --private-key <key>", "Private key")
@@ -7,6 +7,7 @@
7
7
  * Adapters are created lazily from environment variables.
8
8
  */
9
9
  import "dotenv/config";
10
+ import { createRequire } from "node:module";
10
11
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11
12
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
13
  import { z } from "zod";
@@ -56,7 +57,9 @@ function err(error, meta) {
56
57
  return JSON.stringify({ ok: false, error, meta }, null, 2);
57
58
  }
58
59
  // ── MCP Server ──
59
- const server = new McpServer({ name: "perp-cli", version: "0.3.7" }, { capabilities: { tools: {}, resources: {} } });
60
+ const _require = createRequire(import.meta.url);
61
+ const _pkg = _require("../package.json");
62
+ const server = new McpServer({ name: "perp-cli", version: _pkg.version }, { capabilities: { tools: {}, resources: {} } });
60
63
  // ============================================================
61
64
  // Market Data tools (read-only, no private key needed)
62
65
  // ============================================================
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "perp-cli",
3
- "version": "0.3.10",
3
+ "version": "0.3.12",
4
4
  "description": "Multi-DEX Perpetual Futures CLI - Pacifica, Hyperliquid, Lighter",
5
5
  "bin": {
6
- "perp": "./dist/index.js",
7
- "perp-mcp": "./dist/mcp-server.js"
6
+ "perp": "dist/index.js",
7
+ "perp-mcp": "dist/mcp-server.js"
8
8
  },
9
9
  "files": [
10
10
  "dist",