@usherlabs/cex-broker 0.2.44 → 0.2.46

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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/cli.js +16231 -15573
  3. package/dist/handlers/subscribe/handler.d.ts +2 -0
  4. package/dist/helpers/market-data-archive/capture-contract.d.ts +3 -2
  5. package/dist/helpers/market-data-archive/types.d.ts +8 -4
  6. package/dist/helpers/market-data-vendor-backfill/archive-reader.d.ts +26 -0
  7. package/dist/helpers/market-data-vendor-backfill/batching.d.ts +10 -0
  8. package/dist/helpers/market-data-vendor-backfill/conformance-fixtures.d.ts +80 -0
  9. package/dist/helpers/market-data-vendor-backfill/contracts.d.ts +393 -0
  10. package/dist/helpers/market-data-vendor-backfill/core.d.ts +100 -0
  11. package/dist/helpers/market-data-vendor-backfill/cryptohftdata.d.ts +77 -0
  12. package/dist/helpers/market-data-vendor-backfill/forwarder-client.d.ts +25 -0
  13. package/dist/helpers/market-data-vendor-backfill/identity.d.ts +10 -0
  14. package/dist/helpers/market-data-vendor-backfill/manifests.d.ts +1086 -0
  15. package/dist/helpers/market-data-vendor-backfill/promotion.d.ts +9 -0
  16. package/dist/helpers/market-data-vendor-backfill/qualification.d.ts +20 -0
  17. package/dist/helpers/market-data-vendor-backfill/selection.d.ts +30 -0
  18. package/dist/helpers/market-data-vendor-backfill/semantic-verification.d.ts +24 -0
  19. package/dist/helpers/public-market-data-feed/identity.d.ts +12 -0
  20. package/dist/helpers/public-market-data-feed/index.d.ts +5 -0
  21. package/dist/helpers/public-market-data-feed/orderbook-coalescing-evidence.d.ts +79 -0
  22. package/dist/helpers/public-market-data-feed/orderbook-profile.d.ts +54 -0
  23. package/dist/helpers/public-market-data-feed/subscriber-buffer.d.ts +31 -0
  24. package/dist/helpers/public-market-data-feed/supervisor.d.ts +82 -0
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.js +16221 -15563
  27. package/dist/index.js.map +21 -18
  28. package/dist/market-data-vendor-backfill/fixtures/conformance-v1.json +448 -0
  29. package/dist/market-data-vendor-backfill/policies/capability-policy.json +28 -0
  30. package/dist/market-data-vendor-backfill/policies/resource-policy.json +16 -0
  31. package/dist/market-data-vendor-backfill/schema-manifest.json +31 -0
  32. package/dist/market-data-vendor-backfill/schemas/archive-selection.schema.json +224 -0
  33. package/dist/market-data-vendor-backfill/schemas/promotion-receipt.schema.json +171 -0
  34. package/dist/market-data-vendor-backfill/schemas/request.schema.json +166 -0
  35. package/dist/market-data-vendor-backfill/schemas/required-clock.schema.json +47 -0
  36. package/dist/market-data-vendor-backfill/schemas/result.schema.json +198 -0
  37. package/dist/market-data-vendor-backfill.d.ts +18 -0
  38. package/dist/market-data-vendor-backfill.js +18819 -0
  39. package/dist/market-data-vendor-backfill.js.map +206 -0
  40. package/dist/server.d.ts +2 -1
  41. package/package.json +24 -2
