perp-cli 0.14.2 → 0.15.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 +152 -13
- package/dist/agent-wallet/store.d.ts +3 -2
- package/dist/agent-wallet/store.js +2 -2
- package/dist/api/public/hyperliquid.js +4 -0
- package/dist/api/public/pacifica.js +83 -13
- package/dist/api/public/urls.d.ts +2 -0
- package/dist/api/public/urls.js +3 -0
- package/dist/arb/utils.d.ts +1 -2
- package/dist/arb/utils.js +1 -2
- package/dist/bot/apex/pulse.js +3 -0
- package/dist/bot/apex/radar.js +2 -1
- package/dist/bot/engine.d.ts +10 -1
- package/dist/bot/engine.js +14 -6
- package/dist/bot/indicators.d.ts +7 -0
- package/dist/bot/indicators.js +16 -0
- package/dist/bot/perp-order.d.ts +4 -4
- package/dist/bot/perp-order.js +5 -5
- package/dist/bot/quarantine.d.ts +1 -1
- package/dist/bot/quarantine.js +1 -1
- package/dist/bot/strategies/apex-strategy.js +3 -2
- package/dist/bot/strategies/engine-mm.js +6 -5
- package/dist/bot/strategies/funding-arb-strategy.js +9 -9
- package/dist/bot/strategies/funding-arb-utils.d.ts +15 -2
- package/dist/bot/strategies/funding-arb-utils.js +43 -24
- package/dist/bot/strategies/funding-auto.js +2 -2
- package/dist/bot/strategies/liquidation-mm.d.ts +1 -0
- package/dist/bot/strategies/liquidation-mm.js +8 -2
- package/dist/bot/strategies/momentum-breakout.d.ts +1 -0
- package/dist/bot/strategies/momentum-breakout.js +11 -3
- package/dist/bot/strategies/spot-perp-arb-strategy.js +23 -12
- package/dist/bot/strategies/spot-perp-executor.d.ts +1 -1
- package/dist/bot/strategies/spot-perp-executor.js +1 -1
- package/dist/bot/strategy-types.d.ts +2 -1
- package/dist/bot/tui/BotDashboard.d.ts +1 -1
- package/dist/bot/tui/BotDashboard.js +1 -1
- package/dist/cache.js +12 -6
- package/dist/cli-program.d.ts +15 -0
- package/dist/cli-program.js +125 -5
- package/dist/commands/agent-import.d.ts +7 -0
- package/dist/commands/agent-import.js +30 -1
- package/dist/commands/agent.d.ts +6 -3
- package/dist/commands/agent.js +160 -12
- package/dist/commands/arb/index.js +4 -4
- package/dist/commands/arb-auto.js +21 -17
- package/dist/commands/arb.d.ts +12 -0
- package/dist/commands/arb.js +61 -143
- package/dist/commands/bot.js +1 -1
- package/dist/commands/builder.js +1 -1
- package/dist/commands/funds.js +113 -3
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +27 -7
- package/dist/commands/manage.js +23 -21
- package/dist/commands/market.js +168 -36
- package/dist/commands/options.d.ts +9 -0
- package/dist/commands/options.js +134 -0
- package/dist/commands/pacifica-earn.d.ts +5 -0
- package/dist/commands/pacifica-earn.js +468 -0
- package/dist/commands/pacifica-orders.d.ts +14 -0
- package/dist/commands/pacifica-orders.js +142 -0
- package/dist/commands/portfolio.js +32 -47
- package/dist/commands/rebalance.d.ts +1 -0
- package/dist/commands/rebalance.js +15 -0
- package/dist/commands/risk.d.ts +11 -2
- package/dist/commands/risk.js +39 -44
- package/dist/commands/trade.d.ts +1 -0
- package/dist/commands/trade.js +63 -58
- package/dist/commands/wallet.js +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.js +15 -4
- package/dist/constants.js +6 -0
- package/dist/dashboard/server.js +1 -1
- package/dist/dashboard/ui.js +1 -1
- package/dist/errors.d.ts +24 -1
- package/dist/errors.js +25 -3
- package/dist/exchanges/arcus/adapter.d.ts +7 -7
- package/dist/exchanges/arcus/adapter.js +12 -12
- package/dist/exchanges/arcus/agent.d.ts +1 -1
- package/dist/exchanges/arcus/agent.js +1 -1
- package/dist/exchanges/arcus/client.js +1 -1
- package/dist/exchanges/arcus/signing.d.ts +2 -3
- package/dist/exchanges/arcus/signing.js +1 -1
- package/dist/exchanges/arcus/spot-chain.d.ts +1 -1
- package/dist/exchanges/arcus/spot-chain.js +1 -1
- package/dist/exchanges/arcus/spot-router.d.ts +1 -1
- package/dist/exchanges/arcus/spot-router.js +2 -2
- package/dist/exchanges/arcus/spot.d.ts +2 -3
- package/dist/exchanges/arcus/spot.js +2 -3
- package/dist/exchanges/aster-spot.d.ts +3 -3
- package/dist/exchanges/aster-spot.js +6 -9
- package/dist/exchanges/aster-typed-data.d.ts +1 -1
- package/dist/exchanges/aster-typed-data.js +1 -1
- package/dist/exchanges/aster.d.ts +9 -4
- package/dist/exchanges/aster.js +125 -55
- package/dist/exchanges/builder-fee.d.ts +1 -1
- package/dist/exchanges/builder-fee.js +13 -2
- package/dist/exchanges/canonical-symbols.d.ts +1 -2
- package/dist/exchanges/canonical-symbols.js +26 -2
- package/dist/exchanges/derive/client.d.ts +37 -0
- package/dist/exchanges/derive/client.js +135 -0
- package/dist/exchanges/derive/options.d.ts +68 -0
- package/dist/exchanges/derive/options.js +360 -0
- package/dist/exchanges/extended/adapter.d.ts +82 -0
- package/dist/exchanges/extended/adapter.js +179 -0
- package/dist/exchanges/extended/client.d.ts +38 -0
- package/dist/exchanges/extended/client.js +88 -0
- package/dist/exchanges/extended/public.d.ts +130 -0
- package/dist/exchanges/extended/public.js +429 -0
- package/dist/exchanges/grvt/adapter.d.ts +86 -0
- package/dist/exchanges/grvt/adapter.js +206 -0
- package/dist/exchanges/grvt/client.d.ts +25 -0
- package/dist/exchanges/grvt/client.js +86 -0
- package/dist/exchanges/grvt/public.d.ts +151 -0
- package/dist/exchanges/grvt/public.js +438 -0
- package/dist/exchanges/hyperliquid-spot.d.ts +1 -1
- package/dist/exchanges/hyperliquid-spot.js +5 -5
- package/dist/exchanges/hyperliquid.d.ts +22 -16
- package/dist/exchanges/hyperliquid.js +80 -55
- package/dist/exchanges/index.d.ts +1 -1
- package/dist/exchanges/index.js +1 -1
- package/dist/exchanges/interface.d.ts +97 -8
- package/dist/exchanges/interface.js +19 -2
- package/dist/exchanges/ioc-outcome.d.ts +1 -1
- package/dist/exchanges/ioc-outcome.js +1 -1
- package/dist/exchanges/legacy-trading-v2.d.ts +2 -2
- package/dist/exchanges/legacy-trading-v2.js +7 -2
- package/dist/exchanges/lighter-public.d.ts +2 -2
- package/dist/exchanges/lighter-public.js +2 -2
- package/dist/exchanges/lighter-signer.d.ts +1 -1
- package/dist/exchanges/lighter-signer.js +1 -1
- package/dist/exchanges/lighter-spot.d.ts +3 -4
- package/dist/exchanges/lighter-spot.js +6 -7
- package/dist/exchanges/lighter.d.ts +11 -11
- package/dist/exchanges/lighter.js +28 -14
- package/dist/exchanges/ondo/adapter.d.ts +5 -6
- package/dist/exchanges/ondo/adapter.js +16 -14
- package/dist/exchanges/ondo/agent.d.ts +1 -1
- package/dist/exchanges/ondo/agent.js +1 -1
- package/dist/exchanges/ondo/client.d.ts +1 -1
- package/dist/exchanges/ondo/client.js +2 -2
- package/dist/exchanges/ondo/public.d.ts +8 -1
- package/dist/exchanges/ondo/public.js +13 -2
- package/dist/exchanges/ondo/spot.d.ts +2 -2
- package/dist/exchanges/ondo/spot.js +3 -3
- package/dist/exchanges/options-interface.d.ts +158 -0
- package/dist/exchanges/options-interface.js +17 -0
- package/dist/exchanges/options-venues.d.ts +12 -0
- package/dist/exchanges/options-venues.js +35 -0
- package/dist/exchanges/pacifica-atomic.d.ts +211 -0
- package/dist/exchanges/pacifica-atomic.js +440 -0
- package/dist/exchanges/pacifica-decimal.d.ts +10 -0
- package/dist/exchanges/pacifica-decimal.js +51 -0
- package/dist/exchanges/pacifica-presigned.d.ts +53 -0
- package/dist/exchanges/pacifica-presigned.js +141 -0
- package/dist/exchanges/pacifica-print.d.ts +200 -0
- package/dist/exchanges/pacifica-print.js +417 -0
- package/dist/exchanges/pacifica-spot.d.ts +2 -2
- package/dist/exchanges/pacifica-spot.js +3 -3
- package/dist/exchanges/pacifica-typed-data.d.ts +1 -1
- package/dist/exchanges/pacifica-typed-data.js +1 -1
- package/dist/exchanges/pacifica-vaults.d.ts +121 -0
- package/dist/exchanges/pacifica-vaults.js +264 -0
- package/dist/exchanges/pacifica.d.ts +32 -5
- package/dist/exchanges/pacifica.js +114 -48
- package/dist/exchanges/precision.d.ts +3 -1
- package/dist/exchanges/precision.js +9 -2
- package/dist/exchanges/qfex/adapter.d.ts +18 -5
- package/dist/exchanges/qfex/adapter.js +32 -12
- package/dist/exchanges/qfex/agent.d.ts +1 -1
- package/dist/exchanges/qfex/agent.js +1 -1
- package/dist/exchanges/qfex/client.d.ts +1 -1
- package/dist/exchanges/qfex/client.js +1 -1
- package/dist/exchanges/qfex/errors.d.ts +1 -1
- package/dist/exchanges/qfex/errors.js +2 -2
- package/dist/exchanges/qfex/public.d.ts +3 -3
- package/dist/exchanges/qfex/public.js +3 -3
- package/dist/exchanges/qfex/signing.d.ts +2 -2
- package/dist/exchanges/qfex/signing.js +4 -5
- package/dist/exchanges/qfex/ws-transport.d.ts +2 -2
- package/dist/exchanges/qfex/ws-transport.js +3 -3
- package/dist/exchanges/rate-limiter.d.ts +1 -1
- package/dist/exchanges/rate-limiter.js +5 -2
- package/dist/exchanges/registry.d.ts +1 -1
- package/dist/exchanges/registry.js +1 -1
- package/dist/exchanges/risex/adapter.d.ts +148 -0
- package/dist/exchanges/risex/adapter.js +796 -0
- package/dist/exchanges/risex/agent.d.ts +154 -0
- package/dist/exchanges/risex/agent.js +384 -0
- package/dist/exchanges/risex/client.d.ts +47 -0
- package/dist/exchanges/risex/client.js +174 -0
- package/dist/exchanges/risex/nonce.d.ts +43 -0
- package/dist/exchanges/risex/nonce.js +212 -0
- package/dist/exchanges/risex/public.d.ts +64 -0
- package/dist/exchanges/risex/public.js +150 -0
- package/dist/exchanges/risex/session.d.ts +71 -0
- package/dist/exchanges/risex/session.js +171 -0
- package/dist/exchanges/risex/typed-data.d.ts +173 -0
- package/dist/exchanges/risex/typed-data.js +240 -0
- package/dist/exchanges/risex/units.d.ts +29 -0
- package/dist/exchanges/risex/units.js +104 -0
- package/dist/exchanges/slippage.d.ts +1 -1
- package/dist/exchanges/slippage.js +1 -1
- package/dist/exchanges/spot-factory.d.ts +3 -3
- package/dist/exchanges/spot-factory.js +7 -7
- package/dist/exchanges/spot-interface.d.ts +5 -5
- package/dist/exchanges/spot-interface.js +2 -2
- package/dist/exchanges/spot-result.d.ts +3 -3
- package/dist/exchanges/spot-result.js +3 -3
- package/dist/exchanges/trading-v2.d.ts +3 -3
- package/dist/exchanges/trading-v2.js +9 -6
- package/dist/exchanges/txflow/adapter.d.ts +54 -0
- package/dist/exchanges/txflow/adapter.js +118 -0
- package/dist/exchanges/txflow/client.d.ts +47 -0
- package/dist/exchanges/txflow/client.js +153 -0
- package/dist/exchanges/txflow/public.d.ts +76 -0
- package/dist/exchanges/txflow/public.js +284 -0
- package/dist/exchanges/unknown-symbol.d.ts +29 -0
- package/dist/exchanges/unknown-symbol.js +51 -0
- package/dist/exchanges/variational/adapter.d.ts +71 -0
- package/dist/exchanges/variational/adapter.js +137 -0
- package/dist/exchanges/variational/client.d.ts +21 -0
- package/dist/exchanges/variational/client.js +66 -0
- package/dist/exchanges/variational/public.d.ts +126 -0
- package/dist/exchanges/variational/public.js +430 -0
- package/dist/exchanges/venue-types.d.ts +6 -7
- package/dist/exchanges/venue-types.js +2 -2
- package/dist/exchanges/venue.d.ts +51 -8
- package/dist/exchanges/venue.js +54 -4
- package/dist/exchanges/venues/arcus.d.ts +1 -2
- package/dist/exchanges/venues/arcus.js +5 -4
- package/dist/exchanges/venues/aster.d.ts +2 -2
- package/dist/exchanges/venues/aster.js +6 -4
- package/dist/exchanges/venues/create-helpers.d.ts +1 -1
- package/dist/exchanges/venues/create-helpers.js +3 -3
- package/dist/exchanges/venues/extended.d.ts +21 -0
- package/dist/exchanges/venues/extended.js +96 -0
- package/dist/exchanges/venues/grvt.d.ts +30 -0
- package/dist/exchanges/venues/grvt.js +98 -0
- package/dist/exchanges/venues/hyperliquid.d.ts +2 -2
- package/dist/exchanges/venues/hyperliquid.js +10 -8
- package/dist/exchanges/venues/index.d.ts +7 -2
- package/dist/exchanges/venues/index.js +8 -2
- package/dist/exchanges/venues/lighter-family.d.ts +7 -9
- package/dist/exchanges/venues/lighter-family.js +9 -11
- package/dist/exchanges/venues/lighter-rh.d.ts +2 -2
- package/dist/exchanges/venues/lighter-rh.js +7 -5
- package/dist/exchanges/venues/lighter.d.ts +1 -1
- package/dist/exchanges/venues/lighter.js +5 -3
- package/dist/exchanges/venues/ondo.d.ts +1 -1
- package/dist/exchanges/venues/ondo.js +5 -3
- package/dist/exchanges/venues/pacifica.d.ts +2 -2
- package/dist/exchanges/venues/pacifica.js +6 -4
- package/dist/exchanges/venues/qfex.d.ts +1 -1
- package/dist/exchanges/venues/qfex.js +4 -2
- package/dist/exchanges/venues/risex-release.d.ts +14 -0
- package/dist/exchanges/venues/risex-release.js +14 -0
- package/dist/exchanges/venues/risex.d.ts +31 -0
- package/dist/exchanges/venues/risex.js +116 -0
- package/dist/exchanges/venues/txflow.d.ts +18 -0
- package/dist/exchanges/venues/txflow.js +77 -0
- package/dist/exchanges/venues/variational.d.ts +21 -0
- package/dist/exchanges/venues/variational.js +85 -0
- package/dist/execution-log.d.ts +1 -1
- package/dist/funding/legacy-public.d.ts +1 -1
- package/dist/funding/legacy-public.js +9 -4
- package/dist/funding/normalize.d.ts +1 -1
- package/dist/funding/normalize.js +1 -1
- package/dist/funding/rates.d.ts +44 -4
- package/dist/funding/rates.js +56 -12
- package/dist/index.js +7 -6
- package/dist/jobs.d.ts +1 -0
- package/dist/jobs.js +25 -1
- package/dist/landing.d.ts +2 -0
- package/dist/landing.js +1 -1
- package/dist/mcp-pacifica-earn.d.ts +9 -0
- package/dist/mcp-pacifica-earn.js +58 -0
- package/dist/mcp-server.js +113 -59
- package/dist/pacifica/client.d.ts +67 -4
- package/dist/pacifica/client.js +170 -8
- package/dist/pacifica/rate-limit.d.ts +144 -0
- package/dist/pacifica/rate-limit.js +267 -0
- package/dist/pacifica/types/order.d.ts +2 -1
- package/dist/plan-executor.js +7 -2
- package/dist/rebalance.js +1 -1
- package/dist/risk.d.ts +2 -1
- package/dist/risk.js +2 -4
- package/dist/settings.d.ts +32 -3
- package/dist/signer/ows-evm.d.ts +1 -1
- package/dist/signer/ows-evm.js +1 -1
- package/dist/smart-order.d.ts +1 -1
- package/dist/smart-order.js +1 -1
- package/dist/strategies/funding-arb.d.ts +1 -1
- package/dist/strategies/funding-arb.js +1 -1
- package/dist/trade-validator.d.ts +1 -1
- package/dist/trade-validator.js +9 -4
- package/dist/utils.d.ts +12 -3
- package/dist/utils.js +11 -3
- package/dist/venue-health.d.ts +40 -0
- package/dist/venue-health.js +75 -0
- package/dist/withdraw-gate.d.ts +1 -1
- package/dist/withdraw-gate.js +1 -1
- package/dist/ws/index.d.ts +959 -0
- package/dist/ws/index.js +4295 -0
- package/dist/ws/node.d.ts +975 -0
- package/dist/ws/node.js +4366 -0
- package/dist/ws/pacifica-instrument.d.ts +8 -0
- package/dist/ws/pacifica-instrument.js +8 -0
- package/dist/ws-cli/credentials.d.ts +62 -0
- package/dist/ws-cli/credentials.js +126 -0
- package/package.json +58 -10
- package/skills/perp-cli/SKILL.md +62 -9
- package/skills/perp-cli/references/agent-operations.md +7 -0
- package/skills/perp-cli/references/commands.md +76 -5
- package/skills/perp-cli/references/ws-library.md +492 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { makeTable, formatUsd, formatPnl, printJson, jsonOk, jsonError, withJsonErrors } from "../utils.js";
|
|
3
3
|
import { isDexCapable } from "../exchanges/capabilities.js";
|
|
4
|
-
import { getVenue, listVenuesWithRole, tryResolveVenueId } from "../exchanges/venue.js";
|
|
4
|
+
import { getVenue, listVenuesWithRole, roleUnsupported, tryResolveVenueId } from "../exchanges/venue.js";
|
|
5
5
|
import { PerpError } from "../errors.js";
|
|
6
6
|
import "../exchanges/venues/index.js";
|
|
7
7
|
import { listConfiguredAccountVenues } from "../config.js";
|
|
@@ -9,6 +9,7 @@ import { HYPERLIQUID_API_URL } from "../api/public/urls.js";
|
|
|
9
9
|
import { fetchValuedSpotBalances, getSpotAdapter, spotSharesPerpMargin, withSpotTimeout } from "../exchanges/spot-factory.js";
|
|
10
10
|
import { scrubSecretEnv } from "../secret-env.js";
|
|
11
11
|
import { networkOf } from "../cli-flags.js";
|
|
12
|
+
import { probeVenueHealth } from "../venue-health.js";
|
|
12
13
|
// ── Types ──────────────────────────────────────────────────────────────────
|
|
13
14
|
/** Venues with an account API (market-data-only venues are excluded). */
|
|
14
15
|
function accountVenueIds() {
|
|
@@ -51,6 +52,12 @@ function validateExchanges(list) {
|
|
|
51
52
|
const valid = accountVenueIds();
|
|
52
53
|
// Aliases (hl, pac, lt, lrh, ast, …) resolve through the venue registry, like every other command.
|
|
53
54
|
const ids = list.map(s => tryResolveVenueId(s) ?? s.toLowerCase());
|
|
55
|
+
// A registered market-data-only venue (TxFlow) is a capability refusal, not an unknown name.
|
|
56
|
+
for (const id of ids) {
|
|
57
|
+
const known = tryResolveVenueId(id);
|
|
58
|
+
if (known !== null && !valid.includes(known))
|
|
59
|
+
throw roleUnsupported(getVenue(known), "account");
|
|
60
|
+
}
|
|
54
61
|
const unknown = ids.filter(e => !valid.includes(e));
|
|
55
62
|
if (unknown.length > 0) {
|
|
56
63
|
throw new PerpError("INVALID_PARAMS", `Unknown exchange: ${unknown.join(", ")}`, { remediation: `Use one of: ${valid.join(", ")} (or an alias such as hl, pac, lt, lrh, ast)` });
|
|
@@ -178,7 +185,7 @@ async function fetchExchangeEntry(exName, getAdapter) {
|
|
|
178
185
|
adapter.getOpenOrders(),
|
|
179
186
|
adapter.getFundingPayments(200).then((rows) => ({ rows, error: null }), (e) => ({ rows: null, error: e instanceof Error ? e.message : String(e) })),
|
|
180
187
|
]);
|
|
181
|
-
// Spot balances for every venue with def.spot
|
|
188
|
+
// Spot balances for every venue with def.spot. Failures are surfaced on
|
|
182
189
|
// stderr (the perp snapshot is still reported); unpriced tokens are excluded + warned.
|
|
183
190
|
let spot = [];
|
|
184
191
|
let isUnified = false;
|
|
@@ -205,7 +212,7 @@ async function fetchExchangeEntry(exName, getAdapter) {
|
|
|
205
212
|
const funding24h = fundingPayments.rows === null
|
|
206
213
|
? null
|
|
207
214
|
: fundingPayments.rows.filter(f => f.time >= cutoff24h).reduce((sum, f) => sum + Number(f.payment), 0);
|
|
208
|
-
// Shared balances (Pacifica USDC, HL unified USDC) are already in perp equity
|
|
215
|
+
// Shared balances (Pacifica USDC, HL unified USDC) are already in perp equity.
|
|
209
216
|
const nonUsdcSpotValue = spot.filter(b => !b.shared).reduce((s, b) => s + b.valueUsd, 0);
|
|
210
217
|
return {
|
|
211
218
|
name: exName,
|
|
@@ -288,42 +295,12 @@ function buildTotals(entries) {
|
|
|
288
295
|
}
|
|
289
296
|
// ── Health check (no balance fetches) ──────────────────────────────────────
|
|
290
297
|
async function runHealth(exchangeList, network) {
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
const start = Date.now();
|
|
294
|
-
try {
|
|
295
|
-
const res = await fetch("https://fapi.asterdex.com/fapi/v1/time");
|
|
296
|
-
return { ok: res.ok, latencyMs: Date.now() - start, status: res.status };
|
|
297
|
-
}
|
|
298
|
-
catch {
|
|
299
|
-
return { ok: false, latencyMs: Date.now() - start, status: 0 };
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
const pingMap = {
|
|
303
|
-
pacifica: pingPacifica,
|
|
304
|
-
hyperliquid: pingHyperliquid,
|
|
305
|
-
lighter: pingLighter,
|
|
306
|
-
aster: pingAster,
|
|
307
|
-
};
|
|
298
|
+
// The same probe as `perp health` and the MCP health_check, over the selected venues.
|
|
299
|
+
const h = await probeVenueHealth(network, exchangeList);
|
|
308
300
|
const exchanges = {};
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
if (!fn) {
|
|
313
|
-
// No dedicated ping helper: probe the venue's public market-data path.
|
|
314
|
-
await getVenue(ex).publicData.fetchMarkets(network);
|
|
315
|
-
exchanges[ex] = "ok";
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
const r = await fn();
|
|
319
|
-
exchanges[ex] = r.ok ? "ok" : "error";
|
|
320
|
-
}
|
|
321
|
-
catch {
|
|
322
|
-
exchanges[ex] = "error";
|
|
323
|
-
}
|
|
324
|
-
}));
|
|
325
|
-
const anyDown = Object.values(exchanges).some(v => v === "error");
|
|
326
|
-
return { exchanges, anyDown };
|
|
301
|
+
for (const p of h.probes)
|
|
302
|
+
exchanges[p.venue] = p.ok ? "ok" : "error";
|
|
303
|
+
return { exchanges, anyDown: !h.allHealthy, probes: h.probes, skipped: h.skipped };
|
|
327
304
|
}
|
|
328
305
|
// ── Arb top-5 ──────────────────────────────────────────────────────────────
|
|
329
306
|
async function fetchArbTop() {
|
|
@@ -514,11 +491,15 @@ function renderSnapshotText(data) {
|
|
|
514
491
|
}
|
|
515
492
|
function renderHealthText(h) {
|
|
516
493
|
console.log(chalk.cyan.bold("\n Exchange Health Check\n"));
|
|
517
|
-
const rows =
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
494
|
+
const rows = h.probes.map((p) => [
|
|
495
|
+
chalk.white.bold(p.venue),
|
|
496
|
+
p.ok ? chalk.green("OK") : chalk.red("DOWN"),
|
|
497
|
+
`${p.latencyMs}ms`,
|
|
498
|
+
p.error !== null ? chalk.red(p.error) : chalk.gray("-"),
|
|
499
|
+
]);
|
|
500
|
+
console.log(makeTable(["Exchange", "Status", "Latency", "Error"], rows));
|
|
501
|
+
for (const s of h.skipped)
|
|
502
|
+
console.log(chalk.gray(` ${s.venue}: not probed — ${s.reason}`));
|
|
522
503
|
const overall = h.anyDown ? chalk.red("ISSUES DETECTED") : chalk.green("ALL HEALTHY");
|
|
523
504
|
console.log(`\n Overall: ${overall}\n`);
|
|
524
505
|
}
|
|
@@ -773,7 +754,11 @@ export function registerPortfolioCommand(program, getAdapterForExchange, isJson,
|
|
|
773
754
|
catch (err) {
|
|
774
755
|
const msg = err instanceof Error ? err.message : String(err);
|
|
775
756
|
if (json) {
|
|
776
|
-
|
|
757
|
+
// A typed refusal (CAPABILITY_UNSUPPORTED for a market-data-only venue) keeps its code.
|
|
758
|
+
const s = err instanceof PerpError ? err.structured : null;
|
|
759
|
+
console.log(JSON.stringify(s !== null
|
|
760
|
+
? jsonError(s.code, msg, { ...(s.details !== undefined ? { details: s.details } : {}), ...(s.remediation !== undefined ? { remediation: s.remediation } : {}) })
|
|
761
|
+
: jsonError("INVALID_PARAMS", msg)));
|
|
777
762
|
}
|
|
778
763
|
else {
|
|
779
764
|
console.error(chalk.red(`Error: ${msg}`));
|
|
@@ -794,9 +779,9 @@ export function registerPortfolioCommand(program, getAdapterForExchange, isJson,
|
|
|
794
779
|
version,
|
|
795
780
|
scope: resolved.scope,
|
|
796
781
|
mode: "health",
|
|
797
|
-
exchanges:
|
|
798
|
-
totals:
|
|
799
|
-
risk:
|
|
782
|
+
exchanges: null,
|
|
783
|
+
totals: null,
|
|
784
|
+
risk: null,
|
|
800
785
|
health,
|
|
801
786
|
};
|
|
802
787
|
if (json)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import type { ExchangeAdapter } from "../exchanges/index.js";
|
|
3
3
|
import type { Network } from "../exchanges/venue-types.js";
|
|
4
|
+
import "../exchanges/venues/index.js";
|
|
4
5
|
export declare function registerFundsRebalanceCommands(parent: Command, getAdapterForExchange: (exchange: string) => Promise<ExchangeAdapter>, isJson: () => boolean, getNetwork: () => Network): void;
|
|
@@ -5,6 +5,10 @@ import { PerpError } from "../errors.js";
|
|
|
5
5
|
import { fetchBalancesWithFailures, computeRebalancePlan, describeBridgeRoute, estimateMoveTime, } from "../rebalance.js";
|
|
6
6
|
import { EXCHANGE_TO_CHAIN, assertBridgeNetwork, executeBestBridge } from "../bridge-engine.js";
|
|
7
7
|
import { cliCredentialOptsFrom } from "../config.js";
|
|
8
|
+
import { getVenue, roleUnsupported, tryResolveVenueId } from "../exchanges/venue.js";
|
|
9
|
+
import { unsupported } from "../exchanges/trading-v2.js";
|
|
10
|
+
import { RISEX_FUNDS_APP_ONLY } from "../exchanges/venues/risex.js";
|
|
11
|
+
import "../exchanges/venues/index.js";
|
|
8
12
|
export function registerFundsRebalanceCommands(parent, getAdapterForExchange, isJson, getNetwork) {
|
|
9
13
|
const rebalance = parent.command("rebalance").description("Cross-exchange balance management");
|
|
10
14
|
// ── rebalance check ──
|
|
@@ -149,6 +153,17 @@ export function registerFundsRebalanceCommands(parent, getAdapterForExchange, is
|
|
|
149
153
|
if (opts.autoBridge && !dryRun)
|
|
150
154
|
assertBridgeNetwork(getNetwork());
|
|
151
155
|
const exchangeNames = opts.exchanges.split(",").map((e) => e.trim());
|
|
156
|
+
// Venues whose funds perp-cli cannot move are refused before any read (no partial plan).
|
|
157
|
+
for (const name of exchangeNames) {
|
|
158
|
+
const id = tryResolveVenueId(name);
|
|
159
|
+
if (id === null)
|
|
160
|
+
continue;
|
|
161
|
+
const def = getVenue(id);
|
|
162
|
+
if (!def.roles.includes("account"))
|
|
163
|
+
throw roleUnsupported(def, "rebalance");
|
|
164
|
+
if (id === "risex")
|
|
165
|
+
throw unsupported("risex", "rebalance", RISEX_FUNDS_APP_ONLY.reason, RISEX_FUNDS_APP_ONLY.remediation);
|
|
166
|
+
}
|
|
152
167
|
const adapters = new Map();
|
|
153
168
|
const unavailable = [];
|
|
154
169
|
for (const name of exchangeNames) {
|
package/dist/commands/risk.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import type { ExchangeAdapter } from "../exchanges/index.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import type { Network } from "../exchanges/venue-types.js";
|
|
4
|
+
/**
|
|
5
|
+
* `perp health`: probe EVERY registered venue on the selected network — the same probe as
|
|
6
|
+
* `perp portfolio --health` and the MCP health_check (src/venue-health.ts). A venue with no
|
|
7
|
+
* environment on that network is listed under `skipped`, never silently dropped.
|
|
8
|
+
*
|
|
9
|
+
* JSON: `exchanges` = official-API venues, `unofficial` = venues read through an undocumented API
|
|
10
|
+
* (TxFlow), each entry with `error` (null when ok). `healthy` = every OFFICIAL venue is up — an
|
|
11
|
+
* unofficial API being down does not make the CLI unhealthy; `allHealthy` includes them.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runHealthCheck(isJson: () => boolean, network: Network): Promise<void>;
|
|
5
14
|
export declare function registerRiskCommands(program: Command, getAdapterForExchange: (exchange: string) => Promise<ExchangeAdapter>, isJson: () => boolean): void;
|
package/dist/commands/risk.js
CHANGED
|
@@ -2,61 +2,55 @@ import { listConfiguredAccountVenues } from "../config.js";
|
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { printJson, jsonOk, makeTable, formatUsd, withJsonErrors } from "../utils.js";
|
|
4
4
|
import { loadRiskLimits, saveRiskLimits, assessRisk, getLiquidationDistances } from "../risk.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
pingHyperliquid(),
|
|
21
|
-
pingLighter(),
|
|
22
|
-
pingAster(),
|
|
23
|
-
]);
|
|
24
|
-
const toPingResult = (name, p) => ({
|
|
25
|
-
exchange: name,
|
|
5
|
+
import { probeVenueHealth } from "../venue-health.js";
|
|
6
|
+
import { networkOf } from "../cli-flags.js";
|
|
7
|
+
/**
|
|
8
|
+
* `perp health`: probe EVERY registered venue on the selected network — the same probe as
|
|
9
|
+
* `perp portfolio --health` and the MCP health_check (src/venue-health.ts). A venue with no
|
|
10
|
+
* environment on that network is listed under `skipped`, never silently dropped.
|
|
11
|
+
*
|
|
12
|
+
* JSON: `exchanges` = official-API venues, `unofficial` = venues read through an undocumented API
|
|
13
|
+
* (TxFlow), each entry with `error` (null when ok). `healthy` = every OFFICIAL venue is up — an
|
|
14
|
+
* unofficial API being down does not make the CLI unhealthy; `allHealthy` includes them.
|
|
15
|
+
*/
|
|
16
|
+
export async function runHealthCheck(isJson, network) {
|
|
17
|
+
const health = await probeVenueHealth(network);
|
|
18
|
+
const checks = health.probes.map(p => ({
|
|
19
|
+
exchange: p.venue,
|
|
26
20
|
status: p.ok ? "ok" : "down",
|
|
27
21
|
latency_ms: p.latencyMs,
|
|
28
|
-
error: p.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
];
|
|
36
|
-
const allOk = checks.every(c => c.status === "ok");
|
|
22
|
+
error: p.error,
|
|
23
|
+
probe: p.probe,
|
|
24
|
+
apiStatus: p.apiStatus,
|
|
25
|
+
}));
|
|
26
|
+
const official = checks.filter(c => c.apiStatus === "official");
|
|
27
|
+
const unofficial = checks.filter(c => c.apiStatus === "unofficial");
|
|
28
|
+
const allOk = official.every(c => c.status === "ok");
|
|
37
29
|
if (isJson()) {
|
|
38
|
-
return printJson(jsonOk({ healthy: allOk, exchanges:
|
|
30
|
+
return printJson(jsonOk({ healthy: allOk, allHealthy: health.allHealthy, network, exchanges: official, unofficial, skipped: health.skipped }));
|
|
39
31
|
}
|
|
40
|
-
console.log(chalk.cyan.bold(
|
|
32
|
+
console.log(chalk.cyan.bold(`\n Exchange Health Check (${network})\n`));
|
|
41
33
|
const rows = checks.map(c => {
|
|
42
|
-
const statusIcon = c.status === "ok"
|
|
43
|
-
? chalk.green("OK")
|
|
44
|
-
: c.status === "degraded"
|
|
45
|
-
? chalk.yellow("DEGRADED")
|
|
46
|
-
: chalk.red("DOWN");
|
|
34
|
+
const statusIcon = c.status === "ok" ? chalk.green("OK") : chalk.red("DOWN");
|
|
47
35
|
const latency = c.latency_ms < 500
|
|
48
36
|
? chalk.green(`${c.latency_ms}ms`)
|
|
49
37
|
: c.latency_ms < 2000
|
|
50
38
|
? chalk.yellow(`${c.latency_ms}ms`)
|
|
51
39
|
: chalk.red(`${c.latency_ms}ms`);
|
|
52
40
|
return [
|
|
53
|
-
chalk.white.bold(c.exchange),
|
|
41
|
+
chalk.white.bold(c.exchange) + (c.apiStatus === "unofficial" ? chalk.yellow(" *") : ""),
|
|
54
42
|
statusIcon,
|
|
55
43
|
latency,
|
|
56
|
-
c.
|
|
44
|
+
c.probe,
|
|
45
|
+
c.error !== null ? chalk.red(c.error) : chalk.gray("-"),
|
|
57
46
|
];
|
|
58
47
|
});
|
|
59
|
-
console.log(makeTable(["Exchange", "Status", "Latency", "Error"], rows));
|
|
48
|
+
console.log(makeTable(["Exchange", "Status", "Latency", "Probe", "Error"], rows));
|
|
49
|
+
if (unofficial.length > 0) {
|
|
50
|
+
console.log(chalk.yellow(" * unofficial (undocumented) venue API — may change without notice; not counted in Overall"));
|
|
51
|
+
}
|
|
52
|
+
for (const s of health.skipped)
|
|
53
|
+
console.log(chalk.gray(` ${s.venue}: not probed — ${s.reason}`));
|
|
60
54
|
const overall = allOk ? chalk.green("ALL HEALTHY") : chalk.red("ISSUES DETECTED");
|
|
61
55
|
console.log(`\n Overall: ${overall}\n`);
|
|
62
56
|
}
|
|
@@ -122,11 +116,12 @@ export function registerRiskCommands(program, getAdapterForExchange, isJson) {
|
|
|
122
116
|
console.log(` Positions: ${assessment.metrics.positionCount}`);
|
|
123
117
|
console.log(` Largest Position: $${formatUsd(assessment.metrics.largestPositionUsd)}`);
|
|
124
118
|
console.log(` Max Leverage Used: ${assessment.metrics.maxLeverageUsed}x`);
|
|
125
|
-
|
|
126
|
-
|
|
119
|
+
const minLiq = assessment.metrics.minLiquidationDistancePct;
|
|
120
|
+
if (minLiq !== null) {
|
|
121
|
+
const ldColor = minLiq < assessment.limits.minLiquidationDistance
|
|
127
122
|
? chalk.red
|
|
128
123
|
: chalk.green;
|
|
129
|
-
console.log(` Min Liq Distance: ${ldColor(`${
|
|
124
|
+
console.log(` Min Liq Distance: ${ldColor(`${minLiq.toFixed(1)}%`)}`);
|
|
130
125
|
}
|
|
131
126
|
for (const { exchange, position: p } of positions.filter(x => x.position.liquidationPrice === null)) {
|
|
132
127
|
console.log(` Liq Price ${exchange}:${p.symbol}: ${chalk.yellow("unknown (venue does not report)")} — not in Min Liq Distance`);
|
|
@@ -367,6 +362,6 @@ export function registerRiskCommands(program, getAdapterForExchange, isJson) {
|
|
|
367
362
|
.command("health")
|
|
368
363
|
.description("Adapter health check: ping venue REST endpoints (connectivity + latency)")
|
|
369
364
|
.action(async () => {
|
|
370
|
-
await runHealthCheck(isJson);
|
|
365
|
+
await runHealthCheck(isJson, networkOf(program));
|
|
371
366
|
});
|
|
372
367
|
}
|
package/dist/commands/trade.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { ExchangeAdapter } from "../exchanges/index.js";
|
|
|
3
3
|
import { PerpError } from "../errors.js";
|
|
4
4
|
import "../exchanges/venues/index.js";
|
|
5
5
|
import { type CancelResult } from "../exchanges/venue-types.js";
|
|
6
|
+
export declare function parseSlippageBpsFlag(raw: string | undefined): number | null;
|
|
6
7
|
/**
|
|
7
8
|
* A cancel with anything not proven cancelled (failed, or pending / still listed open after the
|
|
8
9
|
* verifying re-list) → ORDER_PARTIAL carrying the whole result (non-zero exit, also in --json);
|