perp-cli 0.12.17 → 0.14.1
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 +247 -27
- package/dist/_stderr-filter.js +0 -1
- package/dist/agent-wallet/lighter-keystore.d.ts +11 -0
- package/dist/agent-wallet/lighter-keystore.js +92 -10
- package/dist/agent-wallet/passphrase.d.ts +1 -1
- package/dist/agent-wallet/passphrase.js +16 -3
- package/dist/agent-wallet/store.d.ts +37 -4
- package/dist/agent-wallet/store.js +132 -0
- package/dist/agent-wallet/venue-keystore.d.ts +14 -0
- package/dist/agent-wallet/venue-keystore.js +121 -0
- package/dist/api/public/hyperliquid.js +4 -4
- package/dist/api/public/lighter.js +5 -5
- package/dist/api/public/pacifica.d.ts +0 -1
- package/dist/api/public/pacifica.js +4 -13
- package/dist/api/public/urls.d.ts +9 -1
- package/dist/api/public/urls.js +35 -13
- package/dist/arb/file-lock.d.ts +11 -0
- package/dist/arb/file-lock.js +74 -0
- package/dist/arb/index.d.ts +2 -2
- package/dist/arb/index.js +2 -2
- package/dist/arb/pending-entry.d.ts +32 -0
- package/dist/arb/pending-entry.js +77 -0
- package/dist/arb/sizing.d.ts +6 -13
- package/dist/arb/sizing.js +12 -51
- package/dist/arb/state.d.ts +45 -12
- package/dist/arb/state.js +214 -42
- package/dist/arb/utils.d.ts +20 -6
- package/dist/arb/utils.js +43 -39
- package/dist/bot/conditions.d.ts +4 -4
- package/dist/bot/conditions.js +11 -6
- package/dist/bot/config.d.ts +17 -1
- package/dist/bot/config.js +48 -12
- package/dist/bot/engine.d.ts +61 -2
- package/dist/bot/engine.js +610 -144
- package/dist/bot/fill-size.d.ts +7 -0
- package/dist/bot/fill-size.js +18 -0
- package/dist/bot/index.d.ts +1 -1
- package/dist/bot/index.js +1 -1
- package/dist/bot/perp-order.d.ts +99 -0
- package/dist/bot/perp-order.js +299 -0
- package/dist/bot/presets.d.ts +7 -0
- package/dist/bot/presets.js +17 -0
- package/dist/bot/quarantine.d.ts +75 -0
- package/dist/bot/quarantine.js +190 -0
- package/dist/bot/quote-rules.d.ts +23 -0
- package/dist/bot/quote-rules.js +69 -0
- package/dist/bot/strategies/avellaneda-mm.d.ts +32 -2
- package/dist/bot/strategies/avellaneda-mm.js +72 -70
- package/dist/bot/strategies/basis-arb.js +2 -0
- package/dist/bot/strategies/dca-strategy.d.ts +2 -0
- package/dist/bot/strategies/dca-strategy.js +5 -0
- package/dist/bot/strategies/funding-arb-strategy.d.ts +43 -3
- package/dist/bot/strategies/funding-arb-strategy.js +571 -380
- package/dist/bot/strategies/funding-arb-utils.d.ts +48 -23
- package/dist/bot/strategies/funding-arb-utils.js +159 -195
- package/dist/bot/strategies/funding-arb-v2.d.ts +32 -0
- package/dist/bot/strategies/funding-arb-v2.js +258 -47
- package/dist/bot/strategies/funding-auto.js +215 -194
- package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +14 -0
- package/dist/bot/strategies/spot-perp-arb-strategy.js +217 -50
- package/dist/bot/strategies/spot-perp-executor.d.ts +73 -19
- package/dist/bot/strategies/spot-perp-executor.js +319 -120
- package/dist/bot/strategies/spot-perp-state.d.ts +43 -0
- package/dist/bot/strategies/spot-perp-state.js +70 -0
- package/dist/bot/strategy-types.d.ts +6 -0
- package/dist/bot/tui/BotDashboard.d.ts +7 -2
- package/dist/bot/tui/BotDashboard.js +6 -3
- package/dist/bridge-engine.d.ts +120 -19
- package/dist/bridge-engine.js +710 -422
- package/dist/bridge-signers.d.ts +54 -0
- package/dist/bridge-signers.js +161 -0
- package/dist/cache.d.ts +4 -1
- package/dist/cache.js +11 -0
- package/dist/cli-flags.d.ts +50 -0
- package/dist/cli-flags.js +104 -0
- package/dist/cli-program.d.ts +35 -0
- package/dist/cli-program.js +303 -0
- package/dist/cli-spec.js +1 -1
- package/dist/client-id-tracker.js +11 -2
- package/dist/commands/account.d.ts +7 -1
- package/dist/commands/account.js +70 -92
- package/dist/commands/agent-import.d.ts +114 -0
- package/dist/commands/agent-import.js +794 -0
- package/dist/commands/agent.d.ts +232 -2
- package/dist/commands/agent.js +1858 -955
- package/dist/commands/alerts.d.ts +1 -0
- package/dist/commands/alerts.js +31 -28
- package/dist/commands/arb/index.d.ts +60 -1
- package/dist/commands/arb/index.js +381 -384
- package/dist/commands/arb-auto.d.ts +132 -4
- package/dist/commands/arb-auto.js +1474 -967
- package/dist/commands/arb.d.ts +3 -1
- package/dist/commands/arb.js +62 -30
- package/dist/commands/bot.js +127 -47
- package/dist/commands/bridge.d.ts +2 -1
- package/dist/commands/bridge.js +339 -192
- package/dist/commands/builder.d.ts +55 -0
- package/dist/commands/builder.js +387 -0
- package/dist/commands/funds-onchain.d.ts +32 -0
- package/dist/commands/funds-onchain.js +248 -0
- package/dist/commands/funds.d.ts +25 -0
- package/dist/commands/funds.js +925 -245
- package/dist/commands/history.js +102 -54
- package/dist/commands/init.d.ts +107 -15
- package/dist/commands/init.js +1116 -249
- package/dist/commands/jobs.d.ts +2 -1
- package/dist/commands/jobs.js +77 -15
- package/dist/commands/manage.js +136 -91
- package/dist/commands/market.d.ts +4 -1
- package/dist/commands/market.js +35 -32
- package/dist/commands/outcome.d.ts +10 -0
- package/dist/commands/outcome.js +396 -0
- package/dist/commands/plan.js +52 -12
- package/dist/commands/portfolio.d.ts +1 -0
- package/dist/commands/portfolio.js +60 -72
- package/dist/commands/rebalance.d.ts +2 -1
- package/dist/commands/rebalance.js +33 -43
- package/dist/commands/risk.js +46 -19
- package/dist/commands/settings.d.ts +1 -0
- package/dist/commands/settings.js +246 -51
- package/dist/commands/trade.d.ts +50 -0
- package/dist/commands/trade.js +1943 -695
- package/dist/commands/wallet.d.ts +30 -1
- package/dist/commands/wallet.js +357 -459
- package/dist/config.d.ts +60 -9
- package/dist/config.js +252 -82
- package/dist/constants.d.ts +29 -4
- package/dist/constants.js +62 -20
- package/dist/dashboard/server.d.ts +2 -0
- package/dist/dashboard/server.js +9 -6
- package/dist/dashboard/ui.js +6 -4
- package/dist/dashboard/ws-feeds.js +20 -8
- package/dist/dex-asset-map.js +5 -3
- package/dist/errors.d.ts +122 -0
- package/dist/errors.js +194 -0
- package/dist/event-stream.js +75 -19
- package/dist/evm-master-tx.d.ts +59 -0
- package/dist/evm-master-tx.js +154 -0
- package/dist/exchanges/adapter-network.d.ts +10 -0
- package/dist/exchanges/adapter-network.js +10 -0
- package/dist/exchanges/arcus/adapter.d.ts +196 -0
- package/dist/exchanges/arcus/adapter.js +1092 -0
- package/dist/exchanges/arcus/agent.d.ts +55 -0
- package/dist/exchanges/arcus/agent.js +188 -0
- package/dist/exchanges/arcus/client.d.ts +63 -0
- package/dist/exchanges/arcus/client.js +285 -0
- package/dist/exchanges/arcus/public.d.ts +65 -0
- package/dist/exchanges/arcus/public.js +138 -0
- package/dist/exchanges/arcus/signing.d.ts +176 -0
- package/dist/exchanges/arcus/signing.js +288 -0
- package/dist/exchanges/arcus/spot-chain.d.ts +60 -0
- package/dist/exchanges/arcus/spot-chain.js +241 -0
- package/dist/exchanges/arcus/spot-router.d.ts +177 -0
- package/dist/exchanges/arcus/spot-router.js +183 -0
- package/dist/exchanges/arcus/spot.d.ts +109 -0
- package/dist/exchanges/arcus/spot.js +645 -0
- package/dist/exchanges/aster-funds.d.ts +127 -0
- package/dist/exchanges/aster-funds.js +252 -0
- package/dist/exchanges/aster-nonce.d.ts +2 -0
- package/dist/exchanges/aster-nonce.js +107 -0
- package/dist/exchanges/aster-spot.d.ts +117 -0
- package/dist/exchanges/aster-spot.js +686 -0
- package/dist/exchanges/aster-typed-data.d.ts +133 -7
- package/dist/exchanges/aster-typed-data.js +121 -7
- package/dist/exchanges/aster.d.ts +240 -6
- package/dist/exchanges/aster.js +1139 -195
- package/dist/exchanges/builder-fee.d.ts +254 -0
- package/dist/exchanges/builder-fee.js +421 -0
- package/dist/exchanges/canonical-symbols.d.ts +32 -0
- package/dist/exchanges/canonical-symbols.js +96 -0
- package/dist/exchanges/capabilities.d.ts +7 -1
- package/dist/exchanges/capabilities.js +7 -0
- package/dist/exchanges/hl-signing.d.ts +165 -0
- package/dist/exchanges/hl-signing.js +158 -0
- package/dist/exchanges/hyperliquid-outcome.d.ts +211 -0
- package/dist/exchanges/hyperliquid-outcome.js +646 -0
- package/dist/exchanges/hyperliquid-spot.d.ts +44 -5
- package/dist/exchanges/hyperliquid-spot.js +308 -117
- package/dist/exchanges/hyperliquid.d.ts +462 -57
- package/dist/exchanges/hyperliquid.js +1575 -449
- package/dist/exchanges/index.d.ts +6 -0
- package/dist/exchanges/index.js +4 -0
- package/dist/exchanges/interface.d.ts +63 -10
- package/dist/exchanges/interface.js +18 -3
- package/dist/exchanges/ioc-outcome.d.ts +44 -0
- package/dist/exchanges/ioc-outcome.js +57 -0
- package/dist/exchanges/legacy-trading-v2.d.ts +39 -0
- package/dist/exchanges/legacy-trading-v2.js +940 -0
- package/dist/exchanges/lighter-public.d.ts +43 -0
- package/dist/exchanges/lighter-public.js +276 -0
- package/dist/exchanges/lighter-rh-deposit.d.ts +62 -0
- package/dist/exchanges/lighter-rh-deposit.js +185 -0
- package/dist/exchanges/lighter-signer.d.ts +123 -0
- package/dist/exchanges/lighter-signer.js +215 -0
- package/dist/exchanges/lighter-spot.d.ts +91 -13
- package/dist/exchanges/lighter-spot.js +595 -233
- package/dist/exchanges/lighter.d.ts +611 -39
- package/dist/exchanges/lighter.js +1890 -649
- package/dist/exchanges/ondo/adapter.d.ts +152 -0
- package/dist/exchanges/ondo/adapter.js +811 -0
- package/dist/exchanges/ondo/agent.d.ts +31 -0
- package/dist/exchanges/ondo/agent.js +101 -0
- package/dist/exchanges/ondo/client.d.ts +60 -0
- package/dist/exchanges/ondo/client.js +297 -0
- package/dist/exchanges/ondo/funds.d.ts +95 -0
- package/dist/exchanges/ondo/funds.js +198 -0
- package/dist/exchanges/ondo/public.d.ts +95 -0
- package/dist/exchanges/ondo/public.js +214 -0
- package/dist/exchanges/ondo/spot.d.ts +127 -0
- package/dist/exchanges/ondo/spot.js +392 -0
- package/dist/exchanges/outcome-interface.d.ts +140 -0
- package/dist/exchanges/outcome-interface.js +16 -0
- package/dist/exchanges/pacifica-spot.d.ts +83 -0
- package/dist/exchanges/pacifica-spot.js +324 -0
- package/dist/exchanges/pacifica-typed-data.d.ts +30 -13
- package/dist/exchanges/pacifica-typed-data.js +57 -9
- package/dist/exchanges/pacifica.d.ts +293 -4
- package/dist/exchanges/pacifica.js +1044 -90
- package/dist/exchanges/precision.d.ts +47 -0
- package/dist/exchanges/precision.js +209 -0
- package/dist/exchanges/qfex/adapter.d.ts +341 -0
- package/dist/exchanges/qfex/adapter.js +1386 -0
- package/dist/exchanges/qfex/agent.d.ts +58 -0
- package/dist/exchanges/qfex/agent.js +188 -0
- package/dist/exchanges/qfex/client.d.ts +54 -0
- package/dist/exchanges/qfex/client.js +138 -0
- package/dist/exchanges/qfex/errors.d.ts +70 -0
- package/dist/exchanges/qfex/errors.js +236 -0
- package/dist/exchanges/qfex/public.d.ts +122 -0
- package/dist/exchanges/qfex/public.js +268 -0
- package/dist/exchanges/qfex/signing.d.ts +160 -0
- package/dist/exchanges/qfex/signing.js +283 -0
- package/dist/exchanges/qfex/ws-transport.d.ts +294 -0
- package/dist/exchanges/qfex/ws-transport.js +798 -0
- package/dist/exchanges/rate-limiter.d.ts +12 -0
- package/dist/exchanges/rate-limiter.js +64 -0
- package/dist/exchanges/registry.d.ts +14 -2
- package/dist/exchanges/registry.js +20 -32
- package/dist/exchanges/slippage.d.ts +37 -0
- package/dist/exchanges/slippage.js +70 -0
- package/dist/exchanges/spot-factory.d.ts +166 -0
- package/dist/exchanges/spot-factory.js +431 -0
- package/dist/exchanges/spot-interface.d.ts +98 -4
- package/dist/exchanges/spot-interface.js +27 -1
- package/dist/exchanges/spot-result.d.ts +79 -0
- package/dist/exchanges/spot-result.js +273 -0
- package/dist/exchanges/trading-v2.d.ts +117 -0
- package/dist/exchanges/trading-v2.js +301 -0
- package/dist/exchanges/venue-types.d.ts +231 -0
- package/dist/exchanges/venue-types.js +87 -0
- package/dist/exchanges/venue.d.ts +211 -0
- package/dist/exchanges/venue.js +132 -0
- package/dist/exchanges/venues/arcus.d.ts +8 -0
- package/dist/exchanges/venues/arcus.js +109 -0
- package/dist/exchanges/venues/aster.d.ts +49 -0
- package/dist/exchanges/venues/aster.js +176 -0
- package/dist/exchanges/venues/create-helpers.d.ts +18 -0
- package/dist/exchanges/venues/create-helpers.js +199 -0
- package/dist/exchanges/venues/hyperliquid.d.ts +23 -0
- package/dist/exchanges/venues/hyperliquid.js +126 -0
- package/dist/exchanges/venues/index.d.ts +16 -0
- package/dist/exchanges/venues/index.js +26 -0
- package/dist/exchanges/venues/lighter-family.d.ts +92 -0
- package/dist/exchanges/venues/lighter-family.js +166 -0
- package/dist/exchanges/venues/lighter-rh.d.ts +7 -0
- package/dist/exchanges/venues/lighter-rh.js +58 -0
- package/dist/exchanges/venues/lighter.d.ts +6 -0
- package/dist/exchanges/venues/lighter.js +55 -0
- package/dist/exchanges/venues/ondo.d.ts +29 -0
- package/dist/exchanges/venues/ondo.js +136 -0
- package/dist/exchanges/venues/pacifica.d.ts +8 -0
- package/dist/exchanges/venues/pacifica.js +95 -0
- package/dist/exchanges/venues/qfex.d.ts +39 -0
- package/dist/exchanges/venues/qfex.js +140 -0
- package/dist/execution-log.js +10 -2
- package/dist/funding/legacy-public.d.ts +31 -0
- package/dist/funding/legacy-public.js +369 -0
- package/dist/funding/normalize.d.ts +28 -16
- package/dist/funding/normalize.js +61 -29
- package/dist/funding/rates.d.ts +46 -11
- package/dist/funding/rates.js +228 -277
- package/dist/guardrail/perp-guardrail.js +0 -0
- package/dist/index.js +156 -684
- package/dist/jobs.d.ts +84 -6
- package/dist/jobs.js +239 -41
- package/dist/landing.d.ts +7 -2
- package/dist/landing.js +19 -3
- package/dist/mcp-server.d.ts +14 -4
- package/dist/mcp-server.js +821 -403
- package/dist/mcp-trade-guard.d.ts +16 -0
- package/dist/mcp-trade-guard.js +59 -0
- package/dist/onchain-balances.d.ts +40 -0
- package/dist/onchain-balances.js +173 -0
- package/dist/pacifica/client.d.ts +41 -10
- package/dist/pacifica/client.js +167 -63
- package/dist/pacifica/constants.d.ts +0 -1
- package/dist/pacifica/constants.js +0 -5
- package/dist/pacifica/deposit.d.ts +30 -3
- package/dist/pacifica/deposit.js +119 -2
- package/dist/pacifica/faucet.d.ts +29 -0
- package/dist/pacifica/faucet.js +100 -0
- package/dist/pacifica/sign-tx.d.ts +15 -0
- package/dist/pacifica/sign-tx.js +41 -0
- package/dist/pacifica/types/account.d.ts +28 -4
- package/dist/pacifica/types/lake.d.ts +20 -5
- package/dist/pacifica/types/lake.js +4 -0
- package/dist/pacifica/types/market.d.ts +5 -0
- package/dist/pacifica/types/order.d.ts +4 -1
- package/dist/pacifica/types/position.d.ts +9 -1
- package/dist/plan-executor.d.ts +10 -5
- package/dist/plan-executor.js +165 -54
- package/dist/position-history.js +13 -0
- package/dist/rebalance.d.ts +26 -2
- package/dist/rebalance.js +86 -7
- package/dist/relay-swap.d.ts +232 -0
- package/dist/relay-swap.js +630 -0
- package/dist/risk.js +5 -1
- package/dist/secret-env.d.ts +15 -0
- package/dist/secret-env.js +36 -0
- package/dist/settings.d.ts +169 -6
- package/dist/settings.js +219 -38
- package/dist/signer/ows-evm.d.ts +13 -0
- package/dist/signer/ows-evm.js +22 -0
- package/dist/smart-order.d.ts +9 -0
- package/dist/smart-order.js +53 -8
- package/dist/strategies/dca.d.ts +6 -2
- package/dist/strategies/dca.js +66 -26
- package/dist/strategies/funding-arb.d.ts +11 -1
- package/dist/strategies/funding-arb.js +202 -89
- package/dist/strategies/grid.d.ts +31 -0
- package/dist/strategies/grid.js +89 -11
- package/dist/strategies/pending-stop.d.ts +8 -0
- package/dist/strategies/pending-stop.js +12 -0
- package/dist/strategies/split-order.d.ts +45 -17
- package/dist/strategies/split-order.js +157 -91
- package/dist/strategies/trailing-stop.d.ts +2 -1
- package/dist/strategies/trailing-stop.js +52 -6
- package/dist/strategies/twap.d.ts +6 -1
- package/dist/strategies/twap.js +39 -11
- package/dist/trade-validator.d.ts +22 -0
- package/dist/trade-validator.js +119 -15
- package/dist/utils/numeric.d.ts +46 -0
- package/dist/utils/numeric.js +79 -0
- package/dist/utils.d.ts +19 -0
- package/dist/utils.js +96 -19
- package/dist/withdraw-gate.d.ts +49 -0
- package/dist/withdraw-gate.js +131 -0
- package/package.json +15 -6
- package/skills/perp-cli/SKILL.md +159 -55
- package/skills/perp-cli/references/agent-operations.md +112 -58
- package/skills/perp-cli/references/commands.md +269 -73
- package/skills/perp-cli/references/strategies.md +34 -31
- package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
- package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
- package/skills/perp-cli/scripts/preflight.sh +21 -14
- package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
- package/skills/perp-cli/scripts/validate-arb.sh +31 -15
- package/vendor/lighter-signer/SHA256SUMS +2 -0
- package/vendor/lighter-signer/VERSION +8 -0
- package/vendor/lighter-signer/lighter-signer.wasm +0 -0
- package/vendor/lighter-signer/wasm_exec.js +575 -0
- package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
- package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
package/dist/commands/history.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { listConfiguredAccountVenues } from "../config.js";
|
|
1
2
|
import chalk from "chalk";
|
|
2
3
|
import { printJson, jsonOk, jsonError, makeTable, formatUsd, formatPnl, withJsonErrors } from "../utils.js";
|
|
3
4
|
import { readExecutionLog, getExecutionStats, pruneExecutionLog } from "../execution-log.js";
|
|
4
5
|
import { loadArbState } from "../arb/index.js";
|
|
6
|
+
import { networkOf } from "../cli-flags.js";
|
|
5
7
|
import { readPositionHistory, getPositionStats } from "../position-history.js";
|
|
6
8
|
import { saveEquitySnapshot, readEquityHistory, computePnlMetrics, computeDailyPnl, aggregateWeekly, } from "../equity-tracker.js";
|
|
7
|
-
const EXCHANGES = ["pacifica", "hyperliquid", "lighter", "aster"];
|
|
8
9
|
function parseSince(since) {
|
|
9
10
|
if (!since)
|
|
10
11
|
return undefined;
|
|
@@ -16,6 +17,18 @@ function parseSince(since) {
|
|
|
16
17
|
}
|
|
17
18
|
return since;
|
|
18
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Exchange filter of a history subcommand: the ROOT `-e, --exchange`, only when given on the command
|
|
22
|
+
* line. Commander hands `-e` / `--exchange` to the root wherever it appears in argv, so a subcommand
|
|
23
|
+
* copy of the option was never set (the filter was silently dropped). The root's default venue is
|
|
24
|
+
* never used as a filter.
|
|
25
|
+
*/
|
|
26
|
+
function cliExchangeFilter(cmd) {
|
|
27
|
+
let root = cmd;
|
|
28
|
+
while (root.parent)
|
|
29
|
+
root = root.parent;
|
|
30
|
+
return root.getOptionValueSource("exchange") === "cli" ? String(root.opts().exchange) : undefined;
|
|
31
|
+
}
|
|
19
32
|
/** Parse period string (7d, 30d, 90d) to milliseconds. Returns undefined for "all" or missing. */
|
|
20
33
|
function parsePeriodMs(period) {
|
|
21
34
|
if (!period || period === "all")
|
|
@@ -32,14 +45,14 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
|
|
|
32
45
|
// ── history list ──
|
|
33
46
|
history
|
|
34
47
|
.command("list")
|
|
35
|
-
.description("Show recent executions")
|
|
36
|
-
.option("
|
|
37
|
-
.option("-e, --exchange <exchange>", "Filter by exchange")
|
|
48
|
+
.description("Show recent executions — filter with the root -e <exchange>")
|
|
49
|
+
.option("--limit <n>", "Number of records to show", "20")
|
|
38
50
|
.option("-s, --symbol <symbol>", "Filter by symbol")
|
|
39
51
|
.option("-t, --type <type>", "Filter by type (market_order, limit_order, arb_entry, etc.)")
|
|
40
52
|
.option("--since <date>", "Show records since date (ISO format or relative like '24h', '7d')")
|
|
41
53
|
.option("--dry-run-only", "Show only dry-run simulations")
|
|
42
54
|
.action(async (opts) => {
|
|
55
|
+
const exchangeFilter = cliExchangeFilter(history);
|
|
43
56
|
await withJsonErrors(isJson(), async () => {
|
|
44
57
|
// Parse relative dates
|
|
45
58
|
let since = opts.since;
|
|
@@ -53,7 +66,7 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
|
|
|
53
66
|
}
|
|
54
67
|
const records = readExecutionLog({
|
|
55
68
|
limit: parseInt(opts.limit),
|
|
56
|
-
exchange:
|
|
69
|
+
exchange: exchangeFilter,
|
|
57
70
|
symbol: opts.symbol,
|
|
58
71
|
type: opts.type,
|
|
59
72
|
since,
|
|
@@ -143,14 +156,14 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
|
|
|
143
156
|
// ── history positions ──
|
|
144
157
|
history
|
|
145
158
|
.command("positions")
|
|
146
|
-
.description("Show position history (from event stream logging)")
|
|
147
|
-
.option("
|
|
148
|
-
.option("-e, --exchange <exchange>", "Filter by exchange")
|
|
159
|
+
.description("Show position history (from event stream logging) — filter with the root -e <exchange>")
|
|
160
|
+
.option("--limit <n>", "Number of records to show", "20")
|
|
149
161
|
.option("-s, --symbol <symbol>", "Filter by symbol")
|
|
150
162
|
.option("--status <status>", "Filter by status (open, closed, updated)")
|
|
151
163
|
.option("--since <date>", "Show records since date (ISO format or relative like '24h', '7d')")
|
|
152
164
|
.option("--stats", "Show aggregate position stats instead of list")
|
|
153
165
|
.action(async (opts) => {
|
|
166
|
+
const exchangeFilter = cliExchangeFilter(history);
|
|
154
167
|
await withJsonErrors(isJson(), async () => {
|
|
155
168
|
// Parse relative dates
|
|
156
169
|
let since = opts.since;
|
|
@@ -164,7 +177,7 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
|
|
|
164
177
|
}
|
|
165
178
|
// Stats mode
|
|
166
179
|
if (opts.stats) {
|
|
167
|
-
const stats = getPositionStats({ exchange:
|
|
180
|
+
const stats = getPositionStats({ exchange: exchangeFilter, since });
|
|
168
181
|
if (isJson()) {
|
|
169
182
|
return printJson(jsonOk(stats));
|
|
170
183
|
}
|
|
@@ -206,7 +219,7 @@ export function registerHistoryCommands(program, isJson, getAdapterForExchange)
|
|
|
206
219
|
// List mode
|
|
207
220
|
const records = readPositionHistory({
|
|
208
221
|
limit: parseInt(opts.limit),
|
|
209
|
-
exchange:
|
|
222
|
+
exchange: exchangeFilter,
|
|
210
223
|
symbol: opts.symbol,
|
|
211
224
|
status: opts.status,
|
|
212
225
|
since,
|
|
@@ -330,16 +343,16 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
330
343
|
// ── analytics pnl ──
|
|
331
344
|
parent
|
|
332
345
|
.command("pnl")
|
|
333
|
-
.description("P&L analysis — trades, fees, funding income with daily breakdown")
|
|
334
|
-
.option("-e, --exchange <exchanges>", "Comma-separated exchanges")
|
|
346
|
+
.description("P&L analysis — trades, fees, funding income with daily breakdown — filter with the root -e <exchange> (comma-separated)")
|
|
335
347
|
.option("--period <duration>", "Time period: 7d, 30d, 90d, all (default: all)")
|
|
336
348
|
.option("--since <period>", "Alias for --period")
|
|
337
|
-
.option("
|
|
349
|
+
.option("--limit <n>", "History limit per exchange", "200")
|
|
338
350
|
.action(async (opts) => {
|
|
351
|
+
const exchangeFilter = cliExchangeFilter(parent);
|
|
339
352
|
await withJsonErrors(isJson(), async () => {
|
|
340
|
-
const exchanges =
|
|
341
|
-
?
|
|
342
|
-
:
|
|
353
|
+
const exchanges = exchangeFilter
|
|
354
|
+
? exchangeFilter.split(",").map(e => e.trim())
|
|
355
|
+
: await listConfiguredAccountVenues();
|
|
343
356
|
const period = opts.period ?? opts.since;
|
|
344
357
|
const periodMs = parsePeriodMs(period);
|
|
345
358
|
const sinceMs = periodMs ? Date.now() - periodMs : 0;
|
|
@@ -451,17 +464,17 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
451
464
|
// ── analytics funding ──
|
|
452
465
|
parent
|
|
453
466
|
.command("funding")
|
|
454
|
-
.description("Funding income analysis — cumulative, daily, per-arb-position breakdown")
|
|
455
|
-
.option("-e, --exchange <exchanges>", "Comma-separated exchanges")
|
|
467
|
+
.description("Funding income analysis — cumulative, daily, per-arb-position breakdown — filter with the root -e <exchange> (comma-separated)")
|
|
456
468
|
.option("-s, --symbol <symbol>", "Filter by symbol")
|
|
457
469
|
.option("--period <duration>", "Time period: 7d, 30d, 90d, all (default: all)")
|
|
458
470
|
.option("--daily", "Show daily funding breakdown")
|
|
459
|
-
.option("
|
|
471
|
+
.option("--limit <n>", "Funding history limit per exchange", "200")
|
|
460
472
|
.action(async (opts) => {
|
|
473
|
+
const exchangeFilter = cliExchangeFilter(parent);
|
|
461
474
|
await withJsonErrors(isJson(), async () => {
|
|
462
|
-
const exchanges =
|
|
463
|
-
?
|
|
464
|
-
:
|
|
475
|
+
const exchanges = exchangeFilter
|
|
476
|
+
? exchangeFilter.split(",").map(e => e.trim())
|
|
477
|
+
: await listConfiguredAccountVenues();
|
|
465
478
|
const periodMs = parsePeriodMs(opts.period);
|
|
466
479
|
const sinceMs = periodMs ? Date.now() - periodMs : 0;
|
|
467
480
|
const allFunding = [];
|
|
@@ -510,7 +523,7 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
510
523
|
? (allFunding[allFunding.length - 1].time - allFunding[0].time) / 86400000
|
|
511
524
|
: 1;
|
|
512
525
|
// Match funding to arb positions
|
|
513
|
-
const arbState = loadArbState();
|
|
526
|
+
const arbState = loadArbState(networkOf(parent));
|
|
514
527
|
const arbPositions = arbState?.positions ?? [];
|
|
515
528
|
const arbFunding = new Map();
|
|
516
529
|
for (const pos of arbPositions) {
|
|
@@ -611,17 +624,17 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
611
624
|
// ── analytics report ──
|
|
612
625
|
parent
|
|
613
626
|
.command("report")
|
|
614
|
-
.description("Full performance report (summary + pnl + funding)")
|
|
615
|
-
.option("-e, --exchange <exchanges>", "Comma-separated exchanges")
|
|
627
|
+
.description("Full performance report (summary + pnl + funding) — filter with the root -e <exchange> (comma-separated)")
|
|
616
628
|
.option("--since <period>", "Period: 24h, 7d, 30d")
|
|
617
629
|
.action(async (opts) => {
|
|
630
|
+
const exchangeFilter = cliExchangeFilter(parent);
|
|
618
631
|
await withJsonErrors(isJson(), async () => {
|
|
619
632
|
const since = parseSince(opts.since);
|
|
620
633
|
const stats = getExecutionStats(since);
|
|
621
634
|
const records = readExecutionLog({ since });
|
|
622
|
-
const exchanges =
|
|
623
|
-
?
|
|
624
|
-
:
|
|
635
|
+
const exchanges = exchangeFilter
|
|
636
|
+
? exchangeFilter.split(",").map(e => e.trim())
|
|
637
|
+
: await listConfiguredAccountVenues();
|
|
625
638
|
// Volume from log
|
|
626
639
|
let logVolume = 0;
|
|
627
640
|
for (const r of records) {
|
|
@@ -634,24 +647,42 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
634
647
|
let totalEquity = 0;
|
|
635
648
|
let totalUPnl = 0;
|
|
636
649
|
const symbolSet = new Set();
|
|
650
|
+
// A venue whose read failed is reported here and left out of the totals — never counted as 0.
|
|
651
|
+
const errors = {};
|
|
652
|
+
const errText = (e) => (e instanceof Error ? e.message : String(e));
|
|
637
653
|
await Promise.allSettled(exchanges.map(async (ex) => {
|
|
654
|
+
let adapter;
|
|
638
655
|
try {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
656
|
+
adapter = await getAdapterForExchange(ex);
|
|
657
|
+
}
|
|
658
|
+
catch (e) {
|
|
659
|
+
errors[`${ex}.adapter`] = errText(e);
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
try {
|
|
663
|
+
const balance = await adapter.getBalance();
|
|
645
664
|
totalEquity += Number(balance.equity);
|
|
646
665
|
totalUPnl += Number(balance.unrealizedPnl);
|
|
647
|
-
|
|
666
|
+
}
|
|
667
|
+
catch (e) {
|
|
668
|
+
errors[`${ex}.balance`] = errText(e);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
const [trades, funding] = await Promise.allSettled([adapter.getTradeHistory(50), adapter.getFundingPayments(50)]);
|
|
672
|
+
if (trades.status === "fulfilled") {
|
|
673
|
+
for (const t of trades.value) {
|
|
648
674
|
totalFees += Number(t.fee);
|
|
649
675
|
symbolSet.add(t.symbol);
|
|
650
676
|
}
|
|
651
|
-
|
|
677
|
+
}
|
|
678
|
+
else
|
|
679
|
+
errors[`${ex}.trades`] = errText(trades.reason);
|
|
680
|
+
if (funding.status === "fulfilled") {
|
|
681
|
+
for (const f of funding.value)
|
|
652
682
|
totalFunding += Number(f.payment);
|
|
653
683
|
}
|
|
654
|
-
|
|
684
|
+
else
|
|
685
|
+
errors[`${ex}.funding`] = errText(funding.reason);
|
|
655
686
|
}));
|
|
656
687
|
const report = {
|
|
657
688
|
period: opts.since ?? "all time",
|
|
@@ -678,6 +709,7 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
678
709
|
? (stats.totalTrades / Math.max(1, (Date.now() - new Date(records[records.length - 1]?.timestamp ?? Date.now()).getTime()) / 86400000)).toFixed(1)
|
|
679
710
|
: "0",
|
|
680
711
|
},
|
|
712
|
+
errors,
|
|
681
713
|
};
|
|
682
714
|
if (isJson())
|
|
683
715
|
return printJson(jsonOk(report));
|
|
@@ -694,6 +726,8 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
694
726
|
console.log(` Trading Fees: ${chalk.red(`-$${formatUsd(totalFees)}`)}`);
|
|
695
727
|
console.log(` Funding Income: ${formatPnl(totalFunding)}`);
|
|
696
728
|
console.log(` Net: ${formatPnl(totalFunding - totalFees)}`);
|
|
729
|
+
for (const [k, msg] of Object.entries(errors))
|
|
730
|
+
console.log(chalk.yellow(` ⚠ ${k} unavailable (left out of the totals): ${msg}`));
|
|
697
731
|
console.log();
|
|
698
732
|
});
|
|
699
733
|
});
|
|
@@ -702,10 +736,10 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
702
736
|
.command("compare")
|
|
703
737
|
.description("Compare active arb positions — ROI, realized PnL, funding income side by side")
|
|
704
738
|
.option("--period <duration>", "Funding lookup period: 7d, 30d, 90d, all (default: all)")
|
|
705
|
-
.option("
|
|
739
|
+
.option("--limit <n>", "Funding history limit per exchange", "200")
|
|
706
740
|
.action(async (opts) => {
|
|
707
741
|
await withJsonErrors(isJson(), async () => {
|
|
708
|
-
const arbState = loadArbState();
|
|
742
|
+
const arbState = loadArbState(networkOf(parent));
|
|
709
743
|
const positions = arbState?.positions ?? [];
|
|
710
744
|
if (positions.length === 0) {
|
|
711
745
|
if (isJson())
|
|
@@ -744,8 +778,12 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
744
778
|
}
|
|
745
779
|
catch { /* skip */ }
|
|
746
780
|
}));
|
|
781
|
+
// Entries without a verified entry price (a bot leg the venue reported no fill price for)
|
|
782
|
+
// have no price PnL: listed apart, never priced at a guess.
|
|
783
|
+
const priced = positions.filter((p) => p.entryLongPrice !== null && p.entryShortPrice !== null);
|
|
784
|
+
const unpricedPositions = positions.filter(p => p.entryLongPrice === null || p.entryShortPrice === null).map(p => p.symbol);
|
|
747
785
|
// Build comparison data
|
|
748
|
-
const rows =
|
|
786
|
+
const rows = priced.map(pos => {
|
|
749
787
|
const daysHeld = Math.max(1, Math.round((Date.now() - new Date(pos.entryTime).getTime()) / 86400000));
|
|
750
788
|
const longFunding = fundingByExSym.get(`${pos.longExchange}:${pos.symbol}`) ?? 0;
|
|
751
789
|
const shortFunding = fundingByExSym.get(`${pos.shortExchange}:${pos.symbol}`) ?? 0;
|
|
@@ -790,6 +828,7 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
790
828
|
period: opts.period ?? "all",
|
|
791
829
|
positionCount: rows.length,
|
|
792
830
|
positions: rows,
|
|
831
|
+
unpricedPositions,
|
|
793
832
|
totals: {
|
|
794
833
|
...totals,
|
|
795
834
|
roi: totals.notional > 0 ? (totals.totalPnl / totals.notional) * 100 : 0,
|
|
@@ -811,6 +850,8 @@ function registerAnalyticsSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
811
850
|
`${r.annualizedRoi >= 0 ? "+" : ""}${r.annualizedRoi.toFixed(1)}%`,
|
|
812
851
|
]);
|
|
813
852
|
console.log(makeTable(["Symbol", "Long → Short", "Mode", "Held", "Funding", "Price PnL", "Total PnL", "ROI", "Ann.ROI"], tableRows));
|
|
853
|
+
if (unpricedPositions.length > 0)
|
|
854
|
+
console.log(chalk.gray(` No entry price recorded (not compared): ${unpricedPositions.join(", ")}\n`));
|
|
814
855
|
console.log(chalk.white.bold(" Totals:"));
|
|
815
856
|
console.log(` Funding Income: ${formatPnl(totals.funding)}`);
|
|
816
857
|
console.log(` Price PnL: ${formatPnl(totals.pricePnl)}`);
|
|
@@ -866,10 +907,10 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
866
907
|
parent
|
|
867
908
|
.command("snapshot")
|
|
868
909
|
.description("Take equity snapshot across all exchanges")
|
|
869
|
-
.option("--exchanges <list>", "Comma-separated exchange list
|
|
910
|
+
.option("--exchanges <list>", "Comma-separated exchange list (default: all with configured credentials)")
|
|
870
911
|
.action(async (opts) => {
|
|
871
912
|
await withJsonErrors(isJson(), async () => {
|
|
872
|
-
const exchanges = opts.exchanges.split(",").map(e => e.trim());
|
|
913
|
+
const exchanges = opts.exchanges ? opts.exchanges.split(",").map(e => e.trim()) : await listConfiguredAccountVenues();
|
|
873
914
|
const snaps = await takeSnapshot(getAdapterForExchange, exchanges);
|
|
874
915
|
if (isJson()) {
|
|
875
916
|
printJson(jsonOk({ snapshots: snaps }));
|
|
@@ -893,10 +934,10 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
893
934
|
.command("track")
|
|
894
935
|
.description("Continuously track equity (foreground)")
|
|
895
936
|
.option("--interval <sec>", "Snapshot interval in seconds", "300")
|
|
896
|
-
.option("--exchanges <list>", "Comma-separated exchange list
|
|
937
|
+
.option("--exchanges <list>", "Comma-separated exchange list (default: all with configured credentials)")
|
|
897
938
|
.action(async (opts) => {
|
|
898
939
|
const intervalMs = parseInt(opts.interval) * 1000;
|
|
899
|
-
const exchanges = opts.exchanges.split(",").map(e => e.trim());
|
|
940
|
+
const exchanges = opts.exchanges ? opts.exchanges.split(",").map(e => e.trim()) : await listConfiguredAccountVenues();
|
|
900
941
|
console.log(chalk.cyan(`PnL tracker started — snapshot every ${opts.interval}s for [${exchanges.join(", ")}]`));
|
|
901
942
|
console.log(chalk.gray("Press Ctrl+C to stop\n"));
|
|
902
943
|
const controller = new AbortController();
|
|
@@ -907,8 +948,15 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
907
948
|
console.log(`${chalk.gray(new Date().toLocaleTimeString())} Total equity: $${formatUsd(prevTotal)}`);
|
|
908
949
|
while (!controller.signal.aborted) {
|
|
909
950
|
await new Promise((resolve) => {
|
|
910
|
-
|
|
911
|
-
|
|
951
|
+
let timer;
|
|
952
|
+
const onAbort = () => { clearTimeout(timer); resolve(); };
|
|
953
|
+
// Remove the listener when the timer wins so it does not pile up on
|
|
954
|
+
// the controller's signal every snapshot interval (MaxListeners leak).
|
|
955
|
+
timer = setTimeout(() => {
|
|
956
|
+
controller.signal.removeEventListener("abort", onAbort);
|
|
957
|
+
resolve();
|
|
958
|
+
}, intervalMs);
|
|
959
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
912
960
|
});
|
|
913
961
|
if (controller.signal.aborted)
|
|
914
962
|
break;
|
|
@@ -928,20 +976,20 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
928
976
|
// ── perf (unified: daily/weekly/summary) ──
|
|
929
977
|
parent
|
|
930
978
|
.command("perf")
|
|
931
|
-
.description("Performance breakdown — daily, weekly, or summary stats")
|
|
979
|
+
.description("Performance breakdown — daily, weekly, or summary stats — filter with the root -e <exchange>")
|
|
932
980
|
.option("--period <period>", "daily, weekly, or summary", "daily")
|
|
933
|
-
.option("--exchange <name>", "Single exchange filter")
|
|
934
981
|
.option("--days <n>", "Number of days (daily mode)", "14")
|
|
935
982
|
.option("--weeks <n>", "Number of weeks (weekly mode)", "8")
|
|
936
983
|
.option("--since <period>", "Time range (e.g. 7d, 2w, 30d)")
|
|
937
984
|
.action(async (opts) => {
|
|
985
|
+
const exchangeFilter = cliExchangeFilter(parent);
|
|
938
986
|
await withJsonErrors(isJson(), async () => {
|
|
939
987
|
const mode = opts.period.toLowerCase();
|
|
940
988
|
const defaultSince = mode === "weekly"
|
|
941
989
|
? new Date(Date.now() - parseInt(opts.weeks) * 7 * 86400000)
|
|
942
990
|
: new Date(Date.now() - parseInt(opts.days) * 86400000);
|
|
943
991
|
const since = parseSinceDate(opts.since) ?? defaultSince;
|
|
944
|
-
const snapshots = readEquityHistory({ exchange:
|
|
992
|
+
const snapshots = readEquityHistory({ exchange: exchangeFilter, since });
|
|
945
993
|
if (snapshots.length === 0) {
|
|
946
994
|
if (isJson()) {
|
|
947
995
|
printJson(jsonError("NO_DATA", "No equity snapshots found. Run 'perp history snapshot' or 'perp history track' first."));
|
|
@@ -952,12 +1000,12 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
952
1000
|
return;
|
|
953
1001
|
}
|
|
954
1002
|
if (mode === "summary") {
|
|
955
|
-
const metrics = computePnlMetrics(snapshots,
|
|
1003
|
+
const metrics = computePnlMetrics(snapshots, exchangeFilter);
|
|
956
1004
|
if (isJson()) {
|
|
957
1005
|
printJson(jsonOk({ ...metrics, dailyReturns: undefined, dailyCount: metrics.dailyReturns.length }));
|
|
958
1006
|
}
|
|
959
1007
|
else {
|
|
960
|
-
console.log(chalk.cyan.bold(`Performance Summary${
|
|
1008
|
+
console.log(chalk.cyan.bold(`Performance Summary${exchangeFilter ? ` (${exchangeFilter})` : ""}\n`));
|
|
961
1009
|
console.log(` Period: ${metrics.period.from} → ${metrics.period.to} (${metrics.period.days} days)`);
|
|
962
1010
|
console.log(` Total Return: ${formatPnl(metrics.totalReturn)} (${metrics.totalReturnPct >= 0 ? "+" : ""}${metrics.totalReturnPct.toFixed(2)}%)`);
|
|
963
1011
|
console.log(` Peak Equity: $${formatUsd(metrics.peakEquity)}`);
|
|
@@ -976,14 +1024,14 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
976
1024
|
}
|
|
977
1025
|
return;
|
|
978
1026
|
}
|
|
979
|
-
const daily = computeDailyPnl(snapshots,
|
|
1027
|
+
const daily = computeDailyPnl(snapshots, exchangeFilter);
|
|
980
1028
|
if (mode === "weekly") {
|
|
981
1029
|
const weekly = aggregateWeekly(daily);
|
|
982
1030
|
if (isJson()) {
|
|
983
1031
|
printJson(jsonOk({ weekly }));
|
|
984
1032
|
return;
|
|
985
1033
|
}
|
|
986
|
-
console.log(chalk.cyan.bold(`Weekly PnL${
|
|
1034
|
+
console.log(chalk.cyan.bold(`Weekly PnL${exchangeFilter ? ` (${exchangeFilter})` : ""}\n`));
|
|
987
1035
|
const rows = weekly.map(w => [w.date, `$${formatUsd(w.startEquity)}`, `$${formatUsd(w.endEquity)}`, formatPnl(w.pnl), `${w.pnlPct >= 0 ? "+" : ""}${w.pnlPct.toFixed(2)}%`]);
|
|
988
1036
|
console.log(makeTable(["Week", "Start", "End", "PnL", "PnL %"], rows));
|
|
989
1037
|
}
|
|
@@ -993,7 +1041,7 @@ function registerPnlSubcommands(parent, getAdapterForExchange, isJson) {
|
|
|
993
1041
|
printJson(jsonOk({ daily }));
|
|
994
1042
|
return;
|
|
995
1043
|
}
|
|
996
|
-
console.log(chalk.cyan.bold(`Daily PnL${
|
|
1044
|
+
console.log(chalk.cyan.bold(`Daily PnL${exchangeFilter ? ` (${exchangeFilter})` : ""}\n`));
|
|
997
1045
|
const rows = daily.map(d => [d.date, `$${formatUsd(d.startEquity)}`, `$${formatUsd(d.endEquity)}`, formatPnl(d.pnl), `${d.pnlPct >= 0 ? "+" : ""}${d.pnlPct.toFixed(2)}%`]);
|
|
998
1046
|
console.log(makeTable(["Date", "Start", "End", "PnL", "PnL %"], rows));
|
|
999
1047
|
}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
import { type Settings } from "../settings.js";
|
|
3
|
+
import { type StructuredError } from "../errors.js";
|
|
4
|
+
import { type VenueDefinition } from "../exchanges/venue.js";
|
|
5
|
+
import "../exchanges/venues/index.js";
|
|
6
|
+
import type { Network, VenueId } from "../exchanges/venue-types.js";
|
|
7
|
+
import { type ImportVerification } from "./agent-import.js";
|
|
2
8
|
declare const ENV_FILE: string;
|
|
3
9
|
export { ENV_FILE, loadEnvFile, setEnvVar };
|
|
4
10
|
declare function loadEnvFile(): Record<string, string>;
|
|
@@ -13,23 +19,109 @@ export declare function validateKey(chain: "solana" | "evm" | "apikey", key: str
|
|
|
13
19
|
valid: boolean;
|
|
14
20
|
address: string;
|
|
15
21
|
}>;
|
|
16
|
-
|
|
22
|
+
/** Names (never values) of legacy private-key variables present in ~/.perp/.env. */
|
|
23
|
+
export declare function legacyEnvKeyNames(): string[];
|
|
24
|
+
/** Trading venues from the registry (no hardcoded list). */
|
|
25
|
+
export declare function setupVenues(): VenueDefinition[];
|
|
26
|
+
/** Resolve one venue id/alias for setup: must be a trading venue with an environment on `network`. */
|
|
27
|
+
export declare function resolveSetupVenue(input: string, network: Network): VenueId;
|
|
28
|
+
/** Parse a comma-separated venue list (ids or aliases), de-duplicated in input order. */
|
|
29
|
+
export declare function parseVenueList(csv: string, network: Network): VenueId[];
|
|
30
|
+
/** Parse `<venue>=<bps>` per-venue slippage overrides; each bps must fit that venue's maxSlippageBps. */
|
|
31
|
+
export declare function parseVenueSlippage(entries: string[], network: Network): {
|
|
32
|
+
[K in VenueId]?: number;
|
|
33
|
+
};
|
|
34
|
+
export interface SetupSettingsChange {
|
|
35
|
+
/** null = leave settings.owsActiveWallet unchanged (no master wallet on this computer). */
|
|
36
|
+
owsActiveWallet: string | null;
|
|
37
|
+
/** null = leave settings.defaultExchange unchanged. */
|
|
38
|
+
defaultExchange: VenueId | null;
|
|
39
|
+
/** null = leave settings.defaultSlippageBps unchanged. */
|
|
40
|
+
defaultSlippageBps: number | null;
|
|
41
|
+
/** Per-venue overrides to set (other venues' overrides are left alone). */
|
|
42
|
+
slippageBps: {
|
|
43
|
+
[K in VenueId]?: number;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Write the wizard's choices to ~/.perp/settings.json (metadata only — never secrets). */
|
|
47
|
+
export declare function applySetupSettings(change: SetupSettingsChange): Settings;
|
|
48
|
+
/** Real follow-up commands for the configured venues (all exist in this CLI). */
|
|
49
|
+
export declare function nextStepCommands(venues: VenueId[], network: Network): string[];
|
|
50
|
+
/** Plain-language slippage explanation (design §13.2, §13.10 #3). */
|
|
51
|
+
export declare function slippageExplanation(venues: VenueId[]): string[];
|
|
52
|
+
export type AgentStepResult = {
|
|
53
|
+
venue: VenueId;
|
|
54
|
+
status: "approved";
|
|
55
|
+
agentName: string;
|
|
56
|
+
} | {
|
|
57
|
+
venue: VenueId;
|
|
58
|
+
status: "imported";
|
|
59
|
+
agentName: string;
|
|
60
|
+
verification: ImportVerification;
|
|
61
|
+
} | {
|
|
62
|
+
venue: VenueId;
|
|
63
|
+
status: "skipped";
|
|
64
|
+
reason: string;
|
|
65
|
+
} | {
|
|
66
|
+
venue: VenueId;
|
|
67
|
+
status: "failed";
|
|
68
|
+
error: StructuredError;
|
|
69
|
+
};
|
|
70
|
+
/** Prompt I/O for the wizard (injectable for tests). askHidden never echoes. */
|
|
71
|
+
export interface Prompter {
|
|
72
|
+
ask(question: string): Promise<string>;
|
|
73
|
+
askHidden(question: string): Promise<string>;
|
|
74
|
+
}
|
|
17
75
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* - --wallet-name (default: "main")
|
|
22
|
-
* - --default-exchange (must be one of pacifica/hyperliquid/lighter/aster)
|
|
23
|
-
*
|
|
24
|
-
* Side effects:
|
|
25
|
-
* 1. Creates an OWS wallet via createWallet(name, passphrase)
|
|
26
|
-
* 2. Sets settings.owsActiveWallet (if unset) + settings.defaultExchange (if provided)
|
|
27
|
-
*
|
|
28
|
-
* Errors are returned as INVALID_PARAMS / PASSPHRASE_REQUIRED — never via
|
|
29
|
-
* readline. JSON envelope is emitted on stdout when --json is present.
|
|
76
|
+
* Optional builder-fee step — offered only when settings `builder.<venue>` already holds a
|
|
77
|
+
* value for a chosen venue (builder fees ship off). Explains the fee and approves only after
|
|
78
|
+
* an explicit "y" (default No). Never configures a builder itself.
|
|
30
79
|
*/
|
|
31
|
-
export declare function
|
|
80
|
+
export declare function stepBuilder(p: Prompter, venues: VenueId[], network: Network, master: string | null, getPassphrase: () => Promise<string>): Promise<void>;
|
|
81
|
+
/** Interactive `perp setup`. All prompts go through `p`; nothing secret is printed or written to .env. */
|
|
82
|
+
export declare function runInteractiveSetup(p: Prompter, passphraseFlag: string | undefined, preselectedNetwork: Network): Promise<void>;
|
|
83
|
+
export interface SetupOpts {
|
|
84
|
+
nonInteractive?: boolean;
|
|
85
|
+
wallet?: string;
|
|
32
86
|
walletName?: string;
|
|
33
87
|
passphrase?: string;
|
|
88
|
+
/** Root -n/--network (validated by networkOf). */
|
|
89
|
+
network: Network;
|
|
90
|
+
venues?: string;
|
|
91
|
+
defaultVenue?: string;
|
|
34
92
|
defaultExchange?: string;
|
|
35
|
-
|
|
93
|
+
slippageBps?: string;
|
|
94
|
+
slippage: string[];
|
|
95
|
+
approveAgents?: boolean;
|
|
96
|
+
yes?: boolean;
|
|
97
|
+
ondoSecretStdin?: boolean;
|
|
98
|
+
asterCanSpot?: boolean;
|
|
99
|
+
lighterApiKeyIndex?: string;
|
|
100
|
+
lighterRhApiKeyIndex?: string;
|
|
101
|
+
arcusAccountIndex?: string;
|
|
102
|
+
/** QFEX account UUID the imported key trades (--import-agents); it is the non-interactive confirmation. */
|
|
103
|
+
qfexAccountId?: string;
|
|
104
|
+
/** Venues whose key was created on the exchange website (keys read from stdin, in this order). */
|
|
105
|
+
importAgents?: string;
|
|
106
|
+
/** `<venue>=<address>` master / owner public addresses for --import-agents (repeatable). */
|
|
107
|
+
masterAddress: string[];
|
|
108
|
+
/** --import-agents venues the user accepts storing UNVERIFIED (pacifica has no read-only check). */
|
|
109
|
+
allowUnverified?: string;
|
|
110
|
+
lighterAccountIndex?: string;
|
|
111
|
+
lighterRhAccountIndex?: string;
|
|
112
|
+
}
|
|
113
|
+
export declare function registerInitCommand(program: Command): void;
|
|
114
|
+
/**
|
|
115
|
+
* Drive `perp setup` end-to-end without TTY.
|
|
116
|
+
*
|
|
117
|
+
* Master wallet: exactly one of --wallet <existing> or --wallet-name <new>.
|
|
118
|
+
* Passphrase (--passphrase / OWS_PASSPHRASE / stdin) is required to create a
|
|
119
|
+
* wallet or to sign agent approvals. With --ondo-secret-stdin, stdin carries
|
|
120
|
+
* the Ondo key, so the passphrase must come from the flag or env.
|
|
121
|
+
*
|
|
122
|
+
* Side effects, in order: validate everything → create wallet (if asked) →
|
|
123
|
+
* write settings (owsActiveWallet, defaultExchange, slippage) → register
|
|
124
|
+
* agents (only with --approve-agents --yes; a failure on one venue does not
|
|
125
|
+
* stop the others). Never deposits, withdraws, or trades; never writes .env.
|
|
126
|
+
*/
|
|
127
|
+
export declare function runNonInteractiveSetup(opts: SetupOpts): Promise<void>;
|