perp-cli 0.12.15 → 0.14.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 +278 -31
- 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 +286 -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 +74 -84
- 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 +286 -0
- package/dist/commands/funds.d.ts +25 -0
- package/dist/commands/funds.js +939 -245
- package/dist/commands/history.js +72 -45
- 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 +316 -337
- 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 +219 -6
- package/dist/exchanges/aster.js +1023 -153
- 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 +166 -0
- package/dist/exchanges/ondo/adapter.js +835 -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 +122 -0
- package/dist/exchanges/ondo/funds.js +290 -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 +288 -4
- package/dist/exchanges/pacifica.js +1013 -76
- 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 +1383 -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 +34 -0
- package/dist/exchanges/venues/ondo.js +140 -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 +28 -0
- package/dist/exchanges/venues/qfex.js +132 -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 +157 -682
- package/dist/jobs.d.ts +84 -6
- package/dist/jobs.js +239 -41
- package/dist/landing.d.ts +14 -0
- package/dist/landing.js +36 -0
- package/dist/mcp-server.d.ts +14 -4
- package/dist/mcp-server.js +820 -402
- package/dist/mcp-trade-guard.d.ts +16 -0
- package/dist/mcp-trade-guard.js +59 -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 +338 -134
- package/skills/perp-cli/references/agent-operations.md +181 -92
- package/skills/perp-cli/references/commands.md +475 -132
- package/skills/perp-cli/references/strategies.md +44 -38
- package/skills/perp-cli/scripts/arb-monitor.sh +22 -17
- package/skills/perp-cli/scripts/funding-analysis.sh +20 -10
- 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 +33 -16
- 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
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { closeSync, existsSync, mkdirSync, openSync, statSync, unlinkSync } from "fs";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import { PerpError } from "../errors.js";
|
|
4
|
+
/** How long to wait for another process's lock, and when a lock left by a dead process is stale. */
|
|
5
|
+
export const FILE_LOCK_WAIT_MS = 5_000;
|
|
6
|
+
export const FILE_LOCK_STALE_MS = 30_000;
|
|
7
|
+
/** Locks this process holds (path → depth): a nested load-modify-save in the same process never self-deadlocks. */
|
|
8
|
+
const held = new Map();
|
|
9
|
+
/**
|
|
10
|
+
* Run `fn` holding the advisory lock file `<path>.lock` (O_EXCL create) — for a load → modify →
|
|
11
|
+
* save of a state file shared by several perp processes (bots, daemons, CLI), so one process
|
|
12
|
+
* never overwrites another's concurrent write. A lock older than FILE_LOCK_STALE_MS (its holder
|
|
13
|
+
* died) is removed; a live one not released within FILE_LOCK_WAIT_MS → LOCK_HELD (nothing is
|
|
14
|
+
* written on top of an unknown concurrent write).
|
|
15
|
+
*/
|
|
16
|
+
export function withFileLock(path, what, fn) {
|
|
17
|
+
const lock = `${path}.lock`;
|
|
18
|
+
const depth = held.get(lock) ?? 0;
|
|
19
|
+
if (depth > 0) {
|
|
20
|
+
held.set(lock, depth + 1);
|
|
21
|
+
try {
|
|
22
|
+
return fn();
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
held.set(lock, depth);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const dir = resolve(path, "..");
|
|
29
|
+
if (!existsSync(dir))
|
|
30
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
31
|
+
const deadline = Date.now() + FILE_LOCK_WAIT_MS;
|
|
32
|
+
const sleeper = new Int32Array(new SharedArrayBuffer(4));
|
|
33
|
+
for (;;) {
|
|
34
|
+
try {
|
|
35
|
+
closeSync(openSync(lock, "wx", 0o600));
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
if (e.code !== "EEXIST")
|
|
40
|
+
throw e;
|
|
41
|
+
let stale = false;
|
|
42
|
+
try {
|
|
43
|
+
stale = Date.now() - statSync(lock).mtimeMs > FILE_LOCK_STALE_MS;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
continue; // released between the open and the stat: try again
|
|
47
|
+
}
|
|
48
|
+
if (stale) {
|
|
49
|
+
try {
|
|
50
|
+
unlinkSync(lock);
|
|
51
|
+
}
|
|
52
|
+
catch { /* another process removed it */ }
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (Date.now() > deadline) {
|
|
56
|
+
throw new PerpError("LOCK_HELD", `${what} is locked by another perp process (${lock})`, {
|
|
57
|
+
remediation: `Retry shortly; if no other perp process is running, delete ${lock}`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
Atomics.wait(sleeper, 0, 0, 10);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
held.set(lock, 1);
|
|
64
|
+
try {
|
|
65
|
+
return fn();
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
held.delete(lock);
|
|
69
|
+
try {
|
|
70
|
+
unlinkSync(lock);
|
|
71
|
+
}
|
|
72
|
+
catch { /* already gone */ }
|
|
73
|
+
}
|
|
74
|
+
}
|
package/dist/arb/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { computeMatchedSize, computeSpotPerpMatchedSize
|
|
1
|
+
export { computeMatchedSize, computeSpotPerpMatchedSize } from "./sizing.js";
|
|
2
2
|
export { SETTLEMENT_SCHEDULES, getLastSettlement, getMinutesSinceSettlement, aggressiveSettleBoost, estimateFundingUntilSettlement, computeBasisRisk, formatNotifyMessage, sendNotification, notifyIfEnabled, } from "./utils.js";
|
|
3
3
|
export type { SettleStrategy, BasisRisk, ArbNotifyEvent } from "./utils.js";
|
|
4
|
-
export { setStateFilePath, resetStateFilePath, loadArbState, saveArbState, addPosition, removePosition, updatePosition, getPositions, createInitialState, } from "./state.js";
|
|
4
|
+
export { setStateFilePath, resetStateFilePath, loadArbState, saveArbState, addPosition, removePosition, updatePosition, removePositionEntry, updatePositionEntry, positionKey, getPositions, createInitialState, } from "./state.js";
|
|
5
5
|
export type { ArbPositionState, ArbDaemonState } from "./state.js";
|
|
6
6
|
export { computeEnhancedStats } from "./history-stats.js";
|
|
7
7
|
export type { ArbTradeForStats, ExchangePairPerf, TimeOfDayPerf, EnhancedHistoryStats } from "./history-stats.js";
|
package/dist/arb/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// arb/ barrel — public API
|
|
2
|
-
export { computeMatchedSize, computeSpotPerpMatchedSize
|
|
2
|
+
export { computeMatchedSize, computeSpotPerpMatchedSize } from "./sizing.js";
|
|
3
3
|
export { SETTLEMENT_SCHEDULES, getLastSettlement, getMinutesSinceSettlement, aggressiveSettleBoost, estimateFundingUntilSettlement, computeBasisRisk, formatNotifyMessage, sendNotification, notifyIfEnabled, } from "./utils.js";
|
|
4
|
-
export { setStateFilePath, resetStateFilePath, loadArbState, saveArbState, addPosition, removePosition, updatePosition, getPositions, createInitialState, } from "./state.js";
|
|
4
|
+
export { setStateFilePath, resetStateFilePath, loadArbState, saveArbState, addPosition, removePosition, updatePosition, removePositionEntry, updatePositionEntry, positionKey, getPositions, createInitialState, } from "./state.js";
|
|
5
5
|
export { computeEnhancedStats } from "./history-stats.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Network } from "../exchanges/venue-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pending-entry records of the arb daemons (`arb auto`, `arb auto --hip3`) — PER NETWORK, next to
|
|
4
|
+
* the arb state (`arb-state.json` → `arb-state.pending.json`, testnet → `arb-state.testnet.pending.json`).
|
|
5
|
+
*
|
|
6
|
+
* A record is written BEFORE the first leg of a pair entry and removed once the pair is in the
|
|
7
|
+
* arb state / in memory, or rolled back / quarantined. A record that is still there when a daemon
|
|
8
|
+
* of the same source starts means the previous process died (crash, kill) between two legs: what
|
|
9
|
+
* is open is unknown → the symbol is quarantined (never re-entered, never "flat").
|
|
10
|
+
*/
|
|
11
|
+
export interface PendingEntry {
|
|
12
|
+
/** Daemon that wrote it: "arb-auto" | "arb-dex-auto". */
|
|
13
|
+
source: string;
|
|
14
|
+
symbol: string;
|
|
15
|
+
longExchange: string;
|
|
16
|
+
shortExchange: string;
|
|
17
|
+
/** Requested base size per leg. */
|
|
18
|
+
size: string;
|
|
19
|
+
startedAt: string;
|
|
20
|
+
pid: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function pendingEntryFilePath(network: Network): string;
|
|
23
|
+
/** Record an entry about to send its first leg. Throws when it cannot be persisted (the caller must not trade). */
|
|
24
|
+
export declare function writePendingEntry(network: Network, e: Omit<PendingEntry, "startedAt" | "pid">): void;
|
|
25
|
+
/** The entry's outcome is recorded (state / memory / rollback / quarantine): drop its pending record. */
|
|
26
|
+
export declare function clearPendingEntry(network: Network, source: string, symbol: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Pending records of `source` left by a process that is no longer running (crashed / killed
|
|
29
|
+
* mid-entry). Read-only: the caller quarantines each one, then clears it (clearPendingEntry).
|
|
30
|
+
* Records of a live process (another daemon still entering) are not returned.
|
|
31
|
+
*/
|
|
32
|
+
export declare function orphanedPendingEntries(network: Network, source: string): PendingEntry[];
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from "fs";
|
|
2
|
+
import { PerpError } from "../errors.js";
|
|
3
|
+
import { withFileLock } from "./file-lock.js";
|
|
4
|
+
import { arbStateFilePath } from "./state.js";
|
|
5
|
+
export function pendingEntryFilePath(network) {
|
|
6
|
+
const state = arbStateFilePath(network);
|
|
7
|
+
return state.endsWith(".json") ? `${state.slice(0, -5)}.pending.json` : `${state}.pending`;
|
|
8
|
+
}
|
|
9
|
+
function keyOf(source, symbol) {
|
|
10
|
+
return `${source}:${symbol.toUpperCase()}`;
|
|
11
|
+
}
|
|
12
|
+
/** A missing file = no pending entry; an unreadable / malformed one throws (never "none pending"). */
|
|
13
|
+
function load(path) {
|
|
14
|
+
if (!existsSync(path))
|
|
15
|
+
return { version: 1, entries: {} };
|
|
16
|
+
let parsed;
|
|
17
|
+
try {
|
|
18
|
+
parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
throw new PerpError("INVALID_PARAMS", `Arb pending-entry file is unreadable: ${path} (${e instanceof Error ? e.message : String(e)})`, {
|
|
22
|
+
remediation: `Check the symbols it names on the venues (perp arb status), then fix or remove ${path}`,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const f = parsed;
|
|
26
|
+
if (f === null || f.version !== 1 || typeof f.entries !== "object" || f.entries === null) {
|
|
27
|
+
throw new PerpError("INVALID_PARAMS", `Arb pending-entry file has an unexpected shape: ${path}`, {
|
|
28
|
+
remediation: `Check the symbols it names on the venues (perp arb status), then fix or remove ${path}`,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return f;
|
|
32
|
+
}
|
|
33
|
+
function save(path, f) {
|
|
34
|
+
const tmp = `${path}.tmp`;
|
|
35
|
+
writeFileSync(tmp, JSON.stringify(f, null, 2), { mode: 0o600 });
|
|
36
|
+
renameSync(tmp, path);
|
|
37
|
+
}
|
|
38
|
+
function modify(network, fn) {
|
|
39
|
+
const path = pendingEntryFilePath(network);
|
|
40
|
+
return withFileLock(path, `Arb pending-entry file (${network})`, () => {
|
|
41
|
+
const f = load(path);
|
|
42
|
+
const out = fn(f);
|
|
43
|
+
save(path, f);
|
|
44
|
+
return out;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/** Record an entry about to send its first leg. Throws when it cannot be persisted (the caller must not trade). */
|
|
48
|
+
export function writePendingEntry(network, e) {
|
|
49
|
+
modify(network, (f) => {
|
|
50
|
+
f.entries[keyOf(e.source, e.symbol)] = { ...e, startedAt: new Date().toISOString(), pid: process.pid };
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** The entry's outcome is recorded (state / memory / rollback / quarantine): drop its pending record. */
|
|
54
|
+
export function clearPendingEntry(network, source, symbol) {
|
|
55
|
+
modify(network, (f) => { delete f.entries[keyOf(source, symbol)]; });
|
|
56
|
+
}
|
|
57
|
+
function alive(pid) {
|
|
58
|
+
if (pid === process.pid)
|
|
59
|
+
return false;
|
|
60
|
+
try {
|
|
61
|
+
process.kill(pid, 0);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
// EPERM: the process exists (another user) — treat as alive.
|
|
66
|
+
return e.code === "EPERM";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Pending records of `source` left by a process that is no longer running (crashed / killed
|
|
71
|
+
* mid-entry). Read-only: the caller quarantines each one, then clears it (clearPendingEntry).
|
|
72
|
+
* Records of a live process (another daemon still entering) are not returned.
|
|
73
|
+
*/
|
|
74
|
+
export function orphanedPendingEntries(network, source) {
|
|
75
|
+
const f = load(pendingEntryFilePath(network));
|
|
76
|
+
return Object.values(f.entries).filter(e => e.source === source && !alive(e.pid));
|
|
77
|
+
}
|
package/dist/arb/sizing.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ExchangeAdapter } from "../exchanges/index.js";
|
|
2
1
|
/**
|
|
3
2
|
* Calculate the exact same size for both legs of an arb position,
|
|
4
3
|
* respecting both exchanges' minimum order and size precision constraints.
|
|
@@ -9,6 +8,12 @@ export declare function computeMatchedSize(sizeUsd: number, price: number, longE
|
|
|
9
8
|
longSizeDecimals?: number;
|
|
10
9
|
shortSizeDecimals?: number;
|
|
11
10
|
lotSize?: number;
|
|
11
|
+
/**
|
|
12
|
+
* The pair's minimum order value in USD from the venues' published market info (the larger of
|
|
13
|
+
* the two legs; 0 = neither venue publishes one). When given it is the ONLY minimum applied —
|
|
14
|
+
* the per-venue table below is for callers that have no market info at hand.
|
|
15
|
+
*/
|
|
16
|
+
minNotional?: number;
|
|
12
17
|
}): {
|
|
13
18
|
size: string;
|
|
14
19
|
notional: number;
|
|
@@ -21,15 +26,3 @@ export declare function computeSpotPerpMatchedSize(sizeUsd: number, price: numbe
|
|
|
21
26
|
size: string;
|
|
22
27
|
notional: number;
|
|
23
28
|
} | null;
|
|
24
|
-
/**
|
|
25
|
-
* After both legs are submitted, verify actual fills match.
|
|
26
|
-
* If there's a size mismatch, place a correction order on the larger side.
|
|
27
|
-
*
|
|
28
|
-
* @returns the corrected size, or null if already matched
|
|
29
|
-
*/
|
|
30
|
-
export declare function reconcileArbFills(longAdapter: ExchangeAdapter, shortAdapter: ExchangeAdapter, symbol: string, log?: (msg: string) => void): Promise<{
|
|
31
|
-
matched: boolean;
|
|
32
|
-
longSize: number;
|
|
33
|
-
shortSize: number;
|
|
34
|
-
correction?: string;
|
|
35
|
-
}>;
|
package/dist/arb/sizing.js
CHANGED
|
@@ -24,7 +24,9 @@ export function computeMatchedSize(sizeUsd, price, longExchange, shortExchange,
|
|
|
24
24
|
return null;
|
|
25
25
|
// Verify notional meets minimum for both exchanges
|
|
26
26
|
const notional = roundedSize * price;
|
|
27
|
-
const minNotional =
|
|
27
|
+
const minNotional = opts?.minNotional !== undefined
|
|
28
|
+
? opts.minNotional
|
|
29
|
+
: Math.max(getMinNotional(longExchange), getMinNotional(shortExchange));
|
|
28
30
|
if (notional < minNotional) {
|
|
29
31
|
// Try rounding UP instead
|
|
30
32
|
let roundedUp;
|
|
@@ -36,11 +38,14 @@ export function computeMatchedSize(sizeUsd, price, longExchange, shortExchange,
|
|
|
36
38
|
roundedUp = Math.ceil(rawSize * factor) / factor;
|
|
37
39
|
}
|
|
38
40
|
const notionalUp = roundedUp * price;
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
+
// Round up only if it both (a) clears the venue minimum and (b) does not
|
|
42
|
+
// overshoot the requested size by more than 20%. Pre-fix this checked only
|
|
43
|
+
// (b), so a ceil that still fell short of minNotional was returned and then
|
|
44
|
+
// rejected by the venue — SSOT Rule #2: fail honestly with null instead.
|
|
45
|
+
if (notionalUp >= minNotional && notionalUp <= sizeUsd * 1.2) {
|
|
41
46
|
return { size: formatSize(roundedUp, szDecimals, opts?.lotSize), notional: notionalUp };
|
|
42
47
|
}
|
|
43
|
-
return null; // Can't meet minimum
|
|
48
|
+
return null; // Can't meet minimum within tolerance
|
|
44
49
|
}
|
|
45
50
|
return { size: formatSize(roundedSize, szDecimals, opts?.lotSize), notional };
|
|
46
51
|
}
|
|
@@ -94,56 +99,12 @@ export function computeSpotPerpMatchedSize(sizeUsd, price, spotExchange, perpExc
|
|
|
94
99
|
if (notional < minNotional) {
|
|
95
100
|
const roundedUp = Math.ceil(rawSize * factor) / factor;
|
|
96
101
|
const notionalUp = roundedUp * price;
|
|
97
|
-
|
|
102
|
+
// Same minNotional re-check as computeMatchedSize (SSOT Rule #2): a ceil
|
|
103
|
+
// that is still under the venue minimum must fail, not be returned.
|
|
104
|
+
if (notionalUp >= minNotional && notionalUp <= sizeUsd * 1.2) {
|
|
98
105
|
return { size: roundedUp.toFixed(szDecimals), notional: notionalUp };
|
|
99
106
|
}
|
|
100
107
|
return null;
|
|
101
108
|
}
|
|
102
109
|
return { size: roundedSize.toFixed(szDecimals), notional };
|
|
103
110
|
}
|
|
104
|
-
/**
|
|
105
|
-
* After both legs are submitted, verify actual fills match.
|
|
106
|
-
* If there's a size mismatch, place a correction order on the larger side.
|
|
107
|
-
*
|
|
108
|
-
* @returns the corrected size, or null if already matched
|
|
109
|
-
*/
|
|
110
|
-
export async function reconcileArbFills(longAdapter, shortAdapter, symbol, log) {
|
|
111
|
-
const [longPositions, shortPositions] = await Promise.all([
|
|
112
|
-
longAdapter.getPositions(),
|
|
113
|
-
shortAdapter.getPositions(),
|
|
114
|
-
]);
|
|
115
|
-
const longPos = longPositions.find(p => p.symbol.replace("-PERP", "").toUpperCase() === symbol.toUpperCase() && p.side === "long");
|
|
116
|
-
const shortPos = shortPositions.find(p => p.symbol.replace("-PERP", "").toUpperCase() === symbol.toUpperCase() && p.side === "short");
|
|
117
|
-
const longSize = longPos ? Math.abs(Number(longPos.size)) : 0;
|
|
118
|
-
const shortSize = shortPos ? Math.abs(Number(shortPos.size)) : 0;
|
|
119
|
-
if (longSize === 0 && shortSize === 0) {
|
|
120
|
-
return { matched: true, longSize: 0, shortSize: 0 };
|
|
121
|
-
}
|
|
122
|
-
const diff = Math.abs(longSize - shortSize);
|
|
123
|
-
const maxSize = Math.max(longSize, shortSize);
|
|
124
|
-
const diffPct = maxSize > 0 ? (diff / maxSize) * 100 : 0;
|
|
125
|
-
// Allow 1% tolerance (rounding differences)
|
|
126
|
-
if (diffPct <= 1) {
|
|
127
|
-
return { matched: true, longSize, shortSize };
|
|
128
|
-
}
|
|
129
|
-
log?.(`[ARB] Size mismatch: long ${longSize} vs short ${shortSize} (diff: ${diff.toFixed(4)}, ${diffPct.toFixed(1)}%)`);
|
|
130
|
-
// Correct the larger side by reducing it
|
|
131
|
-
const correctionSize = diff.toFixed(6);
|
|
132
|
-
try {
|
|
133
|
-
if (longSize > shortSize) {
|
|
134
|
-
log?.(`[ARB] Correcting: sell ${correctionSize} ${symbol} on ${longAdapter.name} to match`);
|
|
135
|
-
await longAdapter.marketOrder(symbol, "sell", correctionSize);
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
log?.(`[ARB] Correcting: buy ${correctionSize} ${symbol} on ${shortAdapter.name} to match`);
|
|
139
|
-
await shortAdapter.marketOrder(symbol, "buy", correctionSize);
|
|
140
|
-
}
|
|
141
|
-
log?.(`[ARB] Sizes reconciled`);
|
|
142
|
-
return { matched: true, longSize: Math.min(longSize, shortSize), shortSize: Math.min(longSize, shortSize), correction: correctionSize };
|
|
143
|
-
}
|
|
144
|
-
catch (err) {
|
|
145
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
146
|
-
log?.(`[ARB] Correction failed: ${msg}`);
|
|
147
|
-
return { matched: false, longSize, shortSize };
|
|
148
|
-
}
|
|
149
|
-
}
|
package/dist/arb/state.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type { Network } from "../exchanges/venue-types.js";
|
|
1
2
|
export declare function setStateFilePath(path: string): void;
|
|
2
3
|
export declare function resetStateFilePath(): void;
|
|
4
|
+
/** Absolute state-file path for `network` (mainnet = the pre-network path). */
|
|
5
|
+
export declare function arbStateFilePath(network: Network): string;
|
|
3
6
|
export interface ArbPositionState {
|
|
4
7
|
id: string;
|
|
5
8
|
symbol: string;
|
|
@@ -9,8 +12,9 @@ export interface ArbPositionState {
|
|
|
9
12
|
shortSize: number;
|
|
10
13
|
entryTime: string;
|
|
11
14
|
entrySpread: number;
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
/** null = no verified fill price was reported for the leg (a strategy-bot entry; never a guess). */
|
|
16
|
+
entryLongPrice: number | null;
|
|
17
|
+
entryShortPrice: number | null;
|
|
14
18
|
accumulatedFunding: number;
|
|
15
19
|
lastCheckTime: string;
|
|
16
20
|
/** "perp-perp" (default) or "spot-perp" */
|
|
@@ -22,6 +26,8 @@ export interface ArbPositionState {
|
|
|
22
26
|
}
|
|
23
27
|
export interface ArbDaemonState {
|
|
24
28
|
version: 1;
|
|
29
|
+
/** Network the positions live on. Absent only in files written before per-network state (= mainnet). */
|
|
30
|
+
network?: Network;
|
|
25
31
|
lastStartTime: string;
|
|
26
32
|
lastScanTime: string;
|
|
27
33
|
lastSuccessfulScanTime: string;
|
|
@@ -37,21 +43,48 @@ export interface ArbDaemonState {
|
|
|
37
43
|
notifyUrl?: string;
|
|
38
44
|
};
|
|
39
45
|
}
|
|
40
|
-
/** Load daemon state
|
|
41
|
-
export declare function loadArbState(
|
|
46
|
+
/** Load the daemon state for `network`. Falls back to .tmp if main file is corrupted. */
|
|
47
|
+
export declare function loadArbState(network: Network, opts?: {
|
|
48
|
+
readOnly: boolean;
|
|
49
|
+
}): ArbDaemonState | null;
|
|
42
50
|
/**
|
|
43
51
|
* Save daemon state to disk using atomic write pattern.
|
|
44
52
|
* Writes to .tmp first, then renames to main file.
|
|
45
53
|
* If crash occurs mid-write, .tmp is partial but main file is intact.
|
|
46
54
|
*/
|
|
47
|
-
export declare function saveArbState(state: ArbDaemonState): void;
|
|
48
|
-
/**
|
|
49
|
-
export declare function
|
|
50
|
-
/**
|
|
51
|
-
|
|
55
|
+
export declare function saveArbState(network: Network, state: ArbDaemonState): void;
|
|
56
|
+
/** Identity of a state entry: symbol + long venue + short venue + mode (absent mode = perp-perp). */
|
|
57
|
+
export declare function positionKey(p: Pick<ArbPositionState, "symbol" | "longExchange" | "shortExchange" | "mode">): string;
|
|
58
|
+
/**
|
|
59
|
+
* Put `pos` into `positions`: an entry with the same key is replaced (a re-record of the same
|
|
60
|
+
* pair); an entry of the same symbol on OTHER venues / another mode is never overwritten —
|
|
61
|
+
* RISK_VIOLATION (the state tracks one pair per symbol; overwriting would drop a live pair).
|
|
62
|
+
*/
|
|
63
|
+
export declare function upsertPosition(positions: ArbPositionState[], pos: ArbPositionState): ArbPositionState[];
|
|
64
|
+
/** Add a position to the persisted state for `network`. Auto-initializes state if missing. Throws RISK_VIOLATION for a conflicting entry (upsertPosition). */
|
|
65
|
+
export declare function addPosition(network: Network, pos: ArbPositionState): void;
|
|
66
|
+
/** Remove a position by symbol from the persisted state for `network` (one entry per symbol: upsertPosition). */
|
|
67
|
+
export declare function removePosition(network: Network, symbol: string): void;
|
|
68
|
+
/** Remove exactly the entry with `entry`'s key (symbol + venues + mode); another pair of the symbol is left alone. */
|
|
69
|
+
export declare function removePositionEntry(network: Network, entry: Pick<ArbPositionState, "symbol" | "longExchange" | "shortExchange" | "mode">): void;
|
|
52
70
|
/** Update a position by symbol with partial updates. */
|
|
53
|
-
export declare function updatePosition(symbol: string, updates: Partial<ArbPositionState>): void;
|
|
54
|
-
/**
|
|
55
|
-
export declare function
|
|
71
|
+
export declare function updatePosition(network: Network, symbol: string, updates: Partial<ArbPositionState>): void;
|
|
72
|
+
/** Update exactly the entry with `entry`'s key (symbol + venues + mode). */
|
|
73
|
+
export declare function updatePositionEntry(network: Network, entry: Pick<ArbPositionState, "symbol" | "longExchange" | "shortExchange" | "mode">, updates: Partial<ArbPositionState>): void;
|
|
74
|
+
/** Get all persisted positions for `network`. */
|
|
75
|
+
export declare function getPositions(network: Network): ArbPositionState[];
|
|
56
76
|
/** Create a default empty daemon state with the given config. */
|
|
57
77
|
export declare function createInitialState(config: ArbDaemonState["config"]): ArbDaemonState;
|
|
78
|
+
/** State access for the `arb auto` daemon (see createDaemonStateStore). */
|
|
79
|
+
export interface DaemonStateStore {
|
|
80
|
+
load(): ArbDaemonState | null;
|
|
81
|
+
save(next: ArbDaemonState): void;
|
|
82
|
+
add(pos: ArbPositionState): void;
|
|
83
|
+
remove(symbol: string): void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Live: the per-network state file. Dry-run (review N3): an in-memory copy seeded READ-ONLY
|
|
87
|
+
* from the real state — nothing is ever written to disk, so a simulated entry is never picked
|
|
88
|
+
* up by a live run and a simulated close never drops a real position from tracking.
|
|
89
|
+
*/
|
|
90
|
+
export declare function createDaemonStateStore(network: Network, dryRun: boolean, config: ArbDaemonState["config"]): DaemonStateStore;
|