perp-cli 0.4.12 → 0.5.2
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 +34 -10
- package/dist/cli-spec.js +2 -2
- package/dist/commands/account.js +183 -27
- package/dist/commands/agent.js +5 -5
- package/dist/commands/arb/index.js +217 -24
- package/dist/commands/arb-auto.d.ts +9 -0
- package/dist/commands/arb-auto.js +577 -382
- package/dist/commands/arb.d.ts +44 -0
- package/dist/commands/arb.js +239 -514
- package/dist/commands/market.js +108 -73
- package/dist/commands/trade.js +60 -20
- package/dist/exchanges/hyperliquid.d.ts +11 -2
- package/dist/exchanges/hyperliquid.js +165 -32
- package/dist/exchanges/lighter.js +22 -8
- package/dist/liquidity.js +3 -1
- package/dist/mcp-server.js +53 -50
- package/package.json +1 -1
- package/skills/perp-cli/SKILL.md +90 -189
|
@@ -5,7 +5,7 @@ import { toHourlyRate, computeAnnualSpread } from "../../funding.js";
|
|
|
5
5
|
import { fetchPacificaPrices, fetchHyperliquidMeta, fetchLighterOrderBookDetails, fetchLighterFundingRates, } from "../../shared-api.js";
|
|
6
6
|
import { computeBasisRisk } from "../../arb-utils.js";
|
|
7
7
|
import { smartOrder } from "../../smart-order.js";
|
|
8
|
-
import { removePosition as persistRemovePosition, getPositions as getArbStatePositions } from "../../arb-state.js";
|
|
8
|
+
import { removePosition as persistRemovePosition, getPositions as getArbStatePositions, loadArbState } from "../../arb-state.js";
|
|
9
9
|
import { SPOT_PERP_TOKEN_MAP } from "../../exchanges/spot-interface.js";
|
|
10
10
|
import { fetchAllBalances, computeRebalancePlan } from "../../rebalance.js";
|
|
11
11
|
import { EXCHANGE_TO_CHAIN, getBestQuote } from "../../bridge-engine.js";
|
|
@@ -90,8 +90,10 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
90
90
|
// ── arb status ──
|
|
91
91
|
arb
|
|
92
92
|
.command("status")
|
|
93
|
-
.description("Show open arb positions
|
|
94
|
-
.
|
|
93
|
+
.description("Show open arb positions with PnL breakdown + actual funding earned")
|
|
94
|
+
.option("--period <days>", "Funding lookback period in days", "7")
|
|
95
|
+
.option("--symbol <symbol>", "Filter funding data by symbol")
|
|
96
|
+
.action(async (opts) => {
|
|
95
97
|
if (!isJson())
|
|
96
98
|
console.log(chalk.cyan("\n Checking arb positions across exchanges...\n"));
|
|
97
99
|
// Fetch positions from all exchanges
|
|
@@ -482,6 +484,8 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
482
484
|
console.log(` Portfolio APR: ${chalk.cyan(`${portfolioApr.toFixed(1)}%`)}`);
|
|
483
485
|
}
|
|
484
486
|
console.log(chalk.gray(` (Fees assume ${(TAKER_FEE * 100).toFixed(3)}% taker for entry + exit.)\n`));
|
|
487
|
+
// Always show actual funding payments earned
|
|
488
|
+
await printFundingEarned(getAdapterForExchange, isJson, { period: opts.period, symbol: opts.symbol });
|
|
485
489
|
});
|
|
486
490
|
// ── arb close ──
|
|
487
491
|
arb
|
|
@@ -490,9 +494,174 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
490
494
|
.option("--dry-run", "Show what would happen without executing")
|
|
491
495
|
.option("--pair <pair>", "Specify arb pair as longExchange:shortExchange (e.g. pacifica:hyperliquid)")
|
|
492
496
|
.option("--smart", "Smart execution: IOC limit at best bid/ask + 1 tick (reduces slippage)")
|
|
497
|
+
.option("--spot-exch <exchange>", "Override spot exchange for spot-perp close (hl or lt)")
|
|
498
|
+
.option("--perp-exch <exchange>", "Override perp exchange for spot-perp close")
|
|
493
499
|
.action(async (symbol, opts) => {
|
|
494
500
|
const sym = symbol.toUpperCase();
|
|
495
501
|
const dryRun = !!opts.dryRun || process.argv.includes("--dry-run");
|
|
502
|
+
// Check if this is a spot-perp position (auto-detect from arb state)
|
|
503
|
+
const arbState = loadArbState();
|
|
504
|
+
const statePos = arbState?.positions?.find(p => p.symbol.toUpperCase() === sym && p.mode === "spot-perp");
|
|
505
|
+
if (statePos) {
|
|
506
|
+
// ── Inline spot-perp close logic ──
|
|
507
|
+
const aliasMap = { hl: "hyperliquid", pac: "pacifica", lt: "lighter" };
|
|
508
|
+
const spotExch = aliasMap[opts.spotExch?.toLowerCase() ?? ""] || opts.spotExch?.toLowerCase() || statePos.spotExchange || statePos.longExchange;
|
|
509
|
+
const perpExch = aliasMap[opts.perpExch?.toLowerCase() ?? ""] || opts.perpExch?.toLowerCase() || statePos.shortExchange;
|
|
510
|
+
if (!spotExch || !perpExch) {
|
|
511
|
+
const msg = "Cannot determine exchanges. Specify --spot-exch and --perp-exch, or ensure the position is tracked in state.";
|
|
512
|
+
if (isJson())
|
|
513
|
+
return printJson(jsonOk({ error: msg }));
|
|
514
|
+
console.log(chalk.red(` ${msg}`));
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
// Load spot adapter
|
|
518
|
+
const { HyperliquidSpotAdapter } = await import("../../exchanges/hyperliquid-spot.js");
|
|
519
|
+
const { LighterSpotAdapter } = await import("../../exchanges/lighter-spot.js");
|
|
520
|
+
let spotAdapter;
|
|
521
|
+
if (spotExch === "hyperliquid") {
|
|
522
|
+
const hlAdapter = await getAdapterForExchange("hyperliquid");
|
|
523
|
+
const hlSpot = new HyperliquidSpotAdapter(hlAdapter);
|
|
524
|
+
await hlSpot.init();
|
|
525
|
+
spotAdapter = hlSpot;
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
const ltAdapter = await getAdapterForExchange("lighter");
|
|
529
|
+
const ltSpot = new LighterSpotAdapter(ltAdapter);
|
|
530
|
+
await ltSpot.init();
|
|
531
|
+
spotAdapter = ltSpot;
|
|
532
|
+
}
|
|
533
|
+
const perpAdapter = await getAdapterForExchange(perpExch);
|
|
534
|
+
const spotSymbol = `${sym}/USDC`;
|
|
535
|
+
// Find how much to close
|
|
536
|
+
const perpPositions = await perpAdapter.getPositions();
|
|
537
|
+
const perpPos = perpPositions.find(p => p.symbol.replace("-PERP", "").toUpperCase() === sym && p.side === "short");
|
|
538
|
+
if (!perpPos) {
|
|
539
|
+
const msg = `No short perp position found for ${sym} on ${perpExch}`;
|
|
540
|
+
if (isJson())
|
|
541
|
+
return printJson(jsonOk({ error: msg }));
|
|
542
|
+
console.log(chalk.red(` ${msg}`));
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
const closeSize = perpPos.size;
|
|
546
|
+
if (!isJson()) {
|
|
547
|
+
console.log(chalk.cyan(`\n Closing Spot+Perp Arb: ${sym}`));
|
|
548
|
+
console.log(chalk.gray(` SPOT ${spotExch}: sell ${closeSize}`));
|
|
549
|
+
console.log(chalk.gray(` PERP ${perpExch}: buy ${closeSize} (close short)`));
|
|
550
|
+
console.log(chalk.gray(` Executing...\n`));
|
|
551
|
+
}
|
|
552
|
+
// Same exchange -> sequential (nonce collision), different -> parallel
|
|
553
|
+
let spotResult;
|
|
554
|
+
let perpResult;
|
|
555
|
+
if (spotExch === perpExch) {
|
|
556
|
+
spotResult = await spotAdapter.spotMarketOrder(spotSymbol, "sell", closeSize)
|
|
557
|
+
.then(r => ({ status: "fulfilled", value: r }))
|
|
558
|
+
.catch(e => ({ status: "rejected", reason: e }));
|
|
559
|
+
perpResult = await perpAdapter.marketOrder(sym, "buy", closeSize)
|
|
560
|
+
.then(r => ({ status: "fulfilled", value: r }))
|
|
561
|
+
.catch(e => ({ status: "rejected", reason: e }));
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
[spotResult, perpResult] = await Promise.allSettled([
|
|
565
|
+
spotAdapter.spotMarketOrder(spotSymbol, "sell", closeSize),
|
|
566
|
+
perpAdapter.marketOrder(sym, "buy", closeSize),
|
|
567
|
+
]);
|
|
568
|
+
}
|
|
569
|
+
const spotOk = spotResult.status === "fulfilled";
|
|
570
|
+
const perpOk = perpResult.status === "fulfilled";
|
|
571
|
+
if (spotOk && perpOk) {
|
|
572
|
+
// Post-close fill verification
|
|
573
|
+
let closeVerified = true;
|
|
574
|
+
const closeWarnings = [];
|
|
575
|
+
try {
|
|
576
|
+
await new Promise(r => setTimeout(r, 800));
|
|
577
|
+
const spotBals = await spotAdapter.getSpotBalances();
|
|
578
|
+
const spotTokenBal = spotBals.find(b => b.token.toUpperCase().startsWith(sym));
|
|
579
|
+
const remainingSpotAmt = Number(spotTokenBal?.total ?? 0);
|
|
580
|
+
const closedSize = parseFloat(closeSize);
|
|
581
|
+
if (remainingSpotAmt > closedSize * 0.5) {
|
|
582
|
+
closeVerified = false;
|
|
583
|
+
closeWarnings.push(`Spot sell may not have filled: still have ${remainingSpotAmt.toFixed(6)} ${sym} (expected ~0)`);
|
|
584
|
+
}
|
|
585
|
+
const perpPositionsAfter = await perpAdapter.getPositions();
|
|
586
|
+
const remainingPerpPos = perpPositionsAfter.find(p => p.symbol.replace("-PERP", "").toUpperCase() === sym && p.side === "short");
|
|
587
|
+
if (remainingPerpPos && Number(remainingPerpPos.size) > closedSize * 0.5) {
|
|
588
|
+
closeVerified = false;
|
|
589
|
+
closeWarnings.push(`Perp short still open: ${remainingPerpPos.size} ${sym} on ${perpExch} (expected closed)`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
catch (verifyErr) {
|
|
593
|
+
closeWarnings.push(`Close verification failed: ${verifyErr instanceof Error ? verifyErr.message : String(verifyErr)}`);
|
|
594
|
+
}
|
|
595
|
+
if (closeWarnings.length > 0 && !isJson()) {
|
|
596
|
+
for (const w of closeWarnings)
|
|
597
|
+
console.log(chalk.yellow(` Warning: ${w}`));
|
|
598
|
+
}
|
|
599
|
+
persistRemovePosition(sym);
|
|
600
|
+
logExecution({
|
|
601
|
+
type: "arb_close", exchange: `spot:${spotExch}+${perpExch}`,
|
|
602
|
+
symbol: sym, side: "exit", size: closeSize,
|
|
603
|
+
status: closeVerified ? "success" : "unverified", dryRun: false,
|
|
604
|
+
meta: { mode: "spot-perp", ...(closeWarnings.length > 0 && { warnings: closeWarnings }) },
|
|
605
|
+
});
|
|
606
|
+
// Return spot USDC proceeds back to perp account
|
|
607
|
+
if (spotExch === "lighter") {
|
|
608
|
+
try {
|
|
609
|
+
const ltSpot = spotAdapter;
|
|
610
|
+
const bals = await ltSpot.getSpotBalances();
|
|
611
|
+
const usdcBal = bals.find(b => b.token === "USDC");
|
|
612
|
+
const leftover = Number(usdcBal?.available ?? 0);
|
|
613
|
+
if (leftover > 0.01) {
|
|
614
|
+
await ltSpot.transferUsdcToPerp(leftover);
|
|
615
|
+
if (!isJson())
|
|
616
|
+
console.log(chalk.gray(` Returned ~$${leftover.toFixed(2)} USDC spot->perp on Lighter`));
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
catch { /* non-critical */ }
|
|
620
|
+
}
|
|
621
|
+
else if (spotExch === "hyperliquid") {
|
|
622
|
+
try {
|
|
623
|
+
const hlSpot = spotAdapter;
|
|
624
|
+
const bals = await hlSpot.getSpotBalances();
|
|
625
|
+
const usdcBal = bals.find(b => b.token.startsWith("USDC"));
|
|
626
|
+
const leftover = Number(usdcBal?.available ?? 0);
|
|
627
|
+
if (leftover > 1)
|
|
628
|
+
await hlSpot.transferUsdcToPerp(Math.floor(leftover));
|
|
629
|
+
}
|
|
630
|
+
catch { /* non-critical */ }
|
|
631
|
+
}
|
|
632
|
+
const closeResult = {
|
|
633
|
+
status: closeVerified ? "closed" : "closed_unverified",
|
|
634
|
+
mode: "spot-perp", symbol: sym, size: closeSize,
|
|
635
|
+
...(closeWarnings.length > 0 && { warnings: closeWarnings }),
|
|
636
|
+
};
|
|
637
|
+
if (isJson())
|
|
638
|
+
return printJson(jsonOk(closeResult));
|
|
639
|
+
if (closeVerified) {
|
|
640
|
+
console.log(chalk.green(` CLOSED (verified): ${sym} ${closeSize} units`));
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
console.log(chalk.yellow(` CLOSED (unverified): ${sym} ${closeSize} units -- check positions manually`));
|
|
644
|
+
}
|
|
645
|
+
console.log(chalk.green(` SPOT ${spotExch}: sold`));
|
|
646
|
+
console.log(chalk.green(` PERP ${perpExch}: bought (closed short)\n`));
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
const errors = [];
|
|
650
|
+
if (!spotOk)
|
|
651
|
+
errors.push(`Spot sell failed: ${spotResult.reason}`);
|
|
652
|
+
if (!perpOk)
|
|
653
|
+
errors.push(`Perp buy failed: ${perpResult.reason}`);
|
|
654
|
+
const result = { status: "partial_close", symbol: sym, spotOk, perpOk, errors };
|
|
655
|
+
if (isJson())
|
|
656
|
+
return printJson(jsonOk(result));
|
|
657
|
+
console.log(chalk.red(` Close partially failed:`));
|
|
658
|
+
for (const e of errors)
|
|
659
|
+
console.log(chalk.red(` ${e}`));
|
|
660
|
+
console.log(chalk.yellow(` Manual intervention may be needed.\n`));
|
|
661
|
+
}
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
// ── Perp-perp close logic (original) ──
|
|
496
665
|
if (!isJson()) {
|
|
497
666
|
console.log(chalk.cyan(`\n Closing arb position for ${sym}...\n`));
|
|
498
667
|
if (dryRun)
|
|
@@ -745,6 +914,7 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
745
914
|
// ── arb history ──
|
|
746
915
|
arb
|
|
747
916
|
.command("history")
|
|
917
|
+
.alias("log")
|
|
748
918
|
.description("Past arb trade performance and statistics")
|
|
749
919
|
.option("--period <days>", "Number of days to look back", "30")
|
|
750
920
|
.action(async (opts) => {
|
|
@@ -1008,6 +1178,31 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
1008
1178
|
console.log();
|
|
1009
1179
|
});
|
|
1010
1180
|
// ── arb rebalance ──
|
|
1181
|
+
arb
|
|
1182
|
+
.command("config")
|
|
1183
|
+
.description("Show arb configuration defaults (use 'arb auto --help' for all options)")
|
|
1184
|
+
.action(async () => {
|
|
1185
|
+
if (isJson()) {
|
|
1186
|
+
return printJson(jsonOk({
|
|
1187
|
+
minSpread: 30, closeSpread: 5, size: 100, holdDays: 7,
|
|
1188
|
+
bridgeCost: 0, interval: 60, cooldown: 30, minMargin: 30,
|
|
1189
|
+
settleStrategy: "block", maxLegs: 5,
|
|
1190
|
+
}));
|
|
1191
|
+
}
|
|
1192
|
+
console.log(chalk.cyan.bold("\n Arb Auto Defaults\n"));
|
|
1193
|
+
console.log(` Min Spread: 30% annual`);
|
|
1194
|
+
console.log(` Close Spread: 5% annual`);
|
|
1195
|
+
console.log(` Size: $100 per leg`);
|
|
1196
|
+
console.log(` Hold Days: 7d (for cost amortization)`);
|
|
1197
|
+
console.log(` Bridge Cost: $0`);
|
|
1198
|
+
console.log(` Check Interval: 60s`);
|
|
1199
|
+
console.log(` Cooldown: 30min (after closing a symbol)`);
|
|
1200
|
+
console.log(` Min Margin: 30%`);
|
|
1201
|
+
console.log(` Settle Strategy: block`);
|
|
1202
|
+
console.log(` Max Legs: 5`);
|
|
1203
|
+
console.log(chalk.gray(`\n Override with 'perp arb auto --min-spread 20 --size 50 ...'\n`));
|
|
1204
|
+
console.log(chalk.gray(` Run 'perp arb auto --help' for all options.\n`));
|
|
1205
|
+
});
|
|
1011
1206
|
arb
|
|
1012
1207
|
.command("rebalance")
|
|
1013
1208
|
.description("Cross-exchange balance rebalancing for arb")
|
|
@@ -1189,26 +1384,21 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
1189
1384
|
console.log(chalk.yellow("\n To execute, use: perp rebalance execute --auto-bridge\n"));
|
|
1190
1385
|
}
|
|
1191
1386
|
});
|
|
1192
|
-
// ── arb funding
|
|
1193
|
-
|
|
1194
|
-
.command("funding-earned")
|
|
1195
|
-
.description("Actual funding payments received/paid for arb positions")
|
|
1196
|
-
.option("--period <days>", "Number of days to look back", "7")
|
|
1197
|
-
.option("--symbol <symbol>", "Filter by symbol")
|
|
1198
|
-
.action(async (opts) => {
|
|
1387
|
+
// ── printFundingEarned helper (used by arb status --funding) ──
|
|
1388
|
+
async function printFundingEarned(getAdapter, isJsonFn, opts) {
|
|
1199
1389
|
const periodDays = parseInt(opts.period);
|
|
1200
1390
|
const filterSym = opts.symbol?.toUpperCase();
|
|
1201
|
-
if (!
|
|
1391
|
+
if (!isJsonFn())
|
|
1202
1392
|
console.log(chalk.cyan(`\n Fetching funding payments (last ${periodDays} days)...\n`));
|
|
1203
1393
|
// Fetch positions to identify arb pairs
|
|
1204
|
-
const
|
|
1394
|
+
const fundingPositions = [];
|
|
1205
1395
|
for (const exName of EXCHANGES) {
|
|
1206
1396
|
try {
|
|
1207
|
-
const adapter = await
|
|
1397
|
+
const adapter = await getAdapter(exName);
|
|
1208
1398
|
const positions = await adapter.getPositions();
|
|
1209
1399
|
for (const p of positions) {
|
|
1210
1400
|
const normalized = p.symbol.replace("-PERP", "").toUpperCase();
|
|
1211
|
-
|
|
1401
|
+
fundingPositions.push({
|
|
1212
1402
|
exchange: exName,
|
|
1213
1403
|
symbol: normalized,
|
|
1214
1404
|
side: p.side,
|
|
@@ -1224,10 +1414,10 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
1224
1414
|
// Identify arb pairs (long on one exchange, short on another)
|
|
1225
1415
|
const arbPairKeys = new Set();
|
|
1226
1416
|
const arbPairInfo = new Map();
|
|
1227
|
-
const
|
|
1228
|
-
const
|
|
1229
|
-
for (const l of
|
|
1230
|
-
for (const s of
|
|
1417
|
+
const fLongs = fundingPositions.filter(p => p.side === "long");
|
|
1418
|
+
const fShorts = fundingPositions.filter(p => p.side === "short");
|
|
1419
|
+
for (const l of fLongs) {
|
|
1420
|
+
for (const s of fShorts) {
|
|
1231
1421
|
if (l.exchange !== s.exchange && l.symbol === s.symbol) {
|
|
1232
1422
|
const key = l.symbol;
|
|
1233
1423
|
arbPairKeys.add(key);
|
|
@@ -1243,7 +1433,7 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
1243
1433
|
const cutoff = Date.now() - periodDays * 24 * 60 * 60 * 1000;
|
|
1244
1434
|
for (const exName of EXCHANGES) {
|
|
1245
1435
|
try {
|
|
1246
|
-
const adapter = await
|
|
1436
|
+
const adapter = await getAdapter(exName);
|
|
1247
1437
|
const payments = await adapter.getFundingPayments(200);
|
|
1248
1438
|
for (const p of payments) {
|
|
1249
1439
|
if (p.time < cutoff)
|
|
@@ -1331,11 +1521,14 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
1331
1521
|
const portfolioApr = totalArbNotional > 0
|
|
1332
1522
|
? (totals.dailyAvg * 365 / totalArbNotional) * 100
|
|
1333
1523
|
: 0;
|
|
1334
|
-
if (
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1524
|
+
if (isJsonFn()) {
|
|
1525
|
+
printJson(jsonOk({
|
|
1526
|
+
fundingEarned: {
|
|
1527
|
+
pairs,
|
|
1528
|
+
totals: { ...totals, annualizedApr: portfolioApr },
|
|
1529
|
+
},
|
|
1338
1530
|
}));
|
|
1531
|
+
return;
|
|
1339
1532
|
}
|
|
1340
1533
|
if (pairs.length === 0) {
|
|
1341
1534
|
console.log(chalk.gray(" No funding payments found.\n"));
|
|
@@ -1368,5 +1561,5 @@ export function registerArbManageCommands(program, getAdapterForExchange, isJson
|
|
|
1368
1561
|
console.log(` Portfolio APR: ${chalk.cyan(`${portfolioApr.toFixed(1)}%`)} (on $${formatUsd(totalArbNotional)} arb notional)`);
|
|
1369
1562
|
}
|
|
1370
1563
|
console.log();
|
|
1371
|
-
}
|
|
1564
|
+
}
|
|
1372
1565
|
}
|
|
@@ -50,5 +50,14 @@ export declare function isNearSettlement(longExchange: string, shortExchange: st
|
|
|
50
50
|
* meaning we're now paying on both sides instead of collecting.
|
|
51
51
|
*/
|
|
52
52
|
export declare function isSpreadReversed(longExchange: string, shortExchange: string, snapshot: FundingSnapshot): boolean;
|
|
53
|
+
export declare let handleSpotClose: ((sym: string, opts: {
|
|
54
|
+
spotExch?: string;
|
|
55
|
+
perpExch?: string;
|
|
56
|
+
}, getAdapterForExchange: (exchange: string) => Promise<import("../exchanges/interface.js").ExchangeAdapter>, isJson: () => boolean) => Promise<void>) | undefined;
|
|
53
57
|
export declare function registerArbAutoCommands(program: Command, getAdapterForExchange: (exchange: string) => Promise<ExchangeAdapter>, isJson: () => boolean, getHLAdapterForDex?: (dex: string) => Promise<import("../exchanges/hyperliquid.js").HyperliquidAdapter>): void;
|
|
58
|
+
export declare let handleArbPnlRef: (() => Promise<void>) | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Exported wrapper for handleArbPnl.
|
|
61
|
+
*/
|
|
62
|
+
export declare function handleArbPnl(getAdapterForExchange: (exchange: string) => Promise<import("../exchanges/interface.js").ExchangeAdapter>, isJson: () => boolean): Promise<void>;
|
|
54
63
|
export {};
|