perp-cli 0.14.3 → 0.16.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.ja.md +243 -0
- package/README.ko.md +243 -0
- package/README.md +138 -405
- package/README.zh.md +243 -0
- 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/lighter.d.ts +5 -0
- package/dist/api/public/lighter.js +5 -0
- package/dist/api/public/pacifica.js +85 -15
- package/dist/api/public/urls.d.ts +2 -0
- package/dist/api/public/urls.js +3 -0
- package/dist/arb/sizing.js +4 -2
- package/dist/arb/state.d.ts +6 -0
- package/dist/arb/utils.d.ts +1 -2
- package/dist/arb/utils.js +1 -2
- package/dist/balance-by-address.d.ts +39 -0
- package/dist/balance-by-address.js +44 -0
- 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/quote-rules.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 +12 -5
- package/dist/bot/strategies/funding-arb-utils.d.ts +15 -3
- package/dist/bot/strategies/funding-arb-utils.js +53 -20
- 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.d.ts +1 -1
- package/dist/bot/strategies/spot-perp-arb-strategy.js +6 -4
- package/dist/bot/strategies/spot-perp-executor.d.ts +1 -1
- package/dist/bot/strategies/spot-perp-executor.js +3 -3
- 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 +126 -6
- package/dist/commands/account.js +168 -24
- 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 +23 -81
- package/dist/commands/arb-auto.d.ts +24 -0
- package/dist/commands/arb-auto.js +175 -97
- package/dist/commands/arb.d.ts +20 -0
- package/dist/commands/arb.js +107 -163
- package/dist/commands/backtest.js +23 -21
- 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.d.ts +48 -0
- package/dist/commands/market.js +395 -100
- package/dist/commands/options.d.ts +14 -0
- package/dist/commands/options.js +151 -0
- package/dist/commands/pacifica-earn.d.ts +5 -0
- package/dist/commands/pacifica-earn.js +455 -0
- package/dist/commands/pacifica-orders.d.ts +14 -0
- package/dist/commands/pacifica-orders.js +142 -0
- package/dist/commands/portfolio.d.ts +16 -0
- package/dist/commands/portfolio.js +83 -55
- 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 +67 -62
- 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/cross-chain-margin.d.ts +3 -1
- package/dist/cross-chain-margin.js +4 -2
- package/dist/dashboard/server.js +3 -3
- package/dist/dashboard/ui.js +9 -6
- package/dist/errors.d.ts +29 -1
- package/dist/errors.js +35 -3
- package/dist/exchanges/address.d.ts +8 -0
- package/dist/exchanges/address.js +47 -0
- package/dist/exchanges/arcus/adapter.d.ts +16 -12
- package/dist/exchanges/arcus/adapter.js +45 -18
- 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/public.js +3 -2
- 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 +30 -10
- package/dist/exchanges/aster.js +153 -53
- package/dist/exchanges/builder-fee.d.ts +1 -1
- package/dist/exchanges/builder-fee.js +13 -2
- package/dist/exchanges/canonical-symbols.d.ts +8 -2
- package/dist/exchanges/canonical-symbols.js +46 -2
- package/dist/exchanges/capabilities.d.ts +2 -0
- package/dist/exchanges/capabilities.js +2 -1
- package/dist/exchanges/derive/client.d.ts +37 -0
- package/dist/exchanges/derive/client.js +135 -0
- package/dist/exchanges/derive/options.d.ts +73 -0
- package/dist/exchanges/derive/options.js +379 -0
- package/dist/exchanges/extended/adapter.d.ts +96 -0
- package/dist/exchanges/extended/adapter.js +241 -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 +133 -0
- package/dist/exchanges/extended/public.js +436 -0
- package/dist/exchanges/grvt/adapter.d.ts +100 -0
- package/dist/exchanges/grvt/adapter.js +283 -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-outcome.d.ts +2 -0
- package/dist/exchanges/hyperliquid-outcome.js +29 -1
- package/dist/exchanges/hyperliquid-spot.d.ts +9 -1
- package/dist/exchanges/hyperliquid-spot.js +24 -16
- package/dist/exchanges/hyperliquid.d.ts +199 -22
- package/dist/exchanges/hyperliquid.js +550 -202
- package/dist/exchanges/index.d.ts +1 -1
- package/dist/exchanges/index.js +1 -1
- package/dist/exchanges/interface.d.ts +157 -13
- package/dist/exchanges/interface.js +47 -0
- 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 +67 -12
- package/dist/exchanges/lighter-public.js +250 -82
- package/dist/exchanges/lighter-signer.d.ts +1 -1
- package/dist/exchanges/lighter-signer.js +1 -1
- package/dist/exchanges/lighter-spot.d.ts +10 -5
- package/dist/exchanges/lighter-spot.js +105 -97
- package/dist/exchanges/lighter.d.ts +80 -21
- package/dist/exchanges/lighter.js +312 -105
- package/dist/exchanges/ondo/adapter.d.ts +38 -13
- package/dist/exchanges/ondo/adapter.js +86 -27
- 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 +35 -3
- package/dist/exchanges/ondo/public.js +75 -32
- 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/outcome-interface.d.ts +4 -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 +8 -2
- package/dist/exchanges/pacifica-spot.js +26 -18
- 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 +130 -0
- package/dist/exchanges/pacifica-vaults.js +277 -0
- package/dist/exchanges/pacifica.d.ts +108 -10
- package/dist/exchanges/pacifica.js +428 -171
- package/dist/exchanges/precision.d.ts +3 -1
- package/dist/exchanges/precision.js +9 -2
- package/dist/exchanges/public-balances.d.ts +25 -0
- package/dist/exchanges/public-balances.js +158 -0
- package/dist/exchanges/public-positions.d.ts +43 -0
- package/dist/exchanges/public-positions.js +154 -0
- package/dist/exchanges/qfex/adapter.d.ts +69 -13
- package/dist/exchanges/qfex/adapter.js +102 -17
- 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 +65 -12
- package/dist/exchanges/qfex/public.js +131 -25
- 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 +3 -3
- 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 +160 -0
- package/dist/exchanges/risex/adapter.js +842 -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 +8 -8
- 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 +61 -0
- package/dist/exchanges/txflow/adapter.js +150 -0
- package/dist/exchanges/txflow/client.d.ts +47 -0
- package/dist/exchanges/txflow/client.js +155 -0
- package/dist/exchanges/txflow/public.d.ts +87 -0
- package/dist/exchanges/txflow/public.js +355 -0
- package/dist/exchanges/unknown-symbol.d.ts +34 -0
- package/dist/exchanges/unknown-symbol.js +56 -0
- package/dist/exchanges/variational/adapter.d.ts +67 -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 +52 -10
- package/dist/exchanges/venue-types.js +82 -11
- package/dist/exchanges/venue.d.ts +150 -11
- package/dist/exchanges/venue.js +126 -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 +19 -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 +20 -8
- package/dist/exchanges/venues/lighter.d.ts +1 -1
- package/dist/exchanges/venues/lighter.js +18 -6
- 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 +15 -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 +131 -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 +6 -4
- package/dist/funding/legacy-public.js +42 -41
- package/dist/funding/normalize.d.ts +1 -1
- package/dist/funding/normalize.js +1 -1
- package/dist/funding/rates.d.ts +95 -6
- package/dist/funding/rates.js +99 -19
- 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/liquidity.d.ts +3 -1
- package/dist/liquidity.js +8 -4
- package/dist/mcp-pacifica-earn.d.ts +9 -0
- package/dist/mcp-pacifica-earn.js +64 -0
- package/dist/mcp-server.js +211 -68
- package/dist/pacifica/client.d.ts +69 -5
- package/dist/pacifica/client.js +181 -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/positions-by-address.d.ts +34 -0
- package/dist/positions-by-address.js +46 -0
- 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 +36 -63
- package/dist/trade-validator.js +2 -2
- package/dist/utils.d.ts +22 -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/arcus-market.d.ts +9 -0
- package/dist/ws/arcus-market.js +9 -0
- package/dist/ws/aster-market.d.ts +33 -0
- package/dist/ws/aster-market.js +30 -0
- package/dist/ws/index.d.ts +980 -0
- package/dist/ws/index.js +4460 -0
- package/dist/ws/lighter-market.d.ts +14 -0
- package/dist/ws/lighter-market.js +13 -0
- package/dist/ws/node.d.ts +996 -0
- package/dist/ws/node.js +4554 -0
- package/dist/ws/pacifica-instrument.d.ts +8 -0
- package/dist/ws/pacifica-instrument.js +8 -0
- package/dist/ws/unclassified.d.ts +16 -0
- package/dist/ws/unclassified.js +43 -0
- package/dist/ws-cli/credentials.d.ts +62 -0
- package/dist/ws-cli/credentials.js +126 -0
- package/package.json +71 -10
- package/skills/perp-cli/SKILL.md +153 -36
- package/skills/perp-cli/package.json +15 -2
- package/skills/perp-cli/references/agent-operations.md +22 -12
- package/skills/perp-cli/references/commands.md +143 -17
- package/skills/perp-cli/references/strategies.md +38 -3
- package/skills/perp-cli/references/ws-library.md +523 -0
- package/skills/perp-cli/scripts/arb-monitor.sh +13 -10
- package/skills/perp-cli/scripts/funding-analysis.sh +57 -29
- package/skills/perp-cli/scripts/preflight.sh +27 -19
- package/skills/perp-cli/scripts/spot-perp-scan.sh +58 -38
- package/skills/perp-cli/scripts/validate-arb.sh +56 -39
- package/dist/cli-spec.d.ts +0 -46
- package/dist/cli-spec.js +0 -81
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ondo Perps adapter — native TradingV2 + legacy ExchangeAdapter shim
|
|
3
|
-
* (design §10.7, §10.10).
|
|
4
3
|
*
|
|
5
4
|
* Signer: HMAC API key only (OndoAgentMeta → ~/.perp/ondo-agents/<keyId>.json).
|
|
6
5
|
* There is no master-key signing path for trading; read-only adapters serve
|
|
@@ -9,8 +8,8 @@
|
|
|
9
8
|
* Order entry:
|
|
10
9
|
* - market orders: IOC LIMIT at the protection price
|
|
11
10
|
* alignProtectionPrice(slippagePrice(mark, side, bps), quoteIncrement, side),
|
|
12
|
-
* bps = the caller's resolveSlippage() value
|
|
13
|
-
* - TIF
|
|
11
|
+
* bps = the caller's resolveSlippage() value;
|
|
12
|
+
* - TIF: GTC | IOC | ALO, where ALO = GTC + postOnly; FOK is
|
|
14
13
|
* not offered (uniform CAPABILITY_UNSUPPORTED, never emulated); a limit order
|
|
15
14
|
* without a TIF is GTC;
|
|
16
15
|
* - limit orders without a caller clientOrderId get a generated one that
|
|
@@ -19,7 +18,7 @@
|
|
|
19
18
|
* - TP/SL attached to the entry via takeProfit/stopLoss;
|
|
20
19
|
* - stopMarket = position-level stop (POST /v1/perps/stop_order), reduce-only,
|
|
21
20
|
* mark-triggered; stopLimit is not offered by the venue;
|
|
22
|
-
* - amend = cancel, then place
|
|
21
|
+
* - amend = cancel, then place. `size` is the NEW OPEN
|
|
23
22
|
* size. The replacement keeps side / reduceOnly / TIF; post-only comes from
|
|
24
23
|
* the original's generated clientOrderId, or the caller's explicit TIF — an
|
|
25
24
|
* order whose post-only flag is not decodable (placed elsewhere / caller id)
|
|
@@ -35,13 +34,14 @@
|
|
|
35
34
|
* Limit prices and TP/SL triggers must be on tick (INVALID_TICK); sizes are
|
|
36
35
|
* floored to the step (SIZE_TOO_SMALL when that reaches zero).
|
|
37
36
|
*/
|
|
38
|
-
import type { ExchangeAdapter, ExchangeBalance, ExchangeFundingPayment, ExchangeKline, ExchangeMarketInfo, ExchangeOrder, ExchangePosition, ExchangeTrade } from "../interface.js";
|
|
37
|
+
import type { ExchangeAdapter, ExchangeBalance, ExchangeFundingPayment, ExchangeKline, ExchangeMarketInfo, ExchangeOrder, ExchangePosition, ExchangeTrade, ExchangePublicTrade, FundingHistoryRow } from "../interface.js";
|
|
39
38
|
import type { ResolvedSlippage } from "../slippage.js";
|
|
40
39
|
import type { TradingV2 } from "../trading-v2.js";
|
|
41
40
|
import type { VenueCreateContext, VenueDefinition } from "../venue.js";
|
|
42
41
|
import type { AmendRequest, CancelResult, LeverageResult, Network, OrderRef, OrderRequest, OrderResult, VenueMarket } from "../venue-types.js";
|
|
43
42
|
import { type BuilderFeeGate } from "../builder-fee.js";
|
|
44
43
|
import { OndoClient } from "./client.js";
|
|
44
|
+
import { type OndoListedStatus } from "./public.js";
|
|
45
45
|
export declare class OndoAdapter implements ExchangeAdapter, TradingV2 {
|
|
46
46
|
readonly name: "ondo";
|
|
47
47
|
readonly aliases: readonly ["ondo-perps"];
|
|
@@ -50,6 +50,7 @@ export declare class OndoAdapter implements ExchangeAdapter, TradingV2 {
|
|
|
50
50
|
private readonly caps;
|
|
51
51
|
private readonly client;
|
|
52
52
|
private pairsCache;
|
|
53
|
+
private contractsCache;
|
|
53
54
|
/**
|
|
54
55
|
* Builder-fee gate (settings builder.ondo; Ondo has no approval step); null = not
|
|
55
56
|
* configured. Set by the venue definition's create — the adapter never reads settings.
|
|
@@ -66,6 +67,8 @@ export declare class OndoAdapter implements ExchangeAdapter, TradingV2 {
|
|
|
66
67
|
get restClient(): OndoClient;
|
|
67
68
|
/** Account id from GET /v1/account — the `from.id`/`to.id` of withdrawals and spot↔perp transfers. */
|
|
68
69
|
accountId(): Promise<string>;
|
|
70
|
+
private pairsByMarket;
|
|
71
|
+
private contractsByMarket;
|
|
69
72
|
private pairOf;
|
|
70
73
|
/**
|
|
71
74
|
* An order the venue returned as "pending" (not yet open / filled) is read back by id
|
|
@@ -100,18 +103,40 @@ export declare class OndoAdapter implements ExchangeAdapter, TradingV2 {
|
|
|
100
103
|
cancelAllV2(symbol: string | null): Promise<CancelResult>;
|
|
101
104
|
applyLeverage(symbol: string, leverage: number, marginMode: "cross" | "isolated" | null): Promise<LeverageResult>;
|
|
102
105
|
getOrderStatus(_symbol: string, ref: OrderRef): Promise<OrderResult>;
|
|
103
|
-
|
|
106
|
+
/** Legacy rows of LISTED markets plus `tradable` (status "active") and `status` (active / closed / reduceOnly). */
|
|
107
|
+
getMarkets(): Promise<Array<ExchangeMarketInfo & {
|
|
108
|
+
tradable: boolean;
|
|
109
|
+
status: OndoListedStatus;
|
|
110
|
+
}>>;
|
|
111
|
+
/**
|
|
112
|
+
* `market info` for one market, resolved with the Ondo normalizer (ondoVenueSymbol: "AAPL",
|
|
113
|
+
* "AAPL-USD", "AAPL-USD.P", "AAPL-PERP"). A disabled market is refused like every per-symbol read.
|
|
114
|
+
*/
|
|
115
|
+
getMarketInfo(symbol: string): Promise<ExchangeMarketInfo & {
|
|
116
|
+
tradable: boolean;
|
|
117
|
+
status: OndoListedStatus;
|
|
118
|
+
}>;
|
|
119
|
+
/**
|
|
120
|
+
* Venue symbol of a per-symbol read (book / trades / funding / kline), via the one normalizer
|
|
121
|
+
* (ondoVenueSymbol). A disabled (delisted / paused) listing → SYMBOL_NOT_FOUND with status
|
|
122
|
+
* "disabled": its prices are zeroed or frozen and its funding rate is stale, so nothing it returns
|
|
123
|
+
* is live market data. An unlisted symbol is left to each read's own SYMBOL_NOT_FOUND
|
|
124
|
+
* (nonEmptyOrListed / the venue's answer).
|
|
125
|
+
*/
|
|
126
|
+
private readableMarket;
|
|
104
127
|
getOrderbook(symbol: string): Promise<{
|
|
105
128
|
bids: [string, string][];
|
|
106
129
|
asks: [string, string][];
|
|
107
130
|
}>;
|
|
108
|
-
getRecentTrades(symbol: string, limit?: number): Promise<
|
|
109
|
-
getFundingHistory(symbol: string, limit?: number): Promise<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
131
|
+
getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
|
|
132
|
+
getFundingHistory(symbol: string, limit?: number): Promise<FundingHistoryRow[]>;
|
|
133
|
+
/**
|
|
134
|
+
* GET /v1/perps/candles — authenticated (see klinesRequireAuth).
|
|
135
|
+
* Minute-based resolutions are bucketed from `from` (live 2026-10-19: from=10:01:07 → candles at
|
|
136
|
+
* :01), so `from` is floored to the interval boundary first; D / W / M are venue-aligned already.
|
|
137
|
+
* The venue also returns a zero-volume bucket that opens after `to`; candles opening after the
|
|
138
|
+
* requested end are not part of the range and are left out.
|
|
139
|
+
*/
|
|
115
140
|
getKlines(symbol: string, interval: string, startTime: number, endTime: number): Promise<ExchangeKline[]>;
|
|
116
141
|
getBalance(): Promise<ExchangeBalance>;
|
|
117
142
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ondo Perps adapter — native TradingV2 + legacy ExchangeAdapter shim
|
|
3
|
-
* (design §10.7, §10.10).
|
|
4
3
|
*
|
|
5
4
|
* Signer: HMAC API key only (OndoAgentMeta → ~/.perp/ondo-agents/<keyId>.json).
|
|
6
5
|
* There is no master-key signing path for trading; read-only adapters serve
|
|
@@ -9,8 +8,8 @@
|
|
|
9
8
|
* Order entry:
|
|
10
9
|
* - market orders: IOC LIMIT at the protection price
|
|
11
10
|
* alignProtectionPrice(slippagePrice(mark, side, bps), quoteIncrement, side),
|
|
12
|
-
* bps = the caller's resolveSlippage() value
|
|
13
|
-
* - TIF
|
|
11
|
+
* bps = the caller's resolveSlippage() value;
|
|
12
|
+
* - TIF: GTC | IOC | ALO, where ALO = GTC + postOnly; FOK is
|
|
14
13
|
* not offered (uniform CAPABILITY_UNSUPPORTED, never emulated); a limit order
|
|
15
14
|
* without a TIF is GTC;
|
|
16
15
|
* - limit orders without a caller clientOrderId get a generated one that
|
|
@@ -19,7 +18,7 @@
|
|
|
19
18
|
* - TP/SL attached to the entry via takeProfit/stopLoss;
|
|
20
19
|
* - stopMarket = position-level stop (POST /v1/perps/stop_order), reduce-only,
|
|
21
20
|
* mark-triggered; stopLimit is not offered by the venue;
|
|
22
|
-
* - amend = cancel, then place
|
|
21
|
+
* - amend = cancel, then place. `size` is the NEW OPEN
|
|
23
22
|
* size. The replacement keeps side / reduceOnly / TIF; post-only comes from
|
|
24
23
|
* the original's generated clientOrderId, or the caller's explicit TIF — an
|
|
25
24
|
* order whose post-only flag is not decodable (placed elsewhere / caller id)
|
|
@@ -35,6 +34,7 @@
|
|
|
35
34
|
* Limit prices and TP/SL triggers must be on tick (INVALID_TICK); sizes are
|
|
36
35
|
* floored to the step (SIZE_TOO_SMALL when that reaches zero).
|
|
37
36
|
*/
|
|
37
|
+
import { nonEmptyOrListed } from "../unknown-symbol.js";
|
|
38
38
|
import { randomUUID } from "node:crypto";
|
|
39
39
|
import { PerpError, orderNotSent, orderOutcomeUnknown } from "../../errors.js";
|
|
40
40
|
import { alignProtectionPrice, floorSize, formatComputedPrice, requireOnTick, slippagePrice, subDecimal } from "../precision.js";
|
|
@@ -44,7 +44,7 @@ import { parseOrderRef, toLegacyMarketInfo } from "../venue-types.js";
|
|
|
44
44
|
import { builderGateOf, builderRejectionOf, NO_BUILDER, requireFeeBps } from "../builder-fee.js";
|
|
45
45
|
import { loadOndoCredentials, ONDO_APPROVE_REMEDIATION } from "./agent.js";
|
|
46
46
|
import { OndoClient } from "./client.js";
|
|
47
|
-
import { fetchOndoTradingPairs, ondoPlainSymbol, ondoPublicData, ondoVenueSymbol, parseOndoTime, strOrNull, } from "./public.js";
|
|
47
|
+
import { fetchOndoMarketsWithStatus, fetchOndoTradingPairs, ondoDisabled, ondoPlainSymbol, ondoPublicData, ondoVenueSymbol, parseOndoTime, strOrNull, } from "./public.js";
|
|
48
48
|
const ORDERS_PAGE_LIMIT = 100;
|
|
49
49
|
const DEPTH_LEVELS = 50;
|
|
50
50
|
const PAIRS_TTL_MS = 5 * 60_000;
|
|
@@ -57,7 +57,7 @@ function isPositive(s) {
|
|
|
57
57
|
return Number(s) > 0;
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
* Generated clientOrderId carrying the post-only flag
|
|
60
|
+
* Generated clientOrderId carrying the post-only flag: the
|
|
61
61
|
* Ondo API never returns postOnly, so amend recovers it from the id instead of
|
|
62
62
|
* a local file. `pcli-p-` = post-only, `pcli-n-` = not post-only; 39 chars of
|
|
63
63
|
* [A-Za-z0-9_-] (venue rule: 1–64).
|
|
@@ -164,6 +164,7 @@ export class OndoAdapter {
|
|
|
164
164
|
caps;
|
|
165
165
|
client;
|
|
166
166
|
pairsCache = null;
|
|
167
|
+
contractsCache = null;
|
|
167
168
|
/**
|
|
168
169
|
* Builder-fee gate (settings builder.ondo; Ondo has no approval step); null = not
|
|
169
170
|
* configured. Set by the venue definition's create — the adapter never reads settings.
|
|
@@ -217,13 +218,25 @@ export class OndoAdapter {
|
|
|
217
218
|
return account.accountID;
|
|
218
219
|
}
|
|
219
220
|
// ── Helpers ──
|
|
220
|
-
async
|
|
221
|
-
const market = ondoVenueSymbol(symbol);
|
|
221
|
+
async pairsByMarket() {
|
|
222
222
|
if (this.pairsCache === null || Date.now() - this.pairsCache.at > PAIRS_TTL_MS) {
|
|
223
223
|
const pairs = await fetchOndoTradingPairs(this.client);
|
|
224
224
|
this.pairsCache = { at: Date.now(), byMarket: new Map(pairs.map(p => [p.market, p])) };
|
|
225
225
|
}
|
|
226
|
-
|
|
226
|
+
return this.pairsCache.byMarket;
|
|
227
|
+
}
|
|
228
|
+
async contractsByMarket() {
|
|
229
|
+
if (this.contractsCache === null || Date.now() - this.contractsCache.at > PAIRS_TTL_MS) {
|
|
230
|
+
const rows = await this.client.publicGet("/v1/perps/contracts", null);
|
|
231
|
+
if (!Array.isArray(rows))
|
|
232
|
+
throw new PerpError("EXCHANGE_ERROR", "Ondo Perps: /v1/perps/contracts is not a list");
|
|
233
|
+
this.contractsCache = { at: Date.now(), byMarket: new Map(rows.map(c => [c.market, c])) };
|
|
234
|
+
}
|
|
235
|
+
return this.contractsCache.byMarket;
|
|
236
|
+
}
|
|
237
|
+
async pairOf(symbol) {
|
|
238
|
+
const market = ondoVenueSymbol(symbol);
|
|
239
|
+
const pair = (await this.pairsByMarket()).get(market);
|
|
227
240
|
if (pair === undefined) {
|
|
228
241
|
throw new PerpError("SYMBOL_NOT_FOUND", `Ondo Perps has no market ${market}`, {
|
|
229
242
|
remediation: "List markets with: perp market list -e ondo",
|
|
@@ -410,7 +423,7 @@ export class OndoAdapter {
|
|
|
410
423
|
}
|
|
411
424
|
}
|
|
412
425
|
async placeOrderOnVenue(input) {
|
|
413
|
-
//
|
|
426
|
+
// GTC is the uniform default for a limit order without a TIF.
|
|
414
427
|
const tifRequested = input.tif;
|
|
415
428
|
const req = input.type === "limit" && input.tif === null ? { ...input, tif: "GTC" } : input;
|
|
416
429
|
if (req.tif === "FOK") {
|
|
@@ -558,7 +571,7 @@ export class OndoAdapter {
|
|
|
558
571
|
remediation: `Do NOT resubmit. Check the order: perp trade status ${original.orderId} --symbol ${req.symbol} -e ondo`,
|
|
559
572
|
});
|
|
560
573
|
}
|
|
561
|
-
// req.size = new OPEN size; fills that raced the cancel reduce the replacement
|
|
574
|
+
// req.size = new OPEN size; fills that raced the cancel reduce the replacement.
|
|
562
575
|
const racedFill = subDecimal(cancelled.filledSize, filledAtRead);
|
|
563
576
|
const replace = subDecimal(req.size, racedFill.startsWith("-") ? "0" : racedFill);
|
|
564
577
|
let size = null;
|
|
@@ -657,50 +670,96 @@ export class OndoAdapter {
|
|
|
657
670
|
return this.toOrderResult(order, order, readExecution(order));
|
|
658
671
|
}
|
|
659
672
|
// ── Legacy ExchangeAdapter: market data ──
|
|
673
|
+
/** Legacy rows of LISTED markets plus `tradable` (status "active") and `status` (active / closed / reduceOnly). */
|
|
660
674
|
async getMarkets() {
|
|
661
|
-
return (await this.
|
|
675
|
+
return (await fetchOndoMarketsWithStatus(this.network)).map(r => ({ ...toLegacyMarketInfo(r.market), tradable: r.market.tradable, status: r.status }));
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* `market info` for one market, resolved with the Ondo normalizer (ondoVenueSymbol: "AAPL",
|
|
679
|
+
* "AAPL-USD", "AAPL-USD.P", "AAPL-PERP"). A disabled market is refused like every per-symbol read.
|
|
680
|
+
*/
|
|
681
|
+
async getMarketInfo(symbol) {
|
|
682
|
+
const market = (await this.pairOf(symbol)).market; // unlisted → SYMBOL_NOT_FOUND
|
|
683
|
+
await this.readableMarket(market);
|
|
684
|
+
const row = (await this.getMarkets()).find(m => m.symbol === ondoPlainSymbol(market));
|
|
685
|
+
if (row === undefined) {
|
|
686
|
+
throw new PerpError("SYMBOL_NOT_FOUND", `Ondo Perps ${market} has no mark price (no price feed)`, { exchange: "ondo", remediation: "List markets with: perp market list -e ondo" });
|
|
687
|
+
}
|
|
688
|
+
return row;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Venue symbol of a per-symbol read (book / trades / funding / kline), via the one normalizer
|
|
692
|
+
* (ondoVenueSymbol). A disabled (delisted / paused) listing → SYMBOL_NOT_FOUND with status
|
|
693
|
+
* "disabled": its prices are zeroed or frozen and its funding rate is stale, so nothing it returns
|
|
694
|
+
* is live market data. An unlisted symbol is left to each read's own SYMBOL_NOT_FOUND
|
|
695
|
+
* (nonEmptyOrListed / the venue's answer).
|
|
696
|
+
*/
|
|
697
|
+
async readableMarket(symbol) {
|
|
698
|
+
const market = ondoVenueSymbol(symbol);
|
|
699
|
+
const pair = (await this.pairsByMarket()).get(market);
|
|
700
|
+
// Same predicate as the listing (ondoDisabled): the /v1/markets pair OR the contracts row.
|
|
701
|
+
if (pair !== undefined && ondoDisabled(pair, (await this.contractsByMarket()).get(market) ?? null)) {
|
|
702
|
+
throw new PerpError("SYMBOL_NOT_FOUND", `Ondo Perps ${market} is disabled (delisted / paused) — no live market data`, {
|
|
703
|
+
exchange: "ondo", status: "disabled", remediation: "List tradable markets with: perp market list -e ondo",
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
return market;
|
|
662
707
|
}
|
|
663
708
|
async getOrderbook(symbol) {
|
|
664
|
-
const book = await this.client.publicGet("/v1/perps/depth", { market:
|
|
709
|
+
const book = await this.client.publicGet("/v1/perps/depth", { market: await this.readableMarket(symbol), depth: DEPTH_LEVELS });
|
|
665
710
|
const lvl = (l) => [l[0], l[1]];
|
|
666
711
|
return { bids: book.bids.map(lvl), asks: book.asks.map(lvl) };
|
|
667
712
|
}
|
|
668
713
|
async getRecentTrades(symbol, limit) {
|
|
714
|
+
const market = await this.readableMarket(symbol);
|
|
669
715
|
const trades = await this.client.publicGet("/v1/perps/trades", {
|
|
670
|
-
market
|
|
716
|
+
market, limit: limit === undefined ? null : limit,
|
|
671
717
|
});
|
|
672
|
-
|
|
718
|
+
// `200 []` for an unlisted market (live 2026-10-14): checked against the market directory.
|
|
719
|
+
return nonEmptyOrListed(this, symbol, listOf(trades).map(t => ({
|
|
673
720
|
time: parseOndoTime(t.time, "trade"),
|
|
674
721
|
symbol: ondoPlainSymbol(t.market),
|
|
675
722
|
side: t.aggressor_side,
|
|
676
723
|
price: t.price,
|
|
677
724
|
size: t.size,
|
|
678
|
-
fee:
|
|
679
|
-
}));
|
|
725
|
+
fee: null, // public tape: no fee applies to the viewer
|
|
726
|
+
})), ondoPlainSymbol(market));
|
|
680
727
|
}
|
|
681
728
|
async getFundingHistory(symbol, limit) {
|
|
682
729
|
const rows = await this.client.publicGet("/v1/perps/funding_rate_history", {
|
|
683
|
-
market:
|
|
730
|
+
market: await this.readableMarket(symbol), limit: limit === undefined ? null : limit,
|
|
684
731
|
});
|
|
685
|
-
return listOf(rows).map(r => ({ time: parseOndoTime(r.time, "funding"), rate: r.fundingRate, price: null }));
|
|
732
|
+
return listOf(rows).map(r => ({ time: parseOndoTime(r.time, "funding"), rate: r.fundingRate, price: null, intervalHours: 1, rateKind: "lastSettled" }));
|
|
686
733
|
}
|
|
687
|
-
/**
|
|
734
|
+
/**
|
|
735
|
+
* GET /v1/perps/candles — authenticated (see klinesRequireAuth).
|
|
736
|
+
* Minute-based resolutions are bucketed from `from` (live 2026-10-19: from=10:01:07 → candles at
|
|
737
|
+
* :01), so `from` is floored to the interval boundary first; D / W / M are venue-aligned already.
|
|
738
|
+
* The venue also returns a zero-volume bucket that opens after `to`; candles opening after the
|
|
739
|
+
* requested end are not part of the range and are left out.
|
|
740
|
+
*/
|
|
688
741
|
async getKlines(symbol, interval, startTime, endTime) {
|
|
742
|
+
const resolution = toResolution(interval);
|
|
743
|
+
const minuteMs = /^\d+$/.test(resolution) ? Number(resolution) * 60_000 : null;
|
|
744
|
+
const from = minuteMs === null ? startTime : Math.floor(startTime / minuteMs) * minuteMs;
|
|
745
|
+
const market = await this.readableMarket(symbol);
|
|
689
746
|
const candles = await this.client.get("/v1/perps/candles", {
|
|
690
|
-
market
|
|
691
|
-
resolution
|
|
692
|
-
from: Math.floor(
|
|
747
|
+
market,
|
|
748
|
+
resolution,
|
|
749
|
+
from: Math.floor(from / 1000),
|
|
693
750
|
to: Math.floor(endTime / 1000),
|
|
694
751
|
});
|
|
695
|
-
|
|
752
|
+
const inRange = listOf(candles).filter(c => parseOndoTime(c.startTime, "candle") <= endTime);
|
|
753
|
+
return nonEmptyOrListed(this, symbol, inRange.map(c => ({
|
|
696
754
|
time: parseOndoTime(c.startTime, "candle"),
|
|
697
755
|
open: c.open,
|
|
698
756
|
high: c.high,
|
|
699
757
|
low: c.low,
|
|
700
758
|
close: c.close,
|
|
701
759
|
volume: c.volume,
|
|
760
|
+
quoteVolume: null,
|
|
702
761
|
trades: null, // Ondo publishes no per-candle trade count
|
|
703
|
-
}));
|
|
762
|
+
})), ondoPlainSymbol(market));
|
|
704
763
|
}
|
|
705
764
|
// ── Legacy ExchangeAdapter: account ──
|
|
706
765
|
async getBalance() {
|
|
@@ -760,7 +819,7 @@ export class OndoAdapter {
|
|
|
760
819
|
const rows = await this.client.get("/v1/perps/funding_fees", { limit: limit === undefined ? null : limit });
|
|
761
820
|
return listOf(rows).map(r => ({ time: parseOndoTime(r.time, "funding fee"), symbol: ondoPlainSymbol(r.market), payment: r.amount }));
|
|
762
821
|
}
|
|
763
|
-
// ── Legacy ExchangeAdapter: trading (shim → TradingV2
|
|
822
|
+
// ── Legacy ExchangeAdapter: trading (shim → TradingV2) ──
|
|
764
823
|
async marketOrder(symbol, side, size, opts) {
|
|
765
824
|
return this.placeOrder({
|
|
766
825
|
symbol, side, type: "market", size, price: null, triggerPrice: null, triggerSource: null, tif: null,
|
|
@@ -768,7 +827,7 @@ export class OndoAdapter {
|
|
|
768
827
|
});
|
|
769
828
|
}
|
|
770
829
|
async limitOrder(symbol, side, price, size, opts) {
|
|
771
|
-
//
|
|
830
|
+
// no TIF → GTC (uniform default); FOK → uniform CAPABILITY_UNSUPPORTED.
|
|
772
831
|
const tifInput = opts?.tif;
|
|
773
832
|
const tif = tifInput === undefined || tifInput === "" ? null : validateLegacyTif(this.venue, this.caps, tifInput);
|
|
774
833
|
return this.placeOrder({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps API-key ("agent") registration
|
|
2
|
+
* Ondo Perps API-key ("agent") registration.
|
|
3
3
|
*
|
|
4
4
|
* The HMAC key id + secret are created by the user in the Ondo Perps UI and
|
|
5
5
|
* entered via stdin by the CLI (never flags). The secret is persisted only in
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps API-key ("agent") registration
|
|
2
|
+
* Ondo Perps API-key ("agent") registration.
|
|
3
3
|
*
|
|
4
4
|
* The HMAC key id + secret are created by the user in the Ondo Perps UI and
|
|
5
5
|
* entered via stdin by the CLI (never flags). The secret is persisted only in
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps raw REST client (
|
|
2
|
+
* Ondo Perps raw REST client (raw fetch + node:crypto HMAC, no SDK).
|
|
3
3
|
*
|
|
4
4
|
* Auth (live-verified, scratchpad/sdk-findings.md §2 — the OpenAPI spec's
|
|
5
5
|
* `X-API-KEY-ID` header name is wrong):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps raw REST client (
|
|
2
|
+
* Ondo Perps raw REST client (raw fetch + node:crypto HMAC, no SDK).
|
|
3
3
|
*
|
|
4
4
|
* Auth (live-verified, scratchpad/sdk-findings.md §2 — the OpenAPI spec's
|
|
5
5
|
* `X-API-KEY-ID` header name is wrong):
|
|
@@ -220,7 +220,7 @@ export class OndoClient {
|
|
|
220
220
|
}
|
|
221
221
|
// Timeout covers the whole exchange (headers + body). A GET failure is definite
|
|
222
222
|
// (nothing changed); a POST failure may have reached the venue → outcome unknown
|
|
223
|
-
// (ORDER_PENDING, never resubmit
|
|
223
|
+
// (ORDER_PENDING, never resubmit).
|
|
224
224
|
const controller = new AbortController();
|
|
225
225
|
const timer = setTimeout(() => controller.abort(), ONDO_REQUEST_TIMEOUT_MS);
|
|
226
226
|
let res;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps public market data
|
|
2
|
+
* Ondo Perps public market data.
|
|
3
3
|
*
|
|
4
4
|
* Sources (all public, live-verified 2026-09-30):
|
|
5
5
|
* GET /v1/markets result.perps.tradingPairs[] — increments, margin
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* fetchOndoSpotTradingPairs.
|
|
19
19
|
*/
|
|
20
20
|
import type { VenuePublicData } from "../venue.js";
|
|
21
|
-
import type { AssetClass, FundingRateBasis, Network } from "../venue-types.js";
|
|
21
|
+
import type { AssetClass, FundingRateBasis, Network, VenueMarket } from "../venue-types.js";
|
|
22
22
|
import { OndoClient } from "./client.js";
|
|
23
23
|
export declare const ONDO_PERP_SUFFIX = "-USD.P";
|
|
24
24
|
export declare const ONDO_FUNDING_BASIS: FundingRateBasis;
|
|
@@ -84,12 +84,44 @@ export interface OndoMarkPrice {
|
|
|
84
84
|
export declare function ondoAssetClass(market: string, tags: readonly string[] | null | undefined): AssetClass;
|
|
85
85
|
/** "TSLA-USD.P" → "TSLA". Throws for non-perp symbols. */
|
|
86
86
|
export declare function ondoPlainSymbol(venueSymbol: string): string;
|
|
87
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* The one Ondo symbol normalizer, used by every command: "tsla", "TSLA", "TSLA-USD", "TSLA-USD.P",
|
|
89
|
+
* "TSLA-PERP" → venue symbol "TSLA-USD.P". 0.15.0 appended the suffix to whatever it was given
|
|
90
|
+
* ("AAPL-USD" → "AAPL-USD-USD.P", "AAPL-PERP" → "AAPL-PERP-USD.P").
|
|
91
|
+
*/
|
|
88
92
|
export declare function ondoVenueSymbol(symbol: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Listing state of an Ondo perp. "disabled" = delisted / paused (`disabled: true` on the
|
|
95
|
+
* /v1/markets pair or the /v1/perps/contracts row; its price fields are zeroed or frozen and its
|
|
96
|
+
* fundingRate is stale); "closed" = `isClosed` (no new trading); "reduceOnly" = closes only.
|
|
97
|
+
* Only "active" is tradable.
|
|
98
|
+
*/
|
|
99
|
+
export type OndoMarketStatus = "active" | "disabled" | "closed" | "reduceOnly";
|
|
100
|
+
/** State of a LISTED market: a disabled one is not listed (listing policy: delisted / disabled / inactive → not listed). */
|
|
101
|
+
export type OndoListedStatus = Exclude<OndoMarketStatus, "disabled">;
|
|
102
|
+
/** The one "disabled" predicate (listing and every per-symbol read): either source flags it. */
|
|
103
|
+
export declare function ondoDisabled(pair: Pick<OndoTradingPair, "disabled">, contract: Pick<OndoContract, "disabled"> | null): boolean;
|
|
104
|
+
export declare function ondoMarketStatus(pair: Pick<OndoTradingPair, "disabled">, contract: Pick<OndoContract, "disabled" | "isClosed" | "reduceOnly"> | null): OndoMarketStatus;
|
|
89
105
|
/** Empty string / absent → null. Ondo omits or blanks fields it does not publish. */
|
|
90
106
|
export declare function strOrNull(v: string | undefined | null): string | null;
|
|
107
|
+
/**
|
|
108
|
+
* A price field that the venue zeroes when it has no value: /v1/perps/contracts reports
|
|
109
|
+
* indexPrice "0" (and lastPrice "0") on disabled contracts (live 2026-10-14: ADBE, BE, CELH, IBM,
|
|
110
|
+
* NOK, OKLO, RDDT, SHEIN, SMCI, IBB, VXX, EURUSD — all `disabled: true`). A price is never 0, so
|
|
111
|
+
* "0" means "no index" → null (unknown), never $0.00. Volume / OI zeros stay: 0 is a real amount.
|
|
112
|
+
*/
|
|
113
|
+
export declare function priceOrNull(v: string | undefined | null): string | null;
|
|
91
114
|
export declare function parseOndoTime(iso: string, what: string): number;
|
|
92
115
|
export declare function ondoPublicClient(net: Network): OndoClient;
|
|
93
116
|
export declare function fetchOndoTradingPairs(client: OndoClient): Promise<OndoTradingPair[]>;
|
|
94
117
|
export declare function fetchOndoSpotTradingPairs(client: OndoClient): Promise<OndoSpotTradingPair[]>;
|
|
118
|
+
/**
|
|
119
|
+
* Every listed Ondo perp with its state (getMarkets rows carry `status`; VenueMarket has no field
|
|
120
|
+
* for it). Disabled (delisted / paused) listings are NOT listed — per-symbol reads refuse them —
|
|
121
|
+
* while closed / reduce-only markets stay listed with tradable false.
|
|
122
|
+
*/
|
|
123
|
+
export declare function fetchOndoMarketsWithStatus(net: Network): Promise<Array<{
|
|
124
|
+
market: VenueMarket;
|
|
125
|
+
status: OndoListedStatus;
|
|
126
|
+
}>>;
|
|
95
127
|
export declare const ondoPublicData: VenuePublicData;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps public market data
|
|
2
|
+
* Ondo Perps public market data.
|
|
3
3
|
*
|
|
4
4
|
* Sources (all public, live-verified 2026-09-30):
|
|
5
5
|
* GET /v1/markets result.perps.tradingPairs[] — increments, margin
|
|
@@ -33,6 +33,7 @@ const TAG_TO_ASSET_CLASS = {
|
|
|
33
33
|
Index: "index",
|
|
34
34
|
Commodity: "commodity",
|
|
35
35
|
FX: "fx",
|
|
36
|
+
"Pre-IPO": "preIpo", // live 2026-10-19: OPENAI-USD.P
|
|
36
37
|
};
|
|
37
38
|
export function ondoAssetClass(market, tags) {
|
|
38
39
|
if (tags === null || tags === undefined) {
|
|
@@ -53,17 +54,44 @@ export function ondoPlainSymbol(venueSymbol) {
|
|
|
53
54
|
}
|
|
54
55
|
return venueSymbol.slice(0, -ONDO_PERP_SUFFIX.length);
|
|
55
56
|
}
|
|
56
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* The one Ondo symbol normalizer, used by every command: "tsla", "TSLA", "TSLA-USD", "TSLA-USD.P",
|
|
59
|
+
* "TSLA-PERP" → venue symbol "TSLA-USD.P". 0.15.0 appended the suffix to whatever it was given
|
|
60
|
+
* ("AAPL-USD" → "AAPL-USD-USD.P", "AAPL-PERP" → "AAPL-PERP-USD.P").
|
|
61
|
+
*/
|
|
57
62
|
export function ondoVenueSymbol(symbol) {
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
63
|
+
const base = symbol.trim().toUpperCase().replace(/(-USD\.P|-PERP|-USD)$/, "");
|
|
64
|
+
if (base.length === 0)
|
|
60
65
|
throw new PerpError("INVALID_PARAMS", "symbol is empty");
|
|
61
|
-
return
|
|
66
|
+
return `${base}${ONDO_PERP_SUFFIX}`;
|
|
67
|
+
}
|
|
68
|
+
/** The one "disabled" predicate (listing and every per-symbol read): either source flags it. */
|
|
69
|
+
export function ondoDisabled(pair, contract) {
|
|
70
|
+
return pair.disabled === true || contract?.disabled === true;
|
|
71
|
+
}
|
|
72
|
+
export function ondoMarketStatus(pair, contract) {
|
|
73
|
+
if (ondoDisabled(pair, contract))
|
|
74
|
+
return "disabled";
|
|
75
|
+
if (contract?.isClosed === true)
|
|
76
|
+
return "closed";
|
|
77
|
+
if (contract?.reduceOnly === true)
|
|
78
|
+
return "reduceOnly";
|
|
79
|
+
return "active";
|
|
62
80
|
}
|
|
63
81
|
/** Empty string / absent → null. Ondo omits or blanks fields it does not publish. */
|
|
64
82
|
export function strOrNull(v) {
|
|
65
83
|
return v === undefined || v === null || v === "" ? null : v;
|
|
66
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* A price field that the venue zeroes when it has no value: /v1/perps/contracts reports
|
|
87
|
+
* indexPrice "0" (and lastPrice "0") on disabled contracts (live 2026-10-14: ADBE, BE, CELH, IBM,
|
|
88
|
+
* NOK, OKLO, RDDT, SHEIN, SMCI, IBB, VXX, EURUSD — all `disabled: true`). A price is never 0, so
|
|
89
|
+
* "0" means "no index" → null (unknown), never $0.00. Volume / OI zeros stay: 0 is a real amount.
|
|
90
|
+
*/
|
|
91
|
+
export function priceOrNull(v) {
|
|
92
|
+
const s = strOrNull(v);
|
|
93
|
+
return s === null || Number(s) === 0 ? null : s;
|
|
94
|
+
}
|
|
67
95
|
export function parseOndoTime(iso, what) {
|
|
68
96
|
const t = Date.parse(iso);
|
|
69
97
|
if (!Number.isFinite(t))
|
|
@@ -139,7 +167,12 @@ function requireRow(m, market, source) {
|
|
|
139
167
|
}
|
|
140
168
|
return row;
|
|
141
169
|
}
|
|
142
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Every listed Ondo perp with its state (getMarkets rows carry `status`; VenueMarket has no field
|
|
172
|
+
* for it). Disabled (delisted / paused) listings are NOT listed — per-symbol reads refuse them —
|
|
173
|
+
* while closed / reduce-only markets stay listed with tradable false.
|
|
174
|
+
*/
|
|
175
|
+
export async function fetchOndoMarketsWithStatus(net) {
|
|
143
176
|
const client = ondoPublicClient(net);
|
|
144
177
|
const pairs = await fetchOndoTradingPairs(client);
|
|
145
178
|
const contracts = byMarket(await client.publicGet("/v1/perps/contracts", null));
|
|
@@ -151,37 +184,47 @@ async function fetchMarkets(net) {
|
|
|
151
184
|
if (noMark.length > 0) {
|
|
152
185
|
console.warn(`[ondo] excluded ${noMark.length} market(s) without a mark price: ${noMark.join(", ")}`);
|
|
153
186
|
}
|
|
154
|
-
|
|
187
|
+
const out = [];
|
|
188
|
+
for (const pair of pairs.filter(p => marks[p.market] !== undefined)) {
|
|
155
189
|
const contract = requireRow(contracts, pair.market, "/v1/perps/contracts");
|
|
156
190
|
const mark = marks[pair.market];
|
|
157
191
|
const symbol = ondoPlainSymbol(pair.market);
|
|
158
192
|
const assetClass = ondoAssetClass(pair.market, pair.tags);
|
|
159
193
|
const { maxLeverage, tiers } = marginTiersOf(pair);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
const status = ondoMarketStatus(pair, contract);
|
|
195
|
+
if (status === "disabled")
|
|
196
|
+
continue;
|
|
197
|
+
out.push({ status, market: {
|
|
198
|
+
venue: "ondo",
|
|
199
|
+
venueSymbol: pair.market,
|
|
200
|
+
symbol,
|
|
201
|
+
canonical: canonicalFor("ondo", symbol, assetClass),
|
|
202
|
+
assetClass,
|
|
203
|
+
settle: "USDC",
|
|
204
|
+
quoteAsset: pair.pair.quote,
|
|
205
|
+
markPrice: mark.markPrice,
|
|
206
|
+
// /v1/perps/contracts `indexPrice` is frozen (live 2026-10-19: BTC 82702.30 unchanged for 17 min
|
|
207
|
+
// while the mark_prices oracle moved 0.5%); the oracle of /v1/perps/mark_prices is the live index.
|
|
208
|
+
indexPrice: priceOrNull(mark.oraclePrice),
|
|
209
|
+
fundingRate: strOrNull(contract.fundingRate),
|
|
210
|
+
fundingRateBasis: ONDO_FUNDING_BASIS,
|
|
211
|
+
settlementIntervalHours: ONDO_SETTLEMENT_HOURS,
|
|
212
|
+
openInterest: strOrNull(contract.openInterest),
|
|
213
|
+
volume24h: strOrNull(contract.usdVolume),
|
|
214
|
+
tickSize: pair.quoteIncrement,
|
|
215
|
+
stepSize: pair.baseIncrement,
|
|
216
|
+
minSize: null,
|
|
217
|
+
minNotional: null,
|
|
218
|
+
maxLeverage,
|
|
219
|
+
marginTiers: tiers,
|
|
220
|
+
session: sessionOf(pair, mark),
|
|
221
|
+
tradable: status === "active",
|
|
222
|
+
} });
|
|
223
|
+
}
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
async function fetchMarkets(net) {
|
|
227
|
+
return (await fetchOndoMarketsWithStatus(net)).map(r => ({ ...r.market, status: r.status }));
|
|
185
228
|
}
|
|
186
229
|
async function fetchFundingRates(net) {
|
|
187
230
|
const client = ondoPublicClient(net);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps spot adapter
|
|
2
|
+
* Ondo Perps spot adapter.
|
|
3
3
|
*
|
|
4
4
|
* Same host and HMAC API key as perps (shares OndoAdapter's OndoClient).
|
|
5
5
|
* Account model "separate": the Spot wallet ("spot") next to the Perps margin
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* Market orders: IOC LIMIT at
|
|
36
36
|
* alignProtectionPrice(slippagePrice(mid, side, bps), quoteIncrement, side)
|
|
37
37
|
* which is the web app's own pattern. bps = the caller's resolveSlippage()
|
|
38
|
-
* value
|
|
38
|
+
* value. The mid comes from the spot
|
|
39
39
|
* ticker's bid/ask; a one-sided book is PRICE_STALE (no lastPrice fallback).
|
|
40
40
|
*
|
|
41
41
|
* Unverified (needs a funded key):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ondo Perps spot adapter
|
|
2
|
+
* Ondo Perps spot adapter.
|
|
3
3
|
*
|
|
4
4
|
* Same host and HMAC API key as perps (shares OndoAdapter's OndoClient).
|
|
5
5
|
* Account model "separate": the Spot wallet ("spot") next to the Perps margin
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* Market orders: IOC LIMIT at
|
|
36
36
|
* alignProtectionPrice(slippagePrice(mid, side, bps), quoteIncrement, side)
|
|
37
37
|
* which is the web app's own pattern. bps = the caller's resolveSlippage()
|
|
38
|
-
* value
|
|
38
|
+
* value. The mid comes from the spot
|
|
39
39
|
* ticker's bid/ask; a one-sided book is PRICE_STALE (no lastPrice fallback).
|
|
40
40
|
*
|
|
41
41
|
* Unverified (needs a funded key):
|
|
@@ -361,7 +361,7 @@ export class OndoSpotAdapter {
|
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
363
|
/**
|
|
364
|
-
* Classify a POST /v1/spot/orders failure
|
|
364
|
+
* Classify a POST /v1/spot/orders failure. Definite: a definite-code
|
|
365
365
|
* PerpError (auth, signer, validation) or a venue error envelope on HTTP 4xx (generic
|
|
366
366
|
* EXCHANGE_ERROR → ORDER_REJECTED). RATE_LIMITED is kept (rejected before processing).
|
|
367
367
|
* Unknown → ORDER_PENDING: network failure, HTTP 5xx, a non-JSON / result-less body,
|