perp-cli 0.12.17 → 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 +247 -27
- package/dist/_stderr-filter.js +0 -1
- package/dist/agent-wallet/lighter-keystore.d.ts +11 -0
- package/dist/agent-wallet/lighter-keystore.js +92 -10
- package/dist/agent-wallet/passphrase.d.ts +1 -1
- package/dist/agent-wallet/passphrase.js +16 -3
- package/dist/agent-wallet/store.d.ts +37 -4
- package/dist/agent-wallet/store.js +132 -0
- package/dist/agent-wallet/venue-keystore.d.ts +14 -0
- package/dist/agent-wallet/venue-keystore.js +121 -0
- package/dist/api/public/hyperliquid.js +4 -4
- package/dist/api/public/lighter.js +5 -5
- package/dist/api/public/pacifica.d.ts +0 -1
- package/dist/api/public/pacifica.js +4 -13
- package/dist/api/public/urls.d.ts +9 -1
- package/dist/api/public/urls.js +35 -13
- package/dist/arb/file-lock.d.ts +11 -0
- package/dist/arb/file-lock.js +74 -0
- package/dist/arb/index.d.ts +2 -2
- package/dist/arb/index.js +2 -2
- package/dist/arb/pending-entry.d.ts +32 -0
- package/dist/arb/pending-entry.js +77 -0
- package/dist/arb/sizing.d.ts +6 -13
- package/dist/arb/sizing.js +12 -51
- package/dist/arb/state.d.ts +45 -12
- package/dist/arb/state.js +214 -42
- package/dist/arb/utils.d.ts +20 -6
- package/dist/arb/utils.js +43 -39
- package/dist/bot/conditions.d.ts +4 -4
- package/dist/bot/conditions.js +11 -6
- package/dist/bot/config.d.ts +17 -1
- package/dist/bot/config.js +48 -12
- package/dist/bot/engine.d.ts +61 -2
- package/dist/bot/engine.js +610 -144
- package/dist/bot/fill-size.d.ts +7 -0
- package/dist/bot/fill-size.js +18 -0
- package/dist/bot/index.d.ts +1 -1
- package/dist/bot/index.js +1 -1
- package/dist/bot/perp-order.d.ts +99 -0
- package/dist/bot/perp-order.js +299 -0
- package/dist/bot/presets.d.ts +7 -0
- package/dist/bot/presets.js +17 -0
- package/dist/bot/quarantine.d.ts +75 -0
- package/dist/bot/quarantine.js +190 -0
- package/dist/bot/quote-rules.d.ts +23 -0
- package/dist/bot/quote-rules.js +69 -0
- package/dist/bot/strategies/avellaneda-mm.d.ts +32 -2
- package/dist/bot/strategies/avellaneda-mm.js +72 -70
- package/dist/bot/strategies/basis-arb.js +2 -0
- package/dist/bot/strategies/dca-strategy.d.ts +2 -0
- package/dist/bot/strategies/dca-strategy.js +5 -0
- package/dist/bot/strategies/funding-arb-strategy.d.ts +43 -3
- package/dist/bot/strategies/funding-arb-strategy.js +571 -380
- package/dist/bot/strategies/funding-arb-utils.d.ts +48 -23
- package/dist/bot/strategies/funding-arb-utils.js +159 -195
- package/dist/bot/strategies/funding-arb-v2.d.ts +32 -0
- package/dist/bot/strategies/funding-arb-v2.js +258 -47
- package/dist/bot/strategies/funding-auto.js +215 -194
- package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +14 -0
- package/dist/bot/strategies/spot-perp-arb-strategy.js +217 -50
- package/dist/bot/strategies/spot-perp-executor.d.ts +73 -19
- package/dist/bot/strategies/spot-perp-executor.js +319 -120
- package/dist/bot/strategies/spot-perp-state.d.ts +43 -0
- package/dist/bot/strategies/spot-perp-state.js +70 -0
- package/dist/bot/strategy-types.d.ts +6 -0
- package/dist/bot/tui/BotDashboard.d.ts +7 -2
- package/dist/bot/tui/BotDashboard.js +6 -3
- package/dist/bridge-engine.d.ts +120 -19
- package/dist/bridge-engine.js +710 -422
- package/dist/bridge-signers.d.ts +54 -0
- package/dist/bridge-signers.js +161 -0
- package/dist/cache.d.ts +4 -1
- package/dist/cache.js +11 -0
- package/dist/cli-flags.d.ts +50 -0
- package/dist/cli-flags.js +104 -0
- package/dist/cli-program.d.ts +35 -0
- package/dist/cli-program.js +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 +70 -92
- package/dist/commands/agent-import.d.ts +114 -0
- package/dist/commands/agent-import.js +794 -0
- package/dist/commands/agent.d.ts +232 -2
- package/dist/commands/agent.js +1858 -955
- package/dist/commands/alerts.d.ts +1 -0
- package/dist/commands/alerts.js +31 -28
- package/dist/commands/arb/index.d.ts +60 -1
- package/dist/commands/arb/index.js +381 -384
- package/dist/commands/arb-auto.d.ts +132 -4
- package/dist/commands/arb-auto.js +1474 -967
- package/dist/commands/arb.d.ts +3 -1
- package/dist/commands/arb.js +62 -30
- package/dist/commands/bot.js +127 -47
- package/dist/commands/bridge.d.ts +2 -1
- package/dist/commands/bridge.js +339 -192
- package/dist/commands/builder.d.ts +55 -0
- package/dist/commands/builder.js +387 -0
- package/dist/commands/funds-onchain.d.ts +32 -0
- package/dist/commands/funds-onchain.js +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 +156 -684
- package/dist/jobs.d.ts +84 -6
- package/dist/jobs.js +239 -41
- package/dist/landing.d.ts +7 -2
- package/dist/landing.js +19 -3
- package/dist/mcp-server.d.ts +14 -4
- package/dist/mcp-server.js +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 +142 -55
- package/skills/perp-cli/references/agent-operations.md +110 -56
- package/skills/perp-cli/references/commands.md +266 -71
- package/skills/perp-cli/references/strategies.md +34 -31
- package/skills/perp-cli/scripts/arb-monitor.sh +10 -5
- package/skills/perp-cli/scripts/funding-analysis.sh +14 -9
- package/skills/perp-cli/scripts/preflight.sh +21 -14
- package/skills/perp-cli/scripts/spot-perp-scan.sh +12 -7
- package/skills/perp-cli/scripts/validate-arb.sh +31 -15
- package/vendor/lighter-signer/SHA256SUMS +2 -0
- package/vendor/lighter-signer/VERSION +8 -0
- package/vendor/lighter-signer/lighter-signer.wasm +0 -0
- package/vendor/lighter-signer/wasm_exec.js +575 -0
- package/dist/bot/strategies/funding-arb-v2-strategy.d.ts +0 -42
- package/dist/bot/strategies/funding-arb-v2-strategy.js +0 -864
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spot order outcome → filled size, for bots / arb (design §12.4 #5).
|
|
3
|
+
*
|
|
4
|
+
* A resolved `spotMarketOrder()` promise does NOT mean "filled": the §12 adapters
|
|
5
|
+
* return a `SpotOrderResult` (rejected / cancelled / pending / partial / filled),
|
|
6
|
+
* and the legacy Hyperliquid / Lighter adapters return a venue payload. Every bot /
|
|
7
|
+
* arb spot leg goes through `spotMarketFill()` so the hedge is sized to what
|
|
8
|
+
* actually filled:
|
|
9
|
+
*
|
|
10
|
+
* - rejected / cancelled (nothing filled) → throws ORDER_REJECTED
|
|
11
|
+
* - pending / open / fill size not reported → throws ORDER_PENDING (do NOT retry)
|
|
12
|
+
* - the order call itself throws → a PerpError with a definite code
|
|
13
|
+
* (isDefiniteOrderFailure: validation / policy / explicit venue rejection) is
|
|
14
|
+
* rethrown as a definite failure; ANYTHING else (non-PerpError, EXCHANGE_UNREACHABLE,
|
|
15
|
+
* TIMEOUT, EXCHANGE_ERROR, RATE_LIMITED, UNKNOWN, …) becomes ORDER_PENDING — the
|
|
16
|
+
* request may have reached the venue, so callers quarantine instead of retrying.
|
|
17
|
+
* - partial → returns the filled size
|
|
18
|
+
* - filled → returns the filled size
|
|
19
|
+
*
|
|
20
|
+
* Legacy results:
|
|
21
|
+
* - Hyperliquid: `response.data.statuses[0].filled.totalSz` (resting → pending).
|
|
22
|
+
* - Lighter: the adapter reads the fill from Lighter's own /tx event_info (taker
|
|
23
|
+
* order "filled") or, for any other status, the order's accountOrders row
|
|
24
|
+
* (filled_base_amount), and returns a final SpotOrderResult that iocOutcomeOf() reports
|
|
25
|
+
* (venueFinalSpotFill below). A SpotOrderResult marked TX_EVENT_FILL_SOURCE that is not
|
|
26
|
+
* routed through iocOutcomeOf is cross-checked as follows; because
|
|
27
|
+
* the is/rs semantics are not venue-documented, that fill must be backed by a fresh
|
|
28
|
+
* base-balance delta of ≥ 80% (else ORDER_PENDING). Only when the venue gives no fill
|
|
29
|
+
* report does it return the raw tx hash; the fill is then MEASURED as the base-token
|
|
30
|
+
* balance delta around the order using UNCACHED reads (readSpotBalancesFresh). A
|
|
31
|
+
* zero delta is ORDER_PENDING (the IOC may still be unconfirmed), never "nothing
|
|
32
|
+
* filled"; a failed read is never zero.
|
|
33
|
+
*
|
|
34
|
+
* Venue-final IOC outcome (design §13.10 #4): when the spot adapter is IocOutcomeCapable
|
|
35
|
+
* and iocOutcomeOf(result) reports the order's FINAL filled size, that report is used in
|
|
36
|
+
* preference to the balance delta, cross-checked against a fresh base-balance delta:
|
|
37
|
+
* - final 0 and the balance did not move (≤ one lot) → ORDER_REJECTED (definite);
|
|
38
|
+
* the balance DID move → the measured delta is used (discrepancy logged to stderr);
|
|
39
|
+
* - final > 0 → filledSize = the reported size when the delta is ≥ 80% of it (base-token
|
|
40
|
+
* fees), else ORDER_PENDING; an unreadable balance → ORDER_PENDING.
|
|
41
|
+
*/
|
|
42
|
+
import { PerpError, isDefiniteOrderFailure, orderOutcomeUnknown } from "../errors.js";
|
|
43
|
+
import { resolveAdapterSlippage } from "./slippage.js";
|
|
44
|
+
import { iocLotTolerance, isIocOutcomeCapable } from "./ioc-outcome.js";
|
|
45
|
+
import { isSpotFreshBalancesCapable, TX_EVENT_FILL_SOURCE } from "./spot-interface.js";
|
|
46
|
+
import { spotTokenBase } from "./spot-factory.js";
|
|
47
|
+
/** A tx-event-derived / venue-final fill must be backed by at least this share of balance movement (base-token fees). */
|
|
48
|
+
const TX_FILL_MIN_BALANCE_RATIO = 0.8;
|
|
49
|
+
function isTxEventFill(r) {
|
|
50
|
+
const raw = r.venueRaw;
|
|
51
|
+
return raw !== null && typeof raw === "object" && raw.fillSource === TX_EVENT_FILL_SOURCE;
|
|
52
|
+
}
|
|
53
|
+
/** A fill below requested × (1 − this) is reported as "partial" (step flooring dust excluded). */
|
|
54
|
+
const FULL_FILL_TOLERANCE = 1e-6;
|
|
55
|
+
function isSpotOrderResult(r) {
|
|
56
|
+
if (r === null || typeof r !== "object")
|
|
57
|
+
return false;
|
|
58
|
+
const o = r;
|
|
59
|
+
return typeof o.status === "string" && (o.finality === "final" || o.finality === "pending") && "filledSize" in o;
|
|
60
|
+
}
|
|
61
|
+
function pendingError(venue, symbol, why, orderId, remediation, raw) {
|
|
62
|
+
return new PerpError("ORDER_PENDING", `${venue} spot ${symbol}: ${why}${orderId !== null ? ` (order ${orderId})` : ""}`, {
|
|
63
|
+
exchange: venue,
|
|
64
|
+
orderId,
|
|
65
|
+
raw,
|
|
66
|
+
remediation: remediation ?? `Do NOT resubmit — the order may still fill. Check: perp -e ${venue} trade spot-balance / spot-orders`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function positive(v) {
|
|
70
|
+
if (v === null || v === undefined)
|
|
71
|
+
return null;
|
|
72
|
+
const n = Number(v);
|
|
73
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
74
|
+
}
|
|
75
|
+
function classify(filled, requested) {
|
|
76
|
+
return filled >= requested * (1 - FULL_FILL_TOLERANCE) ? "filled" : "partial";
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Interpret a spot order result. `measuredFill` = base balance delta measured around
|
|
80
|
+
* the order (null when not measured); used only for results that carry no fill report.
|
|
81
|
+
*/
|
|
82
|
+
export function interpretSpotFill(venue, symbol, result, requestedSize, measuredFill) {
|
|
83
|
+
if (isSpotOrderResult(result)) {
|
|
84
|
+
const r = result;
|
|
85
|
+
if (r.status === "rejected" || r.status === "cancelled") {
|
|
86
|
+
// "cancelled" with a fill would be "partial" (adapters map it so); here nothing filled.
|
|
87
|
+
throw new PerpError("ORDER_REJECTED", `${venue} spot ${symbol}: order ${r.status}${r.remediation ? ` — ${r.remediation}` : ""}`, {
|
|
88
|
+
exchange: venue, orderId: r.orderId, raw: r.venueRaw,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (r.finality === "pending" || r.status === "pending" || r.status === "open") {
|
|
92
|
+
throw pendingError(venue, symbol, `order not final (status ${r.status})`, r.orderId, r.remediation, r.venueRaw);
|
|
93
|
+
}
|
|
94
|
+
const filled = positive(r.filledSize);
|
|
95
|
+
if (filled === null) {
|
|
96
|
+
throw pendingError(venue, symbol, `order ${r.status} but the venue reported no filled size`, r.orderId, null, r.venueRaw);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
status: r.status === "partial" ? "partial" : classify(filled, requestedSize),
|
|
100
|
+
filledSize: filled,
|
|
101
|
+
avgPrice: positive(r.avgPrice),
|
|
102
|
+
orderId: r.orderId,
|
|
103
|
+
raw: result,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// Legacy Hyperliquid: { status: "ok", response: { data: { statuses: [{ filled | resting | error }] } } }
|
|
107
|
+
const hl = result;
|
|
108
|
+
const statuses = hl?.response?.data?.statuses;
|
|
109
|
+
if (Array.isArray(statuses)) {
|
|
110
|
+
const st = statuses[0];
|
|
111
|
+
if (st === undefined)
|
|
112
|
+
throw pendingError(venue, symbol, "no order status in the response", null, null, result);
|
|
113
|
+
if (st.error)
|
|
114
|
+
throw new PerpError("ORDER_REJECTED", `${venue} spot ${symbol}: ${String(st.error)}`, { exchange: venue });
|
|
115
|
+
const f = st.filled;
|
|
116
|
+
const filled = positive(f?.totalSz);
|
|
117
|
+
if (filled === null) {
|
|
118
|
+
const resting = st.resting;
|
|
119
|
+
throw pendingError(venue, symbol, "order not filled (resting or unreported)", resting?.oid !== undefined ? String(resting.oid) : null, null, result);
|
|
120
|
+
}
|
|
121
|
+
return { status: classify(filled, requestedSize), filledSize: filled, avgPrice: positive(f?.avgPx), orderId: f?.oid !== undefined ? String(f.oid) : null, raw: result };
|
|
122
|
+
}
|
|
123
|
+
// Legacy Lighter (tx hash only): measured balance delta.
|
|
124
|
+
if (measuredFill === null) {
|
|
125
|
+
throw pendingError(venue, symbol, "the venue reported no fill and none was measured", null, null, result);
|
|
126
|
+
}
|
|
127
|
+
if (!(measuredFill > 0)) {
|
|
128
|
+
throw pendingError(venue, symbol, "no balance change observed after the order (it may still be unconfirmed)", null, null, result);
|
|
129
|
+
}
|
|
130
|
+
return { status: classify(measuredFill, requestedSize), filledSize: Math.min(measuredFill, requestedSize), avgPrice: null, orderId: null, raw: result };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Uncached spot balances: getSpotBalancesFresh() on adapters whose getSpotBalances()
|
|
134
|
+
* is TTL-cached (SpotFreshBalancesCapable contract), getSpotBalances() on adapters that
|
|
135
|
+
* read live. Use for fill measurement and post-trade verification. Throws on failure.
|
|
136
|
+
*/
|
|
137
|
+
export async function readSpotBalancesFresh(spot) {
|
|
138
|
+
return isSpotFreshBalancesCapable(spot) ? spot.getSpotBalancesFresh() : spot.getSpotBalances();
|
|
139
|
+
}
|
|
140
|
+
/** Base-token balance (total) on the spot venue, read uncached; a token with no balance row holds 0. */
|
|
141
|
+
async function baseBalance(spot, symbol) {
|
|
142
|
+
const base = spotTokenBase(symbol.split("/")[0] ?? symbol);
|
|
143
|
+
const row = (await readSpotBalancesFresh(spot)).find(b => spotTokenBase(b.token) === base);
|
|
144
|
+
if (row === undefined)
|
|
145
|
+
return 0;
|
|
146
|
+
const n = Number(row.total);
|
|
147
|
+
if (!Number.isFinite(n))
|
|
148
|
+
throw new PerpError("EXCHANGE_ERROR", `${spot.name} spot balance for ${base} is not a number: ${row.total}`, { exchange: spot.name });
|
|
149
|
+
return n;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Place a spot market order and return what filled (see header). The base balance is
|
|
153
|
+
* read before the order so venues without a fill report can be measured; a failure of
|
|
154
|
+
* that read aborts BEFORE anything is placed. After the order, errors never throw a
|
|
155
|
+
* retryable error: an unreadable outcome is ORDER_PENDING.
|
|
156
|
+
*/
|
|
157
|
+
export async function spotMarketFill(spot, symbol, side, size, stepSize = null) {
|
|
158
|
+
const requested = Number(size);
|
|
159
|
+
if (!(requested > 0))
|
|
160
|
+
throw new PerpError("INVALID_PARAMS", `spot ${side} size must be positive (got ${size})`);
|
|
161
|
+
// Bot/arb spot legs carry no per-call flag: settings slippageBps[venue] → defaultSlippageBps.
|
|
162
|
+
const slippage = resolveAdapterSlippage(spot, null);
|
|
163
|
+
const before = await baseBalance(spot, symbol);
|
|
164
|
+
let result;
|
|
165
|
+
try {
|
|
166
|
+
result = await spot.spotMarketOrder(symbol, side, size, { slippage });
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
if (isDefiniteOrderFailure(e))
|
|
170
|
+
throw e;
|
|
171
|
+
// Not a definite rejection: the request may have reached the venue.
|
|
172
|
+
throw orderOutcomeUnknown(spot.name, `spot ${side} ${size} ${symbol}`, e, `Do NOT resubmit — the order may still fill. Check: perp -e ${spot.name} trade spot-balance / spot-orders`);
|
|
173
|
+
}
|
|
174
|
+
const outcome = isIocOutcomeCapable(spot) ? spot.iocOutcomeOf(result) : null;
|
|
175
|
+
if (outcome !== null)
|
|
176
|
+
return venueFinalSpotFill(spot, symbol, side, size, before, result, outcome, stepSize);
|
|
177
|
+
if (isSpotOrderResult(result)) {
|
|
178
|
+
const fill = interpretSpotFill(spot.name, symbol, result, requested, null);
|
|
179
|
+
if (!isTxEventFill(result))
|
|
180
|
+
return fill;
|
|
181
|
+
// Lighter-family fills are derived from the tx event_info (`is` − `rs`), whose
|
|
182
|
+
// semantics are not venue-documented: cross-check against a FRESH balance delta.
|
|
183
|
+
let after;
|
|
184
|
+
try {
|
|
185
|
+
after = await baseBalance(spot, symbol);
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
throw pendingError(spot.name, symbol, `tx reported ${fill.filledSize} filled but the post-order balance could not be read (${e instanceof Error ? e.message : String(e)})`, fill.orderId, null, result);
|
|
189
|
+
}
|
|
190
|
+
const delta = side === "buy" ? after - before : before - after;
|
|
191
|
+
if (delta < fill.filledSize * TX_FILL_MIN_BALANCE_RATIO) {
|
|
192
|
+
throw pendingError(spot.name, symbol, `tx reported ${fill.filledSize} filled but the balance moved only ${delta}`, fill.orderId, null, result);
|
|
193
|
+
}
|
|
194
|
+
return fill;
|
|
195
|
+
}
|
|
196
|
+
const hl = result;
|
|
197
|
+
if (Array.isArray(hl?.response?.data?.statuses))
|
|
198
|
+
return interpretSpotFill(spot.name, symbol, result, requested, null);
|
|
199
|
+
let after;
|
|
200
|
+
try {
|
|
201
|
+
after = await baseBalance(spot, symbol);
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
throw pendingError(spot.name, symbol, `order sent but the post-order balance could not be read (${e instanceof Error ? e.message : String(e)})`, null, null, result);
|
|
205
|
+
}
|
|
206
|
+
const delta = side === "buy" ? after - before : before - after;
|
|
207
|
+
return interpretSpotFill(spot.name, symbol, result, requested, delta);
|
|
208
|
+
}
|
|
209
|
+
/** spotMarketFill for a venue-final IOC outcome (see header): the reported fill, cross-checked against the balance delta. */
|
|
210
|
+
async function venueFinalSpotFill(spot, symbol, side, size, before, result, outcome, stepSize) {
|
|
211
|
+
const requested = Number(size);
|
|
212
|
+
const hlStatus = result?.response?.data?.statuses?.[0];
|
|
213
|
+
const hlFilled = hlStatus?.filled;
|
|
214
|
+
const orderId = isSpotOrderResult(result) ? result.orderId : hlFilled?.oid !== undefined ? String(hlFilled.oid) : null;
|
|
215
|
+
const reported = Number(outcome.filledSize);
|
|
216
|
+
if (!(Number.isFinite(reported) && reported >= 0)) {
|
|
217
|
+
throw pendingError(spot.name, symbol, `venue reported an unusable final fill "${outcome.filledSize}"`, orderId, null, result);
|
|
218
|
+
}
|
|
219
|
+
const tol = iocLotTolerance(size, outcome.filledSize, stepSize);
|
|
220
|
+
if (reported > requested + tol) {
|
|
221
|
+
throw pendingError(spot.name, symbol, `venue reported a final fill of ${outcome.filledSize}, more than the ${size} ordered`, orderId, null, result);
|
|
222
|
+
}
|
|
223
|
+
let after;
|
|
224
|
+
try {
|
|
225
|
+
after = await baseBalance(spot, symbol);
|
|
226
|
+
}
|
|
227
|
+
catch (e) {
|
|
228
|
+
throw pendingError(spot.name, symbol, `venue reported a final fill of ${outcome.filledSize} but the post-order balance could not be read (${e instanceof Error ? e.message : String(e)})`, orderId, null, result);
|
|
229
|
+
}
|
|
230
|
+
const delta = side === "buy" ? after - before : before - after;
|
|
231
|
+
if (reported === 0) {
|
|
232
|
+
if (!(delta > tol)) {
|
|
233
|
+
const venueError = hlStatus?.error;
|
|
234
|
+
throw new PerpError("ORDER_REJECTED", `${spot.name} spot ${symbol}: ${venueError ? String(venueError) : "IOC filled nothing"} (venue-final, balance unchanged)`, {
|
|
235
|
+
exchange: spot.name, orderId, raw: result,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
process.stderr.write(`[warn] ${spot.name} spot ${side} ${size} ${symbol}: venue reported a final fill of 0 but the balance moved ${delta} — using the measured fill\n`);
|
|
239
|
+
return { status: classify(delta, requested), filledSize: Math.min(delta, requested), avgPrice: null, orderId, raw: result };
|
|
240
|
+
}
|
|
241
|
+
if (delta < reported * TX_FILL_MIN_BALANCE_RATIO) {
|
|
242
|
+
throw pendingError(spot.name, symbol, `venue reported a final fill of ${outcome.filledSize} but the balance moved only ${delta}`, orderId, null, result);
|
|
243
|
+
}
|
|
244
|
+
const avgPrice = isSpotOrderResult(result) ? positive(result.avgPrice) : positive(hlFilled?.avgPx);
|
|
245
|
+
return { status: classify(reported, requested), filledSize: Math.min(reported, requested), avgPrice, orderId, raw: result };
|
|
246
|
+
}
|
|
247
|
+
/** Decimal string for a filled size (no exponent), floored to `decimals`. */
|
|
248
|
+
export function fillSizeString(filled, decimals) {
|
|
249
|
+
const f = 10 ** decimals;
|
|
250
|
+
return (Math.floor(filled * f + 1e-9) / f).toFixed(decimals);
|
|
251
|
+
}
|
|
252
|
+
/** Decimal places of a plain decimal size string ("0.0100" → 4). */
|
|
253
|
+
export function sizeDecimalsOf(size) {
|
|
254
|
+
const frac = size.split(".")[1];
|
|
255
|
+
return frac === undefined ? 0 : frac.length;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Spot lot step (10^-sizeDecimals) from the venue's spot market info. `symbol` is "BASE/QUOTE"
|
|
259
|
+
* or a bare base; a bare base whose markets disagree on the lot, or an unknown market, throws
|
|
260
|
+
* (Rule #2: never size off the typed decimals).
|
|
261
|
+
*/
|
|
262
|
+
export async function spotLotStepOf(spot, symbol) {
|
|
263
|
+
const want = symbol.toUpperCase();
|
|
264
|
+
const markets = (await spot.getSpotMarkets()).filter(m => want.includes("/")
|
|
265
|
+
? m.symbol.toUpperCase() === want
|
|
266
|
+
: spotTokenBase(m.baseToken) === spotTokenBase(want));
|
|
267
|
+
const decs = [...new Set(markets.map(m => m.sizeDecimals))];
|
|
268
|
+
if (decs.length !== 1 || !Number.isInteger(decs[0]) || decs[0] < 0) {
|
|
269
|
+
throw new PerpError(markets.length === 0 ? "SYMBOL_NOT_FOUND" : "EXCHANGE_ERROR", `${spot.name} spot ${symbol}: ${markets.length === 0 ? "market not found" : `ambiguous / unusable lot precision (${decs.join(", ")})`} — lot step unknown`, { exchange: spot.name });
|
|
270
|
+
}
|
|
271
|
+
const d = decs[0];
|
|
272
|
+
return d === 0 ? "1" : `0.${"0".repeat(d - 1)}1`;
|
|
273
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TradingV2 — normalized order entry for venues added under the venue
|
|
3
|
+
* abstraction (docs/DESIGN-venue-abstraction.md §3 L3, §10.7, §10.10).
|
|
4
|
+
*
|
|
5
|
+
* Method names deliberately do not overlap the legacy ExchangeAdapter trading
|
|
6
|
+
* methods, so an adapter can implement both without overloads.
|
|
7
|
+
*/
|
|
8
|
+
import { PerpError } from "../errors.js";
|
|
9
|
+
import type { VenueCapabilities, VenueDefinition } from "./venue.js";
|
|
10
|
+
import type { AmendRequest, CancelResult, LeverageResult, Network, OrderRef, OrderRequest, OrderResult, TimeInForce, VenueId, VenueMarket } from "./venue-types.js";
|
|
11
|
+
export interface VenueBase {
|
|
12
|
+
readonly name: VenueId;
|
|
13
|
+
readonly venue: VenueDefinition;
|
|
14
|
+
readonly network: Network;
|
|
15
|
+
}
|
|
16
|
+
export interface VenueMarketsSource extends VenueBase {
|
|
17
|
+
getVenueMarkets(): Promise<VenueMarket[]>;
|
|
18
|
+
}
|
|
19
|
+
export interface TradingV2 extends VenueMarketsSource {
|
|
20
|
+
placeOrder(req: OrderRequest): Promise<OrderResult>;
|
|
21
|
+
amendOrder(req: AmendRequest): Promise<OrderResult>;
|
|
22
|
+
cancelByRef(symbol: string, ref: OrderRef): Promise<CancelResult>;
|
|
23
|
+
cancelAllV2(symbol: string | null): Promise<CancelResult>;
|
|
24
|
+
applyLeverage(symbol: string, leverage: number, marginMode: "cross" | "isolated" | null): Promise<LeverageResult>;
|
|
25
|
+
getOrderStatus(symbol: string, ref: OrderRef): Promise<OrderResult>;
|
|
26
|
+
}
|
|
27
|
+
export declare function isTradingV2(a: unknown): a is TradingV2;
|
|
28
|
+
/**
|
|
29
|
+
* Uniform "not supported" response (design §13.6, §13.10 #13): CAPABILITY_UNSUPPORTED
|
|
30
|
+
* with details { venue, feature, reason } and an alternative in `remediation`.
|
|
31
|
+
* `venue` is a venue id or display name; `feature` a short capability name
|
|
32
|
+
* ("limitOrder", "fok", "postOnly", "amend", "trading", "orderbook", ...).
|
|
33
|
+
*/
|
|
34
|
+
export declare function unsupported(venue: string, feature: string, reason: string, remediation: string): PerpError;
|
|
35
|
+
/**
|
|
36
|
+
* An adapter whose reduce-only orders are currently refused (a venue whose reduce-only wire
|
|
37
|
+
* format is not set; none today) reports why. Callers that will need a reduce-only order
|
|
38
|
+
* LATER in a flow ask first — an entry carrying --tp/--sl is refused BEFORE the entry is sent
|
|
39
|
+
* (never "entry filled, protection failed"), and a close is refused before any read. Adapters
|
|
40
|
+
* without the method have no such gate.
|
|
41
|
+
*/
|
|
42
|
+
export declare function reduceOnlyGateOf(adapter: unknown): PerpError | null;
|
|
43
|
+
/**
|
|
44
|
+
* An adapter whose STOP orders are currently refused (QFEX until stop acknowledgements can be
|
|
45
|
+
* correlated) reports why. `--tp/--sl` entries and `trade tpsl` ask first, so an entry is never
|
|
46
|
+
* sent when its protective legs would be refused. Adapters without the method have no such gate.
|
|
47
|
+
*/
|
|
48
|
+
export declare function stopOrderGateOf(adapter: unknown): PerpError | null;
|
|
49
|
+
/**
|
|
50
|
+
* An adapter on which UNATTENDED automation is currently refused (QFEX while its stop orders are
|
|
51
|
+
* refused) reports why. Bots, plans, TWAP, DCA, grid, funding-arb, trailing stop and background
|
|
52
|
+
* jobs ask before they start; manual commands never ask. Adapters without the method have no
|
|
53
|
+
* such gate.
|
|
54
|
+
*/
|
|
55
|
+
export declare function automationGateOf(adapter: unknown): PerpError | null;
|
|
56
|
+
/**
|
|
57
|
+
* Refuse to START anything that trades unattended on a venue that cannot close or protect its
|
|
58
|
+
* positions. Bots, plans, TWAP, DCA, grid, funding-arb, trailing stop and background jobs all
|
|
59
|
+
* need a reduce-only order later (close / stop / drawdown exit): on a venue whose reduce-only
|
|
60
|
+
* orders are gated (reduceOnlyGateOf) they would open a position they cannot close, and on a
|
|
61
|
+
* venue that refuses automation (automationGateOf) they would run without a protective exit.
|
|
62
|
+
* Throws the gate before the first order.
|
|
63
|
+
*/
|
|
64
|
+
export declare function assertCanClosePositions(adapter: unknown, what: string): void;
|
|
65
|
+
/** The gate's own code / details / remediation, with what was refused and why in front. */
|
|
66
|
+
export declare function startRefusal(what: string, why: string, gate: PerpError): PerpError;
|
|
67
|
+
/**
|
|
68
|
+
* Validate an order request against the venue's declared capabilities BEFORE
|
|
69
|
+
* anything is sent. Throws; never adjusts the request.
|
|
70
|
+
*/
|
|
71
|
+
export declare function validateOrderRequest(venue: VenueDefinition, caps: VenueCapabilities, req: OrderRequest): void;
|
|
72
|
+
/**
|
|
73
|
+
* Resolve a CLI TIF input (common GTC/IOC/FOK/ALO or a venue alias GTT/GTX/TOB,
|
|
74
|
+
* case-insensitive) to a value the venue declares in its capabilities. Never
|
|
75
|
+
* substitutes a different meaning: FOK is never emulated (§13.3) and an
|
|
76
|
+
* unknown / unoffered value is the uniform CAPABILITY_UNSUPPORTED response.
|
|
77
|
+
*/
|
|
78
|
+
export declare function validateLegacyTif(venue: VenueDefinition, caps: VenueCapabilities, tif: string): TimeInForce;
|
|
79
|
+
/**
|
|
80
|
+
* Poll getOrderStatus until the order reaches a final state, is resting ("open"),
|
|
81
|
+
* or the timeout elapses. On timeout returns the last observation with
|
|
82
|
+
* finality "pending" — never guesses a fill.
|
|
83
|
+
*
|
|
84
|
+
* `untilResting`: treat "open"/"partiallyFilled" as a stopping point (limit orders).
|
|
85
|
+
* `ack`: the placement acknowledgement of an async venue. When set, an
|
|
86
|
+
* ORDER_NOT_FOUND from getOrderStatus inside this loop means "acknowledged but
|
|
87
|
+
* not yet visible on the read path" (Arcus forwards to the engine before the
|
|
88
|
+
* order store has it) and the ack itself (status "accepted") stands as the
|
|
89
|
+
* observation. Outside this loop ORDER_NOT_FOUND is never reinterpreted.
|
|
90
|
+
*/
|
|
91
|
+
export declare function awaitOrderFinal(adapter: TradingV2, symbol: string, ref: OrderRef, opts: {
|
|
92
|
+
timeoutMs: number;
|
|
93
|
+
pollMs: number;
|
|
94
|
+
untilResting: boolean;
|
|
95
|
+
ack: OrderResult | null;
|
|
96
|
+
}): Promise<OrderResult>;
|
|
97
|
+
/** Generate a client order id: time-ordered, 20 chars max, [0-9a-z]. */
|
|
98
|
+
export declare function newClientOrderId(prefix?: string): string;
|
|
99
|
+
/**
|
|
100
|
+
* Client order id in the venue's format: Lighter-family `clientOrderIndex` is a
|
|
101
|
+
* decimal integer ≤ 2^48 − 1 (ms timestamp × 100 + 2 random digits); QFEX and Pacifica take a
|
|
102
|
+
* UUID (QFEX: the format the venue itself generates; Pacifica: "Full UUID string"); Hyperliquid a
|
|
103
|
+
* 128-bit cloid ("0x" + 32 hex); every other venue (Aster: [.A-Z:/a-z0-9_-]{1,36}) takes
|
|
104
|
+
* newClientOrderId().
|
|
105
|
+
*/
|
|
106
|
+
export declare function newVenueClientOrderId(venue: VenueDefinition): string;
|
|
107
|
+
/** OrderResult plus the caller-facing next step when the outcome is not final (null when final). */
|
|
108
|
+
export type PlacedOrder = OrderResult & {
|
|
109
|
+
remediation: string | null;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Place through TradingV2 and settle the outcome as far as the venue can prove it:
|
|
113
|
+
* async-ack venues are polled with awaitOrderFinal until final / resting (non-market)
|
|
114
|
+
* or ASYNC_ACK_TIMEOUT_MS. A non-final result carries a "do NOT resubmit" remediation;
|
|
115
|
+
* a failed status poll after the ack is never reported as a failed order.
|
|
116
|
+
*/
|
|
117
|
+
export declare function placeAndConfirm(adapter: TradingV2, caps: VenueCapabilities, req: OrderRequest): Promise<PlacedOrder>;
|