@lightconexyz/lightcone-sdk 0.8.1-rc.8 → 0.8.2
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 +198 -10
- package/dist/auth/client.d.ts +27 -1
- package/dist/auth/client.d.ts.map +1 -1
- package/dist/auth/client.js +94 -4
- package/dist/auth/client.js.map +1 -1
- package/dist/auth/index.d.ts +59 -5
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +31 -5
- package/dist/auth/index.js.map +1 -1
- package/dist/client.d.ts +49 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +70 -2
- package/dist/client.js.map +1 -1
- package/dist/context.d.ts +59 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +303 -6
- package/dist/context.js.map +1 -1
- package/dist/domain/market/client.d.ts +16 -0
- package/dist/domain/market/client.d.ts.map +1 -1
- package/dist/domain/market/client.js +33 -0
- package/dist/domain/market/client.js.map +1 -1
- package/dist/domain/market/convert.d.ts.map +1 -1
- package/dist/domain/market/convert.js +24 -10
- package/dist/domain/market/convert.js.map +1 -1
- package/dist/domain/market/index.d.ts +18 -4
- package/dist/domain/market/index.d.ts.map +1 -1
- package/dist/domain/market/index.js.map +1 -1
- package/dist/domain/market/outcome.d.ts +9 -3
- package/dist/domain/market/outcome.d.ts.map +1 -1
- package/dist/domain/market/outcome.js +10 -7
- package/dist/domain/market/outcome.js.map +1 -1
- package/dist/domain/market/tokens.js +8 -2
- package/dist/domain/market/tokens.js.map +1 -1
- package/dist/domain/market/wire.d.ts +20 -3
- package/dist/domain/market/wire.d.ts.map +1 -1
- package/dist/domain/market/wire.js.map +1 -1
- package/dist/domain/order/client.d.ts +8 -7
- package/dist/domain/order/client.d.ts.map +1 -1
- package/dist/domain/order/client.js +23 -8
- package/dist/domain/order/client.js.map +1 -1
- package/dist/domain/orderbook/client.d.ts +7 -1
- package/dist/domain/orderbook/client.d.ts.map +1 -1
- package/dist/domain/orderbook/client.js +54 -1
- package/dist/domain/orderbook/client.js.map +1 -1
- package/dist/domain/orderbook/index.d.ts +7 -9
- package/dist/domain/orderbook/index.d.ts.map +1 -1
- package/dist/domain/orderbook/index.js +28 -24
- package/dist/domain/orderbook/index.js.map +1 -1
- package/dist/domain/orderbook/state.d.ts +21 -16
- package/dist/domain/orderbook/state.d.ts.map +1 -1
- package/dist/domain/orderbook/state.js +36 -15
- package/dist/domain/orderbook/state.js.map +1 -1
- package/dist/domain/orderbook/ticker.d.ts +1 -0
- package/dist/domain/orderbook/ticker.d.ts.map +1 -1
- package/dist/domain/orderbook/ticker.js.map +1 -1
- package/dist/domain/orderbook/wire.d.ts +34 -10
- package/dist/domain/orderbook/wire.d.ts.map +1 -1
- package/dist/domain/orderbook/wire.js +47 -0
- package/dist/domain/orderbook/wire.js.map +1 -1
- package/dist/domain/position/builders.d.ts +6 -2
- package/dist/domain/position/builders.d.ts.map +1 -1
- package/dist/domain/position/builders.js +24 -8
- package/dist/domain/position/builders.js.map +1 -1
- package/dist/domain/position/client.d.ts +166 -12
- package/dist/domain/position/client.d.ts.map +1 -1
- package/dist/domain/position/client.js +614 -15
- package/dist/domain/position/client.js.map +1 -1
- package/dist/domain/position/index.d.ts +58 -3
- package/dist/domain/position/index.d.ts.map +1 -1
- package/dist/domain/position/index.js +1 -0
- package/dist/domain/position/index.js.map +1 -1
- package/dist/domain/position/state.d.ts +118 -0
- package/dist/domain/position/state.d.ts.map +1 -0
- package/dist/domain/position/state.js +262 -0
- package/dist/domain/position/state.js.map +1 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +2 -2
- package/dist/env.js.map +1 -1
- package/dist/error.d.ts +32 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +59 -1
- package/dist/error.js.map +1 -1
- package/dist/http/client.d.ts +76 -1
- package/dist/http/client.d.ts.map +1 -1
- package/dist/http/client.js +259 -39
- package/dist/http/client.js.map +1 -1
- package/dist/http/credentialRestorer.d.ts +49 -0
- package/dist/http/credentialRestorer.d.ts.map +1 -0
- package/dist/http/credentialRestorer.js +3 -0
- package/dist/http/credentialRestorer.js.map +1 -0
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/prelude.d.ts +10 -7
- package/dist/prelude.d.ts.map +1 -1
- package/dist/prelude.js +12 -2
- package/dist/prelude.js.map +1 -1
- package/dist/privy/client.d.ts +4 -0
- package/dist/privy/client.d.ts.map +1 -1
- package/dist/privy/client.js +4 -0
- package/dist/privy/client.js.map +1 -1
- package/dist/privy/index.d.ts +4 -4
- package/dist/privy/index.d.ts.map +1 -1
- package/dist/privy/index.js +11 -16
- package/dist/privy/index.js.map +1 -1
- package/dist/program/builder.d.ts +13 -11
- package/dist/program/builder.d.ts.map +1 -1
- package/dist/program/builder.js +31 -16
- package/dist/program/builder.js.map +1 -1
- package/dist/program/constants.d.ts +1 -0
- package/dist/program/constants.d.ts.map +1 -1
- package/dist/program/constants.js +1 -0
- package/dist/program/constants.js.map +1 -1
- package/dist/program/envelope.d.ts +14 -16
- package/dist/program/envelope.d.ts.map +1 -1
- package/dist/program/envelope.js +48 -39
- package/dist/program/envelope.js.map +1 -1
- package/dist/program/index.d.ts +2 -2
- package/dist/program/index.d.ts.map +1 -1
- package/dist/program/index.js +6 -4
- package/dist/program/index.js.map +1 -1
- package/dist/program/instructions.d.ts +17 -9
- package/dist/program/instructions.d.ts.map +1 -1
- package/dist/program/instructions.js +40 -19
- package/dist/program/instructions.js.map +1 -1
- package/dist/program/orders.d.ts +7 -8
- package/dist/program/orders.d.ts.map +1 -1
- package/dist/program/orders.js +20 -22
- package/dist/program/orders.js.map +1 -1
- package/dist/program/types.d.ts +4 -3
- package/dist/program/types.d.ts.map +1 -1
- package/dist/program/types.js.map +1 -1
- package/dist/rpc.d.ts +89 -1
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +285 -4
- package/dist/rpc.js.map +1 -1
- package/dist/shared/api_response.d.ts +16 -1
- package/dist/shared/api_response.d.ts.map +1 -1
- package/dist/shared/api_response.js +26 -1
- package/dist/shared/api_response.js.map +1 -1
- package/dist/shared/index.d.ts +3 -3
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +13 -6
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/json.d.ts +5 -0
- package/dist/shared/json.d.ts.map +1 -0
- package/dist/shared/json.js +38 -0
- package/dist/shared/json.js.map +1 -0
- package/dist/shared/rejection.d.ts.map +1 -1
- package/dist/shared/rejection.js +8 -0
- package/dist/shared/rejection.js.map +1 -1
- package/dist/shared/scaling.d.ts +30 -18
- package/dist/shared/scaling.d.ts.map +1 -1
- package/dist/shared/scaling.js +153 -95
- package/dist/shared/scaling.js.map +1 -1
- package/dist/shared/signing.d.ts +17 -0
- package/dist/shared/signing.d.ts.map +1 -1
- package/dist/shared/signing.js +27 -0
- package/dist/shared/signing.js.map +1 -1
- package/dist/shared/types.d.ts +9 -7
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +12 -4
- package/dist/shared/types.js.map +1 -1
- package/dist/ws/client.browser.d.ts +4 -0
- package/dist/ws/client.browser.d.ts.map +1 -1
- package/dist/ws/client.browser.js +13 -1
- package/dist/ws/client.browser.js.map +1 -1
- package/dist/ws/client.node.d.ts +4 -0
- package/dist/ws/client.node.d.ts.map +1 -1
- package/dist/ws/client.node.js +13 -1
- package/dist/ws/client.node.js.map +1 -1
- package/dist/ws/index.d.ts +24 -0
- package/dist/ws/index.d.ts.map +1 -1
- package/dist/ws/index.js +176 -2
- package/dist/ws/index.js.map +1 -1
- package/dist/ws/subscriptions.d.ts +12 -1
- package/dist/ws/subscriptions.d.ts.map +1 -1
- package/dist/ws/subscriptions.js +11 -0
- package/dist/ws/subscriptions.js.map +1 -1
- package/dist/ws/types.d.ts +5 -0
- package/dist/ws/types.d.ts.map +1 -1
- package/dist/ws/types.js.map +1 -1
- package/package.json +6 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/domain/orderbook/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { Transaction, type PublicKey, type TransactionInstruction } from \"@solana/web3.js\";\nimport type { ClientContext } from \"../../context\";\nimport { requireConnection } from \"../../context\";\nimport { ProgramSdkError } from \"../../program/error\";\nimport { RetryPolicy } from \"../../http\";\nimport {\n buildCloseOrderbookAltIx,\n buildCloseOrderbookIx,\n} from \"../../program/instructions\";\nimport { getOrderbookPda } from \"../../program/pda\";\nimport { deserializeOrderbook as deserializeProgramOrderbook } from \"../../program/accounts\";\nimport type {\n CloseOrderbookAltParams,\n CloseOrderbookParams,\n Orderbook as ProgramOrderbook,\n} from \"../../program/types\";\nimport {\n FULL_PRECISION,\n validateAggregation,\n type BookAggregation,\n} from \"./aggregation\";\nimport type { OrderbookDepthResponse } from \"./wire\";\n\nexport class Orderbooks {\n constructor(private readonly client: ClientContext) {}\n\n // ── PDA helpers ──────────────────────────────────────────────────────\n\n pda(mintA: PublicKey, mintB: PublicKey): PublicKey {\n return getOrderbookPda(mintA, mintB, this.client.programId)[0];\n }\n\n // ── HTTP methods ─────────────────────────────────────────────────────\n\n /**\n * Get live orderbook depth, optionally aggregated (Hyperliquid-style).\n *\n * `depth` is capped server-side at 20 levels per side (omitted, `0`, or\n * `>20` all serve 20). Invalid aggregation combinations throw client-side\n * before any request is made (the server would 400 with\n * `INVALID_ORDERBOOK_QUERY`), and unknown query params are rejected\n * server-side — only `depth`, `nSigFigs`, and `mantissa` are ever sent.\n */\n async get(\n orderbookId: string,\n depth?: number,\n aggregation: BookAggregation = FULL_PRECISION\n ): Promise<OrderbookDepthResponse> {\n const validated = validateAggregation(aggregation);\n const query = new URLSearchParams();\n if (depth !== undefined) {\n query.set(\"depth\", String(depth));\n }\n if (validated.nSigFigs !== undefined) {\n query.set(\"nSigFigs\", String(validated.nSigFigs));\n }\n if (validated.mantissa !== undefined) {\n query.set(\"mantissa\", String(validated.mantissa));\n }\n const queryString = query.toString();\n const url = `${this.client.http.baseUrl()}/api/orderbook/${encodeURIComponent(orderbookId)}${queryString ? `?${queryString}` : \"\"}`;\n return this.client.http.get<OrderbookDepthResponse>(url, RetryPolicy.Idempotent);\n }\n\n // ── On-chain transaction builders ────────────────────────────────────\n\n closeOrderbookAltIx(params: CloseOrderbookAltParams): TransactionInstruction {\n return buildCloseOrderbookAltIx(params, this.client.programId);\n }\n\n closeOrderbookIx(params: CloseOrderbookParams): TransactionInstruction {\n return buildCloseOrderbookIx(params, this.client.programId);\n }\n\n closeOrderbookAltTx(params: CloseOrderbookAltParams): Transaction {\n const ix = this.closeOrderbookAltIx(params);\n return new Transaction({ feePayer: params.operator }).add(ix);\n }\n\n closeOrderbookTx(params: CloseOrderbookParams): Transaction {\n const ix = this.closeOrderbookIx(params);\n return new Transaction({ feePayer: params.operator }).add(ix);\n }\n\n // ── On-chain account fetchers (require Connection) ──────────────────\n\n async getOnchain(mintA: PublicKey, mintB: PublicKey): Promise<ProgramOrderbook> {\n const connection = requireConnection(this.client);\n const orderbookPda = this.pda(mintA, mintB);\n const accountInfo = await connection.getAccountInfo(orderbookPda);\n if (!accountInfo) {\n throw ProgramSdkError.accountNotFound(\n `Orderbook for ${mintA.toBase58()} / ${mintB.toBase58()}`\n );\n }\n return deserializeProgramOrderbook(accountInfo.data as Buffer);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/domain/orderbook/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { Transaction, type PublicKey, type TransactionInstruction } from \"@solana/web3.js\";\nimport type { ClientContext } from \"../../context\";\nimport { requireConnection } from \"../../context\";\nimport { ProgramSdkError } from \"../../program/error\";\nimport { RetryPolicy } from \"../../http\";\nimport {\n buildCloseOrderbookAltIx,\n buildCloseOrderbookIx,\n} from \"../../program/instructions\";\nimport { getOrderbookPda } from \"../../program/pda\";\nimport { deserializeOrderbook as deserializeProgramOrderbook } from \"../../program/accounts\";\nimport type {\n CloseOrderbookAltParams,\n CloseOrderbookParams,\n Orderbook as ProgramOrderbook,\n} from \"../../program/types\";\nimport {\n FULL_PRECISION,\n validateAggregation,\n type BookAggregation,\n} from \"./aggregation\";\nimport type { OrderbookRules } from \"../../shared\";\nimport {\n orderbookRulesFromWire,\n tradingRulesFromWire,\n type DecimalsResponse,\n type OrderbookDepthResponse,\n type TradingRulesWire,\n} from \"./wire\";\n\nexport class Orderbooks {\n private readonly rulesCache: Map<string, Promise<OrderbookRules>>;\n\n constructor(private readonly client: ClientContext) {\n this.rulesCache = client.orderbookRulesCache ?? new Map();\n }\n\n // ── PDA helpers ──────────────────────────────────────────────────────\n\n pda(mintA: PublicKey, mintB: PublicKey): PublicKey {\n return getOrderbookPda(mintA, mintB, this.client.programId)[0];\n }\n\n // ── HTTP methods ─────────────────────────────────────────────────────\n\n /**\n * Get live orderbook depth, optionally aggregated (Hyperliquid-style).\n *\n * `depth` is capped server-side at 20 levels per side (omitted, `0`, or\n * `>20` all serve 20). Invalid aggregation combinations throw client-side\n * before any request is made (the server would 400 with\n * `INVALID_ORDERBOOK_QUERY`), and unknown query params are rejected\n * server-side — only `depth`, `nSigFigs`, and `mantissa` are ever sent.\n */\n async get(\n orderbookId: string,\n depth?: number,\n aggregation: BookAggregation = FULL_PRECISION\n ): Promise<OrderbookDepthResponse> {\n const validated = validateAggregation(aggregation);\n const query = new URLSearchParams();\n if (depth !== undefined) {\n query.set(\"depth\", String(depth));\n }\n if (validated.nSigFigs !== undefined) {\n query.set(\"nSigFigs\", String(validated.nSigFigs));\n }\n if (validated.mantissa !== undefined) {\n query.set(\"mantissa\", String(validated.mantissa));\n }\n const queryString = query.toString();\n const url = `${this.client.http.baseUrl()}/api/orderbook/${encodeURIComponent(orderbookId)}${queryString ? `?${queryString}` : \"\"}`;\n const raw = await this.client.http.get<\n Omit<OrderbookDepthResponse, \"trading_rules\" | \"revision\" | \"captured_at_ms\" | \"bids_truncated\" | \"asks_truncated\"> & {\n trading_rules: TradingRulesWire;\n revision: number | bigint | null;\n captured_at_ms: number | bigint | null;\n bids_truncated?: boolean;\n asks_truncated?: boolean;\n }\n >(url, RetryPolicy.Idempotent);\n if (\n typeof raw.price_quantum !== \"string\" ||\n !raw.trading_rules ||\n !raw.decimals ||\n !Number.isSafeInteger(raw.decimals.price) ||\n !Number.isSafeInteger(raw.decimals.size) ||\n raw.decimals.price < 0 ||\n raw.decimals.size < 0 ||\n (raw.bids_truncated !== undefined && typeof raw.bids_truncated !== \"boolean\") ||\n (raw.asks_truncated !== undefined && typeof raw.asks_truncated !== \"boolean\") ||\n raw.revision === undefined ||\n raw.revision === null ||\n raw.captured_at_ms === undefined ||\n raw.captured_at_ms === null\n ) {\n throw ProgramSdkError.serialization(\n \"orderbook depth is missing required projection or trading-rule metadata\"\n );\n }\n const revision = BigInt(raw.revision);\n const capturedAtMs = BigInt(raw.captured_at_ms);\n if (revision < 0n || capturedAtMs < 0n) {\n throw ProgramSdkError.serialization(\n \"orderbook projection revision and capture time must be non-negative\"\n );\n }\n return {\n ...raw,\n trading_rules: tradingRulesFromWire(raw.trading_rules),\n revision,\n captured_at_ms: capturedAtMs,\n bids_truncated: raw.bids_truncated ?? false,\n asks_truncated: raw.asks_truncated ?? false,\n };\n }\n\n /** Fetch and cache the immutable exact admission rules for an active book. */\n async decimals(orderbookId: string): Promise<OrderbookRules> {\n const cache = this.rulesCache;\n const existing = cache.get(orderbookId);\n if (existing) return existing;\n const request = this.client.http\n .get<DecimalsResponse>(\n `${this.client.http.baseUrl()}/api/orderbooks/${encodeURIComponent(orderbookId)}/decimals`,\n RetryPolicy.Idempotent\n )\n .then(orderbookRulesFromWire);\n cache.set(orderbookId, request);\n request.catch(() => {\n if (cache.get(orderbookId) === request) cache.delete(orderbookId);\n });\n return request;\n }\n\n invalidateDecimals(orderbookId: string): void {\n this.rulesCache.delete(orderbookId);\n }\n\n clearDecimalsCache(): void {\n this.rulesCache.clear();\n }\n\n // ── On-chain transaction builders ────────────────────────────────────\n\n closeOrderbookAltIx(params: CloseOrderbookAltParams): TransactionInstruction {\n return buildCloseOrderbookAltIx(params, this.client.programId);\n }\n\n closeOrderbookIx(params: CloseOrderbookParams): TransactionInstruction {\n return buildCloseOrderbookIx(params, this.client.programId);\n }\n\n closeOrderbookAltTx(params: CloseOrderbookAltParams): Transaction {\n const ix = this.closeOrderbookAltIx(params);\n return new Transaction({ feePayer: params.operator }).add(ix);\n }\n\n closeOrderbookTx(params: CloseOrderbookParams): Transaction {\n const ix = this.closeOrderbookIx(params);\n return new Transaction({ feePayer: params.operator }).add(ix);\n }\n\n // ── On-chain account fetchers (require Connection) ──────────────────\n\n async getOnchain(mintA: PublicKey, mintB: PublicKey): Promise<ProgramOrderbook> {\n const connection = requireConnection(this.client);\n const orderbookPda = this.pda(mintA, mintB);\n const accountInfo = await connection.getAccountInfo(orderbookPda);\n if (!accountInfo) {\n throw ProgramSdkError.accountNotFound(\n `Orderbook for ${mintA.toBase58()} / ${mintB.toBase58()}`\n );\n }\n return deserializeProgramOrderbook(accountInfo.data as Buffer);\n }\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Decimal from "decimal.js";
|
|
2
2
|
import { PublicKey } from "@solana/web3.js";
|
|
3
3
|
import type { OrderBookId, PubkeyStr } from "../../shared";
|
|
4
|
-
import type { OrderbookDecimals } from "../../shared/scaling";
|
|
5
4
|
import type { ConditionalToken } from "../market";
|
|
6
5
|
export * from "./aggregation";
|
|
7
6
|
export * from "./client";
|
|
@@ -23,20 +22,19 @@ export interface OrderBookPair {
|
|
|
23
22
|
lastTradeTime?: Date;
|
|
24
23
|
active: boolean;
|
|
25
24
|
}
|
|
25
|
+
export declare enum ImpactDirection {
|
|
26
|
+
Negative = "negative",
|
|
27
|
+
Zero = "zero",
|
|
28
|
+
Positive = "positive"
|
|
29
|
+
}
|
|
26
30
|
export interface OutcomeImpact {
|
|
27
|
-
|
|
31
|
+
direction: ImpactDirection;
|
|
28
32
|
pct: number;
|
|
29
33
|
dollar: string;
|
|
30
|
-
isPositive: boolean;
|
|
31
34
|
}
|
|
35
|
+
export declare function impactSign(direction: ImpactDirection): string;
|
|
32
36
|
export declare function impactPct(depositPrice: Decimal, conditionalPrice: Decimal): [number, string];
|
|
33
37
|
export declare function impact(depositAssetPrice: Decimal, conditionalPrice: Decimal): OutcomeImpact;
|
|
34
|
-
/**
|
|
35
|
-
* Derive scaling decimals from an orderbook pair's token metadata.
|
|
36
|
-
*
|
|
37
|
-
* No REST call needed — decimals are computed from the base/quote token objects.
|
|
38
|
-
*/
|
|
39
|
-
export declare function orderbookDecimals(pair: OrderBookPair): OrderbookDecimals;
|
|
40
38
|
/** Return the market as a `PublicKey`. */
|
|
41
39
|
export declare function orderBookMarket(pair: OrderBookPair): PublicKey;
|
|
42
40
|
/** Return the base conditional-token mint as a `PublicKey`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,SAAS,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,gBAAgB,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,oBAAY,eAAe;IACzB,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,eAAe,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,eAAe,GAAG,MAAM,CAS7D;AAED,wBAAgB,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAO5F;AAED,wBAAgB,MAAM,CACpB,iBAAiB,EAAE,OAAO,EAC1B,gBAAgB,EAAE,OAAO,GACxB,aAAa,CAmBf;AAED,0CAA0C;AAC1C,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAE9D;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAEhE;AAED,gEAAgE;AAChE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAEjE;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;gBAEf,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;CAMnD"}
|
|
@@ -14,10 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.OrderBookValidationError = exports.orderBookPairFromWire = void 0;
|
|
17
|
+
exports.OrderBookValidationError = exports.ImpactDirection = exports.orderBookPairFromWire = void 0;
|
|
18
|
+
exports.impactSign = impactSign;
|
|
18
19
|
exports.impactPct = impactPct;
|
|
19
20
|
exports.impact = impact;
|
|
20
|
-
exports.orderbookDecimals = orderbookDecimals;
|
|
21
21
|
exports.orderBookMarket = orderBookMarket;
|
|
22
22
|
exports.orderBookBaseMint = orderBookBaseMint;
|
|
23
23
|
exports.orderBookQuoteMint = orderBookQuoteMint;
|
|
@@ -29,6 +29,22 @@ __exportStar(require("./state"), exports);
|
|
|
29
29
|
__exportStar(require("./ticker"), exports);
|
|
30
30
|
var convert_1 = require("./convert");
|
|
31
31
|
Object.defineProperty(exports, "orderBookPairFromWire", { enumerable: true, get: function () { return convert_1.orderBookPairFromWire; } });
|
|
32
|
+
var ImpactDirection;
|
|
33
|
+
(function (ImpactDirection) {
|
|
34
|
+
ImpactDirection["Negative"] = "negative";
|
|
35
|
+
ImpactDirection["Zero"] = "zero";
|
|
36
|
+
ImpactDirection["Positive"] = "positive";
|
|
37
|
+
})(ImpactDirection || (exports.ImpactDirection = ImpactDirection = {}));
|
|
38
|
+
function impactSign(direction) {
|
|
39
|
+
switch (direction) {
|
|
40
|
+
case ImpactDirection.Negative:
|
|
41
|
+
return "-";
|
|
42
|
+
case ImpactDirection.Zero:
|
|
43
|
+
return "";
|
|
44
|
+
case ImpactDirection.Positive:
|
|
45
|
+
return "+";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
32
48
|
function impactPct(depositPrice, conditionalPrice) {
|
|
33
49
|
if (depositPrice.isZero() || conditionalPrice.isZero()) {
|
|
34
50
|
return [0, ""];
|
|
@@ -38,32 +54,20 @@ function impactPct(depositPrice, conditionalPrice) {
|
|
|
38
54
|
}
|
|
39
55
|
function impact(depositAssetPrice, conditionalPrice) {
|
|
40
56
|
if (depositAssetPrice.isZero()) {
|
|
41
|
-
return {
|
|
57
|
+
return { direction: ImpactDirection.Zero, pct: 0, dollar: "0" };
|
|
42
58
|
}
|
|
43
|
-
const
|
|
59
|
+
const dollarDelta = conditionalPrice.minus(depositAssetPrice);
|
|
60
|
+
const pctDecimal = dollarDelta.div(depositAssetPrice).mul(100);
|
|
44
61
|
const pct = pctDecimal.toNumber();
|
|
45
|
-
const
|
|
62
|
+
const direction = dollarDelta.greaterThan(0)
|
|
63
|
+
? ImpactDirection.Positive
|
|
64
|
+
: dollarDelta.lessThan(0)
|
|
65
|
+
? ImpactDirection.Negative
|
|
66
|
+
: ImpactDirection.Zero;
|
|
46
67
|
return {
|
|
47
|
-
|
|
68
|
+
direction,
|
|
48
69
|
pct: Math.abs(pct),
|
|
49
|
-
dollar,
|
|
50
|
-
isPositive: pct > 0,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Derive scaling decimals from an orderbook pair's token metadata.
|
|
55
|
-
*
|
|
56
|
-
* No REST call needed — decimals are computed from the base/quote token objects.
|
|
57
|
-
*/
|
|
58
|
-
function orderbookDecimals(pair) {
|
|
59
|
-
const baseDecimals = pair.base.decimals;
|
|
60
|
-
const quoteDecimals = pair.quote.decimals;
|
|
61
|
-
return {
|
|
62
|
-
orderbookId: pair.orderbookId,
|
|
63
|
-
baseDecimals,
|
|
64
|
-
quoteDecimals,
|
|
65
|
-
priceDecimals: Math.max(0, 6 + quoteDecimals - baseDecimals),
|
|
66
|
-
tickSize: BigInt(Math.max(pair.tickSize, 0)),
|
|
70
|
+
dollar: dollarDelta.abs().toString(),
|
|
67
71
|
};
|
|
68
72
|
}
|
|
69
73
|
/** Return the market as a `PublicKey`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/orderbook/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/orderbook/index.ts"],"names":[],"mappings":"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","sourcesContent":["import Decimal from \"decimal.js\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport type { OrderBookId, PubkeyStr } from \"../../shared\";\nimport type { ConditionalToken } from \"../market\";\n\nexport * from \"./aggregation\";\nexport * from \"./client\";\nexport * from \"./wire\";\nexport * from \"./state\";\nexport * from \"./ticker\";\nexport { orderBookPairFromWire } from \"./convert\";\n\nexport interface OrderBookPair {\n id: number;\n marketPubkey: PubkeyStr;\n orderbookId: OrderBookId;\n base: ConditionalToken;\n quote: ConditionalToken;\n outcomeIndex: number;\n tickSize: number;\n totalBids: number;\n totalAsks: number;\n lastTradePrice?: string;\n lastTradeTime?: Date;\n active: boolean;\n}\n\nexport enum ImpactDirection {\n Negative = \"negative\",\n Zero = \"zero\",\n Positive = \"positive\",\n}\n\nexport interface OutcomeImpact {\n direction: ImpactDirection;\n pct: number;\n dollar: string;\n}\n\nexport function impactSign(direction: ImpactDirection): string {\n switch (direction) {\n case ImpactDirection.Negative:\n return \"-\";\n case ImpactDirection.Zero:\n return \"\";\n case ImpactDirection.Positive:\n return \"+\";\n }\n}\n\nexport function impactPct(depositPrice: Decimal, conditionalPrice: Decimal): [number, string] {\n if (depositPrice.isZero() || conditionalPrice.isZero()) {\n return [0, \"\"];\n }\n\n const value = conditionalPrice.minus(depositPrice).div(depositPrice).mul(100);\n return [value.toNumber(), value.greaterThan(0) ? \"+\" : \"\"];\n}\n\nexport function impact(\n depositAssetPrice: Decimal,\n conditionalPrice: Decimal\n): OutcomeImpact {\n if (depositAssetPrice.isZero()) {\n return { direction: ImpactDirection.Zero, pct: 0, dollar: \"0\" };\n }\n\n const dollarDelta = conditionalPrice.minus(depositAssetPrice);\n const pctDecimal = dollarDelta.div(depositAssetPrice).mul(100);\n const pct = pctDecimal.toNumber();\n const direction = dollarDelta.greaterThan(0)\n ? ImpactDirection.Positive\n : dollarDelta.lessThan(0)\n ? ImpactDirection.Negative\n : ImpactDirection.Zero;\n\n return {\n direction,\n pct: Math.abs(pct),\n dollar: dollarDelta.abs().toString(),\n };\n}\n\n/** Return the market as a `PublicKey`. */\nexport function orderBookMarket(pair: OrderBookPair): PublicKey {\n return new PublicKey(pair.marketPubkey);\n}\n\n/** Return the base conditional-token mint as a `PublicKey`. */\nexport function orderBookBaseMint(pair: OrderBookPair): PublicKey {\n return new PublicKey(pair.base.pubkey);\n}\n\n/** Return the quote conditional-token mint as a `PublicKey`. */\nexport function orderBookQuoteMint(pair: OrderBookPair): PublicKey {\n return new PublicKey(pair.quote.pubkey);\n}\n\nexport class OrderBookValidationError extends Error {\n readonly orderbookId: string;\n readonly details: string[];\n\n constructor(orderbookId: string, details: string[]) {\n super(`OrderBook validation errors (${orderbookId}): ${details.join(\"; \")}`);\n this.name = \"OrderBookValidationError\";\n this.orderbookId = orderbookId;\n this.details = details;\n }\n}\n"]}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import type { OrderBookId } from "../../shared";
|
|
2
2
|
import type { OrderBook } from "./wire";
|
|
3
|
+
import { type BookAggregation } from "./aggregation";
|
|
3
4
|
/**
|
|
4
5
|
* The `book_update` stream is snapshot-only: every data frame carries the
|
|
5
|
-
* full top-20 levels per side and replaces the previous book wholesale
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* full top-20 levels per side and replaces the previous book wholesale.
|
|
7
|
+
* Equal and older revisions are discarded within one generation.
|
|
8
|
+
* Consumers holding multiple aggregation views of one orderbook on the same
|
|
9
|
+
* connection key their `OrderbookState` instances by
|
|
8
10
|
* `(orderbook_id, aggregation)` using
|
|
9
11
|
* `aggregationFromFrame(book.n_sig_figs, book.mantissa)`.
|
|
10
12
|
*/
|
|
11
13
|
export type OrderbookApplyResult = {
|
|
12
14
|
kind: "applied";
|
|
15
|
+
} | {
|
|
16
|
+
kind: "discarded_stale";
|
|
17
|
+
} | {
|
|
18
|
+
kind: "subscription_mismatch";
|
|
13
19
|
} | {
|
|
14
20
|
kind: "refresh_required";
|
|
15
21
|
reason: OrderbookRefreshReason;
|
|
@@ -25,29 +31,26 @@ export type OrderbookRefreshReason =
|
|
|
25
31
|
};
|
|
26
32
|
export declare class OrderbookState {
|
|
27
33
|
readonly orderbookId: OrderBookId;
|
|
34
|
+
readonly aggregation: BookAggregation;
|
|
28
35
|
/**
|
|
29
|
-
*
|
|
30
|
-
* non-contiguous server-side (conflation skips versions), and the initial
|
|
31
|
-
* snapshot after every (re)subscribe is `seq: 0` — informational only,
|
|
32
|
-
* never used to gate frames.
|
|
36
|
+
* Last accepted engine depth revision. Forward gaps are expected.
|
|
33
37
|
*/
|
|
34
|
-
seq:
|
|
38
|
+
seq: bigint;
|
|
39
|
+
private lastSeq;
|
|
40
|
+
bidsTruncated: boolean;
|
|
41
|
+
asksTruncated: boolean;
|
|
35
42
|
private readonly bidsMap;
|
|
36
43
|
private readonly asksMap;
|
|
37
44
|
private cachedBestBid;
|
|
38
45
|
private cachedBestAsk;
|
|
39
|
-
constructor(orderbookId: OrderBookId);
|
|
46
|
+
constructor(orderbookId: OrderBookId, aggregation?: BookAggregation);
|
|
40
47
|
/**
|
|
41
|
-
* Apply a
|
|
48
|
+
* Apply a full snapshot when its revision is newer in this generation.
|
|
42
49
|
*
|
|
43
50
|
* `resync` frames take precedence and leave the book untouched — the
|
|
44
51
|
* caller must re-subscribe with the same parameters. Every other data
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
* initial snapshot delivered after every (re)subscribe: gating on `seq`
|
|
48
|
-
* would freeze the book after a resync or aggregation change, so `seq` is
|
|
49
|
-
* stored as informational only.
|
|
50
|
-
*/
|
|
52
|
+
* accepted frame replaces the book wholesale. Revision gaps are normal.
|
|
53
|
+
*/
|
|
51
54
|
apply(book: OrderBook): OrderbookApplyResult;
|
|
52
55
|
bids(): ReadonlyMap<string, string>;
|
|
53
56
|
asks(): ReadonlyMap<string, string>;
|
|
@@ -56,6 +59,8 @@ export declare class OrderbookState {
|
|
|
56
59
|
midPrice(): string | undefined;
|
|
57
60
|
spread(): string | undefined;
|
|
58
61
|
isEmpty(): boolean;
|
|
62
|
+
/** Reset the revision gate for reconnect/resubscribe without hiding levels. */
|
|
63
|
+
beginGeneration(): void;
|
|
59
64
|
clear(): void;
|
|
60
65
|
}
|
|
61
66
|
//# sourceMappingURL=state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;GAQG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,uBAAuB,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAEjE,MAAM,MAAM,sBAAsB;AAChC;;;;GAIG;AACH;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC;AAE5B,qBAAa,cAAc;IACzB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,OAAO,CAAqB;IACpC,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,aAAa,CAA4B;gBAErC,WAAW,EAAE,WAAW,EAAE,WAAW,GAAE,eAAoB;IAavE;;;;;;MAME;IACF,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,oBAAoB;IA2C5C,IAAI,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC;IAInC,IAAI,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC;IAInC,OAAO,IAAI,MAAM,GAAG,SAAS;IAe7B,OAAO,IAAI,MAAM,GAAG,SAAS;IAc7B,QAAQ,IAAI,MAAM,GAAG,SAAS;IAU9B,MAAM,IAAI,MAAM,GAAG,SAAS;IAU5B,OAAO,IAAI,OAAO;IAIlB,+EAA+E;IAC/E,eAAe,IAAI,IAAI;IAIvB,KAAK,IAAI,IAAI;CAUd"}
|
|
@@ -5,45 +5,56 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.OrderbookState = void 0;
|
|
7
7
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
|
+
const aggregation_1 = require("./aggregation");
|
|
8
9
|
class OrderbookState {
|
|
9
10
|
orderbookId;
|
|
11
|
+
aggregation;
|
|
10
12
|
/**
|
|
11
|
-
*
|
|
12
|
-
* non-contiguous server-side (conflation skips versions), and the initial
|
|
13
|
-
* snapshot after every (re)subscribe is `seq: 0` — informational only,
|
|
14
|
-
* never used to gate frames.
|
|
13
|
+
* Last accepted engine depth revision. Forward gaps are expected.
|
|
15
14
|
*/
|
|
16
15
|
seq;
|
|
16
|
+
lastSeq;
|
|
17
|
+
bidsTruncated;
|
|
18
|
+
asksTruncated;
|
|
17
19
|
bidsMap;
|
|
18
20
|
asksMap;
|
|
19
21
|
cachedBestBid;
|
|
20
22
|
cachedBestAsk;
|
|
21
|
-
constructor(orderbookId) {
|
|
23
|
+
constructor(orderbookId, aggregation = {}) {
|
|
22
24
|
this.orderbookId = orderbookId;
|
|
23
|
-
this.
|
|
25
|
+
this.aggregation = (0, aggregation_1.normalizeAggregation)(aggregation);
|
|
26
|
+
this.seq = 0n;
|
|
27
|
+
this.lastSeq = undefined;
|
|
28
|
+
this.bidsTruncated = false;
|
|
29
|
+
this.asksTruncated = false;
|
|
24
30
|
this.bidsMap = new Map();
|
|
25
31
|
this.asksMap = new Map();
|
|
26
32
|
this.cachedBestBid = null;
|
|
27
33
|
this.cachedBestAsk = null;
|
|
28
34
|
}
|
|
29
35
|
/**
|
|
30
|
-
* Apply a
|
|
36
|
+
* Apply a full snapshot when its revision is newer in this generation.
|
|
31
37
|
*
|
|
32
38
|
* `resync` frames take precedence and leave the book untouched — the
|
|
33
39
|
* caller must re-subscribe with the same parameters. Every other data
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* initial snapshot delivered after every (re)subscribe: gating on `seq`
|
|
37
|
-
* would freeze the book after a resync or aggregation change, so `seq` is
|
|
38
|
-
* stored as informational only.
|
|
39
|
-
*/
|
|
40
|
+
* accepted frame replaces the book wholesale. Revision gaps are normal.
|
|
41
|
+
*/
|
|
40
42
|
apply(book) {
|
|
43
|
+
if (book.seq < 0n)
|
|
44
|
+
throw new Error("book_update seq must be non-negative");
|
|
45
|
+
if (book.orderbook_id !== this.orderbookId ||
|
|
46
|
+
!(0, aggregation_1.aggregationsEqual)((0, aggregation_1.aggregationFromFrame)(book.n_sig_figs, book.mantissa), this.aggregation)) {
|
|
47
|
+
return { kind: "subscription_mismatch" };
|
|
48
|
+
}
|
|
41
49
|
if (book.resync) {
|
|
42
50
|
return {
|
|
43
51
|
kind: "refresh_required",
|
|
44
52
|
reason: { kind: "server_resync" },
|
|
45
53
|
};
|
|
46
54
|
}
|
|
55
|
+
if (this.lastSeq !== undefined && book.seq <= this.lastSeq) {
|
|
56
|
+
return { kind: "discarded_stale" };
|
|
57
|
+
}
|
|
47
58
|
this.bidsMap.clear();
|
|
48
59
|
this.asksMap.clear();
|
|
49
60
|
for (const level of book.bids) {
|
|
@@ -56,7 +67,10 @@ class OrderbookState {
|
|
|
56
67
|
this.asksMap.set(level.price, level.size);
|
|
57
68
|
}
|
|
58
69
|
}
|
|
59
|
-
this.seq = book.seq
|
|
70
|
+
this.seq = book.seq;
|
|
71
|
+
this.lastSeq = book.seq;
|
|
72
|
+
this.bidsTruncated = book.bids_truncated ?? false;
|
|
73
|
+
this.asksTruncated = book.asks_truncated ?? false;
|
|
60
74
|
this.cachedBestBid = null;
|
|
61
75
|
this.cachedBestAsk = null;
|
|
62
76
|
return { kind: "applied" };
|
|
@@ -113,10 +127,17 @@ class OrderbookState {
|
|
|
113
127
|
isEmpty() {
|
|
114
128
|
return this.bidsMap.size === 0 && this.asksMap.size === 0;
|
|
115
129
|
}
|
|
130
|
+
/** Reset the revision gate for reconnect/resubscribe without hiding levels. */
|
|
131
|
+
beginGeneration() {
|
|
132
|
+
this.lastSeq = undefined;
|
|
133
|
+
}
|
|
116
134
|
clear() {
|
|
117
135
|
this.bidsMap.clear();
|
|
118
136
|
this.asksMap.clear();
|
|
119
|
-
this.seq =
|
|
137
|
+
this.seq = 0n;
|
|
138
|
+
this.lastSeq = undefined;
|
|
139
|
+
this.bidsTruncated = false;
|
|
140
|
+
this.asksTruncated = false;
|
|
120
141
|
this.cachedBestBid = null;
|
|
121
142
|
this.cachedBestAsk = null;
|
|
122
143
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/domain/orderbook/state.ts"],"names":[],"mappings":"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","sourcesContent":["import Decimal from \"decimal.js\";\nimport type { OrderBookId } from \"../../shared\";\nimport type { OrderBook } from \"./wire\";\n\n/**\n * The `book_update` stream is snapshot-only: every data frame carries the\n * full top-20 levels per side and replaces the previous book wholesale\n * (last-write-wins). Consumers holding multiple aggregation views of one\n * orderbook on the same connection key their `OrderbookState` instances by\n * `(orderbook_id, aggregation)` using\n * `aggregationFromFrame(book.n_sig_figs, book.mantissa)`.\n */\nexport type OrderbookApplyResult =\n | { kind: \"applied\" }\n | { kind: \"refresh_required\"; reason: OrderbookRefreshReason };\n\nexport type OrderbookRefreshReason =\n /**\n * The backend explicitly requested a resync: unsubscribe and re-subscribe\n * with the same parameters (including aggregation) to receive a fresh\n * snapshot.\n */\n { kind: \"server_resync\" };\n\nexport class OrderbookState {\n readonly orderbookId: OrderBookId;\n /**\n * Projection version of the last applied frame. Strictly increasing but\n * non-contiguous server-side (conflation skips versions), and the initial\n * snapshot after every (re)subscribe is `seq: 0` — informational only,\n * never used to gate frames.\n */\n seq: number;\n private readonly bidsMap: Map<string, string>;\n private readonly asksMap: Map<string, string>;\n private cachedBestBid: string | undefined | null;\n private cachedBestAsk: string | undefined | null;\n\n constructor(orderbookId: OrderBookId) {\n this.orderbookId = orderbookId;\n this.seq = 0;\n this.bidsMap = new Map();\n this.asksMap = new Map();\n this.cachedBestBid = null;\n this.cachedBestAsk = null;\n }\n\n /**\n * Apply a WS orderbook frame (snapshot-only stream, last-write-wins).\n *\n * `resync` frames take precedence and leave the book untouched — the\n * caller must re-subscribe with the same parameters. Every other data\n * frame is a full snapshot by contract and replaces the book wholesale\n * (the `is_snapshot` flag is not consulted), including the `seq: 0`\n * initial snapshot delivered after every (re)subscribe: gating on `seq`\n * would freeze the book after a resync or aggregation change, so `seq` is\n * stored as informational only.\n */\n apply(book: OrderBook): OrderbookApplyResult {\n if (book.resync) {\n return {\n kind: \"refresh_required\",\n reason: { kind: \"server_resync\" },\n };\n }\n\n this.bidsMap.clear();\n this.asksMap.clear();\n for (const level of book.bids) {\n if (!new Decimal(level.size).isZero()) {\n this.bidsMap.set(level.price, level.size);\n }\n }\n for (const level of book.asks) {\n if (!new Decimal(level.size).isZero()) {\n this.asksMap.set(level.price, level.size);\n }\n }\n this.seq = book.seq ?? 0;\n this.cachedBestBid = null;\n this.cachedBestAsk = null;\n\n return { kind: \"applied\" };\n }\n\n bids(): ReadonlyMap<string, string> {\n return this.bidsMap;\n }\n\n asks(): ReadonlyMap<string, string> {\n return this.asksMap;\n }\n\n bestBid(): string | undefined {\n if (this.cachedBestBid !== null) {\n return this.cachedBestBid;\n }\n if (this.bidsMap.size === 0) {\n this.cachedBestBid = undefined;\n return undefined;\n }\n const result = Array.from(this.bidsMap.keys())\n .sort((a, b) => new Decimal(a).cmp(new Decimal(b)))\n .at(-1);\n this.cachedBestBid = result;\n return result;\n }\n\n bestAsk(): string | undefined {\n if (this.cachedBestAsk !== null) {\n return this.cachedBestAsk;\n }\n if (this.asksMap.size === 0) {\n this.cachedBestAsk = undefined;\n return undefined;\n }\n const result = Array.from(this.asksMap.keys())\n .sort((a, b) => new Decimal(a).cmp(new Decimal(b)))[0];\n this.cachedBestAsk = result;\n return result;\n }\n\n midPrice(): string | undefined {\n const bid = this.bestBid();\n const ask = this.bestAsk();\n if (!bid || !ask) {\n return undefined;\n }\n\n return new Decimal(bid).plus(ask).div(2).toString();\n }\n\n spread(): string | undefined {\n const bid = this.bestBid();\n const ask = this.bestAsk();\n if (!bid || !ask) {\n return undefined;\n }\n\n return new Decimal(ask).minus(bid).toString();\n }\n\n isEmpty(): boolean {\n return this.bidsMap.size === 0 && this.asksMap.size === 0;\n }\n\n clear(): void {\n this.bidsMap.clear();\n this.asksMap.clear();\n this.seq = 0;\n this.cachedBestBid = null;\n this.cachedBestAsk = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/domain/orderbook/state.ts"],"names":[],"mappings":"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","sourcesContent":["import Decimal from \"decimal.js\";\nimport type { OrderBookId } from \"../../shared\";\nimport type { OrderBook } from \"./wire\";\nimport {\n aggregationFromFrame,\n aggregationsEqual,\n normalizeAggregation,\n type BookAggregation,\n} from \"./aggregation\";\n\n/**\n * The `book_update` stream is snapshot-only: every data frame carries the\n * full top-20 levels per side and replaces the previous book wholesale.\n * Equal and older revisions are discarded within one generation.\n * Consumers holding multiple aggregation views of one orderbook on the same\n * connection key their `OrderbookState` instances by\n * `(orderbook_id, aggregation)` using\n * `aggregationFromFrame(book.n_sig_figs, book.mantissa)`.\n */\nexport type OrderbookApplyResult =\n | { kind: \"applied\" }\n | { kind: \"discarded_stale\" }\n | { kind: \"subscription_mismatch\" }\n | { kind: \"refresh_required\"; reason: OrderbookRefreshReason };\n\nexport type OrderbookRefreshReason =\n /**\n * The backend explicitly requested a resync: unsubscribe and re-subscribe\n * with the same parameters (including aggregation) to receive a fresh\n * snapshot.\n */\n { kind: \"server_resync\" };\n\nexport class OrderbookState {\n readonly orderbookId: OrderBookId;\n readonly aggregation: BookAggregation;\n /**\n * Last accepted engine depth revision. Forward gaps are expected.\n */\n seq: bigint;\n private lastSeq: bigint | undefined;\n bidsTruncated: boolean;\n asksTruncated: boolean;\n private readonly bidsMap: Map<string, string>;\n private readonly asksMap: Map<string, string>;\n private cachedBestBid: string | undefined | null;\n private cachedBestAsk: string | undefined | null;\n\n constructor(orderbookId: OrderBookId, aggregation: BookAggregation = {}) {\n this.orderbookId = orderbookId;\n this.aggregation = normalizeAggregation(aggregation);\n this.seq = 0n;\n this.lastSeq = undefined;\n this.bidsTruncated = false;\n this.asksTruncated = false;\n this.bidsMap = new Map();\n this.asksMap = new Map();\n this.cachedBestBid = null;\n this.cachedBestAsk = null;\n }\n\n /**\n * Apply a full snapshot when its revision is newer in this generation.\n *\n * `resync` frames take precedence and leave the book untouched — the\n * caller must re-subscribe with the same parameters. Every other data\n * accepted frame replaces the book wholesale. Revision gaps are normal.\n */\n apply(book: OrderBook): OrderbookApplyResult {\n if (book.seq < 0n) throw new Error(\"book_update seq must be non-negative\");\n if (\n book.orderbook_id !== this.orderbookId ||\n !aggregationsEqual(\n aggregationFromFrame(book.n_sig_figs, book.mantissa),\n this.aggregation\n )\n ) {\n return { kind: \"subscription_mismatch\" };\n }\n if (book.resync) {\n return {\n kind: \"refresh_required\",\n reason: { kind: \"server_resync\" },\n };\n }\n if (this.lastSeq !== undefined && book.seq <= this.lastSeq) {\n return { kind: \"discarded_stale\" };\n }\n\n this.bidsMap.clear();\n this.asksMap.clear();\n for (const level of book.bids) {\n if (!new Decimal(level.size).isZero()) {\n this.bidsMap.set(level.price, level.size);\n }\n }\n for (const level of book.asks) {\n if (!new Decimal(level.size).isZero()) {\n this.asksMap.set(level.price, level.size);\n }\n }\n this.seq = book.seq;\n this.lastSeq = book.seq;\n this.bidsTruncated = book.bids_truncated ?? false;\n this.asksTruncated = book.asks_truncated ?? false;\n this.cachedBestBid = null;\n this.cachedBestAsk = null;\n\n return { kind: \"applied\" };\n }\n\n bids(): ReadonlyMap<string, string> {\n return this.bidsMap;\n }\n\n asks(): ReadonlyMap<string, string> {\n return this.asksMap;\n }\n\n bestBid(): string | undefined {\n if (this.cachedBestBid !== null) {\n return this.cachedBestBid;\n }\n if (this.bidsMap.size === 0) {\n this.cachedBestBid = undefined;\n return undefined;\n }\n const result = Array.from(this.bidsMap.keys())\n .sort((a, b) => new Decimal(a).cmp(new Decimal(b)))\n .at(-1);\n this.cachedBestBid = result;\n return result;\n }\n\n bestAsk(): string | undefined {\n if (this.cachedBestAsk !== null) {\n return this.cachedBestAsk;\n }\n if (this.asksMap.size === 0) {\n this.cachedBestAsk = undefined;\n return undefined;\n }\n const result = Array.from(this.asksMap.keys())\n .sort((a, b) => new Decimal(a).cmp(new Decimal(b)))[0];\n this.cachedBestAsk = result;\n return result;\n }\n\n midPrice(): string | undefined {\n const bid = this.bestBid();\n const ask = this.bestAsk();\n if (!bid || !ask) {\n return undefined;\n }\n\n return new Decimal(bid).plus(ask).div(2).toString();\n }\n\n spread(): string | undefined {\n const bid = this.bestBid();\n const ask = this.bestAsk();\n if (!bid || !ask) {\n return undefined;\n }\n\n return new Decimal(ask).minus(bid).toString();\n }\n\n isEmpty(): boolean {\n return this.bidsMap.size === 0 && this.asksMap.size === 0;\n }\n\n /** Reset the revision gate for reconnect/resubscribe without hiding levels. */\n beginGeneration(): void {\n this.lastSeq = undefined;\n }\n\n clear(): void {\n this.bidsMap.clear();\n this.asksMap.clear();\n this.seq = 0n;\n this.lastSeq = undefined;\n this.bidsTruncated = false;\n this.asksTruncated = false;\n this.cachedBestBid = null;\n this.cachedBestAsk = null;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticker.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/ticker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
1
|
+
{"version":3,"file":"ticker.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/ticker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticker.js","sourceRoot":"","sources":["../../../src/domain/orderbook/ticker.ts"],"names":[],"mappings":"","sourcesContent":["import type { OrderBookId } from \"../../shared\";\n\nexport interface TickerData {\n orderbookId: OrderBookId;\n bestBid?: string;\n bestAsk?: string;\n midPrice?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ticker.js","sourceRoot":"","sources":["../../../src/domain/orderbook/ticker.ts"],"names":[],"mappings":"","sourcesContent":["import type { OrderBookId } from \"../../shared\";\n\nexport interface TickerData {\n orderbookId: OrderBookId;\n bestBid?: string;\n bestAsk?: string;\n /** Engine-authoritative; may use one-sided-book or last-trade fallback. */\n midPrice?: string;\n}\n"]}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import type { OrderBookId, Side } from "../../shared";
|
|
1
|
+
import type { OrderBookId, OrderbookRules, Side, TradingRules } from "../../shared";
|
|
2
|
+
export interface TradingRulesWire {
|
|
3
|
+
base_size_decimals: number;
|
|
4
|
+
max_price_decimals: number;
|
|
5
|
+
max_price_significant_figures: number;
|
|
6
|
+
integer_prices_always_allowed: boolean;
|
|
7
|
+
price_quantum: string;
|
|
8
|
+
price_quantum_raw: string;
|
|
9
|
+
base_size_quantum: string;
|
|
10
|
+
base_size_quantum_raw: string;
|
|
11
|
+
}
|
|
2
12
|
export interface OrderbookResponse {
|
|
3
13
|
id: number;
|
|
4
14
|
market_pubkey: string;
|
|
@@ -33,14 +43,19 @@ export interface OrderbookDepthResponse {
|
|
|
33
43
|
best_bid?: string;
|
|
34
44
|
best_ask?: string;
|
|
35
45
|
spread?: string;
|
|
46
|
+
/** Deprecated backend alias; never use for order admission. */
|
|
36
47
|
tick_size?: string;
|
|
48
|
+
price_quantum: string;
|
|
49
|
+
/** Parsed exact rules; raw quantum strings are exposed as bigint values. */
|
|
50
|
+
trading_rules: TradingRules;
|
|
51
|
+
bids_truncated: boolean;
|
|
52
|
+
asks_truncated: boolean;
|
|
53
|
+
revision: bigint;
|
|
54
|
+
captured_at_ms: bigint;
|
|
37
55
|
bids: RestBookLevel[];
|
|
38
56
|
asks: RestBookLevel[];
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
* optional for tolerance of older payloads.
|
|
42
|
-
*/
|
|
43
|
-
decimals?: OrderbookDepthDecimals;
|
|
57
|
+
/** Required display decimals; size is base-token on-chain precision. */
|
|
58
|
+
decimals: OrderbookDepthDecimals;
|
|
44
59
|
}
|
|
45
60
|
/**
|
|
46
61
|
* Price/size display decimals from the depth endpoint. Distinct from
|
|
@@ -55,28 +70,37 @@ export interface DecimalsResponse {
|
|
|
55
70
|
base_decimals: number;
|
|
56
71
|
quote_decimals: number;
|
|
57
72
|
price_decimals: number;
|
|
73
|
+
trading_rules: TradingRulesWire;
|
|
58
74
|
}
|
|
75
|
+
export declare function tradingRulesFromWire(wire: TradingRulesWire): TradingRules;
|
|
76
|
+
export declare function orderbookRulesFromWire(wire: DecimalsResponse): OrderbookRules;
|
|
59
77
|
export interface WsBookLevel {
|
|
60
78
|
side: Side;
|
|
61
79
|
price: string;
|
|
62
80
|
size: string;
|
|
81
|
+
/**
|
|
82
|
+
* Exact quote-token amount represented by the underlying maker orders.
|
|
83
|
+
* For grouped books this is independent of the displayed bucket price.
|
|
84
|
+
*/
|
|
85
|
+
quote_notional: string;
|
|
63
86
|
}
|
|
64
87
|
/**
|
|
65
88
|
* WS orderbook snapshot frame.
|
|
66
89
|
*
|
|
67
90
|
* The stream is snapshot-only: every data frame carries the full top-20
|
|
68
|
-
* levels per side and replaces the previous book wholesale
|
|
69
|
-
*
|
|
70
|
-
* after every (re)subscribe is `seq: 0` — informational only, never a gate.
|
|
91
|
+
* levels per side and replaces the previous book wholesale. `seq` is the
|
|
92
|
+
* engine depth revision and is monotonic only within one subscription generation.
|
|
71
93
|
*/
|
|
72
94
|
export interface OrderBook {
|
|
73
95
|
orderbook_id: OrderBookId;
|
|
74
96
|
is_snapshot?: boolean;
|
|
75
|
-
seq
|
|
97
|
+
seq: bigint;
|
|
76
98
|
resync?: boolean;
|
|
77
99
|
timestamp?: string;
|
|
78
100
|
bids: WsBookLevel[];
|
|
79
101
|
asks: WsBookLevel[];
|
|
102
|
+
bids_truncated?: boolean;
|
|
103
|
+
asks_truncated?: boolean;
|
|
80
104
|
/**
|
|
81
105
|
* Aggregation tags echoed by the backend (omitted = full precision).
|
|
82
106
|
* Always normalized server-side ((5, none) arrives as (5, 1)). Use
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/wire.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../../src/domain/orderbook/wire.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tradingRulesFromWire = tradingRulesFromWire;
|
|
4
|
+
exports.orderbookRulesFromWire = orderbookRulesFromWire;
|
|
5
|
+
function tradingRulesFromWire(wire) {
|
|
6
|
+
if (!wire ||
|
|
7
|
+
!isNonNegativeSafeInteger(wire.base_size_decimals) ||
|
|
8
|
+
!isNonNegativeSafeInteger(wire.max_price_decimals) ||
|
|
9
|
+
!isNonNegativeSafeInteger(wire.max_price_significant_figures) ||
|
|
10
|
+
typeof wire.integer_prices_always_allowed !== "boolean" ||
|
|
11
|
+
typeof wire.price_quantum !== "string" ||
|
|
12
|
+
typeof wire.base_size_quantum !== "string" ||
|
|
13
|
+
typeof wire.price_quantum_raw !== "string" ||
|
|
14
|
+
typeof wire.base_size_quantum_raw !== "string" ||
|
|
15
|
+
!/^\d+$/.test(wire.price_quantum_raw) ||
|
|
16
|
+
!/^\d+$/.test(wire.base_size_quantum_raw)) {
|
|
17
|
+
throw new Error("invalid trading_rules response");
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
baseSizeDecimals: wire.base_size_decimals,
|
|
21
|
+
maxPriceDecimals: wire.max_price_decimals,
|
|
22
|
+
maxPriceSignificantFigures: wire.max_price_significant_figures,
|
|
23
|
+
integerPricesAlwaysAllowed: wire.integer_prices_always_allowed,
|
|
24
|
+
priceQuantum: wire.price_quantum,
|
|
25
|
+
priceQuantumRaw: BigInt(wire.price_quantum_raw),
|
|
26
|
+
baseSizeQuantum: wire.base_size_quantum,
|
|
27
|
+
baseSizeQuantumRaw: BigInt(wire.base_size_quantum_raw),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function orderbookRulesFromWire(wire) {
|
|
31
|
+
if (!wire ||
|
|
32
|
+
typeof wire.orderbook_id !== "string" ||
|
|
33
|
+
!isNonNegativeSafeInteger(wire.base_decimals) ||
|
|
34
|
+
!isNonNegativeSafeInteger(wire.quote_decimals) ||
|
|
35
|
+
!isNonNegativeSafeInteger(wire.price_decimals) ||
|
|
36
|
+
!wire.trading_rules) {
|
|
37
|
+
throw new Error("invalid orderbook decimals response");
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
orderbookId: wire.orderbook_id,
|
|
41
|
+
baseDecimals: wire.base_decimals,
|
|
42
|
+
quoteDecimals: wire.quote_decimals,
|
|
43
|
+
priceDecimals: wire.price_decimals,
|
|
44
|
+
tradingRules: tradingRulesFromWire(wire.trading_rules),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function isNonNegativeSafeInteger(value) {
|
|
48
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
49
|
+
}
|
|
3
50
|
//# sourceMappingURL=wire.js.map
|