perp-cli 0.9.8 → 0.12.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/README.md +30 -25
- package/dist/_stderr-filter.d.ts +0 -0
- package/dist/_stderr-filter.js +30 -0
- package/dist/agent-wallet/expiry.d.ts +15 -0
- package/dist/agent-wallet/expiry.js +26 -0
- package/dist/agent-wallet/lighter-keystore.d.ts +34 -0
- package/dist/agent-wallet/lighter-keystore.js +232 -0
- package/dist/agent-wallet/passphrase.d.ts +13 -0
- package/dist/agent-wallet/passphrase.js +54 -0
- package/dist/agent-wallet/signing-strategy.d.ts +67 -0
- package/dist/agent-wallet/signing-strategy.js +51 -0
- package/dist/agent-wallet/store.d.ts +37 -0
- package/dist/agent-wallet/store.js +172 -0
- package/dist/api/public/_http.d.ts +15 -0
- package/dist/api/public/_http.js +24 -0
- package/dist/api/public/hyperliquid.js +36 -24
- package/dist/api/public/lighter.d.ts +7 -1
- package/dist/api/public/lighter.js +85 -37
- package/dist/api/public/pacifica.js +47 -18
- package/dist/bot/engine.js +23 -4
- package/dist/bot/presets.js +3 -3
- package/dist/bot/strategies/funding-arb-strategy.d.ts +0 -23
- package/dist/bot/strategies/funding-arb-strategy.js +41 -176
- package/dist/bot/strategies/funding-auto.js +2 -2
- package/dist/bridge-engine.js +102 -49
- package/dist/cli-spec.js +1 -2
- package/dist/commands/account.js +2 -500
- package/dist/commands/agent.d.ts +8 -2
- package/dist/commands/agent.js +1903 -366
- package/dist/commands/alerts.js +3 -1
- package/dist/commands/arb/index.js +37 -7
- package/dist/commands/arb-auto.js +44 -11
- package/dist/commands/arb.js +83 -34
- package/dist/commands/bot.d.ts +1 -1
- package/dist/commands/bot.js +20 -16
- package/dist/commands/bridge.d.ts +1 -1
- package/dist/commands/bridge.js +4 -4
- package/dist/commands/funds.d.ts +1 -1
- package/dist/commands/funds.js +18 -68
- package/dist/commands/jobs.d.ts +1 -1
- package/dist/commands/jobs.js +2 -2
- package/dist/commands/manage.d.ts +1 -1
- package/dist/commands/manage.js +12 -84
- package/dist/commands/plan.d.ts +1 -1
- package/dist/commands/plan.js +2 -2
- package/dist/commands/portfolio.d.ts +19 -3
- package/dist/commands/portfolio.js +747 -163
- package/dist/commands/rebalance.d.ts +1 -1
- package/dist/commands/rebalance.js +18 -12
- package/dist/commands/risk.js +2 -6
- package/dist/commands/settings.js +30 -53
- package/dist/commands/trade.js +16 -15
- package/dist/commands/wallet.d.ts +2 -1
- package/dist/commands/wallet.js +1122 -176
- package/dist/config.d.ts +9 -0
- package/dist/config.js +55 -9
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +82 -2
- package/dist/event-stream.js +12 -1
- package/dist/exchanges/aster-typed-data.d.ts +156 -0
- package/dist/exchanges/aster-typed-data.js +189 -0
- package/dist/exchanges/aster.d.ts +60 -11
- package/dist/exchanges/aster.js +278 -136
- package/dist/exchanges/hyperliquid.d.ts +14 -0
- package/dist/exchanges/hyperliquid.js +88 -34
- package/dist/exchanges/lighter-spot.js +19 -5
- package/dist/exchanges/lighter.d.ts +66 -0
- package/dist/exchanges/lighter.js +213 -31
- package/dist/exchanges/pacifica-typed-data.d.ts +75 -0
- package/dist/exchanges/pacifica-typed-data.js +74 -0
- package/dist/exchanges/pacifica.d.ts +29 -1
- package/dist/exchanges/pacifica.js +94 -6
- package/dist/funding/rates.js +59 -21
- package/dist/guardrail/contracts.d.ts +14 -0
- package/dist/guardrail/contracts.js +72 -0
- package/dist/guardrail/perp-guardrail.d.ts +21 -0
- package/dist/guardrail/perp-guardrail.js +145 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +307 -362
- package/dist/jobs.js +3 -1
- package/dist/mcp-server.js +92 -88
- package/dist/position-history.js +47 -4
- package/dist/settings.d.ts +69 -3
- package/dist/settings.js +3 -2
- package/dist/signer/index.d.ts +2 -0
- package/dist/signer/index.js +2 -0
- package/dist/signer/ows-evm.d.ts +32 -0
- package/dist/signer/ows-evm.js +86 -0
- package/dist/signer/ows-loader.d.ts +2 -0
- package/dist/signer/ows-loader.js +6 -0
- package/dist/signer/ows-solana.d.ts +25 -0
- package/dist/signer/ows-solana.js +56 -0
- package/dist/smart-order.d.ts +8 -2
- package/dist/smart-order.js +46 -11
- package/dist/strategies/funding-arb.js +29 -8
- package/dist/trade-validator.js +30 -5
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +19 -0
- package/package.json +4 -2
- package/skills/perp-cli/SKILL.md +23 -14
- package/skills/perp-cli/references/agent-operations.md +6 -4
- package/skills/perp-cli/references/commands.md +55 -34
- package/skills/perp-cli/scripts/preflight.sh +4 -4
- package/skills/perp-cli/scripts/spot-perp-scan.sh +2 -2
- package/dist/__tests__/alert-logic.test.d.ts +0 -1
- package/dist/__tests__/alert-logic.test.js +0 -107
- package/dist/__tests__/arb-auto-3dex.test.d.ts +0 -1
- package/dist/__tests__/arb-auto-3dex.test.js +0 -397
- package/dist/__tests__/arb-history-stats.test.d.ts +0 -1
- package/dist/__tests__/arb-history-stats.test.js +0 -176
- package/dist/__tests__/arb-logic.test.d.ts +0 -1
- package/dist/__tests__/arb-logic.test.js +0 -84
- package/dist/__tests__/arb-manage.test.d.ts +0 -1
- package/dist/__tests__/arb-manage.test.js +0 -253
- package/dist/__tests__/arb-new-features.test.d.ts +0 -1
- package/dist/__tests__/arb-new-features.test.js +0 -457
- package/dist/__tests__/arb-sizing.test.d.ts +0 -1
- package/dist/__tests__/arb-sizing.test.js +0 -48
- package/dist/__tests__/arb-state.test.d.ts +0 -1
- package/dist/__tests__/arb-state.test.js +0 -284
- package/dist/__tests__/arb-userflow.test.d.ts +0 -1
- package/dist/__tests__/arb-userflow.test.js +0 -945
- package/dist/__tests__/arb-utils.test.d.ts +0 -1
- package/dist/__tests__/arb-utils.test.js +0 -264
- package/dist/__tests__/bot-conditions.test.d.ts +0 -1
- package/dist/__tests__/bot-conditions.test.js +0 -341
- package/dist/__tests__/client-id-tracker.test.d.ts +0 -1
- package/dist/__tests__/client-id-tracker.test.js +0 -137
- package/dist/__tests__/commands/new-atomic-commands.test.d.ts +0 -1
- package/dist/__tests__/commands/new-atomic-commands.test.js +0 -502
- package/dist/__tests__/commands/order-intent.test.d.ts +0 -1
- package/dist/__tests__/commands/order-intent.test.js +0 -600
- package/dist/__tests__/commands/trade-commands.test.d.ts +0 -1
- package/dist/__tests__/commands/trade-commands.test.js +0 -821
- package/dist/__tests__/config.test.d.ts +0 -1
- package/dist/__tests__/config.test.js +0 -86
- package/dist/__tests__/cross-chain-margin.test.d.ts +0 -1
- package/dist/__tests__/cross-chain-margin.test.js +0 -287
- package/dist/__tests__/dex-asset-map.test.d.ts +0 -1
- package/dist/__tests__/dex-asset-map.test.js +0 -191
- package/dist/__tests__/errors.test.d.ts +0 -1
- package/dist/__tests__/errors.test.js +0 -110
- package/dist/__tests__/event-stream.test.d.ts +0 -1
- package/dist/__tests__/event-stream.test.js +0 -276
- package/dist/__tests__/exchanges/interface.test.d.ts +0 -1
- package/dist/__tests__/exchanges/interface.test.js +0 -132
- package/dist/__tests__/exchanges/mock-adapter.d.ts +0 -69
- package/dist/__tests__/exchanges/mock-adapter.js +0 -137
- package/dist/__tests__/execution-log.test.d.ts +0 -1
- package/dist/__tests__/execution-log.test.js +0 -106
- package/dist/__tests__/funding-calc.test.d.ts +0 -1
- package/dist/__tests__/funding-calc.test.js +0 -71
- package/dist/__tests__/funding-history.test.d.ts +0 -1
- package/dist/__tests__/funding-history.test.js +0 -343
- package/dist/__tests__/funding-rates.test.d.ts +0 -1
- package/dist/__tests__/funding-rates.test.js +0 -342
- package/dist/__tests__/funding.test.d.ts +0 -1
- package/dist/__tests__/funding.test.js +0 -173
- package/dist/__tests__/gap-logic.test.d.ts +0 -1
- package/dist/__tests__/gap-logic.test.js +0 -43
- package/dist/__tests__/hip3-dex.test.d.ts +0 -1
- package/dist/__tests__/hip3-dex.test.js +0 -234
- package/dist/__tests__/integration/agent-features.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/agent-features.integration.test.js +0 -553
- package/dist/__tests__/integration/atomic-commands.integration.test.d.ts +0 -13
- package/dist/__tests__/integration/atomic-commands.integration.test.js +0 -246
- package/dist/__tests__/integration/bridge-simulation.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/bridge-simulation.integration.test.js +0 -453
- package/dist/__tests__/integration/bridge-strict.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/bridge-strict.integration.test.js +0 -812
- package/dist/__tests__/integration/bridge.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/bridge.integration.test.js +0 -309
- package/dist/__tests__/integration/cli-e2e.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/cli-e2e.integration.test.js +0 -202
- package/dist/__tests__/integration/dex-arb.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/dex-arb.integration.test.js +0 -116
- package/dist/__tests__/integration/envelope-consistency.integration.test.d.ts +0 -13
- package/dist/__tests__/integration/envelope-consistency.integration.test.js +0 -205
- package/dist/__tests__/integration/hip3-dex.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/hip3-dex.integration.test.js +0 -147
- package/dist/__tests__/integration/hyperliquid.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/hyperliquid.integration.test.js +0 -79
- package/dist/__tests__/integration/lighter.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/lighter.integration.test.js +0 -53
- package/dist/__tests__/integration/new-commands-e2e.integration.test.d.ts +0 -9
- package/dist/__tests__/integration/new-commands-e2e.integration.test.js +0 -236
- package/dist/__tests__/integration/order-verification.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/order-verification.integration.test.js +0 -321
- package/dist/__tests__/integration/pacifica.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/pacifica.integration.test.js +0 -75
- package/dist/__tests__/integration/response-shapes.integration.test.d.ts +0 -1
- package/dist/__tests__/integration/response-shapes.integration.test.js +0 -278
- package/dist/__tests__/liquidity.test.d.ts +0 -1
- package/dist/__tests__/liquidity.test.js +0 -225
- package/dist/__tests__/plan-executor.test.d.ts +0 -1
- package/dist/__tests__/plan-executor.test.js +0 -314
- package/dist/__tests__/position-history.test.d.ts +0 -1
- package/dist/__tests__/position-history.test.js +0 -367
- package/dist/__tests__/retry.test.d.ts +0 -1
- package/dist/__tests__/retry.test.js +0 -310
- package/dist/__tests__/risk-assessment.test.d.ts +0 -1
- package/dist/__tests__/risk-assessment.test.js +0 -288
- package/dist/__tests__/security-adversarial.test.d.ts +0 -1
- package/dist/__tests__/security-adversarial.test.js +0 -574
- package/dist/__tests__/strategies.test.d.ts +0 -1
- package/dist/__tests__/strategies.test.js +0 -539
- package/dist/__tests__/trade-execution.test.d.ts +0 -1
- package/dist/__tests__/trade-execution.test.js +0 -129
- package/dist/__tests__/trade-validator.test.d.ts +0 -1
- package/dist/__tests__/trade-validator.test.js +0 -655
- package/dist/__tests__/utils.test.d.ts +0 -1
- package/dist/__tests__/utils.test.js +0 -76
- package/dist/arb/reconcile.d.ts +0 -28
- package/dist/arb/reconcile.js +0 -162
- package/dist/commands/alert.d.ts +0 -2
- package/dist/commands/alert.js +0 -421
- package/dist/commands/analytics.d.ts +0 -3
- package/dist/commands/analytics.js +0 -311
- package/dist/commands/arb-manage.d.ts +0 -5
- package/dist/commands/arb-manage.js +0 -5
- package/dist/commands/dashboard.d.ts +0 -3
- package/dist/commands/dashboard.js +0 -176
- package/dist/commands/deposit.d.ts +0 -4
- package/dist/commands/deposit.js +0 -573
- package/dist/commands/dex.d.ts +0 -3
- package/dist/commands/dex.js +0 -120
- package/dist/commands/env.d.ts +0 -2
- package/dist/commands/env.js +0 -136
- package/dist/commands/funding.d.ts +0 -3
- package/dist/commands/funding.js +0 -554
- package/dist/commands/gap.d.ts +0 -2
- package/dist/commands/gap.js +0 -305
- package/dist/commands/health.d.ts +0 -2
- package/dist/commands/health.js +0 -67
- package/dist/commands/multileg.d.ts +0 -16
- package/dist/commands/multileg.js +0 -174
- package/dist/commands/pnl.d.ts +0 -12
- package/dist/commands/pnl.js +0 -243
- package/dist/commands/run.d.ts +0 -3
- package/dist/commands/run.js +0 -202
- package/dist/commands/stream.d.ts +0 -5
- package/dist/commands/stream.js +0 -200
- package/dist/commands/withdraw.d.ts +0 -3
- package/dist/commands/withdraw.js +0 -187
- package/dist/exchanges/edgex.d.ts +0 -62
- package/dist/exchanges/edgex.js +0 -552
- package/dist/exchanges/nado.d.ts +0 -52
- package/dist/exchanges/nado.js +0 -223
- package/dist/funding/index.d.ts +0 -3
- package/dist/funding/index.js +0 -3
- package/dist/retry.d.ts +0 -74
- package/dist/retry.js +0 -129
- package/dist/ws/market-feed.d.ts +0 -74
- package/dist/ws/market-feed.js +0 -227
package/dist/commands/dex.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import { HyperliquidAdapter } from "../exchanges/hyperliquid.js";
|
|
3
|
-
import { printJson, jsonOk, jsonError, makeTable, formatUsd, withJsonErrors } from "../utils.js";
|
|
4
|
-
export function registerDexCommands(program, getAdapter, isJson) {
|
|
5
|
-
const dex = program.command("dex").description("HIP-3 deployed perp dex commands (Hyperliquid)");
|
|
6
|
-
// ── dex list ──
|
|
7
|
-
dex
|
|
8
|
-
.command("list")
|
|
9
|
-
.description("List all available HIP-3 deployed perp dexes")
|
|
10
|
-
.action(async () => {
|
|
11
|
-
await withJsonErrors(isJson(), async () => {
|
|
12
|
-
const adapter = await getAdapter();
|
|
13
|
-
if (!(adapter instanceof HyperliquidAdapter)) {
|
|
14
|
-
if (isJson())
|
|
15
|
-
return printJson(jsonError("INVALID_EXCHANGE", "HIP-3 dexes are only available on Hyperliquid. Use -e hyperliquid."));
|
|
16
|
-
console.error(chalk.red("\n HIP-3 dexes are only available on Hyperliquid. Use -e hyperliquid.\n"));
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const dexes = await adapter.listDeployedDexes();
|
|
20
|
-
if (isJson())
|
|
21
|
-
return printJson(jsonOk(dexes));
|
|
22
|
-
if (dexes.length === 0) {
|
|
23
|
-
console.log(chalk.gray("\n No deployed dexes found.\n"));
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
console.log(chalk.cyan.bold("\n HIP-3 Deployed Perp DEXes\n"));
|
|
27
|
-
const rows = dexes.map(d => [
|
|
28
|
-
chalk.white.bold(d.name),
|
|
29
|
-
chalk.gray(d.deployer.slice(0, 10) + "..."),
|
|
30
|
-
String(d.assets.length),
|
|
31
|
-
d.assets.slice(0, 5).join(", ") + (d.assets.length > 5 ? ` +${d.assets.length - 5}` : ""),
|
|
32
|
-
]);
|
|
33
|
-
console.log(makeTable(["DEX", "Deployer", "Assets", "Markets"], rows));
|
|
34
|
-
console.log(chalk.gray(`\n Use --dex <name> to trade on a deployed dex.\n`));
|
|
35
|
-
console.log(chalk.gray(` Example: perp -e hyperliquid --dex xyz market list\n`));
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
// ── dex markets <dex-name> ──
|
|
39
|
-
dex
|
|
40
|
-
.command("markets <dexName>")
|
|
41
|
-
.description("List all markets on a specific HIP-3 dex")
|
|
42
|
-
.action(async (dexName) => {
|
|
43
|
-
await withJsonErrors(isJson(), async () => {
|
|
44
|
-
const adapter = await getAdapter();
|
|
45
|
-
if (!(adapter instanceof HyperliquidAdapter)) {
|
|
46
|
-
if (isJson())
|
|
47
|
-
return printJson(jsonError("INVALID_EXCHANGE", "HIP-3 dexes are only available on Hyperliquid. Use -e hyperliquid."));
|
|
48
|
-
console.error(chalk.red("\n HIP-3 dexes are only available on Hyperliquid. Use -e hyperliquid.\n"));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
// Temporarily switch dex, fetch markets, then restore
|
|
52
|
-
const prevDex = adapter.dex;
|
|
53
|
-
adapter.setDex(dexName);
|
|
54
|
-
try {
|
|
55
|
-
const markets = await adapter.getMarkets();
|
|
56
|
-
if (isJson())
|
|
57
|
-
return printJson(jsonOk({ dex: dexName, markets }));
|
|
58
|
-
if (markets.length === 0) {
|
|
59
|
-
console.log(chalk.gray(`\n No markets found on dex "${dexName}".\n`));
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
console.log(chalk.cyan.bold(`\n ${dexName.toUpperCase()} DEX Markets\n`));
|
|
63
|
-
const rows = markets.map(m => [
|
|
64
|
-
chalk.white.bold(m.symbol),
|
|
65
|
-
`$${formatUsd(m.markPrice)}`,
|
|
66
|
-
m.fundingRate !== "0" ? `${(Number(m.fundingRate) * 100).toFixed(4)}%` : chalk.gray("-"),
|
|
67
|
-
`$${formatUsd(m.volume24h)}`,
|
|
68
|
-
`$${formatUsd(m.openInterest)}`,
|
|
69
|
-
`${m.maxLeverage}x`,
|
|
70
|
-
]);
|
|
71
|
-
console.log(makeTable(["Symbol", "Mark Price", "Funding", "24h Volume", "OI", "Max Lev"], rows));
|
|
72
|
-
console.log(chalk.gray(`\n Trade: perp -e hyperliquid --dex ${dexName} trade market <symbol> <side> <size>\n`));
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
adapter.setDex(prevDex);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
// ── dex balance <dex-name> ──
|
|
80
|
-
dex
|
|
81
|
-
.command("balance <dexName>")
|
|
82
|
-
.description("Show balance on a specific HIP-3 dex")
|
|
83
|
-
.action(async (dexName) => {
|
|
84
|
-
await withJsonErrors(isJson(), async () => {
|
|
85
|
-
const adapter = await getAdapter();
|
|
86
|
-
if (!(adapter instanceof HyperliquidAdapter)) {
|
|
87
|
-
if (isJson())
|
|
88
|
-
return printJson(jsonError("INVALID_EXCHANGE", "HIP-3 dexes are only available on Hyperliquid. Use -e hyperliquid."));
|
|
89
|
-
console.error(chalk.red("\n HIP-3 dexes are only available on Hyperliquid. Use -e hyperliquid.\n"));
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
const prevDex = adapter.dex;
|
|
93
|
-
adapter.setDex(dexName);
|
|
94
|
-
try {
|
|
95
|
-
const [balance, positions] = await Promise.all([
|
|
96
|
-
adapter.getBalance(),
|
|
97
|
-
adapter.getPositions(),
|
|
98
|
-
]);
|
|
99
|
-
if (isJson())
|
|
100
|
-
return printJson(jsonOk({ dex: dexName, balance, positions }));
|
|
101
|
-
console.log(chalk.cyan.bold(`\n ${dexName.toUpperCase()} DEX Balance\n`));
|
|
102
|
-
console.log(` Equity: $${formatUsd(balance.equity)}`);
|
|
103
|
-
console.log(` Available: $${formatUsd(balance.available)}`);
|
|
104
|
-
console.log(` Margin Used: $${formatUsd(balance.marginUsed)}`);
|
|
105
|
-
console.log(` uPnL: $${formatUsd(balance.unrealizedPnl)}`);
|
|
106
|
-
if (positions.length > 0) {
|
|
107
|
-
console.log(chalk.white.bold("\n Positions:"));
|
|
108
|
-
for (const p of positions) {
|
|
109
|
-
const color = p.side === "long" ? chalk.green : chalk.red;
|
|
110
|
-
console.log(` ${color(p.side.toUpperCase().padEnd(5))} ${chalk.white(p.symbol.padEnd(16))} ${p.size.padEnd(10)} entry: $${Number(p.entryPrice).toFixed(2)} pnl: $${Number(p.unrealizedPnl).toFixed(2)}`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
console.log();
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
adapter.setDex(prevDex);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
}
|
package/dist/commands/env.d.ts
DELETED
package/dist/commands/env.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import { printJson, jsonOk } from "../utils.js";
|
|
3
|
-
import { ENV_FILE, loadEnvFile, setEnvVar, EXCHANGE_ENV_MAP, validateKey } from "./init.js";
|
|
4
|
-
// Resolve exchange alias → env var key
|
|
5
|
-
function resolveEnvKey(nameOrKey) {
|
|
6
|
-
// Direct env var name
|
|
7
|
-
const upper = nameOrKey.toUpperCase();
|
|
8
|
-
for (const info of Object.values(EXCHANGE_ENV_MAP)) {
|
|
9
|
-
if (info.envKey === upper)
|
|
10
|
-
return { envKey: info.envKey, chain: info.chain };
|
|
11
|
-
}
|
|
12
|
-
// Exchange name alias
|
|
13
|
-
const info = EXCHANGE_ENV_MAP[nameOrKey.toLowerCase()];
|
|
14
|
-
if (info)
|
|
15
|
-
return { envKey: info.envKey, chain: info.chain };
|
|
16
|
-
// Common aliases
|
|
17
|
-
const aliases = { hl: "hyperliquid", pac: "pacifica", lt: "lighter" };
|
|
18
|
-
const aliased = aliases[nameOrKey.toLowerCase()];
|
|
19
|
-
if (aliased)
|
|
20
|
-
return resolveEnvKey(aliased);
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
export function registerEnvCommands(program, isJson) {
|
|
24
|
-
const env = program.command("env").description("Manage ~/.perp/.env configuration");
|
|
25
|
-
// ── perp env show ──
|
|
26
|
-
env
|
|
27
|
-
.command("show")
|
|
28
|
-
.description("Show current configuration")
|
|
29
|
-
.action(async () => {
|
|
30
|
-
const stored = loadEnvFile();
|
|
31
|
-
const entries = [];
|
|
32
|
-
for (const [exchange, info] of Object.entries(EXCHANGE_ENV_MAP)) {
|
|
33
|
-
const fromFile = stored[info.envKey];
|
|
34
|
-
const fromEnv = process.env[info.envKey];
|
|
35
|
-
if (fromFile) {
|
|
36
|
-
entries.push({ name: exchange, chain: info.chain, key: fromFile, source: "~/.perp/.env" });
|
|
37
|
-
}
|
|
38
|
-
else if (fromEnv) {
|
|
39
|
-
entries.push({ name: exchange, chain: info.chain, key: fromEnv, source: "environment" });
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// Derive addresses
|
|
43
|
-
const results = [];
|
|
44
|
-
for (const entry of entries) {
|
|
45
|
-
const { valid, address } = await validateKey(entry.chain, entry.key);
|
|
46
|
-
results.push({ name: entry.name, address: valid ? address : "(invalid key)", source: entry.source });
|
|
47
|
-
}
|
|
48
|
-
if (isJson()) {
|
|
49
|
-
const data = results.map((r) => ({ exchange: r.name, address: r.address, source: r.source }));
|
|
50
|
-
return printJson(jsonOk({ envFile: ENV_FILE, exchanges: data }));
|
|
51
|
-
}
|
|
52
|
-
console.log(chalk.cyan.bold("\n perp-cli Configuration\n"));
|
|
53
|
-
console.log(` File: ${chalk.gray(ENV_FILE)}\n`);
|
|
54
|
-
if (results.length === 0) {
|
|
55
|
-
console.log(chalk.gray(" No keys configured. Run 'perp init' or 'perp env set <exchange> <key>'\n"));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
for (const { name, address, source } of results) {
|
|
59
|
-
console.log(` ${chalk.cyan(name.padEnd(14))} ${chalk.green(address)} ${chalk.gray(source)}`);
|
|
60
|
-
}
|
|
61
|
-
console.log();
|
|
62
|
-
});
|
|
63
|
-
// ── perp env set <exchange|key> <value> ──
|
|
64
|
-
env
|
|
65
|
-
.command("set <name> <value>")
|
|
66
|
-
.description("Set a key (exchange name or env var name)")
|
|
67
|
-
.action(async (name, value) => {
|
|
68
|
-
const resolved = resolveEnvKey(name);
|
|
69
|
-
if (resolved) {
|
|
70
|
-
// Validate the key
|
|
71
|
-
const { valid, address } = await validateKey(resolved.chain, value);
|
|
72
|
-
if (!valid) {
|
|
73
|
-
if (isJson()) {
|
|
74
|
-
const { jsonError } = await import("../utils.js");
|
|
75
|
-
return printJson(jsonError("INVALID_PARAMS", `Invalid ${resolved.chain} private key`));
|
|
76
|
-
}
|
|
77
|
-
console.error(chalk.red(`\n Invalid ${resolved.chain} private key.\n`));
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
const normalized = resolved.chain === "evm"
|
|
81
|
-
? (value.startsWith("0x") ? value : `0x${value}`)
|
|
82
|
-
: value;
|
|
83
|
-
setEnvVar(resolved.envKey, normalized);
|
|
84
|
-
if (isJson())
|
|
85
|
-
return printJson(jsonOk({ key: resolved.envKey, address, file: ENV_FILE }));
|
|
86
|
-
console.log(chalk.green(`\n ${resolved.envKey} set.`));
|
|
87
|
-
console.log(` Address: ${chalk.gray(address)}`);
|
|
88
|
-
console.log(` File: ${chalk.gray("~/.perp/.env")}\n`);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
// Raw env var (e.g. LIGHTER_API_KEY, custom vars)
|
|
92
|
-
setEnvVar(name, value);
|
|
93
|
-
if (isJson())
|
|
94
|
-
return printJson(jsonOk({ key: name, file: ENV_FILE }));
|
|
95
|
-
console.log(chalk.green(`\n ${name} set.`));
|
|
96
|
-
console.log(` File: ${chalk.gray("~/.perp/.env")}\n`);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
// ── perp env remove <name> ──
|
|
100
|
-
env
|
|
101
|
-
.command("remove <name>")
|
|
102
|
-
.description("Remove a key from ~/.perp/.env")
|
|
103
|
-
.action(async (name) => {
|
|
104
|
-
const resolved = resolveEnvKey(name);
|
|
105
|
-
const envKey = resolved?.envKey || name;
|
|
106
|
-
const env = loadEnvFile();
|
|
107
|
-
if (!(envKey in env)) {
|
|
108
|
-
if (isJson()) {
|
|
109
|
-
const { jsonError } = await import("../utils.js");
|
|
110
|
-
return printJson(jsonError("NOT_FOUND", `${envKey} not found in ~/.perp/.env`));
|
|
111
|
-
}
|
|
112
|
-
console.log(chalk.gray(`\n ${envKey} not found in ~/.perp/.env\n`));
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
delete env[envKey];
|
|
116
|
-
// Rewrite file
|
|
117
|
-
const { writeFileSync } = await import("fs");
|
|
118
|
-
const lines = ["# perp-cli configuration", "# Generated by 'perp init' — edit freely", ""];
|
|
119
|
-
for (const [k, v] of Object.entries(env))
|
|
120
|
-
lines.push(`${k}=${v}`);
|
|
121
|
-
lines.push("");
|
|
122
|
-
writeFileSync(ENV_FILE, lines.join("\n"), { mode: 0o600 });
|
|
123
|
-
if (isJson())
|
|
124
|
-
return printJson(jsonOk({ removed: envKey }));
|
|
125
|
-
console.log(chalk.yellow(`\n ${envKey} removed from ~/.perp/.env\n`));
|
|
126
|
-
});
|
|
127
|
-
// ── perp env path ──
|
|
128
|
-
env
|
|
129
|
-
.command("path")
|
|
130
|
-
.description("Print env file path")
|
|
131
|
-
.action(() => {
|
|
132
|
-
if (isJson())
|
|
133
|
-
return printJson(jsonOk({ path: ENV_FILE }));
|
|
134
|
-
console.log(ENV_FILE);
|
|
135
|
-
});
|
|
136
|
-
}
|