perp-cli 0.14.2 → 0.15.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 +152 -13
- package/dist/agent-wallet/store.d.ts +3 -2
- package/dist/agent-wallet/store.js +2 -2
- package/dist/api/public/hyperliquid.js +4 -0
- package/dist/api/public/pacifica.js +83 -13
- package/dist/api/public/urls.d.ts +2 -0
- package/dist/api/public/urls.js +3 -0
- package/dist/arb/utils.d.ts +1 -2
- package/dist/arb/utils.js +1 -2
- package/dist/bot/apex/pulse.js +3 -0
- package/dist/bot/apex/radar.js +2 -1
- package/dist/bot/engine.d.ts +10 -1
- package/dist/bot/engine.js +14 -6
- package/dist/bot/indicators.d.ts +7 -0
- package/dist/bot/indicators.js +16 -0
- package/dist/bot/perp-order.d.ts +4 -4
- package/dist/bot/perp-order.js +5 -5
- package/dist/bot/quarantine.d.ts +1 -1
- package/dist/bot/quarantine.js +1 -1
- package/dist/bot/strategies/apex-strategy.js +3 -2
- package/dist/bot/strategies/engine-mm.js +6 -5
- package/dist/bot/strategies/funding-arb-strategy.js +9 -9
- package/dist/bot/strategies/funding-arb-utils.d.ts +15 -2
- package/dist/bot/strategies/funding-arb-utils.js +43 -24
- package/dist/bot/strategies/funding-auto.js +2 -2
- package/dist/bot/strategies/liquidation-mm.d.ts +1 -0
- package/dist/bot/strategies/liquidation-mm.js +8 -2
- package/dist/bot/strategies/momentum-breakout.d.ts +1 -0
- package/dist/bot/strategies/momentum-breakout.js +11 -3
- package/dist/bot/strategies/spot-perp-arb-strategy.js +23 -12
- package/dist/bot/strategies/spot-perp-executor.d.ts +1 -1
- package/dist/bot/strategies/spot-perp-executor.js +1 -1
- package/dist/bot/strategy-types.d.ts +2 -1
- package/dist/bot/tui/BotDashboard.d.ts +1 -1
- package/dist/bot/tui/BotDashboard.js +1 -1
- package/dist/cache.js +12 -6
- package/dist/cli-program.d.ts +15 -0
- package/dist/cli-program.js +125 -5
- package/dist/commands/agent-import.d.ts +7 -0
- package/dist/commands/agent-import.js +30 -1
- package/dist/commands/agent.d.ts +6 -3
- package/dist/commands/agent.js +160 -12
- package/dist/commands/arb/index.js +4 -4
- package/dist/commands/arb-auto.js +21 -17
- package/dist/commands/arb.d.ts +12 -0
- package/dist/commands/arb.js +61 -143
- package/dist/commands/bot.js +1 -1
- package/dist/commands/builder.js +1 -1
- package/dist/commands/funds.js +113 -3
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +27 -7
- package/dist/commands/manage.js +23 -21
- package/dist/commands/market.js +168 -36
- package/dist/commands/options.d.ts +9 -0
- package/dist/commands/options.js +134 -0
- package/dist/commands/pacifica-earn.d.ts +5 -0
- package/dist/commands/pacifica-earn.js +468 -0
- package/dist/commands/pacifica-orders.d.ts +14 -0
- package/dist/commands/pacifica-orders.js +142 -0
- package/dist/commands/portfolio.js +32 -47
- package/dist/commands/rebalance.d.ts +1 -0
- package/dist/commands/rebalance.js +15 -0
- package/dist/commands/risk.d.ts +11 -2
- package/dist/commands/risk.js +39 -44
- package/dist/commands/trade.d.ts +1 -0
- package/dist/commands/trade.js +63 -58
- package/dist/commands/wallet.js +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.js +15 -4
- package/dist/constants.js +6 -0
- package/dist/dashboard/server.js +1 -1
- package/dist/dashboard/ui.js +1 -1
- package/dist/errors.d.ts +24 -1
- package/dist/errors.js +25 -3
- package/dist/exchanges/arcus/adapter.d.ts +7 -7
- package/dist/exchanges/arcus/adapter.js +12 -12
- package/dist/exchanges/arcus/agent.d.ts +1 -1
- package/dist/exchanges/arcus/agent.js +1 -1
- package/dist/exchanges/arcus/client.js +1 -1
- package/dist/exchanges/arcus/signing.d.ts +2 -3
- package/dist/exchanges/arcus/signing.js +1 -1
- package/dist/exchanges/arcus/spot-chain.d.ts +1 -1
- package/dist/exchanges/arcus/spot-chain.js +1 -1
- package/dist/exchanges/arcus/spot-router.d.ts +1 -1
- package/dist/exchanges/arcus/spot-router.js +2 -2
- package/dist/exchanges/arcus/spot.d.ts +2 -3
- package/dist/exchanges/arcus/spot.js +2 -3
- package/dist/exchanges/aster-spot.d.ts +3 -3
- package/dist/exchanges/aster-spot.js +6 -9
- package/dist/exchanges/aster-typed-data.d.ts +1 -1
- package/dist/exchanges/aster-typed-data.js +1 -1
- package/dist/exchanges/aster.d.ts +9 -4
- package/dist/exchanges/aster.js +125 -55
- package/dist/exchanges/builder-fee.d.ts +1 -1
- package/dist/exchanges/builder-fee.js +13 -2
- package/dist/exchanges/canonical-symbols.d.ts +1 -2
- package/dist/exchanges/canonical-symbols.js +26 -2
- package/dist/exchanges/derive/client.d.ts +37 -0
- package/dist/exchanges/derive/client.js +135 -0
- package/dist/exchanges/derive/options.d.ts +68 -0
- package/dist/exchanges/derive/options.js +360 -0
- package/dist/exchanges/extended/adapter.d.ts +82 -0
- package/dist/exchanges/extended/adapter.js +179 -0
- package/dist/exchanges/extended/client.d.ts +38 -0
- package/dist/exchanges/extended/client.js +88 -0
- package/dist/exchanges/extended/public.d.ts +130 -0
- package/dist/exchanges/extended/public.js +429 -0
- package/dist/exchanges/grvt/adapter.d.ts +86 -0
- package/dist/exchanges/grvt/adapter.js +206 -0
- package/dist/exchanges/grvt/client.d.ts +25 -0
- package/dist/exchanges/grvt/client.js +86 -0
- package/dist/exchanges/grvt/public.d.ts +151 -0
- package/dist/exchanges/grvt/public.js +438 -0
- package/dist/exchanges/hyperliquid-spot.d.ts +1 -1
- package/dist/exchanges/hyperliquid-spot.js +5 -5
- package/dist/exchanges/hyperliquid.d.ts +22 -16
- package/dist/exchanges/hyperliquid.js +80 -55
- package/dist/exchanges/index.d.ts +1 -1
- package/dist/exchanges/index.js +1 -1
- package/dist/exchanges/interface.d.ts +97 -8
- package/dist/exchanges/interface.js +19 -2
- package/dist/exchanges/ioc-outcome.d.ts +1 -1
- package/dist/exchanges/ioc-outcome.js +1 -1
- package/dist/exchanges/legacy-trading-v2.d.ts +2 -2
- package/dist/exchanges/legacy-trading-v2.js +7 -2
- package/dist/exchanges/lighter-public.d.ts +2 -2
- package/dist/exchanges/lighter-public.js +2 -2
- package/dist/exchanges/lighter-signer.d.ts +1 -1
- package/dist/exchanges/lighter-signer.js +1 -1
- package/dist/exchanges/lighter-spot.d.ts +3 -4
- package/dist/exchanges/lighter-spot.js +6 -7
- package/dist/exchanges/lighter.d.ts +11 -11
- package/dist/exchanges/lighter.js +28 -14
- package/dist/exchanges/ondo/adapter.d.ts +5 -6
- package/dist/exchanges/ondo/adapter.js +16 -14
- package/dist/exchanges/ondo/agent.d.ts +1 -1
- package/dist/exchanges/ondo/agent.js +1 -1
- package/dist/exchanges/ondo/client.d.ts +1 -1
- package/dist/exchanges/ondo/client.js +2 -2
- package/dist/exchanges/ondo/public.d.ts +8 -1
- package/dist/exchanges/ondo/public.js +13 -2
- package/dist/exchanges/ondo/spot.d.ts +2 -2
- package/dist/exchanges/ondo/spot.js +3 -3
- package/dist/exchanges/options-interface.d.ts +158 -0
- package/dist/exchanges/options-interface.js +17 -0
- package/dist/exchanges/options-venues.d.ts +12 -0
- package/dist/exchanges/options-venues.js +35 -0
- package/dist/exchanges/pacifica-atomic.d.ts +211 -0
- package/dist/exchanges/pacifica-atomic.js +440 -0
- package/dist/exchanges/pacifica-decimal.d.ts +10 -0
- package/dist/exchanges/pacifica-decimal.js +51 -0
- package/dist/exchanges/pacifica-presigned.d.ts +53 -0
- package/dist/exchanges/pacifica-presigned.js +141 -0
- package/dist/exchanges/pacifica-print.d.ts +200 -0
- package/dist/exchanges/pacifica-print.js +417 -0
- package/dist/exchanges/pacifica-spot.d.ts +2 -2
- package/dist/exchanges/pacifica-spot.js +3 -3
- package/dist/exchanges/pacifica-typed-data.d.ts +1 -1
- package/dist/exchanges/pacifica-typed-data.js +1 -1
- package/dist/exchanges/pacifica-vaults.d.ts +121 -0
- package/dist/exchanges/pacifica-vaults.js +264 -0
- package/dist/exchanges/pacifica.d.ts +32 -5
- package/dist/exchanges/pacifica.js +114 -48
- package/dist/exchanges/precision.d.ts +3 -1
- package/dist/exchanges/precision.js +9 -2
- package/dist/exchanges/qfex/adapter.d.ts +18 -5
- package/dist/exchanges/qfex/adapter.js +32 -12
- package/dist/exchanges/qfex/agent.d.ts +1 -1
- package/dist/exchanges/qfex/agent.js +1 -1
- package/dist/exchanges/qfex/client.d.ts +1 -1
- package/dist/exchanges/qfex/client.js +1 -1
- package/dist/exchanges/qfex/errors.d.ts +1 -1
- package/dist/exchanges/qfex/errors.js +2 -2
- package/dist/exchanges/qfex/public.d.ts +3 -3
- package/dist/exchanges/qfex/public.js +3 -3
- package/dist/exchanges/qfex/signing.d.ts +2 -2
- package/dist/exchanges/qfex/signing.js +4 -5
- package/dist/exchanges/qfex/ws-transport.d.ts +2 -2
- package/dist/exchanges/qfex/ws-transport.js +3 -3
- package/dist/exchanges/rate-limiter.d.ts +1 -1
- package/dist/exchanges/rate-limiter.js +5 -2
- package/dist/exchanges/registry.d.ts +1 -1
- package/dist/exchanges/registry.js +1 -1
- package/dist/exchanges/risex/adapter.d.ts +148 -0
- package/dist/exchanges/risex/adapter.js +796 -0
- package/dist/exchanges/risex/agent.d.ts +154 -0
- package/dist/exchanges/risex/agent.js +384 -0
- package/dist/exchanges/risex/client.d.ts +47 -0
- package/dist/exchanges/risex/client.js +174 -0
- package/dist/exchanges/risex/nonce.d.ts +43 -0
- package/dist/exchanges/risex/nonce.js +212 -0
- package/dist/exchanges/risex/public.d.ts +64 -0
- package/dist/exchanges/risex/public.js +150 -0
- package/dist/exchanges/risex/session.d.ts +71 -0
- package/dist/exchanges/risex/session.js +171 -0
- package/dist/exchanges/risex/typed-data.d.ts +173 -0
- package/dist/exchanges/risex/typed-data.js +240 -0
- package/dist/exchanges/risex/units.d.ts +29 -0
- package/dist/exchanges/risex/units.js +104 -0
- package/dist/exchanges/slippage.d.ts +1 -1
- package/dist/exchanges/slippage.js +1 -1
- package/dist/exchanges/spot-factory.d.ts +3 -3
- package/dist/exchanges/spot-factory.js +7 -7
- package/dist/exchanges/spot-interface.d.ts +5 -5
- package/dist/exchanges/spot-interface.js +2 -2
- package/dist/exchanges/spot-result.d.ts +3 -3
- package/dist/exchanges/spot-result.js +3 -3
- package/dist/exchanges/trading-v2.d.ts +3 -3
- package/dist/exchanges/trading-v2.js +9 -6
- package/dist/exchanges/txflow/adapter.d.ts +54 -0
- package/dist/exchanges/txflow/adapter.js +118 -0
- package/dist/exchanges/txflow/client.d.ts +47 -0
- package/dist/exchanges/txflow/client.js +153 -0
- package/dist/exchanges/txflow/public.d.ts +76 -0
- package/dist/exchanges/txflow/public.js +284 -0
- package/dist/exchanges/unknown-symbol.d.ts +29 -0
- package/dist/exchanges/unknown-symbol.js +51 -0
- package/dist/exchanges/variational/adapter.d.ts +71 -0
- package/dist/exchanges/variational/adapter.js +137 -0
- package/dist/exchanges/variational/client.d.ts +21 -0
- package/dist/exchanges/variational/client.js +66 -0
- package/dist/exchanges/variational/public.d.ts +126 -0
- package/dist/exchanges/variational/public.js +430 -0
- package/dist/exchanges/venue-types.d.ts +6 -7
- package/dist/exchanges/venue-types.js +2 -2
- package/dist/exchanges/venue.d.ts +51 -8
- package/dist/exchanges/venue.js +54 -4
- package/dist/exchanges/venues/arcus.d.ts +1 -2
- package/dist/exchanges/venues/arcus.js +5 -4
- package/dist/exchanges/venues/aster.d.ts +2 -2
- package/dist/exchanges/venues/aster.js +6 -4
- package/dist/exchanges/venues/create-helpers.d.ts +1 -1
- package/dist/exchanges/venues/create-helpers.js +3 -3
- package/dist/exchanges/venues/extended.d.ts +21 -0
- package/dist/exchanges/venues/extended.js +96 -0
- package/dist/exchanges/venues/grvt.d.ts +30 -0
- package/dist/exchanges/venues/grvt.js +98 -0
- package/dist/exchanges/venues/hyperliquid.d.ts +2 -2
- package/dist/exchanges/venues/hyperliquid.js +10 -8
- package/dist/exchanges/venues/index.d.ts +7 -2
- package/dist/exchanges/venues/index.js +8 -2
- package/dist/exchanges/venues/lighter-family.d.ts +7 -9
- package/dist/exchanges/venues/lighter-family.js +9 -11
- package/dist/exchanges/venues/lighter-rh.d.ts +2 -2
- package/dist/exchanges/venues/lighter-rh.js +7 -5
- package/dist/exchanges/venues/lighter.d.ts +1 -1
- package/dist/exchanges/venues/lighter.js +5 -3
- package/dist/exchanges/venues/ondo.d.ts +1 -1
- package/dist/exchanges/venues/ondo.js +5 -3
- package/dist/exchanges/venues/pacifica.d.ts +2 -2
- package/dist/exchanges/venues/pacifica.js +6 -4
- package/dist/exchanges/venues/qfex.d.ts +1 -1
- package/dist/exchanges/venues/qfex.js +4 -2
- package/dist/exchanges/venues/risex-release.d.ts +14 -0
- package/dist/exchanges/venues/risex-release.js +14 -0
- package/dist/exchanges/venues/risex.d.ts +31 -0
- package/dist/exchanges/venues/risex.js +116 -0
- package/dist/exchanges/venues/txflow.d.ts +18 -0
- package/dist/exchanges/venues/txflow.js +77 -0
- package/dist/exchanges/venues/variational.d.ts +21 -0
- package/dist/exchanges/venues/variational.js +85 -0
- package/dist/execution-log.d.ts +1 -1
- package/dist/funding/legacy-public.d.ts +1 -1
- package/dist/funding/legacy-public.js +9 -4
- package/dist/funding/normalize.d.ts +1 -1
- package/dist/funding/normalize.js +1 -1
- package/dist/funding/rates.d.ts +44 -4
- package/dist/funding/rates.js +56 -12
- package/dist/index.js +7 -6
- package/dist/jobs.d.ts +1 -0
- package/dist/jobs.js +25 -1
- package/dist/landing.d.ts +2 -0
- package/dist/landing.js +1 -1
- package/dist/mcp-pacifica-earn.d.ts +9 -0
- package/dist/mcp-pacifica-earn.js +58 -0
- package/dist/mcp-server.js +113 -59
- package/dist/pacifica/client.d.ts +67 -4
- package/dist/pacifica/client.js +170 -8
- package/dist/pacifica/rate-limit.d.ts +144 -0
- package/dist/pacifica/rate-limit.js +267 -0
- package/dist/pacifica/types/order.d.ts +2 -1
- package/dist/plan-executor.js +7 -2
- package/dist/rebalance.js +1 -1
- package/dist/risk.d.ts +2 -1
- package/dist/risk.js +2 -4
- package/dist/settings.d.ts +32 -3
- package/dist/signer/ows-evm.d.ts +1 -1
- package/dist/signer/ows-evm.js +1 -1
- package/dist/smart-order.d.ts +1 -1
- package/dist/smart-order.js +1 -1
- package/dist/strategies/funding-arb.d.ts +1 -1
- package/dist/strategies/funding-arb.js +1 -1
- package/dist/trade-validator.d.ts +1 -1
- package/dist/trade-validator.js +9 -4
- package/dist/utils.d.ts +12 -3
- package/dist/utils.js +11 -3
- package/dist/venue-health.d.ts +40 -0
- package/dist/venue-health.js +75 -0
- package/dist/withdraw-gate.d.ts +1 -1
- package/dist/withdraw-gate.js +1 -1
- package/dist/ws/index.d.ts +959 -0
- package/dist/ws/index.js +4295 -0
- package/dist/ws/node.d.ts +975 -0
- package/dist/ws/node.js +4366 -0
- package/dist/ws/pacifica-instrument.d.ts +8 -0
- package/dist/ws/pacifica-instrument.js +8 -0
- package/dist/ws-cli/credentials.d.ts +62 -0
- package/dist/ws-cli/credentials.js +126 -0
- package/package.json +58 -10
- package/skills/perp-cli/SKILL.md +62 -9
- package/skills/perp-cli/references/agent-operations.md +7 -0
- package/skills/perp-cli/references/commands.md +76 -5
- package/skills/perp-cli/references/ws-library.md +492 -0
|
@@ -9,9 +9,9 @@ import { rateLimitedError } from "./rate-limiter.js";
|
|
|
9
9
|
import { fetchAndCache, withCache, TTL_ACCOUNT } from "../cache.js";
|
|
10
10
|
import { approvalFromMax, builderGateOf, hlFeeTenthsBps, NO_BUILDER, requireFeeBps } from "./builder-fee.js";
|
|
11
11
|
/**
|
|
12
|
-
* Map a TIF input to HL's native value
|
|
12
|
+
* Map a TIF input to HL's native value. Accepts the common names
|
|
13
13
|
* GTC/IOC/ALO and the native spellings case-insensitively. FOK is not offered by
|
|
14
|
-
* HL (no FOK emulation
|
|
14
|
+
* HL (no FOK emulation) → CAPABILITY_UNSUPPORTED; anything else likewise.
|
|
15
15
|
*/
|
|
16
16
|
export function hlTif(raw) {
|
|
17
17
|
const t = raw.trim().toUpperCase();
|
|
@@ -31,7 +31,7 @@ export function hlSizeStep(szDecimals) {
|
|
|
31
31
|
return szDecimals <= 0 ? "1" : `0.${"0".repeat(szDecimals - 1)}1`;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* Slippage-bounded IOC protection price
|
|
34
|
+
* Slippage-bounded IOC protection price.
|
|
35
35
|
*
|
|
36
36
|
* `reference` × (1 ± bps/10000), then aligned TOWARD CROSSING (buy → up, sell →
|
|
37
37
|
* down) on HL's price grid: at most 5 significant figures and at most
|
|
@@ -56,8 +56,8 @@ export function hlProtectionPrice(reference, side, bps, szDecimals, maxDecimals)
|
|
|
56
56
|
return { protectionPrice, appliedBps };
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* A USER-SUPPLIED limit / trigger / modify price checked against HL's price grid
|
|
60
|
-
* an off-grid limit price is refused, never rounded — rounding to nearest can move a buy price UP
|
|
59
|
+
* A USER-SUPPLIED limit / trigger / modify price checked against HL's price grid:
|
|
60
|
+
* an off-grid limit price is refused, never rounded — rounding to nearest can move a buy price UP.
|
|
61
61
|
* HL docs (trading/tick-and-lot-size): "Prices can have up to 5 significant figures, but no more
|
|
62
62
|
* than MAX_DECIMALS - szDecimals decimal places where MAX_DECIMALS is 6 for perps and 8 for spot.
|
|
63
63
|
* Integer prices are always allowed, regardless of the number of significant figures."
|
|
@@ -140,7 +140,7 @@ export async function assertHlAppliedBps(appliedBps, what) {
|
|
|
140
140
|
}
|
|
141
141
|
/**
|
|
142
142
|
* Definite IOC outcome of a raw HL `order` response (shared contract with the
|
|
143
|
-
* perp-order lane
|
|
143
|
+
* perp-order lane). Reads `response.data.statuses[0]`:
|
|
144
144
|
* - `{ filled: { totalSz } }` with a plain decimal totalSz → that size, final;
|
|
145
145
|
* - `{ error }` that is HL's IOC no-match cancel ("could not immediately match")
|
|
146
146
|
* → the venue explicitly cancelled the IOC with nothing filled → "0", final;
|
|
@@ -653,7 +653,7 @@ export class HyperliquidAdapter {
|
|
|
653
653
|
// A dex-prefixed symbol must name THIS adapter's dex — never rewritten onto another dex.
|
|
654
654
|
const [prefix, base] = sym.split(":");
|
|
655
655
|
if (prefix.toLowerCase() !== this._dex.toLowerCase()) {
|
|
656
|
-
throw new PerpError("SYMBOL_NOT_FOUND", `Hyperliquid symbol ${
|
|
656
|
+
throw new PerpError("SYMBOL_NOT_FOUND", `Hyperliquid symbol ${prefix.toLowerCase()}:${base} is on dex "${prefix.toLowerCase()}", not ${this._dex ? `this adapter's dex "${this._dex}"` : "the native perp dex"}`, {
|
|
657
657
|
exchange: "hyperliquid", remediation: `Select the dex: perp -e hyperliquid --dex ${prefix.toLowerCase()} ...`,
|
|
658
658
|
});
|
|
659
659
|
}
|
|
@@ -726,7 +726,14 @@ export class HyperliquidAdapter {
|
|
|
726
726
|
}
|
|
727
727
|
return idx;
|
|
728
728
|
}
|
|
729
|
-
throw
|
|
729
|
+
throw this._unknownSymbol(symbol, `Unknown asset: ${symbol}`);
|
|
730
|
+
}
|
|
731
|
+
/** SYMBOL_NOT_FOUND for a coin the venue does not list (on this adapter's dex), with the listing command. */
|
|
732
|
+
_unknownSymbol(symbol, message) {
|
|
733
|
+
return new PerpError("SYMBOL_NOT_FOUND", message ?? `Hyperliquid has no market ${symbol.toUpperCase()}${this._dex ? ` on dex "${this._dex}"` : ""}`, {
|
|
734
|
+
exchange: "hyperliquid",
|
|
735
|
+
remediation: `List markets: perp -e hyperliquid${this._dex ? ` --dex ${this._dex}` : ""} market list`,
|
|
736
|
+
});
|
|
730
737
|
}
|
|
731
738
|
async getMarkets() {
|
|
732
739
|
if (this._marketsCache && Date.now() - this._marketsCacheTime < HyperliquidAdapter.CACHE_TTL)
|
|
@@ -785,32 +792,57 @@ export class HyperliquidAdapter {
|
|
|
785
792
|
this._assetMapReverse.set(i, sym);
|
|
786
793
|
});
|
|
787
794
|
}
|
|
788
|
-
|
|
795
|
+
// Delisted assets (meta `isDelisted: true`; live 2026-10-14: 56 of 234 native perps, all with
|
|
796
|
+
// funding / dayNtlVlm / openInterest "0.0") are not markets: excluded from the listing and
|
|
797
|
+
// everything built on it. They stay in the asset map (_loadAssetMap), so an explicit symbol
|
|
798
|
+
// still resolves for orders / position reads.
|
|
799
|
+
const delisted = new Set();
|
|
800
|
+
const result = universe.flatMap((asset, i) => {
|
|
801
|
+
if (asset.isDelisted === true) {
|
|
802
|
+
delisted.add(String(asset.name));
|
|
803
|
+
return [];
|
|
804
|
+
}
|
|
789
805
|
const ctx = (ctxs[i] ?? {});
|
|
790
806
|
const sym = String(asset.name);
|
|
791
807
|
const szDec = this._szDecimalsMap.get(sym) ?? (asset.szDecimals !== undefined ? Number(asset.szDecimals) : null);
|
|
792
|
-
return {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
808
|
+
return [{
|
|
809
|
+
symbol: sym,
|
|
810
|
+
markPrice: String(ctx.markPx ?? mids[sym] ?? "0"),
|
|
811
|
+
indexPrice: ctx.oraclePx != null ? String(ctx.oraclePx) : null,
|
|
812
|
+
fundingRate: ctx.funding != null ? String(ctx.funding) : null,
|
|
813
|
+
volume24h: ctx.dayNtlVlm != null ? String(ctx.dayNtlVlm) : null,
|
|
814
|
+
openInterest: ctx.openInterest != null ? String(ctx.openInterest) : null,
|
|
815
|
+
maxLeverage: Number(asset.maxLeverage ?? 50),
|
|
816
|
+
sizeDecimals: szDec,
|
|
817
|
+
// HL has no separate lot-size field; the step is implied by szDecimals.
|
|
818
|
+
stepSize: null,
|
|
819
|
+
// HL funding is uniform (venue definition), not per-market.
|
|
820
|
+
fundingHours: null,
|
|
821
|
+
marginTiers: tierMap.get(Number(asset.marginTableId)) ?? null,
|
|
822
|
+
}];
|
|
807
823
|
});
|
|
824
|
+
this._delisted = delisted;
|
|
808
825
|
this._marketsCache = result;
|
|
809
826
|
this._marketsCacheTime = Date.now();
|
|
810
827
|
return result;
|
|
811
828
|
}
|
|
829
|
+
/** Display names of the delisted assets seen by the last getMarkets() (meta isDelisted). */
|
|
830
|
+
_delisted = new Set();
|
|
831
|
+
/**
|
|
832
|
+
* Why `symbol` is not in getMarkets(): it is delisted (message), or null when it is not a
|
|
833
|
+
* delisted asset. Read after getMarkets(). `market info` uses it to say "delisted" rather than
|
|
834
|
+
* "not found" — the asset map still resolves it for orders / positions / history.
|
|
835
|
+
*/
|
|
836
|
+
delistedMessage(symbol) {
|
|
837
|
+
const resolved = this.resolveSymbol(symbol.toUpperCase());
|
|
838
|
+
if (!this._delisted.has(resolved))
|
|
839
|
+
return null;
|
|
840
|
+
return `${resolved.replace(/-PERP$/, "")} is delisted on Hyperliquid (positions / history still readable)`;
|
|
841
|
+
}
|
|
812
842
|
async getOrderbook(symbol) {
|
|
813
843
|
let levels;
|
|
844
|
+
// l2Book answers `null` for a coin the venue does not list (live 2026-10-14, coin "NOPE"):
|
|
845
|
+
// SYMBOL_NOT_FOUND, never an empty book (which reads as "no liquidity").
|
|
814
846
|
if (this._dex) {
|
|
815
847
|
// HIP-3 dex: full dex-prefixed coin (e.g. "US500" → "km:US500") + dex param
|
|
816
848
|
const book = await this._infoPost({
|
|
@@ -818,11 +850,15 @@ export class HyperliquidAdapter {
|
|
|
818
850
|
coin: this._venueCoin(symbol),
|
|
819
851
|
dex: this._dex,
|
|
820
852
|
});
|
|
821
|
-
|
|
853
|
+
if (book === null)
|
|
854
|
+
throw this._unknownSymbol(symbol);
|
|
855
|
+
levels = book.levels ?? [[], []];
|
|
822
856
|
}
|
|
823
857
|
else {
|
|
824
858
|
const book = await this._infoPost({ type: "l2Book", coin: this._venueCoin(symbol) });
|
|
825
|
-
|
|
859
|
+
if (book === null)
|
|
860
|
+
throw this._unknownSymbol(symbol);
|
|
861
|
+
levels = book.levels ?? [[], []];
|
|
826
862
|
}
|
|
827
863
|
return {
|
|
828
864
|
bids: (levels[0] ?? []).map((l) => [
|
|
@@ -1234,11 +1270,11 @@ export class HyperliquidAdapter {
|
|
|
1234
1270
|
}
|
|
1235
1271
|
}
|
|
1236
1272
|
/**
|
|
1237
|
-
* Market order = slippage-bounded IOC limit
|
|
1273
|
+
* Market order = slippage-bounded IOC limit for
|
|
1238
1274
|
* native perps and HIP-3 dexes alike. Replaces the SDK's marketOpen/marketClose
|
|
1239
1275
|
* (hidden built-in slippage) and the former HIP-3 5% constant.
|
|
1240
1276
|
*
|
|
1241
|
-
* Reference price (the single declared source
|
|
1277
|
+
* Reference price (the single declared source): the l2Book mid
|
|
1242
1278
|
* (best bid + best ask) / 2 of this coin — see referencePrice(). No runtime
|
|
1243
1279
|
* substitute (mark, allMids, last trade): a missing side → PRICE_STALE before
|
|
1244
1280
|
* anything is sent. Protection = reference ± opts.slippage.bps, aligned toward
|
|
@@ -1531,7 +1567,7 @@ export class HyperliquidAdapter {
|
|
|
1531
1567
|
return hlAlignPriceToGrid(price, this.getSzDecimals(symbol), 6, side === "buy" ? "down" : "up");
|
|
1532
1568
|
}
|
|
1533
1569
|
async limitOrder(symbol, side, price, size, opts) {
|
|
1534
|
-
// TIF aliases
|
|
1570
|
+
// TIF aliases: GTC/IOC/ALO or native spellings; FOK → CAPABILITY_UNSUPPORTED.
|
|
1535
1571
|
let action;
|
|
1536
1572
|
const cloid = opts?.clientOrderId === undefined ? null : HyperliquidAdapter.requireCloid(opts.clientOrderId);
|
|
1537
1573
|
try { // pre-send (see marketOrder)
|
|
@@ -1680,7 +1716,7 @@ export class HyperliquidAdapter {
|
|
|
1680
1716
|
}
|
|
1681
1717
|
// ── Interface methods ──
|
|
1682
1718
|
/**
|
|
1683
|
-
* Amend
|
|
1719
|
+
* Amend via HL native batchModify. `size` = the NEW
|
|
1684
1720
|
* open (unfilled) size — native-modify semantics, not the original total. The
|
|
1685
1721
|
* order's own tif (Gtc/Alo) and reduceOnly are read from frontendOpenOrders
|
|
1686
1722
|
* and preserved; nothing is hardcoded.
|
|
@@ -1770,8 +1806,13 @@ export class HyperliquidAdapter {
|
|
|
1770
1806
|
});
|
|
1771
1807
|
}
|
|
1772
1808
|
async getRecentTrades(symbol, limit = 20) {
|
|
1809
|
+
// recentTrades answers HTTP 500 "null" for an unlisted coin (live 2026-10-14), which would read
|
|
1810
|
+
// as a retryable venue error: resolve the coin against the asset map first (SYMBOL_NOT_FOUND).
|
|
1811
|
+
await this.getAssetIndex(symbol);
|
|
1773
1812
|
const trades = await this._infoPost({ type: "recentTrades", coin: this._venueCoin(symbol) });
|
|
1774
|
-
|
|
1813
|
+
if (trades === null)
|
|
1814
|
+
throw this._unknownSymbol(symbol);
|
|
1815
|
+
return trades
|
|
1775
1816
|
.slice(0, limit)
|
|
1776
1817
|
.map((t) => ({
|
|
1777
1818
|
time: Number(t.time ?? 0),
|
|
@@ -1779,10 +1820,11 @@ export class HyperliquidAdapter {
|
|
|
1779
1820
|
side: String(t.side) === "B" ? "buy" : "sell",
|
|
1780
1821
|
price: String(t.px ?? "0"),
|
|
1781
1822
|
size: String(t.sz ?? ""),
|
|
1782
|
-
fee:
|
|
1823
|
+
fee: null, // the public tape carries no fee
|
|
1783
1824
|
}));
|
|
1784
1825
|
}
|
|
1785
1826
|
async getKlines(symbol, interval, startTime, endTime) {
|
|
1827
|
+
await this.getAssetIndex(symbol); // unlisted coin: SYMBOL_NOT_FOUND (candleSnapshot answers HTTP 500 "null")
|
|
1786
1828
|
const candles = await this._infoPost({
|
|
1787
1829
|
type: "candleSnapshot",
|
|
1788
1830
|
req: { coin: this._venueCoin(symbol), interval, startTime, endTime },
|
|
@@ -1793,7 +1835,10 @@ export class HyperliquidAdapter {
|
|
|
1793
1835
|
high: String(c.h ?? "0"),
|
|
1794
1836
|
low: String(c.l ?? "0"),
|
|
1795
1837
|
close: String(c.c ?? "0"),
|
|
1796
|
-
|
|
1838
|
+
// absent / non-numeric → null (never "")
|
|
1839
|
+
volume: typeof c.v === "string" && c.v.trim() !== "" && Number.isFinite(Number(c.v)) ? c.v
|
|
1840
|
+
: typeof c.v === "number" && Number.isFinite(c.v) ? String(c.v) : null,
|
|
1841
|
+
quoteVolume: null, // candleSnapshot carries base volume only
|
|
1797
1842
|
trades: Number(c.n ?? 0),
|
|
1798
1843
|
}));
|
|
1799
1844
|
}
|
|
@@ -1943,6 +1988,7 @@ export class HyperliquidAdapter {
|
|
|
1943
1988
|
return !/[:@#/]/.test(coin);
|
|
1944
1989
|
}
|
|
1945
1990
|
async getFundingHistory(symbol, limit = 10) {
|
|
1991
|
+
await this.getAssetIndex(symbol); // unlisted coin: SYMBOL_NOT_FOUND (fundingHistory answers HTTP 500)
|
|
1946
1992
|
const now = Date.now();
|
|
1947
1993
|
const history = await this._infoPost({ type: "fundingHistory", coin: this._venueCoin(symbol), startTime: now - 24 * 60 * 60 * 1000 });
|
|
1948
1994
|
return (history ?? []).slice(-limit).map((h) => ({
|
|
@@ -1958,7 +2004,7 @@ export class HyperliquidAdapter {
|
|
|
1958
2004
|
* Place a trigger order (stop loss / take profit).
|
|
1959
2005
|
* Python SDK: order() with trigger type {"trigger": {triggerPx, isMarket, tpsl: "tp"|"sl"}}
|
|
1960
2006
|
*
|
|
1961
|
-
* Pricing
|
|
2007
|
+
* Pricing:
|
|
1962
2008
|
* - isMarket (default): HL native market trigger; `p` = trigger ± 10 % (the venue's documented
|
|
1963
2009
|
* market TP/SL slippage tolerance, HL_MARKET_TPSL_SLIPPAGE_BPS), aligned toward crossing.
|
|
1964
2010
|
* - limit trigger with an explicit `limitPrice`: that price, rounded to HL's grid.
|
|
@@ -2385,27 +2431,6 @@ export class HyperliquidAdapter {
|
|
|
2385
2431
|
}
|
|
2386
2432
|
return res;
|
|
2387
2433
|
}
|
|
2388
|
-
/**
|
|
2389
|
-
* Get funding history for a symbol.
|
|
2390
|
-
*/
|
|
2391
|
-
async getFundingHistoryRaw(symbol, startTime, endTime) {
|
|
2392
|
-
const baseUrl = this._testnet
|
|
2393
|
-
? "https://api.hyperliquid-testnet.xyz"
|
|
2394
|
-
: "https://api.hyperliquid.xyz";
|
|
2395
|
-
const body = {
|
|
2396
|
-
type: "fundingHistory",
|
|
2397
|
-
coin: symbol.toUpperCase(),
|
|
2398
|
-
startTime,
|
|
2399
|
-
};
|
|
2400
|
-
if (endTime)
|
|
2401
|
-
body.endTime = endTime;
|
|
2402
|
-
const res = await fetch(`${baseUrl}/info`, {
|
|
2403
|
-
method: "POST",
|
|
2404
|
-
headers: { "Content-Type": "application/json" },
|
|
2405
|
-
body: JSON.stringify(body),
|
|
2406
|
-
});
|
|
2407
|
-
return res.json();
|
|
2408
|
-
}
|
|
2409
2434
|
/**
|
|
2410
2435
|
* Get user trade fills.
|
|
2411
2436
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangeFundingPayment, ExchangeKline, ExchangeAdapter, } from "./interface.js";
|
|
1
|
+
export type { ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangePublicTrade, ExchangeFundingPayment, ExchangeKline, ExchangeAdapter, } from "./interface.js";
|
|
2
2
|
export type { SpotMarketInfo, SpotBalance, SpotAdapter } from "./spot-interface.js";
|
|
3
3
|
export { SPOT_PERP_TOKEN_MAP, PERP_TO_SPOT_MAP, MAX_PRICE_DEVIATION_PCT } from "./spot-interface.js";
|
|
4
4
|
export * from "./capabilities.js";
|
package/dist/exchanges/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export { LighterAdapter } from "./lighter.js";
|
|
|
9
9
|
export { AsterAdapter } from "./aster.js";
|
|
10
10
|
export { HyperliquidSpotAdapter } from "./hyperliquid-spot.js";
|
|
11
11
|
export { LighterSpotAdapter } from "./lighter-spot.js";
|
|
12
|
-
// Venue abstraction
|
|
12
|
+
// Venue abstraction
|
|
13
13
|
export { getVenue, listVenues, listVenuesWithRole, resolveVenueId, tryResolveVenueId, parseVenueRef, networkConfig, requireCapabilities, fundingBasisOf, settlementIntervalOf, isLegacyVenue, isVenueId, READ_ONLY_CREDENTIALS, } from "./venue.js";
|
|
14
14
|
export { ensureVenuesRegistered, ALL_VENUES } from "./venues/index.js";
|
|
15
15
|
export { isTradingV2, validateOrderRequest, validateLegacyTif } from "./trading-v2.js";
|
|
@@ -9,11 +9,16 @@ export interface ExchangeMarketInfo {
|
|
|
9
9
|
/** null = venue does not publish an index/oracle price for this market */
|
|
10
10
|
indexPrice: string | null;
|
|
11
11
|
fundingRate: string | null;
|
|
12
|
-
/** null = venue does not publish 24h volume */
|
|
12
|
+
/** 24h volume in USD notional; null = venue does not publish 24h volume */
|
|
13
13
|
volume24h: string | null;
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Open interest in BASE-asset units (contracts of the underlying, e.g. BTC) — every venue
|
|
16
|
+
* publishes it that way, so it is never a USD figure. null = venue does not publish it
|
|
17
|
+
* (never "0" as a stand-in).
|
|
18
|
+
*/
|
|
15
19
|
openInterest: string | null;
|
|
16
|
-
|
|
20
|
+
/** null = the venue does not publish it (Aster: the public exchangeInfo carries no leverage) */
|
|
21
|
+
maxLeverage: number | null;
|
|
17
22
|
/** quantity precision (e.g. 0 = integers only, 2 = 0.01); null = unknown */
|
|
18
23
|
sizeDecimals: number | null;
|
|
19
24
|
/** lot step size (e.g. "1", "0.1", "0.001"); null = unknown */
|
|
@@ -38,7 +43,7 @@ export interface ExchangeMarketInfo {
|
|
|
38
43
|
* A venue that publishes no tiers (`marginTiers === null`) has one flat cap,
|
|
39
44
|
* `maxLeverage`, at every size — that is the venue's definition, not a fallback.
|
|
40
45
|
*/
|
|
41
|
-
export declare function maxLeverageForNotional(market: ExchangeMarketInfo, notional: number): number;
|
|
46
|
+
export declare function maxLeverageForNotional(market: ExchangeMarketInfo, notional: number): number | null;
|
|
42
47
|
export interface ExchangePosition {
|
|
43
48
|
symbol: string;
|
|
44
49
|
side: "long" | "short";
|
|
@@ -78,6 +83,27 @@ export interface ExchangeTrade {
|
|
|
78
83
|
size: string;
|
|
79
84
|
fee: string;
|
|
80
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* A row of the PUBLIC trade tape (getRecentTrades). The tape carries no fee for the viewer —
|
|
88
|
+
* a fee exists only on the account's own fills (getTradeHistory) — so `fee` is always null
|
|
89
|
+
* here, never "0" as a stand-in.
|
|
90
|
+
*/
|
|
91
|
+
export interface ExchangePublicTrade extends Omit<ExchangeTrade, "fee"> {
|
|
92
|
+
fee: null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Rows of a public tape the adapter left out because they carry a value the venue documents but
|
|
96
|
+
* does not declare exhaustive (e.g. a new Pacifica event_type) — never guessed into a direction.
|
|
97
|
+
* Attached to the returned array under this symbol key (not serialized); `market trades` reports
|
|
98
|
+
* it as `meta.skippedRows`. Absent = nothing skipped.
|
|
99
|
+
*/
|
|
100
|
+
export declare const TAPE_SKIPPED: unique symbol;
|
|
101
|
+
export interface TapeSkipped {
|
|
102
|
+
count: number;
|
|
103
|
+
reason: string;
|
|
104
|
+
}
|
|
105
|
+
export declare function withTapeSkipped<T>(rows: T[], skipped: TapeSkipped | null): T[];
|
|
106
|
+
export declare function tapeSkippedOf(rows: readonly unknown[]): TapeSkipped | null;
|
|
81
107
|
export interface ExchangeFundingPayment {
|
|
82
108
|
time: number;
|
|
83
109
|
symbol: string;
|
|
@@ -89,10 +115,69 @@ export interface ExchangeKline {
|
|
|
89
115
|
high: string;
|
|
90
116
|
low: string;
|
|
91
117
|
close: string;
|
|
92
|
-
volume
|
|
118
|
+
/** Base-asset volume of the candle; null = venue does not publish it (never "0" as a stand-in) */
|
|
119
|
+
volume: string | null;
|
|
120
|
+
/** Quote (USD) notional volume of the candle; null = venue does not publish it */
|
|
121
|
+
quoteVolume: string | null;
|
|
93
122
|
/** null = venue does not publish a trade count for the candle */
|
|
94
123
|
trades: number | null;
|
|
95
124
|
}
|
|
125
|
+
/** One indicative quote of an RFQ venue's maker at a fixed size. */
|
|
126
|
+
export interface RfqQuoteTier {
|
|
127
|
+
/** Venue tier id ("base" = the market's minimum order size). */
|
|
128
|
+
tier: string;
|
|
129
|
+
/** USD notional of the tier; null when the venue does not publish it (minimum order size). */
|
|
130
|
+
notionalUsd: string | null;
|
|
131
|
+
bid: string;
|
|
132
|
+
ask: string;
|
|
133
|
+
}
|
|
134
|
+
/** An RFQ venue's indicative maker quotes — NOT order-book levels (`market book` on such a venue). */
|
|
135
|
+
export interface RfqQuotes {
|
|
136
|
+
kind: "rfqQuotes";
|
|
137
|
+
venue: string;
|
|
138
|
+
symbol: string;
|
|
139
|
+
ticker: string;
|
|
140
|
+
markPrice: string;
|
|
141
|
+
/** null = no quotes published right now (e.g. a closed market). */
|
|
142
|
+
updatedAt: string | null;
|
|
143
|
+
baseSpreadBps: string | null;
|
|
144
|
+
quotes: RfqQuoteTier[];
|
|
145
|
+
note: string;
|
|
146
|
+
}
|
|
147
|
+
/** Separate long / short rates of one daily swap funding payment (fractions). */
|
|
148
|
+
export interface SwapFundingRates {
|
|
149
|
+
annualizedLong: string;
|
|
150
|
+
annualizedShort: string;
|
|
151
|
+
intervalLong: string;
|
|
152
|
+
intervalShort: string;
|
|
153
|
+
}
|
|
154
|
+
/** Current funding terms of one market, for a venue that publishes no funding history (`market funding`). */
|
|
155
|
+
export interface CurrentFundingTerms {
|
|
156
|
+
kind: "currentFunding";
|
|
157
|
+
venue: string;
|
|
158
|
+
symbol: string;
|
|
159
|
+
ticker: string;
|
|
160
|
+
contractType: "perpetual" | "swap";
|
|
161
|
+
/** "predicted": the rate charged at nextFundingTime, recomputed during the window. */
|
|
162
|
+
rateKind: "predicted" | null;
|
|
163
|
+
/** Fraction per interval as published (perpetual); null for a swap or when unknown. */
|
|
164
|
+
intervalRate: string | null;
|
|
165
|
+
intervalHours: number | null;
|
|
166
|
+
/** intervalRate / intervalHours. */
|
|
167
|
+
hourlyRate: number | null;
|
|
168
|
+
/** hourlyRate × 24 × 365 × 100 (same normalization as arb scan). */
|
|
169
|
+
annualizedPct: number | null;
|
|
170
|
+
/** The venue's own annualized rate (fraction), for cross-checking. */
|
|
171
|
+
venueAnnualizedRate: string | null;
|
|
172
|
+
/** Unix ms; null when not published. */
|
|
173
|
+
nextFundingTime: number | null;
|
|
174
|
+
/** Swap only: long / short rates of the last applied and the upcoming payment. */
|
|
175
|
+
swap: {
|
|
176
|
+
last: SwapFundingRates | null;
|
|
177
|
+
next: SwapFundingRates | null;
|
|
178
|
+
} | null;
|
|
179
|
+
note: string;
|
|
180
|
+
}
|
|
96
181
|
export interface ExchangeAdapter {
|
|
97
182
|
readonly name: string;
|
|
98
183
|
readonly chain?: string;
|
|
@@ -105,13 +190,17 @@ export interface ExchangeAdapter {
|
|
|
105
190
|
bids: [string, string][];
|
|
106
191
|
asks: [string, string][];
|
|
107
192
|
}>;
|
|
108
|
-
getRecentTrades(symbol: string, limit?: number): Promise<
|
|
193
|
+
getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
|
|
109
194
|
getFundingHistory(symbol: string, limit?: number): Promise<{
|
|
110
195
|
time: number;
|
|
111
196
|
rate: string;
|
|
112
197
|
price: string | null;
|
|
113
198
|
}[]>;
|
|
114
199
|
getKlines(symbol: string, interval: string, startTime: number, endTime: number): Promise<ExchangeKline[]>;
|
|
200
|
+
/** RFQ venue (no order book): the maker's indicative quotes. Absent = the venue has an order book. */
|
|
201
|
+
getRfqQuotes?(symbol: string): Promise<RfqQuotes>;
|
|
202
|
+
/** Venue without a funding-history API: the current funding terms. Absent = use getFundingHistory. */
|
|
203
|
+
getFundingTerms?(symbol: string): Promise<CurrentFundingTerms>;
|
|
115
204
|
getBalance(): Promise<ExchangeBalance>;
|
|
116
205
|
getPositions(): Promise<ExchangePosition[]>;
|
|
117
206
|
getOpenOrders(): Promise<ExchangeOrder[]>;
|
|
@@ -119,7 +208,7 @@ export interface ExchangeAdapter {
|
|
|
119
208
|
getTradeHistory(limit?: number): Promise<ExchangeTrade[]>;
|
|
120
209
|
getFundingPayments(limit?: number): Promise<ExchangeFundingPayment[]>;
|
|
121
210
|
/**
|
|
122
|
-
* Market order = IOC within the resolved slippage bound
|
|
211
|
+
* Market order = IOC within the resolved slippage bound. `opts` is
|
|
123
212
|
* required so every caller states reduceOnly and passes resolveSlippage() output.
|
|
124
213
|
*/
|
|
125
214
|
marketOrder(symbol: string, side: "buy" | "sell", size: string, opts: {
|
|
@@ -141,7 +230,7 @@ export interface ExchangeAdapter {
|
|
|
141
230
|
* `slippage` (resolveSlippage() output) bounds the execution price of a market
|
|
142
231
|
* trigger on venues that send it as a protection-priced limit once triggered
|
|
143
232
|
* (Lighter, Arcus: required there for a market trigger — adapters never read
|
|
144
|
-
* settings
|
|
233
|
+
* settings); venue-native market triggers ignore it.
|
|
145
234
|
* `kind` ("tp" | "sl") states the protective intent explicitly: venues with distinct
|
|
146
235
|
* take-profit / stop-loss trigger types (Aster, Lighter) send that type as given — no
|
|
147
236
|
* price-based classification — and a trigger already crossed is left for the venue to
|
|
@@ -10,11 +10,28 @@ export function maxLeverageForNotional(market, notional) {
|
|
|
10
10
|
}
|
|
11
11
|
const tiers = market.marginTiers;
|
|
12
12
|
if (tiers === null || tiers.length === 0)
|
|
13
|
-
return market.maxLeverage;
|
|
14
|
-
|
|
13
|
+
return market.maxLeverage; // null = not published
|
|
14
|
+
// No headline but published tiers: the first (lowest-notional) tier is the cap below every threshold.
|
|
15
|
+
let effective = market.maxLeverage ?? tiers[0].maxLeverage;
|
|
15
16
|
for (const t of tiers) {
|
|
16
17
|
if (notional >= t.lowerBound)
|
|
17
18
|
effective = t.maxLeverage;
|
|
18
19
|
}
|
|
19
20
|
return effective;
|
|
20
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Rows of a public tape the adapter left out because they carry a value the venue documents but
|
|
24
|
+
* does not declare exhaustive (e.g. a new Pacifica event_type) — never guessed into a direction.
|
|
25
|
+
* Attached to the returned array under this symbol key (not serialized); `market trades` reports
|
|
26
|
+
* it as `meta.skippedRows`. Absent = nothing skipped.
|
|
27
|
+
*/
|
|
28
|
+
export const TAPE_SKIPPED = Symbol.for("perp-cli.tapeSkipped");
|
|
29
|
+
export function withTapeSkipped(rows, skipped) {
|
|
30
|
+
if (skipped !== null && skipped.count > 0)
|
|
31
|
+
Object.defineProperty(rows, TAPE_SKIPPED, { value: skipped, enumerable: false });
|
|
32
|
+
return rows;
|
|
33
|
+
}
|
|
34
|
+
export function tapeSkippedOf(rows) {
|
|
35
|
+
const v = rows[TAPE_SKIPPED];
|
|
36
|
+
return v === undefined ? null : v;
|
|
37
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Venue-final IOC / market order outcome
|
|
2
|
+
* Venue-final IOC / market order outcome.
|
|
3
3
|
*
|
|
4
4
|
* An adapter whose market / IOC responses report the order's FINAL filled size (nothing
|
|
5
5
|
* of the order can still execute) implements `iocOutcomeOf(raw)` on the RAW result its
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Venue-final IOC / market order outcome
|
|
2
|
+
* Venue-final IOC / market order outcome.
|
|
3
3
|
*
|
|
4
4
|
* An adapter whose market / IOC responses report the order's FINAL filled size (nothing
|
|
5
5
|
* of the order can still execute) implements `iocOutcomeOf(raw)` on the RAW result its
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TradingV2 for the four pre-existing venues (pacifica, hyperliquid, lighter /
|
|
3
|
-
* lighter-rh, aster)
|
|
3
|
+
* lighter-rh, aster).
|
|
4
4
|
*
|
|
5
5
|
* Composition, not modification: the legacy ExchangeAdapter methods keep returning
|
|
6
6
|
* their raw venue responses (in-process contract for smart-order, perp-order,
|
|
@@ -17,7 +17,7 @@ import { type TradingV2 } from "./trading-v2.js";
|
|
|
17
17
|
import { type Network, type OrderResult } from "./venue-types.js";
|
|
18
18
|
export declare function tradingV2Of(adapter: ExchangeAdapter, network: Network): TradingV2;
|
|
19
19
|
export declare function toTradingV2(adapter: ExchangeAdapter, network: Network): TradingV2;
|
|
20
|
-
/** One reduce-only protective trigger (TP or SL) of a separateOrders venue
|
|
20
|
+
/** One reduce-only protective trigger (TP or SL) of a separateOrders venue. */
|
|
21
21
|
export interface TpSlLeg {
|
|
22
22
|
symbol: string;
|
|
23
23
|
/** Side that closes the protected position (sell closes a long). */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TradingV2 for the four pre-existing venues (pacifica, hyperliquid, lighter /
|
|
3
|
-
* lighter-rh, aster)
|
|
3
|
+
* lighter-rh, aster).
|
|
4
4
|
*
|
|
5
5
|
* Composition, not modification: the legacy ExchangeAdapter methods keep returning
|
|
6
6
|
* their raw venue responses (in-process contract for smart-order, perp-order,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { PerpError, orderOutcomeUnknown } from "../errors.js";
|
|
15
15
|
import { isPacificaStopType, pacificaRefused } from "./pacifica.js";
|
|
16
|
+
import { isPacificaRateLimited } from "../pacifica/rate-limit.js";
|
|
16
17
|
import { iocLotTolerance, isIocOutcomeCapable } from "./ioc-outcome.js";
|
|
17
18
|
import { isQueryOrderCapable } from "./capabilities.js";
|
|
18
19
|
import { floorSize, lotStepOf } from "./precision.js";
|
|
@@ -621,7 +622,11 @@ class LegacyTradingV2 {
|
|
|
621
622
|
if (this.family !== "pacifica" || !pacificaRefused(e))
|
|
622
623
|
throw e;
|
|
623
624
|
raw = { error: e instanceof Error ? e.message : String(e) };
|
|
624
|
-
|
|
625
|
+
// RATE_LIMITED with sent:false (local throttle or HTTP 429): this cancel was not executed —
|
|
626
|
+
// failed (nothing cancelled), no history read needed. Unknown-after-send never lands here.
|
|
627
|
+
refusal = isPacificaRateLimited(e)
|
|
628
|
+
? { kind: "failed", error: `cancel of ${ref.value} not executed (rate limited, nothing sent / refused): ${e instanceof Error ? e.message : String(e)}` }
|
|
629
|
+
: await this.adapter.cancelRefusalOutcome(ref.value, e);
|
|
625
630
|
}
|
|
626
631
|
const out = (v, reason = "") => {
|
|
627
632
|
if (v === "cancelled")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lighter-family public market data (`lighter`, `lighter-rh`)
|
|
2
|
+
* Lighter-family public market data (`lighter`, `lighter-rh`).
|
|
3
3
|
*
|
|
4
4
|
* Sources (REST base from venues/lighter-family.ts, per venue + network):
|
|
5
5
|
* GET /api/v1/orderBookDetails → perps in `order_book_details` (decimals, min
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* venue's own; the RH host labels its own rows "lighter" too (live
|
|
12
12
|
* 2026-09-30: 57 "lighter" rows = RH's 57 perps, matched by market_id).
|
|
13
13
|
*
|
|
14
|
-
* FUNDING: basis 8h per quoted rate, hourly settlement (
|
|
14
|
+
* FUNDING: basis 8h per quoted rate, hourly settlement (Lighter
|
|
15
15
|
* and Lighter RH identical).
|
|
16
16
|
*
|
|
17
17
|
* ASSET CLASS: the API has no asset-class field (the undocumented
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lighter-family public market data (`lighter`, `lighter-rh`)
|
|
2
|
+
* Lighter-family public market data (`lighter`, `lighter-rh`).
|
|
3
3
|
*
|
|
4
4
|
* Sources (REST base from venues/lighter-family.ts, per venue + network):
|
|
5
5
|
* GET /api/v1/orderBookDetails → perps in `order_book_details` (decimals, min
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* venue's own; the RH host labels its own rows "lighter" too (live
|
|
12
12
|
* 2026-09-30: 57 "lighter" rows = RH's 57 perps, matched by market_id).
|
|
13
13
|
*
|
|
14
|
-
* FUNDING: basis 8h per quoted rate, hourly settlement (
|
|
14
|
+
* FUNDING: basis 8h per quoted rate, hourly settlement (Lighter
|
|
15
15
|
* and Lighter RH identical).
|
|
16
16
|
*
|
|
17
17
|
* ASSET CLASS: the API has no asset-class field (the undocumented
|
|
@@ -22,7 +22,7 @@ export declare const LIGHTER_ALL_MARKETS = 255;
|
|
|
22
22
|
/**
|
|
23
23
|
* One Go runtime of the official signer. The Go `main` registers its functions on
|
|
24
24
|
* globalThis and then blocks; they are captured synchronously right after `go.run()`
|
|
25
|
-
* and the globals restored, so several runtimes (one per venue+network
|
|
25
|
+
* and the globals restored, so several runtimes (one per venue+network)
|
|
26
26
|
* never see each other's functions.
|
|
27
27
|
*/
|
|
28
28
|
export declare class LighterWasmSigner {
|
|
@@ -55,7 +55,7 @@ function nonceArg(v) {
|
|
|
55
55
|
/**
|
|
56
56
|
* One Go runtime of the official signer. The Go `main` registers its functions on
|
|
57
57
|
* globalThis and then blocks; they are captured synchronously right after `go.run()`
|
|
58
|
-
* and the globals restored, so several runtimes (one per venue+network
|
|
58
|
+
* and the globals restored, so several runtimes (one per venue+network)
|
|
59
59
|
* never see each other's functions.
|
|
60
60
|
*/
|
|
61
61
|
export class LighterWasmSigner {
|
|
@@ -74,7 +74,7 @@ export declare class LighterSpotAdapter implements SpotAdapter {
|
|
|
74
74
|
tif?: string;
|
|
75
75
|
}): Promise<unknown>;
|
|
76
76
|
/**
|
|
77
|
-
* TIF mapping, as perps
|
|
77
|
+
* TIF mapping, as perps: GTC/GTT → GTT, IOC → IOC, ALO / POST_ONLY → post-only (2).
|
|
78
78
|
* FOK and anything else → CAPABILITY_UNSUPPORTED (never silently GTT).
|
|
79
79
|
*/
|
|
80
80
|
private _limitTif;
|
|
@@ -107,7 +107,7 @@ export declare class LighterSpotAdapter implements SpotAdapter {
|
|
|
107
107
|
transferUsdcToSpot(amount: number): Promise<unknown>;
|
|
108
108
|
/** Transfer USDC from spot account back to perp account */
|
|
109
109
|
transferUsdcToPerp(amount: number): Promise<unknown>;
|
|
110
|
-
/** SpotTransferCapable
|
|
110
|
+
/** SpotTransferCapable: only the venue collateral (USDC on Lighter, USDG on Lighter RH). */
|
|
111
111
|
transferToSpot(amount: string, asset: string): Promise<unknown>;
|
|
112
112
|
transferToPerp(amount: string, asset: string): Promise<unknown>;
|
|
113
113
|
private _transferAmount;
|
|
@@ -139,8 +139,7 @@ export declare class LighterSpotAdapter implements SpotAdapter {
|
|
|
139
139
|
private _nextClientOrderIndex;
|
|
140
140
|
private _getNextNonce;
|
|
141
141
|
/**
|
|
142
|
-
* POST /sendTx. `kind` "place" (order placement): failures are typed
|
|
143
|
-
* §12.3): before the request → ORDER_REJECTED; transport error, HTTP 5xx or an
|
|
142
|
+
* POST /sendTx. `kind` "place" (order placement): failures are typed: before the request → ORDER_REJECTED; transport error, HTTP 5xx or an
|
|
144
143
|
* unreadable body after it → ORDER_PENDING (the tx may have been accepted — never
|
|
145
144
|
* resubmit); an explicit non-200 code → ORDER_REJECTED. "order" (cancels) / "action"
|
|
146
145
|
* (transfers): an explicit non-200 code → ORDER_REJECTED / ACTION_REJECTED
|