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
|
@@ -291,7 +291,7 @@ export class LighterSpotAdapter {
|
|
|
291
291
|
}
|
|
292
292
|
async spotMarketOrder(symbol, side, size, opts) {
|
|
293
293
|
// Everything up to sendTx is pre-send: a failure there is a definite "not placed"
|
|
294
|
-
// (ORDER_REJECTED); sendTx transport failures are ORDER_PENDING
|
|
294
|
+
// (ORDER_REJECTED); sendTx transport failures are ORDER_PENDING.
|
|
295
295
|
let prep;
|
|
296
296
|
try {
|
|
297
297
|
prep = await this._prepareMarketOrder(symbol, side, size, opts.slippage.bps);
|
|
@@ -400,7 +400,7 @@ export class LighterSpotAdapter {
|
|
|
400
400
|
if (minSize && sizeNum < minSize.base) {
|
|
401
401
|
throw new Error(`Size ${size} below min_base_amount ${minSize.base} for ${resolved}`);
|
|
402
402
|
}
|
|
403
|
-
// Protection price = best opposite quote ± the resolved slippage bound
|
|
403
|
+
// Protection price = best opposite quote ± the resolved slippage bound
|
|
404
404
|
const ob = await this.getSpotOrderbook(resolved);
|
|
405
405
|
let refPrice;
|
|
406
406
|
if (side === "buy") {
|
|
@@ -453,7 +453,7 @@ export class LighterSpotAdapter {
|
|
|
453
453
|
const sizeStep = dec.size <= 0 ? "1" : `0.${"0".repeat(dec.size - 1)}1`;
|
|
454
454
|
const tick = dec.price <= 0 ? "1" : `0.${"0".repeat(dec.price - 1)}1`;
|
|
455
455
|
// Size floored to the size step (never rounded up); price must already be on tick
|
|
456
|
-
// (INVALID_TICK, never rounded
|
|
456
|
+
// (INVALID_TICK, never rounded).
|
|
457
457
|
const sentSize = floorSize(size, sizeStep);
|
|
458
458
|
const sentPrice = requireOnTick(price, tick);
|
|
459
459
|
// Venue minimums: refused, never bumped up to the minimum (the order would exceed the request).
|
|
@@ -505,7 +505,7 @@ export class LighterSpotAdapter {
|
|
|
505
505
|
};
|
|
506
506
|
}
|
|
507
507
|
/**
|
|
508
|
-
* TIF mapping, as perps
|
|
508
|
+
* TIF mapping, as perps: GTC/GTT → GTT, IOC → IOC, ALO / POST_ONLY → post-only (2).
|
|
509
509
|
* FOK and anything else → CAPABILITY_UNSUPPORTED (never silently GTT).
|
|
510
510
|
*/
|
|
511
511
|
_limitTif(tif) {
|
|
@@ -656,7 +656,7 @@ export class LighterSpotAdapter {
|
|
|
656
656
|
async transferUsdcToPerp(amount) {
|
|
657
657
|
return this._selfTransfer(String(amount), 1, 0); // route: Spot(1) → Perp(0)
|
|
658
658
|
}
|
|
659
|
-
/** SpotTransferCapable
|
|
659
|
+
/** SpotTransferCapable: only the venue collateral (USDC on Lighter, USDG on Lighter RH). */
|
|
660
660
|
async transferToSpot(amount, asset) {
|
|
661
661
|
return this._selfTransfer(this._transferAmount(amount, asset), 0, 1);
|
|
662
662
|
}
|
|
@@ -864,8 +864,7 @@ export class LighterSpotAdapter {
|
|
|
864
864
|
return nonce;
|
|
865
865
|
}
|
|
866
866
|
/**
|
|
867
|
-
* POST /sendTx. `kind` "place" (order placement): failures are typed
|
|
868
|
-
* §12.3): before the request → ORDER_REJECTED; transport error, HTTP 5xx or an
|
|
867
|
+
* POST /sendTx. `kind` "place" (order placement): failures are typed: before the request → ORDER_REJECTED; transport error, HTTP 5xx or an
|
|
869
868
|
* unreadable body after it → ORDER_PENDING (the tx may have been accepted — never
|
|
870
869
|
* resubmit); an explicit non-200 code → ORDER_REJECTED. "order" (cancels) / "action"
|
|
871
870
|
* (transfers): an explicit non-200 code → ORDER_REJECTED / ACTION_REJECTED
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
|
|
1
|
+
import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangePublicTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
|
|
2
2
|
import type { ResolvedSlippage } from "./slippage.js";
|
|
3
3
|
import type { EvmSigner } from "../signer/index.js";
|
|
4
4
|
import type { AgentMeta } from "../settings.js";
|
|
@@ -34,7 +34,7 @@ export declare const LIGHTER_TIF: {
|
|
|
34
34
|
readonly POST_ONLY: 2;
|
|
35
35
|
};
|
|
36
36
|
/**
|
|
37
|
-
* CLI format rule for a Lighter client order id
|
|
37
|
+
* CLI format rule for a Lighter client order id: the venue's
|
|
38
38
|
* `clientOrderIndex` is numeric, so the id must be a plain decimal integer string
|
|
39
39
|
* (digits only, no sign / leading zero / exponent) in 1 ≤ n ≤ 2^48 − 1.
|
|
40
40
|
* Anything else → INVALID_PARAMS before anything is sent.
|
|
@@ -276,7 +276,7 @@ export interface LighterAdapterOpts {
|
|
|
276
276
|
apiKeyIndex?: number;
|
|
277
277
|
}
|
|
278
278
|
export declare class LighterAdapter implements ExchangeAdapter {
|
|
279
|
-
/** GTC→GTT resting-order lifetime (28 days) for the execution record
|
|
279
|
+
/** GTC→GTT resting-order lifetime (28 days) for the execution record. */
|
|
280
280
|
static readonly gttExpiryMs: number;
|
|
281
281
|
/** Venue id ("lighter" | "lighter-rh"). */
|
|
282
282
|
readonly name: LighterVenueId;
|
|
@@ -468,7 +468,7 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
468
468
|
*/
|
|
469
469
|
private pollTx;
|
|
470
470
|
/**
|
|
471
|
-
* Definite IOC outcome
|
|
471
|
+
* Definite IOC outcome from the executed tx: poll /tx by hash. A taker order the
|
|
472
472
|
* venue reports "filled" (event_info `to.st` 3, `is` = sent) filled the whole order. Any other
|
|
473
473
|
* status (the remainder was cancelled — the venue zeroes `rs`, so is − rs is NOT a fill) →
|
|
474
474
|
* the venue's own `filled_base_amount` from accountOrders by client order index. Zero fill →
|
|
@@ -501,7 +501,7 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
501
501
|
*/
|
|
502
502
|
orderRowOutcome(clientOrderIndex: number, orderId: string | null, what: string, settled?: (out: LighterOrderOutcome, row: Record<string, unknown>) => boolean, match?: LighterRowMatch | null): Promise<LighterOrderOutcome | null>;
|
|
503
503
|
/**
|
|
504
|
-
* Final outcome of a placed resting / post-only order (
|
|
504
|
+
* Final outcome of a placed resting / post-only order (analogue for non-IOC): poll
|
|
505
505
|
* /tx (rejected → ORDER_REJECTED). Our order (`to`, matched by client order index) reported
|
|
506
506
|
* "filled" in event_info → filled = is (the whole order). Any other status — open, or a
|
|
507
507
|
* canceled-* whose remainder the venue zeroed (`rs` 0, so is − rs is NOT a fill) — or an
|
|
@@ -558,7 +558,7 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
558
558
|
/** Order / trade side from Lighter's `is_ask`; a missing / non-boolean value throws (never defaults to "buy"). */
|
|
559
559
|
private sideOfIsAsk;
|
|
560
560
|
/**
|
|
561
|
-
* Slippage-bounded IOC
|
|
561
|
+
* Slippage-bounded IOC: protection price = orderbook mid ± opts.slippage.bps,
|
|
562
562
|
* tick-aligned toward crossing. The returned raw sendTx result carries `protection`
|
|
563
563
|
* and, when the venue reported the fill, `iocOutcome` (see iocOutcomeOf).
|
|
564
564
|
* `opts.clientOrderIndex` (optional) = caller's numeric client order id (lighterClientOrderIndex rule).
|
|
@@ -569,9 +569,9 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
569
569
|
clientOrderIndex?: number;
|
|
570
570
|
}): Promise<unknown>;
|
|
571
571
|
/**
|
|
572
|
-
* TIF mapping
|
|
572
|
+
* TIF mapping: GTC/GTT → GTT (28-day expiry, gttExpiryMs), IOC → IOC,
|
|
573
573
|
* ALO / POST_ONLY → time-in-force 2 (POST_ONLY per apidocs trading.md and the official
|
|
574
|
-
* lighter-go signer; 28-day expiry like GTT — testnet confirmation pending
|
|
574
|
+
* lighter-go signer; 28-day expiry like GTT — testnet confirmation pending).
|
|
575
575
|
* FOK and any other value → CAPABILITY_UNSUPPORTED (never silently GTT).
|
|
576
576
|
* `opts.clientOrderIndex` as in marketOrder.
|
|
577
577
|
* IOC: the same definite outcome as marketOrder (awaitIocOutcome — zero fill →
|
|
@@ -640,7 +640,7 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
640
640
|
/**
|
|
641
641
|
* Trigger order. Market trigger (no limitPrice): execution price bound = trigger price ±
|
|
642
642
|
* `opts.slippage` bps (the caller's resolveSlippage() output — required; the adapter never
|
|
643
|
-
* reads settings
|
|
643
|
+
* reads settings), tick-aligned toward crossing, recorded in the
|
|
644
644
|
* result as `protection`. Accepted risk: a fast move through the bound leaves the
|
|
645
645
|
* triggered order unfilled.
|
|
646
646
|
* TP vs SL: `opts.kind` given (TP/SL legs) → that type as given (a trigger already crossed
|
|
@@ -665,7 +665,7 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
665
665
|
private _withdrawRaw;
|
|
666
666
|
editOrder(symbol: string, orderId: string, price: string, size: string): Promise<unknown>;
|
|
667
667
|
setLeverage(symbol: string, leverage: number, marginMode?: "cross" | "isolated"): Promise<unknown>;
|
|
668
|
-
getRecentTrades(symbol: string, limit?: number): Promise<
|
|
668
|
+
getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
|
|
669
669
|
getFundingHistory(symbol: string, limit?: number): Promise<{
|
|
670
670
|
time: number;
|
|
671
671
|
rate: string;
|
|
@@ -779,7 +779,7 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
779
779
|
private nextClientOrderIndex;
|
|
780
780
|
private ensureSigner;
|
|
781
781
|
/**
|
|
782
|
-
* One WASM signer (one Go runtime) per `${venueId}:${network}
|
|
782
|
+
* One WASM signer (one Go runtime) per `${venueId}:${network}`.
|
|
783
783
|
* lighter-go keys its clients by (accountIndex, apiKeyIndex) only and keeps a
|
|
784
784
|
* package-global chainId for L1 messages, so two venues must never share a
|
|
785
785
|
* runtime. Keyed by venue+network rather than chainId because Lighter testnet
|
|
@@ -40,7 +40,7 @@ function lighterStep(decimals) {
|
|
|
40
40
|
return decimals <= 0 ? "1" : `0.${"0".repeat(decimals - 1)}1`;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* CLI format rule for a Lighter client order id
|
|
43
|
+
* CLI format rule for a Lighter client order id: the venue's
|
|
44
44
|
* `clientOrderIndex` is numeric, so the id must be a plain decimal integer string
|
|
45
45
|
* (digits only, no sign / leading zero / exponent) in 1 ≤ n ≤ 2^48 − 1.
|
|
46
46
|
* Anything else → INVALID_PARAMS before anything is sent.
|
|
@@ -409,8 +409,16 @@ export function lighterSelectAccount(accounts, accountIndex, venue) {
|
|
|
409
409
|
* window is unknown (SYMBOL_NOT_FOUND) until the entry expires.
|
|
410
410
|
*/
|
|
411
411
|
export const LIGHTER_MARKET_LIST_TTL_MS = 5 * 60_000;
|
|
412
|
+
/** A candle volume field: a finite number / numeric string → its string form; absent or non-numeric → null (never "" / "undefined"). */
|
|
413
|
+
function candleNumber(v) {
|
|
414
|
+
if (typeof v === "number" && Number.isFinite(v))
|
|
415
|
+
return String(v);
|
|
416
|
+
if (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v)))
|
|
417
|
+
return v;
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
412
420
|
export class LighterAdapter {
|
|
413
|
-
/** GTC→GTT resting-order lifetime (28 days) for the execution record
|
|
421
|
+
/** GTC→GTT resting-order lifetime (28 days) for the execution record. */
|
|
414
422
|
static gttExpiryMs = LIGHTER_GTT_EXPIRY_MS;
|
|
415
423
|
/** Venue id ("lighter" | "lighter-rh"). */
|
|
416
424
|
name;
|
|
@@ -679,7 +687,7 @@ export class LighterAdapter {
|
|
|
679
687
|
return { tier: "master" };
|
|
680
688
|
if (this._evmKey)
|
|
681
689
|
return { tier: "pk" };
|
|
682
|
-
// Lighter RH master key is OWS-only
|
|
690
|
+
// Lighter RH master key is OWS-only: no env-key remediation for it.
|
|
683
691
|
const remediation = this.venueId === "lighter"
|
|
684
692
|
? "Run one of: (a) perp wallet agent approve lighter --master <wallet>; (b) perp wallet generate && perp -e lighter --ows <wallet>; (c) export LIGHTER_PRIVATE_KEY=0x..."
|
|
685
693
|
: `Run one of: (a) perp wallet agent approve ${this.name} --master <wallet>; (b) perp wallet generate && perp -e ${this.name} --ows <wallet>`;
|
|
@@ -863,7 +871,7 @@ export class LighterAdapter {
|
|
|
863
871
|
getMarketIndex(symbol) {
|
|
864
872
|
const idx = this._marketMap.get(symbol.toUpperCase());
|
|
865
873
|
if (idx === undefined)
|
|
866
|
-
throw new PerpError("SYMBOL_NOT_FOUND", `Unknown Lighter market: ${symbol}`, { exchange: this.name });
|
|
874
|
+
throw new PerpError("SYMBOL_NOT_FOUND", `Unknown Lighter market: ${symbol}`, { exchange: this.name, remediation: `List markets: perp -e ${this.name} market list` });
|
|
867
875
|
return idx;
|
|
868
876
|
}
|
|
869
877
|
/**
|
|
@@ -976,7 +984,7 @@ export class LighterAdapter {
|
|
|
976
984
|
return last;
|
|
977
985
|
}
|
|
978
986
|
/**
|
|
979
|
-
* Definite IOC outcome
|
|
987
|
+
* Definite IOC outcome from the executed tx: poll /tx by hash. A taker order the
|
|
980
988
|
* venue reports "filled" (event_info `to.st` 3, `is` = sent) filled the whole order. Any other
|
|
981
989
|
* status (the remainder was cancelled — the venue zeroes `rs`, so is − rs is NOT a fill) →
|
|
982
990
|
* the venue's own `filled_base_amount` from accountOrders by client order index. Zero fill →
|
|
@@ -1117,7 +1125,7 @@ export class LighterAdapter {
|
|
|
1117
1125
|
return null;
|
|
1118
1126
|
}
|
|
1119
1127
|
/**
|
|
1120
|
-
* Final outcome of a placed resting / post-only order (
|
|
1128
|
+
* Final outcome of a placed resting / post-only order (analogue for non-IOC): poll
|
|
1121
1129
|
* /tx (rejected → ORDER_REJECTED). Our order (`to`, matched by client order index) reported
|
|
1122
1130
|
* "filled" in event_info → filled = is (the whole order). Any other status — open, or a
|
|
1123
1131
|
* canceled-* whose remainder the venue zeroed (`rs` 0, so is − rs is NOT a fill) — or an
|
|
@@ -1451,7 +1459,7 @@ export class LighterAdapter {
|
|
|
1451
1459
|
return isAsk ? "sell" : "buy";
|
|
1452
1460
|
}
|
|
1453
1461
|
/**
|
|
1454
|
-
* Slippage-bounded IOC
|
|
1462
|
+
* Slippage-bounded IOC: protection price = orderbook mid ± opts.slippage.bps,
|
|
1455
1463
|
* tick-aligned toward crossing. The returned raw sendTx result carries `protection`
|
|
1456
1464
|
* and, when the venue reported the fill, `iocOutcome` (see iocOutcomeOf).
|
|
1457
1465
|
* `opts.clientOrderIndex` (optional) = caller's numeric client order id (lighterClientOrderIndex rule).
|
|
@@ -1502,9 +1510,9 @@ export class LighterAdapter {
|
|
|
1502
1510
|
return this.awaitIocOutcome(result, symbol, baseAmount, `market ${side} ${size} ${symbol}`, { protection, clientOrderIndex }, match);
|
|
1503
1511
|
}
|
|
1504
1512
|
/**
|
|
1505
|
-
* TIF mapping
|
|
1513
|
+
* TIF mapping: GTC/GTT → GTT (28-day expiry, gttExpiryMs), IOC → IOC,
|
|
1506
1514
|
* ALO / POST_ONLY → time-in-force 2 (POST_ONLY per apidocs trading.md and the official
|
|
1507
|
-
* lighter-go signer; 28-day expiry like GTT — testnet confirmation pending
|
|
1515
|
+
* lighter-go signer; 28-day expiry like GTT — testnet confirmation pending).
|
|
1508
1516
|
* FOK and any other value → CAPABILITY_UNSUPPORTED (never silently GTT).
|
|
1509
1517
|
* `opts.clientOrderIndex` as in marketOrder.
|
|
1510
1518
|
* IOC: the same definite outcome as marketOrder (awaitIocOutcome — zero fill →
|
|
@@ -1841,7 +1849,7 @@ export class LighterAdapter {
|
|
|
1841
1849
|
/**
|
|
1842
1850
|
* Trigger order. Market trigger (no limitPrice): execution price bound = trigger price ±
|
|
1843
1851
|
* `opts.slippage` bps (the caller's resolveSlippage() output — required; the adapter never
|
|
1844
|
-
* reads settings
|
|
1852
|
+
* reads settings), tick-aligned toward crossing, recorded in the
|
|
1845
1853
|
* result as `protection`. Accepted risk: a fast move through the bound leaves the
|
|
1846
1854
|
* triggered order unfilled.
|
|
1847
1855
|
* TP vs SL: `opts.kind` given (TP/SL legs) → that type as given (a trigger already crossed
|
|
@@ -2013,10 +2021,13 @@ export class LighterAdapter {
|
|
|
2013
2021
|
side: t.is_maker_ask ? "buy" : "sell",
|
|
2014
2022
|
price: String(t.price ?? "0"),
|
|
2015
2023
|
size: String(t.size ?? t.base_amount ?? t.amount ?? ""),
|
|
2016
|
-
fee
|
|
2024
|
+
// The tape's taker_fee / maker_fee are the parties' fee RATES, not a fee the viewer paid.
|
|
2025
|
+
fee: null,
|
|
2017
2026
|
}));
|
|
2018
2027
|
}
|
|
2019
2028
|
async getFundingHistory(symbol, limit = 10) {
|
|
2029
|
+
await this.ensureMarketMap();
|
|
2030
|
+
this.getMarketIndex(symbol); // unlisted market: SYMBOL_NOT_FOUND, not an empty history
|
|
2020
2031
|
const rates = await this.getFundingRates();
|
|
2021
2032
|
const r = rates.get(symbol.toUpperCase());
|
|
2022
2033
|
if (!r)
|
|
@@ -2035,8 +2046,11 @@ export class LighterAdapter {
|
|
|
2035
2046
|
high: String(c.high ?? c.h ?? "0"),
|
|
2036
2047
|
low: String(c.low ?? c.l ?? "0"),
|
|
2037
2048
|
close: String(c.close ?? c.c ?? "0"),
|
|
2038
|
-
volume:
|
|
2039
|
-
|
|
2049
|
+
volume: candleNumber(c.base_token_volume ?? c.v),
|
|
2050
|
+
// /candles: v = base volume, V = quote (USD) volume; no per-candle trade count (live
|
|
2051
|
+
// 2026-10-14 keys: t o h l c v V i — `i` is the last trade id, not a count).
|
|
2052
|
+
quoteVolume: candleNumber(c.V),
|
|
2053
|
+
trades: typeof c.trades_count === "number" ? c.trades_count : typeof c.n === "number" ? c.n : null,
|
|
2040
2054
|
}));
|
|
2041
2055
|
}
|
|
2042
2056
|
/**
|
|
@@ -2428,7 +2442,7 @@ export class LighterAdapter {
|
|
|
2428
2442
|
}
|
|
2429
2443
|
}
|
|
2430
2444
|
/**
|
|
2431
|
-
* One WASM signer (one Go runtime) per `${venueId}:${network}
|
|
2445
|
+
* One WASM signer (one Go runtime) per `${venueId}:${network}`.
|
|
2432
2446
|
* lighter-go keys its clients by (accountIndex, apiKeyIndex) only and keeps a
|
|
2433
2447
|
* package-global chainId for L1 messages, so two venues must never share a
|
|
2434
2448
|
* runtime. Keyed by venue+network rather than chainId because Lighter testnet
|
|
@@ -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,7 +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
|
*/
|
|
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 } 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";
|
|
@@ -105,7 +104,7 @@ export declare class OndoAdapter implements ExchangeAdapter, TradingV2 {
|
|
|
105
104
|
bids: [string, string][];
|
|
106
105
|
asks: [string, string][];
|
|
107
106
|
}>;
|
|
108
|
-
getRecentTrades(symbol: string, limit?: number): Promise<
|
|
107
|
+
getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
|
|
109
108
|
getFundingHistory(symbol: string, limit?: number): Promise<{
|
|
110
109
|
time: number;
|
|
111
110
|
rate: string;
|
|
@@ -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";
|
|
@@ -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).
|
|
@@ -410,7 +410,7 @@ export class OndoAdapter {
|
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
412
|
async placeOrderOnVenue(input) {
|
|
413
|
-
//
|
|
413
|
+
// GTC is the uniform default for a limit order without a TIF.
|
|
414
414
|
const tifRequested = input.tif;
|
|
415
415
|
const req = input.type === "limit" && input.tif === null ? { ...input, tif: "GTC" } : input;
|
|
416
416
|
if (req.tif === "FOK") {
|
|
@@ -558,7 +558,7 @@ export class OndoAdapter {
|
|
|
558
558
|
remediation: `Do NOT resubmit. Check the order: perp trade status ${original.orderId} --symbol ${req.symbol} -e ondo`,
|
|
559
559
|
});
|
|
560
560
|
}
|
|
561
|
-
// req.size = new OPEN size; fills that raced the cancel reduce the replacement
|
|
561
|
+
// req.size = new OPEN size; fills that raced the cancel reduce the replacement.
|
|
562
562
|
const racedFill = subDecimal(cancelled.filledSize, filledAtRead);
|
|
563
563
|
const replace = subDecimal(req.size, racedFill.startsWith("-") ? "0" : racedFill);
|
|
564
564
|
let size = null;
|
|
@@ -669,14 +669,15 @@ export class OndoAdapter {
|
|
|
669
669
|
const trades = await this.client.publicGet("/v1/perps/trades", {
|
|
670
670
|
market: ondoVenueSymbol(symbol), limit: limit === undefined ? null : limit,
|
|
671
671
|
});
|
|
672
|
-
|
|
672
|
+
// `200 []` for an unlisted market (live 2026-10-14): checked against the market directory.
|
|
673
|
+
return nonEmptyOrListed(this, symbol, listOf(trades).map(t => ({
|
|
673
674
|
time: parseOndoTime(t.time, "trade"),
|
|
674
675
|
symbol: ondoPlainSymbol(t.market),
|
|
675
676
|
side: t.aggressor_side,
|
|
676
677
|
price: t.price,
|
|
677
678
|
size: t.size,
|
|
678
|
-
fee:
|
|
679
|
-
}));
|
|
679
|
+
fee: null, // public tape: no fee applies to the viewer
|
|
680
|
+
})), ondoPlainSymbol(ondoVenueSymbol(symbol)));
|
|
680
681
|
}
|
|
681
682
|
async getFundingHistory(symbol, limit) {
|
|
682
683
|
const rows = await this.client.publicGet("/v1/perps/funding_rate_history", {
|
|
@@ -692,15 +693,16 @@ export class OndoAdapter {
|
|
|
692
693
|
from: Math.floor(startTime / 1000),
|
|
693
694
|
to: Math.floor(endTime / 1000),
|
|
694
695
|
});
|
|
695
|
-
return listOf(candles).map(c => ({
|
|
696
|
+
return nonEmptyOrListed(this, symbol, listOf(candles).map(c => ({
|
|
696
697
|
time: parseOndoTime(c.startTime, "candle"),
|
|
697
698
|
open: c.open,
|
|
698
699
|
high: c.high,
|
|
699
700
|
low: c.low,
|
|
700
701
|
close: c.close,
|
|
701
702
|
volume: c.volume,
|
|
703
|
+
quoteVolume: null,
|
|
702
704
|
trades: null, // Ondo publishes no per-candle trade count
|
|
703
|
-
}));
|
|
705
|
+
})), ondoPlainSymbol(ondoVenueSymbol(symbol)));
|
|
704
706
|
}
|
|
705
707
|
// ── Legacy ExchangeAdapter: account ──
|
|
706
708
|
async getBalance() {
|
|
@@ -760,7 +762,7 @@ export class OndoAdapter {
|
|
|
760
762
|
const rows = await this.client.get("/v1/perps/funding_fees", { limit: limit === undefined ? null : limit });
|
|
761
763
|
return listOf(rows).map(r => ({ time: parseOndoTime(r.time, "funding fee"), symbol: ondoPlainSymbol(r.market), payment: r.amount }));
|
|
762
764
|
}
|
|
763
|
-
// ── Legacy ExchangeAdapter: trading (shim → TradingV2
|
|
765
|
+
// ── Legacy ExchangeAdapter: trading (shim → TradingV2) ──
|
|
764
766
|
async marketOrder(symbol, side, size, opts) {
|
|
765
767
|
return this.placeOrder({
|
|
766
768
|
symbol, side, type: "market", size, price: null, triggerPrice: null, triggerSource: null, tif: null,
|
|
@@ -768,7 +770,7 @@ export class OndoAdapter {
|
|
|
768
770
|
});
|
|
769
771
|
}
|
|
770
772
|
async limitOrder(symbol, side, price, size, opts) {
|
|
771
|
-
//
|
|
773
|
+
// no TIF → GTC (uniform default); FOK → uniform CAPABILITY_UNSUPPORTED.
|
|
772
774
|
const tifInput = opts?.tif;
|
|
773
775
|
const tif = tifInput === undefined || tifInput === "" ? null : validateLegacyTif(this.venue, this.caps, tifInput);
|
|
774
776
|
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
|
|
@@ -88,6 +88,13 @@ export declare function ondoPlainSymbol(venueSymbol: string): string;
|
|
|
88
88
|
export declare function ondoVenueSymbol(symbol: string): string;
|
|
89
89
|
/** Empty string / absent → null. Ondo omits or blanks fields it does not publish. */
|
|
90
90
|
export declare function strOrNull(v: string | undefined | null): string | null;
|
|
91
|
+
/**
|
|
92
|
+
* A price field that the venue zeroes when it has no value: /v1/perps/contracts reports
|
|
93
|
+
* indexPrice "0" (and lastPrice "0") on disabled contracts (live 2026-10-14: ADBE, BE, CELH, IBM,
|
|
94
|
+
* NOK, OKLO, RDDT, SHEIN, SMCI, IBB, VXX, EURUSD — all `disabled: true`). A price is never 0, so
|
|
95
|
+
* "0" means "no index" → null (unknown), never $0.00. Volume / OI zeros stay: 0 is a real amount.
|
|
96
|
+
*/
|
|
97
|
+
export declare function priceOrNull(v: string | undefined | null): string | null;
|
|
91
98
|
export declare function parseOndoTime(iso: string, what: string): number;
|
|
92
99
|
export declare function ondoPublicClient(net: Network): OndoClient;
|
|
93
100
|
export declare function fetchOndoTradingPairs(client: OndoClient): Promise<OndoTradingPair[]>;
|
|
@@ -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) {
|
|
@@ -64,6 +65,16 @@ export function ondoVenueSymbol(symbol) {
|
|
|
64
65
|
export function strOrNull(v) {
|
|
65
66
|
return v === undefined || v === null || v === "" ? null : v;
|
|
66
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* A price field that the venue zeroes when it has no value: /v1/perps/contracts reports
|
|
70
|
+
* indexPrice "0" (and lastPrice "0") on disabled contracts (live 2026-10-14: ADBE, BE, CELH, IBM,
|
|
71
|
+
* NOK, OKLO, RDDT, SHEIN, SMCI, IBB, VXX, EURUSD — all `disabled: true`). A price is never 0, so
|
|
72
|
+
* "0" means "no index" → null (unknown), never $0.00. Volume / OI zeros stay: 0 is a real amount.
|
|
73
|
+
*/
|
|
74
|
+
export function priceOrNull(v) {
|
|
75
|
+
const s = strOrNull(v);
|
|
76
|
+
return s === null || Number(s) === 0 ? null : s;
|
|
77
|
+
}
|
|
67
78
|
export function parseOndoTime(iso, what) {
|
|
68
79
|
const t = Date.parse(iso);
|
|
69
80
|
if (!Number.isFinite(t))
|
|
@@ -166,7 +177,7 @@ async function fetchMarkets(net) {
|
|
|
166
177
|
settle: "USDC",
|
|
167
178
|
quoteAsset: pair.pair.quote,
|
|
168
179
|
markPrice: mark.markPrice,
|
|
169
|
-
indexPrice:
|
|
180
|
+
indexPrice: priceOrNull(contract.indexPrice),
|
|
170
181
|
fundingRate: strOrNull(contract.fundingRate),
|
|
171
182
|
fundingRateBasis: ONDO_FUNDING_BASIS,
|
|
172
183
|
settlementIntervalHours: ONDO_SETTLEMENT_HOURS,
|
|
@@ -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,
|