@@ -0,0 +1,9 @@
1
+ import { type BackfillArchiveRow, type PromotionReceipt, type PromotionReceiptWire } from "./contracts";
2
+ export type StablePromotionReceipt = Omit<PromotionReceipt, "receiptId" | "verificationTimeMs">;
3
+ export declare function promotionReceiptId(receipt: StablePromotionReceipt): string;
4
+ type UnfinalizedPromotionReceiptWire = Omit<PromotionReceiptWire, "receipt_id" | "promotion_identity_sha256"> & Partial<Pick<PromotionReceiptWire, "receipt_id" | "promotion_identity_sha256">>;
5
+ export declare function finalizePromotionReceipt(receipt: UnfinalizedPromotionReceiptWire): PromotionReceiptWire;
6
+ export declare function finalizePromotionReceipt(receipt: StablePromotionReceipt, verificationTimeMs: number): PromotionReceipt;
7
+ export declare function promotionReceiptToArchiveRow(receiptInput: PromotionReceipt | PromotionReceiptWire): BackfillArchiveRow;
8
+ export declare function promotionReceiptFromArchiveRow(row: Record<string, unknown>): PromotionReceipt | PromotionReceiptWire;
9
+ export {};
@@ -0,0 +1,20 @@
1
+ import type { BackfillArchiveRow, FixedUtcTimestamp, Sha256Hex } from "./contracts";
2
+ export type QualificationEvent = {
3
+ qualification_event_id: string;
4
+ capture_bundle_id: Sha256Hex;
5
+ state: "qualified" | "quarantined" | "revoked";
6
+ receipt_id: Sha256Hex;
7
+ promotion_identity_sha256: Sha256Hex;
8
+ window: {
9
+ start_at: FixedUtcTimestamp;
10
+ end_at: FixedUtcTimestamp;
11
+ };
12
+ event_at: FixedUtcTimestamp;
13
+ reason_code: string;
14
+ };
15
+ type UnfinalizedQualificationEvent = Omit<QualificationEvent, "qualification_event_id"> & Partial<Pick<QualificationEvent, "qualification_event_id">>;
16
+ export declare function parseQualificationEvent(value: unknown): QualificationEvent;
17
+ export declare function finalizeQualificationEvent(event: UnfinalizedQualificationEvent): QualificationEvent;
18
+ export declare function qualificationEventToArchiveRow(eventInput: QualificationEvent): BackfillArchiveRow;
19
+ export declare function qualificationEventFromArchiveRow(row: Record<string, unknown>): QualificationEvent;
20
+ export {};
@@ -0,0 +1,30 @@
1
+ import { type ArchiveSelectionWire, type BackfillArchiveRow, type BackfillRequestWire, type MarketDataVendorBackfillRequest } from "./contracts";
2
+ export type ArchiveQualificationEvidence = {
3
+ qualificationEventId: string;
4
+ state: "qualified" | "quarantined" | "revoked";
5
+ receiptId: string;
6
+ promotionIdentitySha256: string;
7
+ };
8
+ export type ArchiveSupportAnchorEvidence = {
9
+ captureBundleId: string;
10
+ rawCaptureId: string;
11
+ snapshotId: string;
12
+ sourceTimeMs: number;
13
+ normalizedSummaryChecksum: string;
14
+ };
15
+ export type ArchiveBundleEvidence = {
16
+ captureBundleId: string;
17
+ captureOrigin: "production_capture" | "vendor_historical_backfill";
18
+ startTimeMs: number;
19
+ endTimeMs: number;
20
+ qualification: ArchiveQualificationEvidence | null;
21
+ supportAnchors: ArchiveSupportAnchorEvidence[];
22
+ };
23
+ export declare function resolveArchiveSelection(input: {
24
+ request: MarketDataVendorBackfillRequest;
25
+ bundles: readonly ArchiveBundleEvidence[];
26
+ resolvedAtMs: number;
27
+ storedSelection?: unknown;
28
+ }): ArchiveSelectionWire;
29
+ export declare function archiveSelectionToArchiveRow(request: BackfillRequestWire, selectionInput: ArchiveSelectionWire): BackfillArchiveRow;
30
+ export declare function archiveSelectionFromArchiveRow(row: Record<string, unknown>): ArchiveSelectionWire;
@@ -0,0 +1,24 @@
1
+ import type { BackfillArchiveRow, MarketDataVendorBackfillRequest } from "./contracts";
2
+ export declare function semanticDigest(rows: readonly BackfillArchiveRow[]): string;
3
+ export type SemanticPromotionEvidence = {
4
+ request: MarketDataVendorBackfillRequest;
5
+ normalizedRows: readonly BackfillArchiveRow[];
6
+ candidateRows: readonly BackfillArchiveRow[];
7
+ conflictCount: number;
8
+ prefixDigestBefore: string;
9
+ prefixDigestAfter: string;
10
+ suffixDigestBefore: string;
11
+ suffixDigestAfter: string;
12
+ seamVerified: boolean;
13
+ exporterCompatible: boolean;
14
+ };
15
+ export type SemanticPromotionResult = {
16
+ passed: boolean;
17
+ reasonCode: string;
18
+ canonicalSemanticDigest: string;
19
+ prefixDigest: string;
20
+ suffixDigest: string;
21
+ seamVerified: boolean;
22
+ coverageVerified: boolean;
23
+ };
24
+ export declare function verifySemanticPromotion(evidence: SemanticPromotionEvidence): SemanticPromotionResult;
@@ -0,0 +1,12 @@
1
+ export type PublicFeedName = "ORDERBOOK" | "TICKER" | "TRADES" | "OHLCV";
2
+ export type PublicFeedKeyInput = {
3
+ exchange: string;
4
+ symbol: string;
5
+ marketType: string;
6
+ feed: PublicFeedName;
7
+ acquisitionProfileId?: string;
8
+ timeframe?: string;
9
+ };
10
+ export declare function normalizePublicExchange(exchange: string): string;
11
+ export declare function resolvePublicOhlcvTimeframe(timeframe: string | undefined): string;
12
+ export declare function buildPublicFeedKey(input: PublicFeedKeyInput): string;
@@ -0,0 +1,5 @@
1
+ export * from "./identity";
2
+ export * from "./orderbook-coalescing-evidence";
3
+ export * from "./orderbook-profile";
4
+ export * from "./subscriber-buffer";
5
+ export * from "./supervisor";
@@ -0,0 +1,79 @@
1
+ import type { OrderBookBandCoverage } from "./orderbook-profile";
2
+ export declare const CEX_ORDERBOOK_COALESCING_EVIDENCE_SCHEMA: "cex-orderbook-coalescing-evidence/v1";
3
+ export type CexOrderBookEvidenceVenue = "binance" | "mexc";
4
+ export type CexPolicyVisibleOrderBookSnapshot = {
5
+ bids: number[][];
6
+ asks: number[][];
7
+ timestamp: number;
8
+ exchange: CexOrderBookEvidenceVenue;
9
+ symbol: string;
10
+ depthLimit: number;
11
+ };
12
+ export type CexOrderBookObservationEvidence = {
13
+ index: number;
14
+ conservative: {
15
+ live: CexPolicyVisibleOrderBookSnapshot;
16
+ rehydrated: CexPolicyVisibleOrderBookSnapshot;
17
+ };
18
+ coalesced: {
19
+ live: CexPolicyVisibleOrderBookSnapshot;
20
+ rehydrated: CexPolicyVisibleOrderBookSnapshot;
21
+ };
22
+ coverage: {
23
+ conservativeLive: OrderBookBandCoverage[];
24
+ conservativeRehydrated: OrderBookBandCoverage[];
25
+ coalescedLive: OrderBookBandCoverage[];
26
+ coalescedRehydrated: OrderBookBandCoverage[];
27
+ };
28
+ snapshotHashes: {
29
+ conservativeLive: string;
30
+ conservativeRehydrated: string;
31
+ coalescedLive: string;
32
+ coalescedRehydrated: string;
33
+ };
34
+ };
35
+ export type CexOrderBookPhysicalWorkEvidence = {
36
+ workers: number;
37
+ watchIterations: number;
38
+ frames: number;
39
+ archiveDecisions: number;
40
+ };
41
+ export type CexOrderBookCoalescingCaseEvidence = {
42
+ venue: CexOrderBookEvidenceVenue;
43
+ profileId: string;
44
+ observations: CexOrderBookObservationEvidence[];
45
+ cexVerdicts: {
46
+ logicalPayloadsEqual: true;
47
+ canonicalArchiveEqual: true;
48
+ liveReplayInputsEqual: true;
49
+ bandCoverageComplete: true;
50
+ reducedPhysicalWork: true;
51
+ physicalWork: {
52
+ conservative: CexOrderBookPhysicalWorkEvidence;
53
+ coalesced: CexOrderBookPhysicalWorkEvidence;
54
+ };
55
+ };
56
+ insufficientReplayCase: {
57
+ archiveDepth: number;
58
+ policyDepth: number;
59
+ rejected: true;
60
+ observations: Array<{
61
+ index: number;
62
+ coverage: OrderBookBandCoverage[];
63
+ diagnostics: string[];
64
+ }>;
65
+ };
66
+ };
67
+ export type CexOrderBookCoalescingEvidence = {
68
+ schemaVersion: typeof CEX_ORDERBOOK_COALESCING_EVIDENCE_SCHEMA;
69
+ policyDepth: number;
70
+ archiveDepth: number;
71
+ bandsBps: number[];
72
+ cases: [
73
+ CexOrderBookCoalescingCaseEvidence,
74
+ CexOrderBookCoalescingCaseEvidence
75
+ ];
76
+ };
77
+ export declare function validateCexOrderBookCoalescingEvidence(value: unknown): CexOrderBookCoalescingEvidence;
78
+ export declare function serializeCexOrderBookCoalescingEvidence(value: unknown): Uint8Array;
79
+ export declare function sha256CexOrderBookCoalescingEvidence(value: unknown): string;
@@ -0,0 +1,54 @@
1
+ import type { NormalizedOrderBookSnapshot } from "../order-book";
2
+ export type OrderBookAcquisitionProfile = {
3
+ id: string;
4
+ upstreamLimit?: number;
5
+ upstreamOptions?: Record<string, unknown>;
6
+ guaranteedRetainedDepth?: number;
7
+ coalescingSupported: boolean;
8
+ };
9
+ export type OrderBookAcquisitionProfileInput = {
10
+ exchange: string;
11
+ requestedDepth: number | undefined;
12
+ archiveDepth: number;
13
+ enabledProfileIds?: ReadonlySet<string>;
14
+ };
15
+ export declare function resolveConservativeOrderBookAcquisitionProfile(input: OrderBookAcquisitionProfileInput): OrderBookAcquisitionProfile;
16
+ export declare function resolveOrderBookAcquisitionProfile(input: OrderBookAcquisitionProfileInput): OrderBookAcquisitionProfile;
17
+ export declare function projectOrderBookSnapshot(snapshot: NormalizedOrderBookSnapshot, requestedDepth: number | undefined): NormalizedOrderBookSnapshot;
18
+ type SideCoverage = {
19
+ covered: boolean;
20
+ boundaryPrice: number;
21
+ farthestPrice?: number;
22
+ retainedCount: number;
23
+ exhausted: boolean;
24
+ };
25
+ export type OrderBookBandCoverage = {
26
+ covered: boolean;
27
+ mid: number;
28
+ bandBps: number;
29
+ bid: SideCoverage;
30
+ ask: SideCoverage;
31
+ diagnostics: string[];
32
+ };
33
+ export type ImmediateHedgeabilityEvidence = OrderBookBandCoverage & {
34
+ /** Base quantity that can be sold immediately into displayed bids. */
35
+ bidDepth: number;
36
+ /** Base quantity that can be bought immediately from displayed asks. */
37
+ askDepth: number;
38
+ limitingSide: "bid" | "ask" | "balanced";
39
+ liquidityCap: number;
40
+ };
41
+ export declare function evaluateOrderBookBandCoverage(snapshot: Pick<NormalizedOrderBookSnapshot, "bids" | "asks">, bandBps: number, options?: {
42
+ bidExhausted?: boolean;
43
+ askExhausted?: boolean;
44
+ }): OrderBookBandCoverage;
45
+ /**
46
+ * Derives the L2 inputs used to cap immediately hedgeable counterpart liquidity.
47
+ * A result is exact only when `covered` is true; otherwise the two depth values
48
+ * are conservative lower bounds because the retained book ends inside the band.
49
+ */
50
+ export declare function evaluateImmediateHedgeability(snapshot: Pick<NormalizedOrderBookSnapshot, "bids" | "asks">, bandBps: number, options?: {
51
+ bidExhausted?: boolean;
52
+ askExhausted?: boolean;
53
+ }): ImmediateHedgeabilityEvidence;
54
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { SubscriptionType } from "../constants";
2
+ export type PublicFeedFrame = {
3
+ data: string;
4
+ timestamp: number;
5
+ symbol: string;
6
+ type: SubscriptionType;
7
+ };
8
+ export declare const PUBLIC_FEED_SUBSCRIBER_FRAME_LIMIT = 16;
9
+ export declare const PUBLIC_FEED_SUBSCRIBER_BYTE_LIMIT: number;
10
+ export declare const PUBLIC_FEED_SUBSCRIBER_OVERFLOW_ERROR = "Public market-data subscriber fell behind";
11
+ /** Returns the proto3 wire size of the complete SubscribeResponse message. */
12
+ export declare function encodeSubscribeResponseWireSize(response: PublicFeedFrame): number;
13
+ export type PublicFeedSubscriberBufferOptions = {
14
+ /** Test-only override. Production callers omit this value. */
15
+ frameLimit?: number;
16
+ /** Test-only override. Production callers omit this value. */
17
+ byteLimit?: number;
18
+ };
19
+ /** Fixed-capacity O(1) FIFO for disposable public gRPC subscriber frames. */
20
+ export declare class PublicFeedSubscriberBuffer implements AsyncIterable<PublicFeedFrame> {
21
+ #private;
22
+ readonly frameLimit: number;
23
+ readonly byteLimit: number;
24
+ constructor(options?: PublicFeedSubscriberBufferOptions);
25
+ get queuedFrames(): number;
26
+ get queuedBytes(): number;
27
+ enqueue(frame: PublicFeedFrame): boolean;
28
+ close(): void;
29
+ fail(error: Error): void;
30
+ [Symbol.asyncIterator](): AsyncIterator<PublicFeedFrame>;
31
+ }
@@ -0,0 +1,82 @@
1
+ import type { Metadata } from "@grpc/grpc-js";
2
+ import type { Exchange } from "@usherlabs/ccxt";
3
+ import { type BrokerPoolEntry } from "../broker";
4
+ import type { BrokerExecutionArchiver } from "../broker-execution-archive";
5
+ import { type OhlcvArchiveInput, type OhlcvBarTracker, type OrderbookArchiveInput, type TickerArchiveInput, type TradesArchiveInput } from "../market-data-archive";
6
+ import { type BrokerMarketType } from "../market-type";
7
+ import type { OtelMetrics } from "../otel";
8
+ import { type PublicFeedName } from "./identity";
9
+ import { type OrderBookAcquisitionProfile, type OrderBookAcquisitionProfileInput } from "./orderbook-profile";
10
+ import { type PublicFeedFrame, type PublicFeedSubscriberBufferOptions } from "./subscriber-buffer";
11
+ export type PublicFeedArchiveContext = {
12
+ deploymentId: string;
13
+ exchange: string;
14
+ symbol: string;
15
+ assetType: BrokerMarketType;
16
+ accountSelector?: string;
17
+ };
18
+ export interface PublicMarketDataArchiveSink {
19
+ orderbook(input: OrderbookArchiveInput, options: {
20
+ sampledOut: boolean;
21
+ }): void;
22
+ ticker(input: TickerArchiveInput): void;
23
+ trades(input: TradesArchiveInput): void;
24
+ ohlcv(tracker: OhlcvBarTracker, input: OhlcvArchiveInput): void;
25
+ ohlcvBootstrap(tracker: OhlcvBarTracker, input: OhlcvArchiveInput): void;
26
+ }
27
+ type Metrics = Pick<OtelMetrics, "recordCounter"> & Partial<Pick<OtelMetrics, "recordGauge">>;
28
+ export type PublicMarketDataFeedSupervisorOptions = {
29
+ brokers: Record<string, BrokerPoolEntry>;
30
+ brokerArchiver?: BrokerExecutionArchiver;
31
+ otelMetrics?: OtelMetrics;
32
+ archiveSink?: PublicMarketDataArchiveSink;
33
+ metrics?: Metrics;
34
+ bufferLimits?: PublicFeedSubscriberBufferOptions;
35
+ retirementTimeoutMs?: number;
36
+ createRequestBroker?: (exchange: string, metadata: Metadata | undefined) => Exchange | null;
37
+ createPublicBroker?: (exchange: string) => Exchange | null;
38
+ resolveOrderBookProfile?: (input: OrderBookAcquisitionProfileInput) => OrderBookAcquisitionProfile;
39
+ enabledOrderBookProfileIds?: ReadonlySet<string>;
40
+ observer?: PublicMarketDataFeedObserver;
41
+ };
42
+ export type PublicFeedObservation = {
43
+ key: string;
44
+ exchange: string;
45
+ feed: PublicFeedName;
46
+ marketType: BrokerMarketType;
47
+ profile?: string;
48
+ subscriberCount: number;
49
+ };
50
+ export interface PublicMarketDataFeedObserver {
51
+ workerStarted?(observation: PublicFeedObservation): void;
52
+ subscriberAttached?(observation: PublicFeedObservation): void;
53
+ physicalFrame?(observation: PublicFeedObservation): void;
54
+ archiveDecision?(observation: PublicFeedObservation): void;
55
+ delivered?(observation: PublicFeedObservation): void;
56
+ overflow?(observation: PublicFeedObservation): void;
57
+ workerRetired?(observation: PublicFeedObservation): void;
58
+ }
59
+ export type PublicFeedSubscribeOptions = {
60
+ exchange: string;
61
+ symbol: string;
62
+ marketType?: string;
63
+ feed: PublicFeedName;
64
+ depthLimit?: number;
65
+ timeframe?: string;
66
+ bootstrapLimit?: number;
67
+ metadata?: Metadata;
68
+ };
69
+ export interface PublicMarketDataSubscription extends AsyncIterable<PublicFeedFrame> {
70
+ readonly key: string;
71
+ readonly acquisitionProfileId?: string;
72
+ close(): void;
73
+ }
74
+ /** Owns one physical public CCXT watch/archive path per canonical runtime key. */
75
+ export declare class PublicMarketDataFeedSupervisor {
76
+ #private;
77
+ private readonly options;
78
+ constructor(options: PublicMarketDataFeedSupervisorOptions);
79
+ subscribe(input: PublicFeedSubscribeOptions): Promise<PublicMarketDataSubscription>;
80
+ close(): Promise<void>;
81
+ }
82
+ export {};
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ export default class CEXBroker {
21
21
  private userAssetArchivePoller?;
22
22
  private balanceUpdateArchiveConsumer?;
23
23
  private userDataStreamSupervisor?;
24
+ private publicMarketDataFeedSupervisor?;
24
25
  /**
25
26
  * Loads environment variables prefixed with CEX_BROKER_
26
27
  * Expected format: