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/account.js
CHANGED
|
@@ -1,99 +1,7 @@
|
|
|
1
|
-
import { makeTable, formatUsd, formatPnl, printJson, jsonOk, jsonError, symbolMatch
|
|
1
|
+
import { makeTable, formatUsd, formatPnl, printJson, jsonOk, jsonError, symbolMatch } from "../utils.js";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import { assessRisk } from "../risk.js";
|
|
4
3
|
import { hasPacificaSdk, isDexCapable } from "../exchanges/capabilities.js";
|
|
5
4
|
const EXCHANGES = ["pacifica", "hyperliquid", "lighter", "aster"];
|
|
6
|
-
async function fetchExchangeSnapshot(name, getAdapter) {
|
|
7
|
-
try {
|
|
8
|
-
const adapter = await getAdapter(name);
|
|
9
|
-
const [balance, positions, orders] = await Promise.all([
|
|
10
|
-
adapter.getBalance(),
|
|
11
|
-
adapter.getPositions(),
|
|
12
|
-
adapter.getOpenOrders(),
|
|
13
|
-
]);
|
|
14
|
-
return {
|
|
15
|
-
exchange: name,
|
|
16
|
-
connected: true,
|
|
17
|
-
balance,
|
|
18
|
-
positions,
|
|
19
|
-
openOrders: orders.length,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
catch (err) {
|
|
23
|
-
return {
|
|
24
|
-
exchange: name,
|
|
25
|
-
connected: false,
|
|
26
|
-
balance: null,
|
|
27
|
-
positions: [],
|
|
28
|
-
openOrders: 0,
|
|
29
|
-
error: err instanceof Error ? err.message : String(err),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function buildSummary(snapshots) {
|
|
34
|
-
let totalEquity = 0;
|
|
35
|
-
let totalAvailable = 0;
|
|
36
|
-
let totalMarginUsed = 0;
|
|
37
|
-
let totalUnrealizedPnl = 0;
|
|
38
|
-
let totalPositions = 0;
|
|
39
|
-
let totalOpenOrders = 0;
|
|
40
|
-
const allPositions = [];
|
|
41
|
-
for (const snap of snapshots) {
|
|
42
|
-
if (snap.balance) {
|
|
43
|
-
totalEquity += Number(snap.balance.equity);
|
|
44
|
-
totalAvailable += Number(snap.balance.available);
|
|
45
|
-
totalMarginUsed += Number(snap.balance.marginUsed);
|
|
46
|
-
totalUnrealizedPnl += Number(snap.balance.unrealizedPnl);
|
|
47
|
-
}
|
|
48
|
-
totalPositions += snap.positions.length;
|
|
49
|
-
totalOpenOrders += snap.openOrders;
|
|
50
|
-
for (const pos of snap.positions) {
|
|
51
|
-
allPositions.push({ ...pos, exchange: snap.exchange });
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Risk metrics
|
|
55
|
-
const marginUtilization = totalEquity > 0 ? (totalMarginUsed / totalEquity) * 100 : 0;
|
|
56
|
-
let largestPosition = null;
|
|
57
|
-
for (const pos of allPositions) {
|
|
58
|
-
const notional = Math.abs(Number(pos.size) * Number(pos.markPrice));
|
|
59
|
-
if (!largestPosition || notional > largestPosition.notional) {
|
|
60
|
-
largestPosition = { symbol: pos.symbol, exchange: pos.exchange, notional };
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const exchangeConcentration = snapshots
|
|
64
|
-
.filter(s => s.balance && Number(s.balance.equity) > 0)
|
|
65
|
-
.map(s => ({
|
|
66
|
-
exchange: s.exchange,
|
|
67
|
-
pct: totalEquity > 0 ? (Number(s.balance.equity) / totalEquity) * 100 : 0,
|
|
68
|
-
}))
|
|
69
|
-
.sort((a, b) => b.pct - a.pct);
|
|
70
|
-
// Full risk assessment (reuses same data, no extra API calls)
|
|
71
|
-
const riskBalances = snapshots
|
|
72
|
-
.filter(s => s.balance)
|
|
73
|
-
.map(s => ({ exchange: s.exchange, balance: s.balance }));
|
|
74
|
-
const riskPositions = allPositions.map(p => ({ exchange: p.exchange, position: p }));
|
|
75
|
-
const assessment = assessRisk(riskBalances, riskPositions);
|
|
76
|
-
return {
|
|
77
|
-
totalEquity,
|
|
78
|
-
totalAvailable,
|
|
79
|
-
totalMarginUsed,
|
|
80
|
-
totalUnrealizedPnl,
|
|
81
|
-
totalPositions,
|
|
82
|
-
totalOpenOrders,
|
|
83
|
-
exchanges: snapshots,
|
|
84
|
-
positions: allPositions,
|
|
85
|
-
riskMetrics: {
|
|
86
|
-
marginUtilization,
|
|
87
|
-
largestPosition,
|
|
88
|
-
exchangeConcentration,
|
|
89
|
-
},
|
|
90
|
-
risk: {
|
|
91
|
-
level: assessment.level,
|
|
92
|
-
canTrade: assessment.canTrade,
|
|
93
|
-
violations: assessment.violations,
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
5
|
function pac(adapter) {
|
|
98
6
|
if (!hasPacificaSdk(adapter))
|
|
99
7
|
throw new Error("Market settings are only available on Pacifica.");
|
|
@@ -101,231 +9,7 @@ function pac(adapter) {
|
|
|
101
9
|
}
|
|
102
10
|
export function registerAccountCommands(program, getAdapter, isJson, getAdapterForExchange) {
|
|
103
11
|
const account = program.command("account").description("Account commands");
|
|
104
|
-
|
|
105
|
-
const name = exName.toLowerCase();
|
|
106
|
-
const [bal, fundingPayments] = await Promise.all([
|
|
107
|
-
adapter.getBalance(),
|
|
108
|
-
adapter.getFundingPayments(200).catch(() => []),
|
|
109
|
-
]);
|
|
110
|
-
let spotBalances = [];
|
|
111
|
-
try {
|
|
112
|
-
if (name === "hyperliquid") {
|
|
113
|
-
const { HyperliquidSpotAdapter } = await import("../exchanges/hyperliquid-spot.js");
|
|
114
|
-
const { HyperliquidAdapter } = await import("../exchanges/hyperliquid.js");
|
|
115
|
-
const hlSpot = new HyperliquidSpotAdapter(adapter);
|
|
116
|
-
await hlSpot.init();
|
|
117
|
-
const raw = await hlSpot.getSpotBalances();
|
|
118
|
-
const markets = await hlSpot.getSpotMarkets();
|
|
119
|
-
const priceMap = new Map(markets.map(m => [m.baseToken.toUpperCase(), Number(m.markPrice)]));
|
|
120
|
-
const stripSuffix = (t) => t.replace(/-SPOT$/i, "").toUpperCase();
|
|
121
|
-
spotBalances = raw
|
|
122
|
-
.filter(b => Number(b.total) > 0)
|
|
123
|
-
.map(b => {
|
|
124
|
-
const base = stripSuffix(b.token);
|
|
125
|
-
return {
|
|
126
|
-
...b,
|
|
127
|
-
valueUsd: base === "USDC" ? Number(b.total) : (priceMap.get(base) ?? 0) * Number(b.total),
|
|
128
|
-
};
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
else if (name === "lighter") {
|
|
132
|
-
const { LighterAdapter } = await import("../exchanges/lighter.js");
|
|
133
|
-
const { LighterSpotAdapter } = await import("../exchanges/lighter-spot.js");
|
|
134
|
-
const ltSpot = new LighterSpotAdapter(adapter);
|
|
135
|
-
await ltSpot.init();
|
|
136
|
-
const raw = await ltSpot.getSpotBalances();
|
|
137
|
-
const markets = await ltSpot.getSpotMarkets();
|
|
138
|
-
const priceMap = new Map(markets.map(m => [m.baseToken.toUpperCase(), Number(m.markPrice)]));
|
|
139
|
-
spotBalances = raw
|
|
140
|
-
.filter(b => Number(b.total) > 0)
|
|
141
|
-
.map(b => ({
|
|
142
|
-
...b,
|
|
143
|
-
valueUsd: b.token === "USDC" || b.token === "USDC_SPOT"
|
|
144
|
-
? Number(b.total)
|
|
145
|
-
: (priceMap.get(b.token.toUpperCase()) ?? 0) * Number(b.total),
|
|
146
|
-
}));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
catch { /* spot not available */ }
|
|
150
|
-
// HL unified account: perp equity already includes spot USDC balance.
|
|
151
|
-
// Detect by checking if adapter is HL without a dex override.
|
|
152
|
-
const isUnified = name === "hyperliquid" && (!isDexCapable(adapter) || !adapter.dex);
|
|
153
|
-
const cutoff24h = Date.now() - 24 * 60 * 60 * 1000;
|
|
154
|
-
const recent = fundingPayments.filter(f => f.time >= cutoff24h);
|
|
155
|
-
const funding24h = recent.reduce((sum, f) => sum + Number(f.payment), 0);
|
|
156
|
-
const totalSpotUsd = spotBalances.reduce((s, b) => s + (b.valueUsd ?? 0), 0);
|
|
157
|
-
// For unified accounts, equity already contains USDC spot value.
|
|
158
|
-
// Only add non-USDC spot token values to avoid double-counting.
|
|
159
|
-
const nonUsdcSpotUsd = isUnified
|
|
160
|
-
? spotBalances
|
|
161
|
-
.filter(b => {
|
|
162
|
-
const tk = b.token.replace(/-SPOT$/i, "").toUpperCase();
|
|
163
|
-
return tk !== "USDC";
|
|
164
|
-
})
|
|
165
|
-
.reduce((s, b) => s + (b.valueUsd ?? 0), 0)
|
|
166
|
-
: totalSpotUsd;
|
|
167
|
-
return {
|
|
168
|
-
exchange: name,
|
|
169
|
-
perp: bal,
|
|
170
|
-
spot: spotBalances,
|
|
171
|
-
funding24h,
|
|
172
|
-
fundingPayments24h: recent.length,
|
|
173
|
-
totalSpotValueUsd: totalSpotUsd,
|
|
174
|
-
totalAccountValueUsd: Number(bal.equity) + nonUsdcSpotUsd,
|
|
175
|
-
unifiedAccount: isUnified,
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
function printSingleBalance(exName, r) {
|
|
179
|
-
console.log(chalk.cyan.bold(`\n ${exName.toUpperCase()} Account Balance`));
|
|
180
|
-
if (r.unifiedAccount)
|
|
181
|
-
console.log(chalk.gray(" (Unified account — perp & spot share single balance)\n"));
|
|
182
|
-
else
|
|
183
|
-
console.log();
|
|
184
|
-
console.log(chalk.white.bold(r.unifiedAccount ? " Account" : " Perp Account"));
|
|
185
|
-
console.log(` Equity: $${formatUsd(r.perp.equity)}`);
|
|
186
|
-
console.log(` Available: $${formatUsd(r.perp.available)}`);
|
|
187
|
-
console.log(` Margin Used: $${formatUsd(r.perp.marginUsed)}`);
|
|
188
|
-
console.log(` Unreal. PnL: ${formatPnl(r.perp.unrealizedPnl)}`);
|
|
189
|
-
// For unified, show non-USDC spot holdings (USDC is already in equity)
|
|
190
|
-
const displaySpot = r.unifiedAccount
|
|
191
|
-
? r.spot.filter(b => b.token.replace(/-SPOT$/i, "").toUpperCase() !== "USDC")
|
|
192
|
-
: r.spot;
|
|
193
|
-
if (displaySpot.length > 0) {
|
|
194
|
-
console.log(chalk.white.bold("\n Spot Holdings"));
|
|
195
|
-
const rows = displaySpot.map(b => [
|
|
196
|
-
chalk.white.bold(b.token),
|
|
197
|
-
b.total,
|
|
198
|
-
b.available,
|
|
199
|
-
b.held !== "0" ? b.held : chalk.gray("-"),
|
|
200
|
-
b.valueUsd ? `$${formatUsd(b.valueUsd)}` : chalk.gray("-"),
|
|
201
|
-
]);
|
|
202
|
-
console.log(makeTable(["Token", "Total", "Available", "Held", "Value"], rows));
|
|
203
|
-
}
|
|
204
|
-
console.log(chalk.white.bold(" Funding (24h)"));
|
|
205
|
-
console.log(` Payments: ${r.fundingPayments24h}`);
|
|
206
|
-
console.log(` Total: ${formatPnl(r.funding24h)}`);
|
|
207
|
-
// Only show Total breakdown when there are non-USDC spot tokens adding value
|
|
208
|
-
const nonUsdcSpotValue = displaySpot.reduce((s, b) => s + (b.valueUsd ?? 0), 0);
|
|
209
|
-
if (nonUsdcSpotValue > 0) {
|
|
210
|
-
console.log(chalk.white.bold("\n Total"));
|
|
211
|
-
console.log(` Equity: $${formatUsd(r.perp.equity)}`);
|
|
212
|
-
console.log(` Spot (other): $${formatUsd(nonUsdcSpotValue)}`);
|
|
213
|
-
console.log(` Total Value: $${formatUsd(r.totalAccountValueUsd)}`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
account
|
|
217
|
-
.command("balance")
|
|
218
|
-
.description("Account overview: perp balance, spot holdings, and 24h funding")
|
|
219
|
-
.action(async () => {
|
|
220
|
-
// Detect if user explicitly set -e (single exchange mode)
|
|
221
|
-
const explicitExchange = program.getOptionValueSource?.("exchange") === "cli";
|
|
222
|
-
// Multi-exchange mode: show all exchanges
|
|
223
|
-
if (!explicitExchange && getAdapterForExchange) {
|
|
224
|
-
const results = [];
|
|
225
|
-
const errors = {};
|
|
226
|
-
await Promise.all(EXCHANGES.map(async (ex) => {
|
|
227
|
-
try {
|
|
228
|
-
const adapter = await getAdapterForExchange(ex);
|
|
229
|
-
results.push(await fetchExchangeBalance(ex, adapter));
|
|
230
|
-
}
|
|
231
|
-
catch (err) {
|
|
232
|
-
errors[ex] = err instanceof Error ? err.message : String(err);
|
|
233
|
-
}
|
|
234
|
-
}));
|
|
235
|
-
// Sort by equity desc
|
|
236
|
-
results.sort((a, b) => b.totalAccountValueUsd - a.totalAccountValueUsd);
|
|
237
|
-
if (isJson()) {
|
|
238
|
-
const grandTotal = results.reduce((s, r) => s + r.totalAccountValueUsd, 0);
|
|
239
|
-
return printJson(jsonOk({
|
|
240
|
-
exchanges: results,
|
|
241
|
-
errors: Object.keys(errors).length > 0 ? errors : undefined,
|
|
242
|
-
totalEquity: results.reduce((s, r) => s + Number(r.perp.equity), 0),
|
|
243
|
-
totalSpotValueUsd: results.reduce((s, r) => {
|
|
244
|
-
if (r.unifiedAccount) {
|
|
245
|
-
return s + r.spot
|
|
246
|
-
.filter(b => b.token.replace(/-SPOT$/i, "").toUpperCase() !== "USDC")
|
|
247
|
-
.reduce((ss, b) => ss + (b.valueUsd ?? 0), 0);
|
|
248
|
-
}
|
|
249
|
-
return s + r.totalSpotValueUsd;
|
|
250
|
-
}, 0),
|
|
251
|
-
totalAccountValueUsd: grandTotal,
|
|
252
|
-
totalFunding24h: results.reduce((s, r) => s + r.funding24h, 0),
|
|
253
|
-
}));
|
|
254
|
-
}
|
|
255
|
-
console.log(chalk.cyan.bold("\n All Exchanges — Account Balance\n"));
|
|
256
|
-
// Summary table
|
|
257
|
-
// For unified accounts, Spot column shows non-USDC only (USDC already in Equity)
|
|
258
|
-
const balRows = results.map(r => {
|
|
259
|
-
const nonUsdcSpot = r.unifiedAccount
|
|
260
|
-
? r.spot
|
|
261
|
-
.filter(b => b.token.replace(/-SPOT$/i, "").toUpperCase() !== "USDC")
|
|
262
|
-
.reduce((s, b) => s + (b.valueUsd ?? 0), 0)
|
|
263
|
-
: r.totalSpotValueUsd;
|
|
264
|
-
return [
|
|
265
|
-
chalk.white.bold(r.exchange) + (r.unifiedAccount ? chalk.gray(" ★") : ""),
|
|
266
|
-
`$${formatUsd(r.perp.equity)}`,
|
|
267
|
-
`$${formatUsd(r.perp.available)}`,
|
|
268
|
-
`$${formatUsd(r.perp.marginUsed)}`,
|
|
269
|
-
nonUsdcSpot > 0 ? `$${formatUsd(nonUsdcSpot)}` : chalk.gray("-"),
|
|
270
|
-
formatPnl(r.funding24h),
|
|
271
|
-
`$${formatUsd(r.totalAccountValueUsd)}`,
|
|
272
|
-
];
|
|
273
|
-
});
|
|
274
|
-
const grandEquity = results.reduce((s, r) => s + Number(r.perp.equity), 0);
|
|
275
|
-
const grandSpot = results.reduce((s, r) => {
|
|
276
|
-
if (r.unifiedAccount) {
|
|
277
|
-
return s + r.spot
|
|
278
|
-
.filter(b => b.token.replace(/-SPOT$/i, "").toUpperCase() !== "USDC")
|
|
279
|
-
.reduce((ss, b) => ss + (b.valueUsd ?? 0), 0);
|
|
280
|
-
}
|
|
281
|
-
return s + r.totalSpotValueUsd;
|
|
282
|
-
}, 0);
|
|
283
|
-
const grandFunding = results.reduce((s, r) => s + r.funding24h, 0);
|
|
284
|
-
const grandTotal = results.reduce((s, r) => s + r.totalAccountValueUsd, 0);
|
|
285
|
-
balRows.push([
|
|
286
|
-
chalk.cyan.bold("TOTAL"),
|
|
287
|
-
chalk.cyan.bold(`$${formatUsd(grandEquity)}`),
|
|
288
|
-
"",
|
|
289
|
-
"",
|
|
290
|
-
grandSpot > 0 ? chalk.cyan.bold(`$${formatUsd(grandSpot)}`) : "",
|
|
291
|
-
formatPnl(grandFunding),
|
|
292
|
-
chalk.cyan.bold(`$${formatUsd(grandTotal)}`),
|
|
293
|
-
]);
|
|
294
|
-
console.log(makeTable(["Exchange", "Equity", "Available", "Margin", "Spot", "Funding 24h", "Total"], balRows));
|
|
295
|
-
if (results.some(r => r.unifiedAccount)) {
|
|
296
|
-
console.log(chalk.gray(" ★ Unified account — Equity includes spot USDC, Spot shows non-USDC tokens only\n"));
|
|
297
|
-
}
|
|
298
|
-
// Spot details per exchange (for unified, skip USDC as it's in equity)
|
|
299
|
-
for (const r of results) {
|
|
300
|
-
const displaySpot = r.unifiedAccount
|
|
301
|
-
? r.spot.filter(b => b.token.replace(/-SPOT$/i, "").toUpperCase() !== "USDC")
|
|
302
|
-
: r.spot;
|
|
303
|
-
if (displaySpot.length > 0) {
|
|
304
|
-
console.log(chalk.white.bold(` ${r.exchange.toUpperCase()} Spot Holdings`));
|
|
305
|
-
const rows = displaySpot.map(b => [
|
|
306
|
-
chalk.white.bold(b.token),
|
|
307
|
-
b.total,
|
|
308
|
-
b.valueUsd ? `$${formatUsd(b.valueUsd)}` : chalk.gray("-"),
|
|
309
|
-
]);
|
|
310
|
-
console.log(makeTable(["Token", "Total", "Value"], rows));
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
// Errors
|
|
314
|
-
for (const [ex, msg] of Object.entries(errors)) {
|
|
315
|
-
console.log(chalk.gray(` ${ex}: ${msg}`));
|
|
316
|
-
}
|
|
317
|
-
console.log();
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
// Single exchange mode (explicit -e or no getAdapterForExchange)
|
|
321
|
-
const adapter = await getAdapter();
|
|
322
|
-
const exName = adapter.name.toLowerCase();
|
|
323
|
-
const result = await fetchExchangeBalance(exName, adapter);
|
|
324
|
-
if (isJson())
|
|
325
|
-
return printJson(jsonOk(result));
|
|
326
|
-
printSingleBalance(exName, result);
|
|
327
|
-
console.log();
|
|
328
|
-
});
|
|
12
|
+
// ── Single exchange balance fetch (used by both single + multi mode) ──
|
|
329
13
|
// ── HIP-3 dex helper: fetch data from all deployed dexes in parallel ──
|
|
330
14
|
async function fetchHip3Data(hlAdapter, fetcher) {
|
|
331
15
|
const dexes = await hlAdapter.listDeployedDexes();
|
|
@@ -932,186 +616,4 @@ export function registerAccountCommands(program, getAdapter, isJson, getAdapterF
|
|
|
932
616
|
]);
|
|
933
617
|
console.log(makeTable(["ID", "Symbol", "Side", "Size", "Filled", "Duration"], rows));
|
|
934
618
|
});
|
|
935
|
-
// ── Portfolio (top-level command) ──
|
|
936
|
-
if (getAdapterForExchange) {
|
|
937
|
-
program
|
|
938
|
-
.command("portfolio")
|
|
939
|
-
.description("Cross-exchange portfolio overview with risk metrics")
|
|
940
|
-
.option("--exchange <exchanges>", "Comma-separated exchanges to include (default: all)")
|
|
941
|
-
.action(async (opts) => {
|
|
942
|
-
await withJsonErrors(isJson(), async () => {
|
|
943
|
-
const exchanges = opts.exchange
|
|
944
|
-
? opts.exchange.split(",").map(e => e.trim())
|
|
945
|
-
: [...EXCHANGES];
|
|
946
|
-
// Fetch snapshots + funding + spot ALL in parallel
|
|
947
|
-
const fundingByExSym = new Map();
|
|
948
|
-
const spotRows = [];
|
|
949
|
-
let totalSpotValue = 0;
|
|
950
|
-
const [snapshots] = await Promise.all([
|
|
951
|
-
// Phase 1: balance + positions + orders
|
|
952
|
-
Promise.all(exchanges.map(ex => fetchExchangeSnapshot(ex, getAdapterForExchange))),
|
|
953
|
-
// Phase 2: funding payments (parallel with Phase 1)
|
|
954
|
-
Promise.allSettled(exchanges.map(async (exName) => {
|
|
955
|
-
try {
|
|
956
|
-
const adapter = await getAdapterForExchange(exName);
|
|
957
|
-
const payments = await adapter.getFundingPayments(200);
|
|
958
|
-
for (const p of payments) {
|
|
959
|
-
const sym = p.symbol.replace("-PERP", "").toUpperCase();
|
|
960
|
-
const key = `${exName}:${sym}`;
|
|
961
|
-
fundingByExSym.set(key, (fundingByExSym.get(key) ?? 0) + Number(p.payment));
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
catch { /* skip */ }
|
|
965
|
-
})),
|
|
966
|
-
// Phase 3: spot balances (parallel with Phase 1+2)
|
|
967
|
-
Promise.allSettled(exchanges.map(async (exName) => {
|
|
968
|
-
try {
|
|
969
|
-
const adapter = await getAdapterForExchange(exName);
|
|
970
|
-
if (exName === "hyperliquid") {
|
|
971
|
-
const { HyperliquidSpotAdapter } = await import("../exchanges/hyperliquid-spot.js");
|
|
972
|
-
const { HyperliquidAdapter } = await import("../exchanges/hyperliquid.js");
|
|
973
|
-
const hlSpot = new HyperliquidSpotAdapter(adapter);
|
|
974
|
-
await hlSpot.init();
|
|
975
|
-
const bals = await hlSpot.getSpotBalances();
|
|
976
|
-
const markets = await hlSpot.getSpotMarkets();
|
|
977
|
-
const priceMap = new Map(markets.map(m => [m.baseToken.toUpperCase(), Number(m.markPrice)]));
|
|
978
|
-
for (const b of bals) {
|
|
979
|
-
const base = b.token.replace(/-SPOT$/i, "").toUpperCase();
|
|
980
|
-
if (base === "USDC" || Number(b.total) <= 0)
|
|
981
|
-
continue;
|
|
982
|
-
const price = priceMap.get(base) ?? 0;
|
|
983
|
-
const value = price * Number(b.total);
|
|
984
|
-
if (value < 1)
|
|
985
|
-
continue;
|
|
986
|
-
totalSpotValue += value;
|
|
987
|
-
spotRows.push([chalk.white.bold(base), chalk.gray("hyperliquid"), b.total, `$${formatUsd(price)}`, `$${formatUsd(value)}`]);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
else if (exName === "lighter") {
|
|
991
|
-
const { LighterAdapter } = await import("../exchanges/lighter.js");
|
|
992
|
-
const { LighterSpotAdapter } = await import("../exchanges/lighter-spot.js");
|
|
993
|
-
const ltSpot = new LighterSpotAdapter(adapter);
|
|
994
|
-
await ltSpot.init();
|
|
995
|
-
const bals = await ltSpot.getSpotBalances();
|
|
996
|
-
const markets = await ltSpot.getSpotMarkets();
|
|
997
|
-
const priceMap = new Map(markets.map(m => [m.baseToken.toUpperCase(), Number(m.markPrice)]));
|
|
998
|
-
for (const b of bals) {
|
|
999
|
-
if (b.token === "USDC" || b.token === "USDC_SPOT" || Number(b.total) <= 0)
|
|
1000
|
-
continue;
|
|
1001
|
-
const price = priceMap.get(b.token.toUpperCase()) ?? 0;
|
|
1002
|
-
const value = price * Number(b.total);
|
|
1003
|
-
if (value < 1)
|
|
1004
|
-
continue;
|
|
1005
|
-
totalSpotValue += value;
|
|
1006
|
-
spotRows.push([chalk.white.bold(b.token), chalk.gray("lighter"), b.total, `$${formatUsd(price)}`, `$${formatUsd(value)}`]);
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
catch { /* spot not available */ }
|
|
1011
|
-
})),
|
|
1012
|
-
]);
|
|
1013
|
-
const summary = buildSummary(snapshots);
|
|
1014
|
-
if (isJson()) {
|
|
1015
|
-
return printJson(jsonOk(summary));
|
|
1016
|
-
}
|
|
1017
|
-
// ── Header ──
|
|
1018
|
-
console.log(chalk.cyan.bold("\n Cross-Exchange Portfolio\n"));
|
|
1019
|
-
// ── Balance Summary ──
|
|
1020
|
-
console.log(chalk.white.bold(" Balances"));
|
|
1021
|
-
const balRows = snapshots.map(s => {
|
|
1022
|
-
if (!s.connected) {
|
|
1023
|
-
return [chalk.white(s.exchange), chalk.red("disconnected"), "-", "-", "-", chalk.gray(s.error ?? "")];
|
|
1024
|
-
}
|
|
1025
|
-
const b = s.balance;
|
|
1026
|
-
return [
|
|
1027
|
-
chalk.white.bold(s.exchange),
|
|
1028
|
-
`$${formatUsd(b.equity)}`,
|
|
1029
|
-
`$${formatUsd(b.available)}`,
|
|
1030
|
-
`$${formatUsd(b.marginUsed)}`,
|
|
1031
|
-
formatPnl(b.unrealizedPnl),
|
|
1032
|
-
chalk.green("connected"),
|
|
1033
|
-
];
|
|
1034
|
-
});
|
|
1035
|
-
balRows.push([
|
|
1036
|
-
chalk.cyan.bold("TOTAL"),
|
|
1037
|
-
chalk.cyan.bold(`$${formatUsd(summary.totalEquity)}`),
|
|
1038
|
-
chalk.cyan.bold(`$${formatUsd(summary.totalAvailable)}`),
|
|
1039
|
-
chalk.cyan.bold(`$${formatUsd(summary.totalMarginUsed)}`),
|
|
1040
|
-
formatPnl(summary.totalUnrealizedPnl),
|
|
1041
|
-
"",
|
|
1042
|
-
]);
|
|
1043
|
-
console.log(makeTable(["Exchange", "Equity", "Available", "Margin Used", "uPnL", "Status"], balRows));
|
|
1044
|
-
if (summary.positions.length > 0) {
|
|
1045
|
-
console.log(chalk.white.bold("\n Open Positions"));
|
|
1046
|
-
const posRows = summary.positions.map(p => {
|
|
1047
|
-
const sideColor = p.side === "long" ? chalk.green : chalk.red;
|
|
1048
|
-
const notional = Math.abs(Number(p.size) * Number(p.markPrice));
|
|
1049
|
-
const sym = p.symbol.replace("-PERP", "").toUpperCase();
|
|
1050
|
-
const funding = fundingByExSym.get(`${p.exchange}:${sym}`) ?? 0;
|
|
1051
|
-
return [
|
|
1052
|
-
chalk.white.bold(p.symbol),
|
|
1053
|
-
chalk.gray(p.exchange),
|
|
1054
|
-
sideColor(p.side.toUpperCase()),
|
|
1055
|
-
p.size,
|
|
1056
|
-
`$${formatUsd(p.entryPrice)}`,
|
|
1057
|
-
`$${formatUsd(p.markPrice)}`,
|
|
1058
|
-
formatPnl(p.unrealizedPnl),
|
|
1059
|
-
formatPnl(funding),
|
|
1060
|
-
`$${formatUsd(notional)}`,
|
|
1061
|
-
`${p.leverage}x`,
|
|
1062
|
-
];
|
|
1063
|
-
});
|
|
1064
|
-
console.log(makeTable(["Symbol", "Exchange", "Side", "Size", "Entry", "Mark", "uPnL", "Funding", "Notional", "Lev"], posRows));
|
|
1065
|
-
}
|
|
1066
|
-
else {
|
|
1067
|
-
console.log(chalk.gray("\n No open positions.\n"));
|
|
1068
|
-
}
|
|
1069
|
-
// ── Spot Holdings (already fetched in parallel above) ──
|
|
1070
|
-
if (spotRows.length > 0) {
|
|
1071
|
-
console.log(chalk.white.bold("\n Spot Holdings"));
|
|
1072
|
-
console.log(makeTable(["Token", "Exchange", "Amount", "Price", "Value"], spotRows));
|
|
1073
|
-
}
|
|
1074
|
-
// ── Total (perp + spot) ──
|
|
1075
|
-
if (totalSpotValue > 0) {
|
|
1076
|
-
const totalValue = summary.totalEquity + totalSpotValue;
|
|
1077
|
-
console.log(chalk.white.bold(" Total Account Value"));
|
|
1078
|
-
console.log(` Perp Equity: $${formatUsd(summary.totalEquity)}`);
|
|
1079
|
-
console.log(` Spot Value: $${formatUsd(totalSpotValue)}`);
|
|
1080
|
-
console.log(` ${chalk.cyan.bold(`Total: $${formatUsd(totalValue)}`)}`);
|
|
1081
|
-
}
|
|
1082
|
-
// ── Risk Metrics ──
|
|
1083
|
-
console.log(chalk.white.bold("\n Risk Metrics"));
|
|
1084
|
-
const levelColor = {
|
|
1085
|
-
low: chalk.green,
|
|
1086
|
-
medium: chalk.yellow,
|
|
1087
|
-
high: chalk.red,
|
|
1088
|
-
critical: chalk.bgRed.white,
|
|
1089
|
-
}[summary.risk.level];
|
|
1090
|
-
console.log(` Risk Level: ${levelColor(summary.risk.level.toUpperCase())}`);
|
|
1091
|
-
console.log(` Can Trade: ${summary.risk.canTrade ? chalk.green("YES") : chalk.red("NO")}`);
|
|
1092
|
-
const mu = summary.riskMetrics.marginUtilization;
|
|
1093
|
-
const muColor = mu < 30 ? chalk.green : mu < 60 ? chalk.yellow : chalk.red;
|
|
1094
|
-
console.log(` Margin Utilization: ${muColor(`${mu.toFixed(1)}%`)}`);
|
|
1095
|
-
if (summary.riskMetrics.largestPosition) {
|
|
1096
|
-
const lp = summary.riskMetrics.largestPosition;
|
|
1097
|
-
console.log(` Largest Position: ${lp.symbol} on ${lp.exchange} ($${formatUsd(lp.notional)})`);
|
|
1098
|
-
}
|
|
1099
|
-
if (summary.riskMetrics.exchangeConcentration.length > 0) {
|
|
1100
|
-
console.log(` Exchange Allocation:`);
|
|
1101
|
-
for (const ec of summary.riskMetrics.exchangeConcentration) {
|
|
1102
|
-
const bar = "\u2588".repeat(Math.round(ec.pct / 5)) + "\u2591".repeat(20 - Math.round(ec.pct / 5));
|
|
1103
|
-
console.log(` ${ec.exchange.padEnd(12)} ${bar} ${ec.pct.toFixed(1)}%`);
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
if (summary.risk.violations.length > 0) {
|
|
1107
|
-
console.log(chalk.red.bold("\n Risk Violations"));
|
|
1108
|
-
for (const v of summary.risk.violations) {
|
|
1109
|
-
const sevColor = { low: chalk.green, medium: chalk.yellow, high: chalk.red, critical: chalk.bgRed.white }[v.severity];
|
|
1110
|
-
console.log(` ${sevColor(v.severity.toUpperCase().padEnd(8))} ${v.message}`);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
console.log();
|
|
1114
|
-
});
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
619
|
}
|
package/dist/commands/agent.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Register the per-DEX agent-wallet management subtree (`approve` /
|
|
4
|
+
* `list` / `revoke` / `rotate` / `verify`) under the supplied parent
|
|
5
|
+
* `wallet` command. The function previously registered `agent` as a
|
|
6
|
+
* top-level command on `program`; the hard-cut consolidation in v0.11+
|
|
7
|
+
* relocates it to `wallet agent ...`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerWalletAgentCommands(walletCmd: Command, isJson: () => boolean): void;
|