@liberfi.io/react-predict 0.3.71 → 0.3.73

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/predict/events.params.ts","../src/hooks/predict/market.params.ts","../src/hooks/predict/matches.params.ts","../src/hooks/predict/matchMarkets.params.ts","../src/hooks/predict/sports.params.ts","../src/hooks/predict/esports.params.ts","../src/hooks/predict/sports-routing.params.ts","../src/hooks/predict/sports-match-detail.params.ts","../src/hooks/predict/search.params.ts","../src/client/types.ts","../src/client/client.ts","../src/client/ws.ts","../src/utils/polymarket-hmac.ts","../src/utils/polymarket-order.ts"],"names":["rawMakerAmt","rawTakerAmt"],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * Server-safe pure functions for events query parameters.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictClient,\n PredictEvent,\n EventSortField,\n EventStatus,\n ListEventsParams,\n PredictPage,\n ProviderSource,\n} from \"../../client\";\n\nexport type { ProviderSource };\n\n/** Default page size for list queries. */\nexport const DEFAULT_PAGE_SIZE = 24;\n\n/**\n * Selection emitted by a categories/tag selector widget.\n * Duplicated here to avoid pulling in UI component barrel into server-only bundles.\n */\nexport interface TagSlugSelection {\n categorySlug: string | null;\n tagSlug: string | null;\n}\n\n/**\n * Resolve a `TagSlugSelection` to a single `tag_slug` string for the API.\n */\nexport function resolveTagSlug(\n selection: TagSlugSelection | null | undefined,\n): string | undefined {\n if (!selection) return undefined;\n return selection.tagSlug ?? selection.categorySlug ?? undefined;\n}\n\n/**\n * Input accepted by {@link resolveEventsParams}. All fields optional;\n * defaults match the client-side `useInfiniteEvents` hook's initial state.\n */\nexport interface ResolveEventsParamsInput {\n tagSlugSelection?: TagSlugSelection | null;\n limit?: number;\n status?: EventStatus;\n sort_by?: EventSortField;\n sort_asc?: boolean;\n source?: ProviderSource;\n with_markets?: boolean;\n /**\n * Minimum total volume in USD (numeric string or number).\n * Converted to `min_volume` in the API request.\n */\n minVolume?: string | number;\n /**\n * Minimum liquidity in USD (numeric string or number).\n * Converted to `min_liquidity` in the API request.\n */\n minLiquidity?: string | number;\n /**\n * Time-remaining bucket. Converts to an `end_before` RFC 3339 timestamp.\n * \"1d\" = events closing within 24 h, \"7d\" = 7 days, \"30d\" = 30 days.\n */\n timeRemaining?: string;\n /**\n * Max number of markets per event (sorted by volume DESC).\n * Defaults to `3` in `resolveEventsParams`.\n */\n markets_limit?: number;\n /**\n * Resolved UI language. Included in the API query and query key so localized\n * payloads are not shared across languages.\n */\n lang?: string;\n}\n\n/**\n * Convert a time-remaining bucket string to an RFC 3339 `end_before` timestamp.\n * Returns `undefined` when `timeRemaining` is not set.\n */\nfunction resolveEndBefore(\n timeRemaining: string | undefined,\n): string | undefined {\n if (!timeRemaining) return undefined;\n const days = timeRemaining === \"1d\" ? 1 : timeRemaining === \"7d\" ? 7 : 30;\n return new Date(Date.now() + days * 24 * 60 * 60 * 1000).toISOString();\n}\n\n/**\n * Build a clean `ListEventsParams` from loose user inputs.\n *\n * Server-side `prefetchInfiniteQuery` and client-side `useInfiniteEvents` must\n * both use this function to guarantee identical query keys.\n */\nexport function resolveEventsParams(\n input: ResolveEventsParamsInput = {},\n): ListEventsParams {\n const {\n tagSlugSelection,\n limit = DEFAULT_PAGE_SIZE,\n status = \"open\",\n with_markets = true,\n source,\n sort_by,\n sort_asc,\n minVolume,\n minLiquidity,\n timeRemaining,\n markets_limit = 3,\n lang,\n } = input;\n const tag_slug = resolveTagSlug(tagSlugSelection);\n\n const min_volume =\n minVolume !== undefined && minVolume !== \"\" ? Number(minVolume) : undefined;\n const min_liquidity =\n minLiquidity !== undefined && minLiquidity !== \"\"\n ? Number(minLiquidity)\n : undefined;\n const end_before = resolveEndBefore(timeRemaining);\n\n return {\n limit,\n status,\n with_markets,\n ...(source ? { source } : {}),\n ...(tag_slug ? { tag_slug } : {}),\n ...(sort_by ? { sort_by } : {}),\n ...(sort_asc !== undefined ? { sort_asc } : {}),\n ...(min_volume !== undefined && !isNaN(min_volume) ? { min_volume } : {}),\n ...(min_liquidity !== undefined && !isNaN(min_liquidity)\n ? { min_liquidity }\n : {}),\n ...(end_before ? { end_before } : {}),\n ...(markets_limit ? { markets_limit } : {}),\n ...(lang ? { lang } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Events infinite query (server-safe)\n// ---------------------------------------------------------------------------\n\n/** Stable TanStack Query key for the events infinite query. */\nexport function infiniteEventsQueryKey(params: ListEventsParams): unknown[] {\n return [\"predict\", \"events-infinite\", params];\n}\n\n/**\n * Fetch a single page of events. Can be used outside of React\n * (e.g. in Server Components, loaders, or tests).\n */\nexport async function fetchEventsPage(\n client: PredictClient,\n params: ListEventsParams,\n): Promise<PredictPage<PredictEvent>> {\n return client.listEvents(params);\n}\n\n// ---------------------------------------------------------------------------\n// Single event (server-safe)\n// ---------------------------------------------------------------------------\n\n/** Stable TanStack Query key for a single event. */\nexport function eventQueryKey(\n slug: string,\n source?: ProviderSource,\n lang?: string,\n): unknown[] {\n return [\"predict\", \"event\", slug, source, lang];\n}\n\n/**\n * Fetch a single event. Can be used outside of React\n * (e.g. in Server Components, loaders, or tests).\n */\nexport async function fetchEvent(\n client: PredictClient,\n slug: string,\n source?: ProviderSource,\n lang?: string,\n): Promise<PredictEvent> {\n return client.getEvent(slug, source, { lang });\n}\n\nexport type { PredictEvent, ListEventsParams, PredictPage };\n","/**\n * Server-safe pure functions for market query helpers.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictMarket,\n ProviderSource,\n PredictClient,\n} from \"../../client\";\n\n/** Stable TanStack Query key for a single market. */\nexport function marketQueryKey(\n slug: string,\n source?: ProviderSource,\n): unknown[] {\n return [\"predict\", \"market\", slug, source];\n}\n\n/**\n * Fetch function usable outside React (e.g. in loaders or tests).\n */\nexport async function fetchMarket(\n client: PredictClient,\n slug: string,\n source?: ProviderSource,\n): Promise<PredictMarket> {\n return client.getMarket(slug, source);\n}\n","/**\n * Server-safe pure functions for matches query parameters.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictClient,\n MatchesParams,\n MatchGroupPage,\n} from \"../../client\";\n\n/** Query key for match group list queries. */\nexport function matchesQueryKey(params?: MatchesParams): unknown[] {\n return [\"predict\", \"matches\", params];\n}\n\n/** Query key for a single match group. */\nexport function matchQueryKey(id: number): unknown[] {\n return [\"predict\", \"match\", id];\n}\n\n/** Fetch a page of matches (usable in both client and server contexts). */\nexport async function fetchMatchesPage(\n client: PredictClient,\n params: MatchesParams,\n): Promise<MatchGroupPage> {\n return client.listMatches(params);\n}\n","/**\n * Server-safe pure functions for match markets query parameters.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictClient,\n MatchMarketParams,\n MatchMarketPage,\n} from \"../../client\";\n\n/** Query key for market-level match queries. */\nexport function matchMarketsQueryKey(params?: MatchMarketParams): unknown[] {\n return [\"predict\", \"matchMarkets\", params];\n}\n\n/** Fetch a page of match markets (usable in both client and server contexts). */\nexport async function fetchMatchMarketsPage(\n client: PredictClient,\n params: MatchMarketParams,\n): Promise<MatchMarketPage> {\n return client.listMatchMarkets(params);\n}\n","import type {\n PredictClient,\n SportsMatchesParams,\n SportsMatchesResponse,\n SportsPropsParams,\n SportsPropsResponse,\n SportsTaxonomyParams,\n SportsTaxonomyResponse,\n} from \"../../client\";\n\nexport function sportsTaxonomyQueryKey(\n params?: SportsTaxonomyParams,\n): unknown[] {\n return [\"predict\", \"sports\", \"taxonomy\", params];\n}\n\nexport function sportsMatchesQueryKey(params?: SportsMatchesParams): unknown[] {\n return [\"predict\", \"sports\", \"matches\", params];\n}\n\nexport function sportsPropsQueryKey(params?: SportsPropsParams): unknown[] {\n return [\"predict\", \"sports\", \"props\", params];\n}\n\nexport function resolveSportsTaxonomyParams(\n params: SportsTaxonomyParams = {},\n): SportsTaxonomyParams {\n return { ...params, section: \"sports\" };\n}\n\nexport function resolveSportsMatchesParams(\n params: SportsMatchesParams = {},\n): SportsMatchesParams {\n return params;\n}\n\nexport function resolveSportsPropsParams(\n params: SportsPropsParams = {},\n): SportsPropsParams {\n return params;\n}\n\nexport async function fetchSportsTaxonomy(\n client: PredictClient,\n params?: SportsTaxonomyParams,\n): Promise<SportsTaxonomyResponse> {\n return client.getSportsTaxonomy(resolveSportsTaxonomyParams(params));\n}\n\nexport async function fetchSportsMatches(\n client: PredictClient,\n params?: SportsMatchesParams,\n): Promise<SportsMatchesResponse> {\n return client.getSportsMatches(resolveSportsMatchesParams(params));\n}\n\nexport async function fetchSportsProps(\n client: PredictClient,\n params?: SportsPropsParams,\n): Promise<SportsPropsResponse> {\n return client.getSportsProps(resolveSportsPropsParams(params));\n}\n","import type {\n EsportsMatchesParams,\n EsportsPropsParams,\n EsportsTaxonomyParams,\n PredictClient,\n SportsMatchesResponse,\n SportsPropsResponse,\n SportsTaxonomyResponse,\n} from \"../../client\";\n\nexport function esportsTaxonomyQueryKey(\n params?: EsportsTaxonomyParams,\n): unknown[] {\n return [\"predict\", \"esports\", \"taxonomy\", params];\n}\n\nexport function esportsMatchesQueryKey(\n params?: EsportsMatchesParams,\n): unknown[] {\n return [\"predict\", \"esports\", \"matches\", params];\n}\n\nexport function esportsPropsQueryKey(params?: EsportsPropsParams): unknown[] {\n return [\"predict\", \"esports\", \"props\", params];\n}\n\nexport function resolveEsportsTaxonomyParams(\n params: EsportsTaxonomyParams = {},\n): EsportsTaxonomyParams {\n return params;\n}\n\nexport function resolveEsportsMatchesParams(\n params: EsportsMatchesParams = {},\n): EsportsMatchesParams {\n return params;\n}\n\nexport function resolveEsportsPropsParams(\n params: EsportsPropsParams = {},\n): EsportsPropsParams {\n return params;\n}\n\nexport async function fetchEsportsTaxonomy(\n client: PredictClient,\n params?: EsportsTaxonomyParams,\n): Promise<SportsTaxonomyResponse> {\n return client.getEsportsTaxonomy(resolveEsportsTaxonomyParams(params));\n}\n\nexport async function fetchEsportsMatches(\n client: PredictClient,\n params?: EsportsMatchesParams,\n): Promise<SportsMatchesResponse> {\n return client.getEsportsMatches(resolveEsportsMatchesParams(params));\n}\n\nexport async function fetchEsportsProps(\n client: PredictClient,\n params?: EsportsPropsParams,\n): Promise<SportsPropsResponse> {\n return client.getEsportsProps(resolveEsportsPropsParams(params));\n}\n","import type {\n PredictClient,\n SportsRoutingParams,\n SportsRoutingResponse,\n} from \"../../client\";\n\nexport function sportsRoutingQueryKey(\n slug: string,\n params?: SportsRoutingParams,\n): unknown[] {\n return [\"predict\", \"sports\", \"routing\", slug, params];\n}\n\nexport function resolveSportsRoutingParams(\n params: SportsRoutingParams = {},\n): SportsRoutingParams {\n return params;\n}\n\nexport async function fetchSportsRouting(\n client: PredictClient,\n slug: string,\n params?: SportsRoutingParams,\n): Promise<SportsRoutingResponse> {\n return client.getSportsRouting(slug, resolveSportsRoutingParams(params));\n}\n","import type {\n EsportsMatchDetailParams,\n PredictClient,\n SportsMatchDetail,\n SportsMatchDetailParams,\n SportsSection,\n} from \"../../client\";\n\nexport function sportsMatchDetailQueryKey(\n section: SportsSection,\n matchGroupSlug: string,\n params?: SportsMatchDetailParams,\n): unknown[] {\n return [\"predict\", section, \"match-detail\", matchGroupSlug, params];\n}\n\nexport function esportsMatchDetailQueryKey(\n matchGroupSlug: string,\n params?: EsportsMatchDetailParams,\n): unknown[] {\n return sportsMatchDetailQueryKey(\"esports\", matchGroupSlug, params);\n}\n\nexport function resolveSportsMatchDetailParams(\n params: SportsMatchDetailParams = {},\n): SportsMatchDetailParams {\n return params;\n}\n\nexport function resolveEsportsMatchDetailParams(\n params: EsportsMatchDetailParams = {},\n): EsportsMatchDetailParams {\n return params;\n}\n\nexport async function fetchSportsMatchDetail(\n client: PredictClient,\n section: SportsSection,\n matchGroupSlug: string,\n params?: SportsMatchDetailParams,\n): Promise<SportsMatchDetail> {\n return client.getSportsMatchDetail(\n section,\n matchGroupSlug,\n resolveSportsMatchDetailParams(params),\n );\n}\n\nexport async function fetchEsportsMatchDetail(\n client: PredictClient,\n matchGroupSlug: string,\n params?: EsportsMatchDetailParams,\n): Promise<SportsMatchDetail> {\n return client.getEsportsMatchDetail(\n matchGroupSlug,\n resolveEsportsMatchDetailParams(params),\n );\n}\n","import type {\n PredictClient,\n PredictSearchParams,\n PredictSearchResponse,\n} from \"../../client\";\n\nexport function predictSearchQueryKey(params?: PredictSearchParams): unknown[] {\n return [\"predict\", \"search-documents\", params];\n}\n\nexport function resolvePredictSearchParams(\n params: PredictSearchParams = {},\n): PredictSearchParams {\n const q = params.q ?? \"\";\n return {\n ...params,\n q,\n sort_by: params.sort_by ?? (q ? \"relevance\" : \"volume\"),\n sort_asc: params.sort_asc ?? (q ? undefined : false),\n };\n}\n\nexport async function fetchPredictSearch(\n client: PredictClient,\n params?: PredictSearchParams,\n): Promise<PredictSearchResponse> {\n return client.search(resolvePredictSearchParams(params));\n}\n","/**\n * Domain types for the prediction-server REST API.\n *\n * Mirrors: github.com/liberfi-io/prediction-server/internal/domain\n */\n\n// ---------------------------------------------------------------------------\n// Shared / provider\n// ---------------------------------------------------------------------------\n\n/** Upstream data provider that produced a domain object. */\nexport type ProviderSource = \"kalshi\" | \"polymarket\";\n\n/**\n * Provider-specific metadata attached to every domain aggregate.\n * Keys are namespaced field paths, e.g. \"polymarket.conditionId\" or \"dflow.yesMint\".\n * Values are raw JSON-decoded values.\n */\nexport type ProviderMeta = Record<string, unknown>;\n\n// ---------------------------------------------------------------------------\n// Tags\n// ---------------------------------------------------------------------------\n\n/** Provider-sourced label attached to an Event. */\nexport interface PredictTag {\n slug: string;\n label: string;\n source: ProviderSource;\n provider_meta?: ProviderMeta;\n}\n\n// ---------------------------------------------------------------------------\n// Event\n// ---------------------------------------------------------------------------\n\n/** Lifecycle status of a prediction event (normalised across all providers). */\nexport type EventStatus = \"pending\" | \"open\" | \"closed\" | \"voided\";\n\n/** Settlement / resolution data source for an event. */\nexport interface SettlementSource {\n url: string;\n name?: string;\n}\n\n/** Root aggregate for a prediction event from the prediction-server API. */\nexport interface PredictEvent {\n /** Internal database surrogate key (absent when not yet persisted). */\n id?: number;\n /**\n * Canonical business key shared across all providers.\n * - DFlow: ticker (e.g. \"KXBTCD-25FEB-T68000\")\n * - Polymarket: slug (e.g. \"will-trump-win-2024\")\n */\n slug: string;\n\n title: string;\n /** Localized title for the request language. Falls back to `title` when absent. */\n title_trans?: string;\n subtitle?: string;\n /** Localized subtitle for the request language. Falls back to `subtitle` when absent. */\n subtitle_trans?: string;\n description?: string;\n /** Localized description for the request language. Falls back to `description` when absent. */\n description_trans?: string;\n image_url?: string;\n\n status: EventStatus;\n /** ISO 8601 timestamp; absent if the provider does not supply it. */\n start_at?: string;\n end_at?: string;\n created_at?: string;\n updated_at?: string;\n\n /** Provider-sourced labels for display only. */\n tags?: PredictTag[];\n\n /** All values are USD amounts. */\n volume?: number;\n volume_24h?: number;\n liquidity?: number;\n open_interest?: number;\n\n settlement_sources?: SettlementSource[];\n\n /** Nested markets; omitted when the request used `with_markets=false`. */\n markets?: PredictMarket[];\n /** Cache-only quote snapshot embedded when the market-data contract is enabled. */\n initial_quotes?: MarketDataInitialQuotes;\n\n source: ProviderSource;\n provider_meta?: ProviderMeta;\n}\n\n// ---------------------------------------------------------------------------\n// Market\n// ---------------------------------------------------------------------------\n\n/** Lifecycle status of a prediction market (normalised across all providers). */\nexport type MarketStatus = \"pending\" | \"open\" | \"closed\" | \"voided\";\n\n/** Final resolution of a closed market. Empty string means unresolved. */\nexport type MarketResult = \"yes\" | \"no\" | \"voided\" | \"\";\n\n/** One possible outcome in a binary (or multi-outcome) prediction market. */\nexport interface MarketOutcome {\n /** Provider-neutral structural identity; unique within the parent market. */\n key: string;\n /** Display name, e.g. \"Yes\" or \"No\". */\n label: string;\n /** Localized label for the request language. Falls back to `label` when absent. */\n label_trans?: string;\n /** Current implied probability [0, 1]. */\n price?: number;\n best_bid?: number;\n best_ask?: number;\n}\n\n/** Tradeable prediction outcome within an Event. */\nexport interface PredictMarket {\n id?: number;\n event_id?: number;\n\n slug: string;\n event_slug: string;\n\n question: string;\n /** Localized question for the request language. Falls back to `question` when absent. */\n question_trans?: string;\n description?: string;\n /** Localized description for the request language. Falls back to `description` when absent. */\n description_trans?: string;\n image_url?: string;\n /** Resolution/settlement rules in order. */\n rules?: string[];\n\n status: MarketStatus;\n result?: MarketResult;\n\n start_at?: string;\n end_at?: string;\n expires_at?: string;\n closed_at?: string;\n created_at?: string;\n updated_at?: string;\n\n /** Always present; binary markets have exactly 2 outcomes (YES at [0], NO at [1]). */\n outcomes: MarketOutcome[];\n\n volume?: number;\n volume_24h?: number;\n liquidity?: number;\n open_interest?: number;\n\n source: ProviderSource;\n provider_meta?: ProviderMeta;\n}\n\n// ---------------------------------------------------------------------------\n// Provider-neutral market data\n// ---------------------------------------------------------------------------\n\nexport const MARKET_STRUCTURE_MEDIA_TYPE_V1 =\n \"application/vnd.liberfi.market-structure+json;v=1\";\n\nexport type MarketDataSchemaVersion = 1;\nexport type MarketDataMarketView = \"summary\" | \"full\";\n\nexport interface MarketDataMarketKey {\n source: ProviderSource;\n market_slug: string;\n}\n\nexport interface MarketDataEventWatch {\n source: ProviderSource;\n event_slug: string;\n market_view: MarketDataMarketView;\n}\n\nexport interface MarketDataWatchRequest {\n quote_events?: MarketDataEventWatch[];\n quote_markets?: MarketDataMarketKey[];\n orderbook_market?: MarketDataMarketKey;\n}\n\nexport interface MarketDataWatchResponse {\n refresh_after_ms: number;\n}\n\nexport interface MarketDataQuotesRequest {\n markets: MarketDataMarketKey[];\n}\n\nexport interface MarketDataValueComponent {\n available: boolean;\n value?: number;\n provider_timestamp?: string;\n observed_at?: string;\n}\n\nexport interface MarketDataBBAComponent {\n available: boolean;\n empty: boolean;\n best_bid?: number;\n best_ask?: number;\n midpoint?: number;\n provider_timestamp?: string;\n observed_at?: string;\n}\n\nexport interface MarketDataOutcomeQuote extends MarketDataMarketKey {\n outcome: string;\n bba: MarketDataBBAComponent;\n last_trade: MarketDataValueComponent;\n tick_size: MarketDataValueComponent;\n}\n\nexport interface MarketDataMarketQuoteResult extends MarketDataMarketKey {\n realtime_supported: boolean;\n outcomes: MarketDataOutcomeQuote[];\n}\n\nexport interface MarketDataQuotesResponse {\n schema_version: MarketDataSchemaVersion;\n markets: MarketDataMarketQuoteResult[];\n}\n\nexport type MarketDataInitialQuotes = MarketDataQuotesResponse;\n\nexport interface MarketDataBookLevel {\n price: string;\n size: string;\n}\n\nexport interface MarketDataOutcomeOrderbook {\n outcome: string;\n provider_timestamp?: string;\n observed_at: string;\n bids: MarketDataBookLevel[];\n asks: MarketDataBookLevel[];\n}\n\nexport interface MarketDataOrderbooksResponse extends MarketDataMarketKey {\n schema_version: MarketDataSchemaVersion;\n orderbooks: MarketDataOutcomeOrderbook[];\n}\n\nexport type MarketStructureResourceType = \"event\" | \"match\" | \"prop\";\n\nexport interface MarketStructureOutcome {\n key: string;\n label: string;\n label_trans?: string;\n quote_capable: boolean;\n orderbook_capable: boolean;\n price_history_supported: boolean;\n book_channel?: string;\n}\n\nexport interface MarketStructureMarket extends MarketDataMarketKey {\n question: string;\n question_trans?: string;\n status: MarketStatus;\n realtime_supported: boolean;\n realtime_book_supported: boolean;\n outcomes: MarketStructureOutcome[];\n}\n\nexport interface MarketStructureItem {\n resource_type: MarketStructureResourceType;\n source?: ProviderSource;\n resource_slug: string;\n section?: SportsSection;\n title: string;\n title_trans?: string;\n status: string;\n market_view: MarketDataMarketView;\n markets_included: boolean;\n item_channel?: string;\n markets: MarketStructureMarket[];\n}\n\nexport interface MarketStructureResponse {\n representation_schema_version: 1;\n initial_quotes_contract_enabled: boolean;\n items: MarketStructureItem[];\n}\n\nexport type MarketStructureHttpResponse =\n | {\n status: 200;\n etag: string;\n body: MarketStructureResponse;\n }\n | {\n status: 304;\n etag: string;\n body?: never;\n };\n\n// ---------------------------------------------------------------------------\n// Pagination\n// ---------------------------------------------------------------------------\n\n/** Generic paginated result set returned by the prediction-server list endpoints. */\nexport interface PredictPage<T> {\n items: T[];\n next_cursor?: string;\n has_more?: boolean;\n limit?: number;\n /** Not all backends support total count. */\n total?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Request parameters\n// ---------------------------------------------------------------------------\n\n/** Valid sort fields accepted by `GET /api/v1/events`. */\nexport type EventSortField =\n | \"volume\"\n | \"volume_24h\"\n | \"liquidity\"\n | \"open_interest\"\n | \"end_at\"\n | \"start_at\"\n | \"created_at\";\n\n/** Query parameters for `listEvents`. All fields are optional. */\nexport interface ListEventsParams {\n /** Page size. Server default: 20. */\n limit?: number;\n /** Opaque pagination cursor returned by the previous page's `next_cursor`. */\n cursor?: string;\n /** Filter by event lifecycle status. */\n status?: EventStatus;\n /** Filter by upstream provider. */\n source?: ProviderSource;\n /** Unified navigation tag slug (e.g. \"politics\", \"sports\"). */\n tag_slug?: string;\n /** Full-text search query. */\n search?: string;\n /** Field to sort by. */\n sort_by?: EventSortField;\n /** When `true`, sort ascending. Defaults to descending. */\n sort_asc?: boolean;\n /**\n * When `false`, markets are omitted from each event for lighter payloads.\n * Defaults to `true` on the server.\n */\n with_markets?: boolean;\n /** Keep only events whose total volume (USD) is >= this value. */\n min_volume?: number;\n /** Keep only events whose liquidity (USD) is >= this value. */\n min_liquidity?: number;\n /**\n * RFC 3339 timestamp. Keep only events whose `end_at` is before this deadline\n * (i.e. the event closes within the specified window).\n */\n end_before?: string;\n /**\n * Max number of markets per event (sorted by volume DESC).\n * `0` means no limit. Defaults to `3` when set via `resolveEventsParams`.\n */\n markets_limit?: number;\n /**\n * Resolved UI language. Sent as `?lang=` so localized event/market fields are\n * returned and TanStack Query keys remain language-specific.\n */\n lang?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Orderbook\n// ---------------------------------------------------------------------------\n\n/** Single price level in an order book. */\nexport interface OrderbookLevel {\n price: number;\n size: number;\n}\n\n/** Binary outcome side for per-outcome order books. */\nexport type OrderbookOutcome = \"yes\" | \"no\";\n\n/** Aggregated order book for a market. */\nexport interface Orderbook {\n market_id: string;\n /** Outcome side this book belongs to. */\n outcome?: OrderbookOutcome;\n /** Sorted by price descending. */\n bids: OrderbookLevel[];\n /** Sorted by price ascending. */\n asks: OrderbookLevel[];\n /** best_ask − best_bid; absent when either side is empty. */\n spread?: number;\n}\n\n/** One market to fetch in a batch order book request. */\nexport interface OrderbookBatchItem {\n slug: string;\n source: ProviderSource;\n /** Outcome side; defaults to `\"yes\"`. */\n outcome?: OrderbookOutcome;\n}\n\n/** Request body for `POST /api/v1/markets/orderbooks`. */\nexport interface OrderbooksBatchRequest {\n /** Up to 100 markets to fetch in one call. */\n items: OrderbookBatchItem[];\n}\n\n/**\n * One result of a batch order book response, aligned with the request order.\n * `orderbook` is `null` when the item failed (see `error`); per-item failures\n * never fail the whole batch.\n */\nexport interface OrderbookBatchResult {\n slug: string;\n source: ProviderSource;\n outcome: OrderbookOutcome;\n orderbook: Orderbook | null;\n /** Present only when this item failed. */\n error?: string;\n}\n\n/** Response from `POST /api/v1/markets/orderbooks`. */\nexport interface OrderbooksBatchResponse {\n results: OrderbookBatchResult[];\n}\n\n// ---------------------------------------------------------------------------\n// Sports / esports\n// ---------------------------------------------------------------------------\n\n/** Top-level evergreen sports section. */\nexport type SportsSection = \"sports\" | \"esports\";\n\n/** Sports provider used by orderbook keys and search results. */\nexport type SportsProviderSource = ProviderSource;\n\n/** Public Sports event card type. */\nexport type SportsEventType = \"match\" | \"prop\";\n\n/** Sports event route result kind. */\nexport type SportsRouteType =\n | \"match\"\n | \"prop\"\n | \"child_redirect\"\n | \"not_sports\";\n\n/** Taxonomy node kind. */\nexport type SportsTaxonomyNodeType =\n | \"sport\"\n | \"game\"\n | \"league\"\n | \"tournament\"\n | \"category\";\n\n/** Binary outcome side accepted by existing Predict orderbook APIs. */\nexport type SportsBinaryOutcome = OrderbookOutcome;\n\nexport interface SportsTaxonomyNode {\n section?: SportsSection;\n node_type: SportsTaxonomyNodeType;\n slug: string;\n label: string;\n children?: SportsTaxonomyNode[];\n}\n\nexport interface SportsTaxonomySection {\n section: SportsSection;\n children: SportsTaxonomyNode[];\n}\n\nexport interface SportsTaxonomyResponse {\n sections: SportsTaxonomySection[];\n}\n\nexport interface SportsParticipant {\n name: string;\n role?: string;\n slug?: string;\n logo_url?: string;\n abbreviation?: string;\n}\n\nexport interface SportsLiveState {\n status?: string;\n status_text?: string;\n clock?: string | null;\n period?: string | null;\n score?: unknown;\n score_state?: unknown;\n observed_at_unix_ms?: number;\n}\n\nexport interface SportsOrderbookKey {\n market_slug: string;\n source: SportsProviderSource;\n outcome: SportsBinaryOutcome;\n}\n\nexport interface SportsMarketOutcome {\n outcome: SportsBinaryOutcome;\n label: string;\n price?: number;\n best_bid?: number;\n best_ask?: number;\n last_trade_price?: number;\n orderbook?: SportsOrderbookKey;\n}\n\nexport interface SportsInlineMarket {\n market_slug: string;\n market_type?: string;\n label: string;\n outcomes: SportsMarketOutcome[];\n}\n\nexport interface SportsMarket extends SportsInlineMarket {\n condition_id?: string;\n market_category?: string;\n period?: string;\n line?: number;\n active?: boolean;\n closed?: boolean;\n accepting_orders?: boolean;\n volume?: number;\n liquidity?: number;\n}\n\nexport interface SportsMarketGroup {\n market_category: string;\n label: string;\n markets: SportsMarket[];\n}\n\nexport interface SportsMatchCard {\n match_group_slug: string;\n section: SportsSection;\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n title: string;\n status: string;\n start_time?: string;\n participants?: SportsParticipant[];\n market_count?: number;\n live_state?: SportsLiveState;\n inline_markets?: SportsInlineMarket[];\n initial_quotes?: MarketDataInitialQuotes;\n}\n\nexport type SportsMatchesResponse = PredictPage<SportsMatchCard>;\n\nexport interface SportsPropEventCard {\n event_slug: string;\n event_type: SportsEventType;\n prop_type?: \"futures\" | \"outright\" | \"player_prop\" | \"all\" | string;\n section: SportsSection;\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n title: string;\n status?: string;\n start_time?: string;\n parent_match_group_slug?: string;\n markets?: SportsInlineMarket[];\n initial_quotes?: MarketDataInitialQuotes;\n}\n\nexport type SportsPropsResponse = PredictPage<SportsPropEventCard>;\n\nexport interface SportsRoutingResponse {\n route_type: SportsRouteType;\n slug: string;\n section?: SportsSection;\n match_group_slug?: string;\n event_slug?: string;\n redirect_to?: string;\n status?: number;\n}\n\nexport interface SportsMatchDetail extends SportsMatchCard {\n market_groups: SportsMarketGroup[];\n}\n\nexport interface SportsTaxonomyParams {\n section?: SportsSection;\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n lang?: string;\n}\n\nexport interface SportsMatchesParams {\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n status?: string;\n limit?: number;\n cursor?: string;\n lang?: string;\n}\n\nexport interface SportsPropsParams {\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n prop_type?: \"futures\" | \"outright\" | \"player_prop\" | \"all\";\n limit?: number;\n cursor?: string;\n lang?: string;\n}\n\nexport interface SportsRoutingParams {\n lang?: string;\n}\n\nexport interface SportsMatchDetailParams {\n lang?: string;\n}\n\nexport type EsportsTaxonomyParams = Omit<SportsTaxonomyParams, \"section\">;\nexport type EsportsMatchesParams = SportsMatchesParams;\nexport type EsportsPropsParams = SportsPropsParams;\nexport type EsportsMatchDetailParams = SportsMatchDetailParams;\n\n// ---------------------------------------------------------------------------\n// Mixed search\n// ---------------------------------------------------------------------------\n\nexport type PredictSearchResultType =\n | \"event\"\n | \"match_group\"\n | \"prop_event\"\n | \"market\";\n\nexport type PredictSearchSortField =\n | \"relevance\"\n | \"volume\"\n | \"start_time\"\n | \"updated_at\";\n\nexport interface PredictSearchParams {\n q?: string;\n result_type?: PredictSearchResultType | PredictSearchResultType[] | string;\n source?: ProviderSource;\n section?: SportsSection | string;\n include_closed?: boolean;\n sort_by?: PredictSearchSortField;\n sort_asc?: boolean;\n limit?: number;\n cursor?: string;\n lang?: string;\n}\n\nexport interface PredictSearchResult {\n result_type: PredictSearchResultType;\n document_id: string;\n title: string;\n source?: ProviderSource;\n section?: SportsSection | string;\n event_slug?: string;\n match_group_slug?: string;\n market_slug?: string;\n detail_url: string;\n status?: string;\n score?: number;\n}\n\nexport type PredictSearchResponse = PredictPage<PredictSearchResult>;\n\n// ---------------------------------------------------------------------------\n// Trade\n// ---------------------------------------------------------------------------\n\n/** On-chain trade type. */\nexport type TradeType =\n | \"TRADE\"\n | \"SPLIT\"\n | \"MERGE\"\n | \"REDEEM\"\n | \"REWARD\"\n | \"CONVERSION\"\n | \"MAKER_REBATE\"\n | \"REFERRAL_REWARD\";\n\n/** Lightweight event summary embedded in a trade. */\nexport interface EventSummary {\n slug: string;\n title: string;\n image_url?: string;\n status: EventStatus;\n}\n\n/** Lightweight market summary embedded in a trade or order. */\nexport interface MarketSummary {\n slug: string;\n question: string;\n image_url?: string;\n status: MarketStatus;\n}\n\n/** A single trade record. */\nexport interface PredictTrade {\n id: string;\n source: ProviderSource;\n side?: string;\n outcome?: string;\n outcome_index?: number;\n price?: number;\n size: number;\n usd_size?: number;\n /** Unix seconds. */\n timestamp: number;\n tx_hash?: string;\n wallet?: string;\n type: TradeType;\n event?: EventSummary;\n market?: MarketSummary;\n provider_meta?: ProviderMeta;\n}\n\n/** Query parameters for `GET /api/v1/markets/{slug}/trades`. */\nexport interface ListMarketTradesParams {\n source: ProviderSource;\n limit?: number;\n cursor?: string;\n /** Filter by side: `\"BUY\"` or `\"SELL\"`. */\n side?: string;\n}\n\n/** Query parameters for `GET /api/v1/trades` (by wallet). */\nexport interface ListTradesParams {\n /** Provider source. Omit to aggregate all providers. */\n source?: ProviderSource;\n wallet: string;\n limit?: number;\n cursor?: string;\n /** Comma-separated trade types. */\n type?: string;\n side?: string;\n}\n\n/**\n * Query parameters for `GET /api/v1/trades` in multi-wallet mode.\n * Each provider uses its own wallet address (e.g. Solana for Kalshi, EVM for Polymarket).\n */\nexport interface ListTradesMultiParams {\n kalshi_user?: string;\n polymarket_user?: string;\n limit?: number;\n cursor?: string;\n /** Comma-separated trade types. */\n type?: string;\n side?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Comments\n// ---------------------------------------------------------------------------\n\n/** Public profile of a comment author. */\nexport interface PredictCommentProfile {\n /** Display name, when the author set one. */\n name?: string;\n /** Generated pseudonym, shown when `name` is empty. */\n pseudonym?: string;\n /** Avatar image URL. */\n profile_image?: string;\n /** Provider proxy wallet (e.g. Polymarket Safe). */\n proxy_wallet?: string;\n /** Author wallet address; falls back to the base address upstream. */\n user_address?: string;\n}\n\n/** A single user comment on a prediction event (or its parent series). */\nexport interface PredictComment {\n id: string;\n body: string;\n /** Present when the comment is a reply to another comment. */\n parent_comment_id?: string;\n /** ISO-8601 timestamp. */\n created_at: string;\n reaction_count: number;\n profile: PredictCommentProfile;\n}\n\n/**\n * Query parameters for `GET /api/v1/events/{slug}/comments`.\n * `slug` is passed positionally to {@link PredictClient.listEventComments}.\n */\nexport interface ListCommentsParams {\n /** Provider source. Only `\"polymarket\"` is supported today. */\n source: ProviderSource;\n limit?: number;\n /** Opaque pagination cursor (offset string) from the previous page. */\n cursor?: string;\n /** Order field, e.g. `\"createdAt\"` or `\"reactionCount\"`. */\n order?: string;\n /** When true, sort ascending (requires `order`). */\n ascending?: boolean;\n /** When true, only comments from position holders. */\n holders_only?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Price history\n// ---------------------------------------------------------------------------\n\n/** A single price-history data point. */\nexport interface PricePoint {\n /** Unix seconds. */\n t: number;\n /** Price [0, 1]. */\n p: number;\n}\n\n/** Response from `GET /api/v1/markets/{slug}/price-history`. */\nexport interface PriceHistoryResponse {\n points: PricePoint[];\n}\n\n/** Accepted values for the `range` query parameter. */\nexport type PriceHistoryRange = \"1h\" | \"6h\" | \"1d\" | \"1w\" | \"1m\" | \"all\";\n\n/** Query parameters for `GET /api/v1/markets/{slug}/price-history`. */\nexport interface PriceHistoryParams {\n source: ProviderSource;\n range?: PriceHistoryRange;\n /** Unix seconds. Mirrors Polymarket `startTs`. */\n startTs?: number;\n /** Unix seconds. Mirrors Polymarket `endTs`. */\n endTs?: number;\n /** Data accuracy in minutes. Mirrors Polymarket `fidelity`. */\n fidelity?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Candlestick\n// ---------------------------------------------------------------------------\n\n/** OHLCV candlestick data point. */\nexport interface Candlestick {\n timestamp: string;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n}\n\n/** Query parameters for `GET /api/v1/markets/{slug}/candlesticks`. */\nexport interface ListCandlesticksParams {\n /** Candle interval (e.g. `\"1m\"`, `\"5m\"`, `\"1h\"`, `\"1d\"`). Default: `\"1h\"`. */\n interval?: string;\n /** Number of candles. Default: 100. */\n limit?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Similar events\n// ---------------------------------------------------------------------------\n\n/** Query parameters for `GET /api/v1/events/{slug}/similar`. */\nexport interface SimilarEventsParams {\n /** Number of results (default 5, max 20). */\n limit?: number;\n /** When true, only return events from the same provider. */\n same_source?: boolean;\n /**\n * Resolved UI language. Sent as `?lang=` so localized event/market fields are\n * returned.\n */\n lang?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Cross-platform matches\n// ---------------------------------------------------------------------------\n\n/** Match group lifecycle status. */\nexport type MatchStatus = \"active\" | \"expired\";\n\n/** One provider's event within a MatchGroup. */\nexport interface MatchGroupEntry {\n id: number;\n group_id: number;\n source: ProviderSource;\n event: PredictEvent;\n}\n\n/** Pairwise market comparison within a MatchGroup. */\nexport interface MatchGroupMarket {\n id: number;\n group_id: number;\n source_a: ProviderSource;\n market_a: PredictMarket;\n source_b: ProviderSource;\n market_b: PredictMarket;\n /**\n * v1.1: now `|a − b|` absolute YES-side gap, no longer fee-adjusted\n * arbitrage edge. Range [0, 1].\n */\n spread?: number;\n /** v1.1: `|a − b| × 100`. */\n spread_percent?: number;\n /** @deprecated PRD v1.1 removed the arbitrage framing. Always `0`. */\n arb_profit?: number;\n /**\n * v1.1: pair quality classification. Mirrors backend signal.go.\n * - `liquid_gap`: both legs vol_24h ≥ vol_active_usd, fresh.\n * - `active_gap`: at least one leg vol_24h ≥ vol_stale_usd, fresh.\n * - `stale_gap`: both legs vol_24h < vol_stale_usd, fresh data.\n * - `stale_data`: snapshot age > stale_age_seconds (data freshness wins).\n */\n signal_tag?: SignalTag;\n /** Pre-filter rejection reason (not surfaced to UI when set). */\n reject_reason?: string;\n}\n\n/**\n * A group of matched events across N providers referring to the same\n * real-world prediction. `entries.length >= 2`.\n */\nexport interface MatchGroup {\n id: number;\n title: string;\n entries: MatchGroupEntry[];\n matched_markets?: MatchGroupMarket[];\n confidence: number;\n max_spread?: number;\n combined_volume?: number;\n combined_volume_24h?: number;\n status: MatchStatus;\n created_at: string;\n updated_at: string;\n}\n\n/** Valid sort fields for the matches list endpoint. */\nexport type MatchSortField = \"spread\" | \"volume\" | \"confidence\";\n\n/** Query parameters for `GET /api/v1/matches`. */\nexport interface MatchesParams {\n sort_by?: MatchSortField;\n sort_asc?: boolean;\n min_spread?: number;\n /** Minimum combined volume (USD) filter. */\n min_volume?: number;\n /** Comma-separated provider sources, e.g. `\"kalshi,polymarket\"`. */\n sources?: string;\n status?: MatchStatus;\n search?: string;\n limit?: number;\n cursor?: string;\n}\n\n/** Aggregate statistics returned inline with the matches listing. */\nexport interface MatchesStats {\n total_matches: number;\n avg_spread: number;\n max_spread: number;\n matches_over_5_percent: number;\n matches_over_3_percent: number;\n total_volume: number;\n total_volume_24h: number;\n}\n\n/** Paginated match group result with inline aggregate stats. */\nexport interface MatchGroupPage {\n items: MatchGroup[];\n next_cursor?: string;\n has_more?: boolean;\n limit?: number;\n total?: number;\n stats?: MatchesStats;\n}\n\n/**\n * Confidence tier for match quality.\n * @deprecated v1.1 — UI surfaces `signal_tag` instead. Kept on the wire\n * for one release for backwards compatibility.\n */\nexport type MatchConfidenceTier = \"high\" | \"medium\" | \"low\";\n\n/**\n * v1.1 pair-quality classification (PRD §5.3). Empty string is never\n * emitted by the server — it's just here to silence narrowing on legacy\n * cached responses that predate the migration.\n */\nexport type SignalTag =\n | \"liquid_gap\"\n | \"active_gap\"\n | \"stale_gap\"\n | \"stale_data\";\n\n/**\n * v1.1 per-leg projection of a market in a matched pair (PRD §5).\n * Renders one side of the MatchMarketCard.\n */\nexport interface MatchLeg {\n source: ProviderSource;\n event_title: string;\n event_slug: string;\n market_id: number;\n market_slug: string;\n question: string;\n status: MarketStatus;\n outcomes?: MarketOutcome[];\n /**\n * YES-side effective best price used for the gap. Mid (bid+ask)/2\n * when both sides exist, else best_ask, else best_bid, else\n * outcome.price. Always in [0, 1] when set.\n */\n best_price?: number;\n /** Per-leg 24h notional in USD. Liquidity proxy now that depth is deferred. */\n vol_24h_usd?: number;\n /**\n * Deep link to this market on the original provider. Surfaced as the\n * small \"view on Polymarket / Kalshi\" icon next to the leg.\n */\n external_url?: string;\n /** now − markets.synced_at for THIS leg, in whole seconds. */\n age_seconds?: number;\n}\n\n/**\n * Flattened market pair from a match group (market-level granularity).\n *\n * v1.1: prefer reading `legs[0]` / `legs[1]` and `signal_tag`. The\n * legacy `market_a` / `market_b` / `spread_percent` fields are still\n * emitted for one release window so existing cached SDK responses do\n * not 500 — they will be removed in v1.2.\n */\nexport interface MatchMarketFlat {\n match_id: number;\n similarity_score: number;\n /** @deprecated v1.1 — prefer `signal_tag`. */\n confidence_tier: MatchConfidenceTier;\n status: MatchStatus;\n\n /** v1.1 primary projection — always length 2, ordered same as source_a/source_b. */\n legs: MatchLeg[];\n /** v1.1 pair quality (see SignalTag). */\n signal_tag?: SignalTag;\n /** v1.1 max(legs[*].age_seconds) — used for the pair-level freshness pill. */\n age_seconds?: number;\n\n source_a: ProviderSource;\n event_a_title: string;\n market_a: PredictMarket;\n source_b: ProviderSource;\n event_b_title: string;\n market_b: PredictMarket;\n /** v1.1 semantics: `|a − b|` absolute gap (0..1). */\n spread?: number;\n /** v1.1 semantics: `|a − b| × 100`. */\n spread_percent?: number;\n /** @deprecated PRD v1.1 removed arbitrage framing. */\n arb_profit?: number;\n combined_volume?: number;\n combined_volume_24h?: number;\n reject_reason?: string;\n}\n\n/** Paginated result for flattened market pairs. */\nexport interface MatchMarketPage {\n items: MatchMarketFlat[];\n total: number;\n limit: number;\n offset: number;\n}\n\n/** Query parameters for `GET /api/v1/matches/markets`. */\nexport interface MatchMarketParams {\n sort_by?: MatchSortField;\n sort_asc?: boolean;\n min_spread?: number;\n min_volume?: number;\n sources?: string;\n status?: MatchStatus;\n search?: string;\n /**\n * v1.1: comma-separated `SignalTag` values, e.g. `\"liquid_gap,active_gap\"`.\n * Pass `\"any\"` (or omit) to disable signal filtering.\n */\n signal?: string;\n limit?: number;\n offset?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Positions\n// ---------------------------------------------------------------------------\n\n/** A single user position in a prediction market. */\nexport interface PredictPosition {\n source: ProviderSource;\n side: string;\n size: number;\n avg_price?: number;\n current_price?: number;\n current_value?: number;\n initial_value?: number;\n pnl?: number;\n pnl_percent?: number;\n realized_pnl?: number;\n redeemable: boolean;\n event?: PredictEvent;\n market?: PredictMarket;\n /**\n * Position-level provider metadata.\n * DFlow positions carry `dflow.outcomeMint` and `dflow.collateralMint`.\n */\n provider_meta?: ProviderMeta;\n}\n\n/** Response from `GET /api/v1/positions`. */\nexport interface PositionsResponse {\n /** Populated for single-source or legacy aggregate queries. */\n user?: string;\n /** Populated for multi-wallet queries (keys are external source names). */\n wallets?: Record<string, string>;\n positions: PredictPosition[];\n}\n\n/** Lightweight current-value summary for one provider wallet. */\nexport interface PositionValue {\n source: ProviderSource;\n user: string;\n /** Current position value in {@link currency}, returned as a decimal string. */\n value: string;\n currency: string;\n}\n\n/** Provider-specific failure returned by aggregate position value queries. */\nexport interface PositionValueError {\n source: ProviderSource;\n user?: string;\n code: string;\n message: string;\n}\n\n/** Response from `GET /api/v1/positions/value`. */\nexport interface PositionValueResponse {\n /** Populated for single-source or legacy aggregate queries. */\n user?: string;\n /** Populated for multi-wallet queries (keys are external source names). */\n wallets?: Record<string, string>;\n /** Populated for single-source queries. */\n source?: ProviderSource;\n /** Aggregate current position value in {@link currency}. */\n value: string;\n currency: string;\n /** Per-provider values for multi-wallet or aggregate queries. */\n values?: PositionValue[];\n /** True when at least one provider failed but others returned values. */\n partial?: boolean;\n errors?: PositionValueError[];\n}\n\n// ---------------------------------------------------------------------------\n// Balance\n// ---------------------------------------------------------------------------\n\n/** Response from `GET /api/v1/balance`. */\nexport interface BalanceResponse {\n user: string;\n source: ProviderSource;\n /** Token symbol (e.g. \"USDC\"). */\n token: string;\n /** Human-readable balance (e.g. \"125.50\"). */\n balance: string;\n /** Raw balance in smallest unit (e.g. \"125500000\"). */\n raw_balance: string;\n /** Token decimals (e.g. 6 for USDC). */\n decimals: number;\n}\n\n// ---------------------------------------------------------------------------\n// Withdraw\n// ---------------------------------------------------------------------------\n\n/** Request body for `POST /api/v1/withdraw/build`. */\nexport interface WithdrawBuildRequest {\n source: ProviderSource;\n from: string;\n to: string;\n /** Human-readable amount (e.g. \"10.5\"). */\n amount: string;\n}\n\n/** Response from `POST /api/v1/withdraw/build`. */\nexport interface WithdrawBuildResponse {\n /** Base64 (Solana) or JSON tx params (Polygon). */\n serialized_tx: string;\n /** Unix timestamp; 0 means no expiry. */\n expires_at: number;\n}\n\n/** Request body for `POST /api/v1/withdraw/submit`. */\nexport interface WithdrawSubmitRequest {\n source: ProviderSource;\n signed_tx: string;\n}\n\n/** Response from `POST /api/v1/withdraw/submit`. */\nexport interface WithdrawSubmitResponse {\n tx_hash: string;\n status: string;\n}\n\n/** Response from `GET /api/v1/withdraw/status`. */\nexport interface WithdrawStatusResponse {\n tx_hash: string;\n /** \"submitted\" | \"confirmed\" | \"failed\" */\n status: \"submitted\" | \"confirmed\" | \"failed\";\n}\n\n// ---------------------------------------------------------------------------\n// Deposit (native USDC → USDC.e for Polymarket)\n// ---------------------------------------------------------------------------\n\n/** Request body for `POST /api/v1/deposit/polymarket/build`. */\nexport interface DepositBuildRequest {\n source: ProviderSource;\n from: string;\n safe_address: string;\n /** Total USDC needed (human-readable, e.g. \"50.0\"). */\n amount: string;\n}\n\n/** A single unsigned EVM transaction in the deposit build response. */\nexport interface UnsignedTx {\n /** \"approve\" or \"swap\" */\n type: \"approve\" | \"swap\";\n /** Transaction params: {from, to, data, value, chainId, gas} */\n params: Record<string, string>;\n}\n\n/** Response from `POST /api/v1/deposit/polymarket/build`. */\nexport interface DepositBuildResponse {\n transactions: UnsignedTx[];\n /** USDC amount that needs to be swapped (human-readable). */\n shortfall: string;\n /** Current Safe USDC.e balance (human-readable). */\n safe_balance: string;\n}\n\n/** Request body for `POST /api/v1/deposit/polymarket/submit`. */\nexport interface DepositSubmitRequest {\n source: ProviderSource;\n signed_tx: string;\n}\n\n/** Response from `POST /api/v1/deposit/polymarket/submit`. */\nexport interface DepositSubmitResponse {\n tx_hash: string;\n status: string;\n}\n\n/** Response from `GET /api/v1/deposit/polymarket/status`. */\nexport interface DepositStatusResponse {\n tx_hash: string;\n /** \"submitted\" | \"confirmed\" | \"failed\" */\n status: \"submitted\" | \"confirmed\" | \"failed\";\n}\n\n/** Multi-chain deposit addresses from the Polymarket Bridge API. */\nexport interface PolymarketDepositAddresses {\n /** EVM bridge address — accepts USDC/USDT on Ethereum, Polygon, Base, Arbitrum, Optimism, BNB, etc. */\n evm: string;\n /** Solana bridge address — accepts USDC on Solana. */\n svm: string;\n /** Bitcoin bridge address — accepts BTC. */\n btc: string;\n /** Tron bridge address — accepts USDT-TRC20 (optional, may be absent). */\n tron?: string;\n}\n\n/**\n * A single ERC20-style token entry returned by the Polymarket Bridge\n * `/supported-assets` endpoint.\n */\nexport interface PolymarketBridgeToken {\n /** Full token name, e.g. \"USD Coin\". */\n name: string;\n /** Token symbol, e.g. \"USDC\". */\n symbol: string;\n /** On-chain token contract address. May be a native-token sentinel for non-EVM chains. */\n address: string;\n /** Token decimals. */\n decimals: number;\n}\n\n/**\n * A single (chain, token) tuple supported by the Polymarket Bridge,\n * carrying the minimum USD amount that the Bridge will process for\n * deposits / withdrawals.\n */\nexport interface PolymarketSupportedAsset {\n /** Chain ID as a string (numeric for EVM, \"solana\"/\"bitcoin\"/\"tron\" for non-EVM, mirrors upstream). */\n chainId: string;\n /** Human-readable chain name, e.g. \"Ethereum\", \"Polygon\", \"Solana\". */\n chainName: string;\n /** Token metadata for this entry. */\n token: PolymarketBridgeToken;\n /** Minimum USD amount accepted by the bridge for this asset. */\n minCheckoutUsd: number;\n}\n\n/**\n * Response shape of `GET /api/v1/deposit/polymarket/supported-assets`.\n *\n * `supportedAssets` is the full list; consumers usually filter by `chainId`.\n */\nexport interface PolymarketSupportedAssetsResponse {\n supportedAssets: PolymarketSupportedAsset[];\n}\n\n/** Request body for `POST /api/v1/withdraw/polymarket/prepare`. */\nexport interface PolymarketWithdrawPrepareRequest {\n safe_address?: string;\n to?: string;\n wallet_address?: string;\n to_chain_id?: string;\n to_token_address?: string;\n recipient_address?: string;\n quote_id?: string;\n}\n\n/** Response from `POST /api/v1/withdraw/polymarket/prepare`. */\nexport interface PolymarketWithdrawPrepareResponse {\n deposit_address: string;\n bridge_address?: string;\n address_type?: \"evm\" | \"svm\" | \"tron\" | \"btc\" | string;\n quote_id?: string;\n}\n\n/** Request body for `POST /api/v1/withdraw/polymarket/execute`. */\nexport interface PolymarketWithdrawRequest {\n wallet_address: string;\n safe_address: string;\n to: string;\n /** Human-readable amount (e.g. \"10.5\"). */\n amount: string;\n}\n\n/** Response from `POST /api/v1/withdraw/polymarket/execute`. */\nexport interface PolymarketWithdrawResponse {\n transaction_id: string;\n status: string;\n}\n\nexport interface PolymarketWithdrawQuoteRequest {\n wallet_address: string;\n amount: string;\n to_chain_id: string;\n to_token_address: string;\n recipient_address: string;\n}\n\nexport interface PolymarketWithdrawQuoteResponse {\n quote_id: string;\n from_amount_base_unit: string;\n est_checkout_time_ms: number;\n est_input_usd: number;\n est_output_usd: number;\n est_to_token_base_unit: string;\n to_token_decimals: number;\n to_token_symbol: string;\n min_checkout_usd: number;\n est_fee_breakdown?: Record<string, unknown>;\n raw_bridge_quote?: Record<string, unknown>;\n}\n\nexport interface PolymarketTypedDataArg {\n name: string;\n type: string;\n}\n\nexport interface PolymarketTypedData {\n domain: Record<string, unknown>;\n types: Record<string, PolymarketTypedDataArg[]>;\n primaryType: string;\n message: Record<string, unknown>;\n}\n\nexport interface PolymarketWithdrawRelayBuildRequest {\n owner_address: string;\n wallet_address: string;\n bridge_address: string;\n amount: string;\n}\n\nexport interface PolymarketWithdrawRelayBuildResponse {\n typed_data: PolymarketTypedData;\n nonce: string;\n deadline: string;\n}\n\nexport interface PolymarketWithdrawRelaySubmitRequest {\n owner_address: string;\n wallet_address: string;\n bridge_address: string;\n amount: string;\n nonce: string;\n deadline: string;\n signature: string;\n}\n\nexport interface PolymarketWithdrawRelaySubmitResponse {\n transaction_id: string;\n status: string;\n bridge_address: string;\n}\n\nexport interface PolymarketWithdrawBridgeStatusResponse {\n bridge_address: string;\n transaction_id?: string;\n relayer_status?: string;\n transaction_hash?: string;\n bridge_status?: string;\n raw_bridge_status?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Orders\n// ---------------------------------------------------------------------------\n\n/** Lifecycle status of a user order. */\nexport type OrderStatus =\n | \"live\"\n | \"matched\"\n | \"cancelled\"\n | \"invalid\"\n | \"submitted\"\n | \"pending\"\n | \"open\"\n | \"pending_close\"\n | \"closed\"\n | \"failed\"\n | \"expired\";\n\n/** Order direction. */\nexport type OrderSide = \"BUY\" | \"SELL\";\n\n/** A single user order record. */\nexport interface PredictOrder {\n id: string;\n source: ProviderSource;\n status: OrderStatus;\n market_id?: string;\n asset_id?: string;\n side?: OrderSide;\n outcome?: string;\n price?: string;\n original_size?: string;\n size_matched?: string;\n in_amount?: string;\n out_amount?: string;\n order_type?: string;\n /** Unix seconds. */\n created_at?: number;\n expires_at?: number;\n provider_meta?: ProviderMeta;\n\n /** Enriched event context (populated by multi-wallet endpoint). */\n event?: EventSummary;\n /** Enriched market context (populated by multi-wallet endpoint). */\n market?: MarketSummary;\n}\n\n/** Query parameters for `GET /api/v1/orders`. */\nexport interface ListOrdersParams {\n /** Provider source. Omit to aggregate all providers. */\n source?: ProviderSource;\n wallet_address?: string;\n market_id?: string;\n asset_id?: string;\n next_cursor?: string;\n}\n\n/** Query parameters for multi-wallet `GET /api/v1/orders` mode. */\nexport interface ListOrdersMultiParams {\n kalshi_user?: string;\n polymarket_user?: string;\n}\n\n/** Response from multi-wallet `GET /api/v1/orders`. */\nexport interface PredictOrdersResponse {\n user?: string;\n wallets?: Record<string, string>;\n orders: PredictOrder[];\n}\n\n/** Result of `DELETE /api/v1/orders/{id}`. */\nexport interface CancelOrderResult {\n cancelled: string[];\n not_cancelled: Record<string, string>;\n}\n\n// ---------------------------------------------------------------------------\n// DFlow trading\n// ---------------------------------------------------------------------------\n\n/** Request body for `POST /api/v1/orders/kalshi/quote`. */\nexport interface DFlowQuoteRequest {\n inputMint: string;\n outputMint: string;\n amount: string;\n userPublicKey: string;\n slippageBps?: number;\n}\n\n/** Raw upstream response from DFlow quote (transparent passthrough). */\nexport type DFlowQuoteResponse = Record<string, unknown>;\n\n/** Context stored alongside a DFlow order for later enrichment. */\nexport interface DFlowOrderContext {\n user_public_key: string;\n input_mint: string;\n output_mint: string;\n amount: string;\n price: string;\n side: string;\n outcome: string;\n market_slug: string;\n slippage_bps: number;\n}\n\n/** Request body for `POST /api/v1/orders/kalshi/submit`. */\nexport interface DFlowSubmitRequest {\n signedTransaction: string;\n orderContext: DFlowOrderContext;\n}\n\n/** Response from `POST /api/v1/orders/kalshi/submit`. */\nexport interface DFlowSubmitResponse {\n signature: string;\n status: OrderStatus;\n}\n\n// ---------------------------------------------------------------------------\n// Polymarket trading\n// ---------------------------------------------------------------------------\n\n/** Order type for Polymarket CLOB. */\nexport type PolymarketOrderType = \"GTC\" | \"FOK\" | \"GTD\" | \"FAK\";\n\n/**\n * Known Polymarket minimum tick sizes. Must stay in sync with the\n * `ROUNDING_CONFIG` of `@polymarket/clob-client-v2` — sports markets use the\n * finer `0.005` / `0.0025` ticks introduced alongside CLOB V2.\n */\nexport type PolymarketTickSize =\n | \"0.1\"\n | \"0.01\"\n | \"0.005\"\n | \"0.0025\"\n | \"0.001\"\n | \"0.0001\";\n\n/**\n * Input for creating a Polymarket order (limit or market).\n * @see https://docs.polymarket.com/trading/orders/create\n */\nexport interface CreateOrderInput {\n /** Token ID (outcome asset ID) from market provider_meta. */\n tokenId: string;\n /** Price in range [0.01, 0.99]. */\n price: number;\n /**\n * Order size — meaning depends on order type:\n * - **Market BUY (FOK/FAK)**: USDC dollar amount to spend.\n * - **Market SELL (FOK/FAK)**: Number of shares to sell.\n * - **Limit BUY/SELL (GTC/GTD)**: Number of shares.\n *\n * This matches the official Polymarket SDK where `createMarketOrder` takes\n * `amount` (USDC for buy, shares for sell), while `createOrder` (limit)\n * takes `size` (always shares).\n * @see https://docs.polymarket.com/trading/orders/create#market-orders\n */\n size: number;\n side: OrderSide;\n orderType?: PolymarketOrderType;\n /** Minimum tick size for this market (from Polymarket gamma API). */\n tickSize: PolymarketTickSize;\n /** Whether this is a neg-risk market (uses different exchange contract). */\n negRisk?: boolean;\n /** Expiration timestamp (Unix seconds). Required for GTD orders. */\n expiration?: number;\n /**\n * The funder address that holds the USDC (proxy/Gnosis Safe wallet).\n * Defaults to the signer address when not provided.\n */\n funderAddress?: string;\n /**\n * Builder code (bytes32 hex, 0x-prefixed) for builder-rebate attribution.\n * Only honoured on CLOB V2 (POLY_1271 / deposit-wallet) orders — the V2\n * order struct carries a native `builder` field. Legacy V1 orders have no\n * builder field, so this is ignored there.\n */\n builderCode?: string;\n}\n\n/** Request body for `POST /api/v1/orders/polymarket/execute`. */\nexport interface PolymarketOrderExecuteRequest {\n /** Already signed Polymarket CLOB `/order` payload. */\n payload: unknown;\n /** L2 API key used as the CLOB order owner. */\n l2_api_key: string;\n /** L2 HMAC secret. */\n l2_secret: string;\n /** L2 HMAC passphrase. */\n l2_passphrase: string;\n /** L1 EVM signer address that owns the L2 credentials. */\n signer_address: string;\n /** Optional explicit owner override; defaults to l2_api_key server-side. */\n owner?: string;\n}\n\n/** Response from `POST /api/v1/orders/polymarket/execute`. */\nexport interface PolymarketOrderExecuteResponse {\n raw: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// KYC\n// ---------------------------------------------------------------------------\n\n/** Response from `GET /api/v1/kyc/kalshi?wallet_address=...`. */\nexport interface DFlowKYCStatus {\n wallet_address: string;\n verified: boolean;\n /** URL to redirect the user to for KYC onboarding (provided by server config). */\n kyc_url: string;\n}\n\n/**\n * Which Polymarket wallet model a user is on.\n * - `safe`: legacy Gnosis Safe (signatureType=2, USDC.e, V1 exchanges).\n * - `deposit`: CLOB V2 deposit wallet / ERC-1967 proxy\n * (signatureType=3 / POLY_1271, pUSD, V2 exchanges).\n */\nexport type PolymarketWalletKind = \"safe\" | \"deposit\";\n\n/** Response from `GET /api/v1/setup/polymarket?wallet_address=...`. */\nexport interface PolymarketSetupStatus {\n wallet_address: string;\n /** Active wallet model the caller should drive. */\n wallet_kind: PolymarketWalletKind;\n\n /** Legacy Safe fields. */\n safe_address?: string;\n safe_deployed: boolean;\n\n /** Deposit wallet (CLOB V2) fields. */\n deposit_wallet_address?: string;\n deposit_wallet_deployed: boolean;\n\n token_approved: boolean;\n /** True when the active wallet is deployed && token_approved. */\n verified: boolean;\n}\n\n/** Request body for `POST /api/v1/setup/polymarket/deposit/deploy`. */\nexport interface PolymarketDepositWalletDeployRequest {\n wallet_address: string;\n}\n\n/** Response from `POST /api/v1/setup/polymarket/deposit/deploy`. */\nexport interface PolymarketDepositWalletDeployResponse {\n deposit_wallet_address: string;\n deposit_wallet_deployed: boolean;\n transaction_id?: string;\n /** Relayer transaction state, e.g. \"STATE_CONFIRMED\". */\n status: string;\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket — mirrors prediction-server internal/domain/ws.go + protocol.go\n// ---------------------------------------------------------------------------\n\n/** WebSocket subscription channel. */\nexport type WsChannel = \"orderbook\" | \"prices\" | \"trades\";\n\n/** WebSocket connection lifecycle status. */\nexport type WsConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"disconnected\"\n | \"reconnecting\";\n\n/**\n * Full orderbook snapshot pushed via the `orderbook` channel.\n * Always a complete replacement — no delta merging required.\n */\nexport interface WsOrderbookEvent {\n market_slug: string;\n /** Outcome side this snapshot belongs to. */\n outcome?: OrderbookOutcome;\n bids: OrderbookLevel[];\n asks: OrderbookLevel[];\n spread?: number;\n}\n\n/** Latest bid/ask prices pushed via the `prices` channel. */\nexport interface WsPriceEvent {\n market_slug: string;\n yes_bid?: number;\n yes_ask?: number;\n no_bid?: number;\n no_ask?: number;\n spread?: number;\n}\n\n/** Single trade execution pushed via the `trades` channel. */\nexport interface WsTradeEvent {\n market_slug: string;\n trade_id?: string;\n side: string;\n price: number;\n size: number;\n outcome?: string;\n}\n\n/** Union of all channel data payloads. */\nexport type WsChannelEvent = WsOrderbookEvent | WsPriceEvent | WsTradeEvent;\n\n// -- Client → Server --------------------------------------------------------\n\n/** Subscribe or unsubscribe message sent to the server. */\nexport interface WsSubscribeMessage {\n type: \"subscribe\" | \"unsubscribe\";\n channels: WsChannel[];\n market_slugs: string[];\n}\n\n/** Client ping (application-level keepalive). */\nexport interface WsPingMessage {\n type: \"ping\";\n}\n\n/** Union of all messages the client can send. */\nexport type WsClientMessage = WsSubscribeMessage | WsPingMessage;\n\n// -- Server → Client --------------------------------------------------------\n\n/** Pong response to a client ping. */\nexport interface WsPongMessage {\n type: \"pong\";\n}\n\n/** Subscription confirmation. */\nexport interface WsSubscribedMessage {\n type: \"subscribed\";\n channels: WsChannel[];\n market_slugs: string[];\n}\n\n/** Error codes the server may return. */\nexport type WsErrorCode =\n | \"invalid_message\"\n | \"market_not_found\"\n | \"provider_unavailable\"\n | \"provider_reconnecting\";\n\n/** Error message from the server. */\nexport interface WsErrorMessage {\n type: \"error\";\n code: WsErrorCode;\n message: string;\n}\n\n/** Data message carrying a channel event payload. */\nexport interface WsDataMessage<T extends WsChannelEvent = WsChannelEvent> {\n channel: WsChannel;\n market_slug: string;\n data: T;\n ts: number;\n}\n\n/** Union of all messages the server can send. */\nexport type WsServerMessage =\n | WsPongMessage\n | WsSubscribedMessage\n | WsErrorMessage\n | WsDataMessage;\n\n// ---------------------------------------------------------------------------\n// Polymarket tick size\n// ---------------------------------------------------------------------------\n\n/** Response from the Polymarket tick-size endpoint. */\nexport interface TickSizeResponse {\n minimum_tick_size: number;\n}\n\n/** Response from the Polymarket fee-rate endpoint. */\nexport interface FeeRateResponse {\n base_fee: number;\n}\n\n// ---------------------------------------------------------------------------\n// Rebate / builder config\n// ---------------------------------------------------------------------------\n\n/**\n * Builder-attribution config from `GET /api/v1/referral/config`. The front-end\n * attaches {@link RebateConfig.builder_code} to CLOB V2 orders (when\n * {@link RebateConfig.builder_enabled}) so fills are credited to our builder\n * program for rebates.\n */\nexport interface RebateConfig {\n builder_enabled: boolean;\n /** Builder code (bytes32 hex, 0x-prefixed). Empty when not configured. */\n builder_code: string;\n builder_taker_fee_bps: number;\n builder_maker_fee_bps: number;\n commission_ratio: number;\n}\n\n// ---------------------------------------------------------------------------\n// Event stats (aggregate)\n// ---------------------------------------------------------------------------\n\n/** Aggregate statistics for all open prediction events. */\nexport interface EventStats {\n total_events: number;\n total_volume_24h: number;\n avg_liquidity: number;\n active_sources: number;\n}\n\n// ---------------------------------------------------------------------------\n// Available shares (for sell flow)\n// ---------------------------------------------------------------------------\n\n/** Response from the available-shares endpoint. */\nexport interface AvailableSharesResponse {\n source: ProviderSource;\n market: string;\n side: string;\n total_shares: number;\n active_order_shares: number;\n available_shares: number;\n precision: number;\n}\n\n// ---------------------------------------------------------------------------\n// Redeem (resolved market redemption)\n// ---------------------------------------------------------------------------\n\n/** Input for the redeem prepare endpoint — returns EIP-712 typed data to sign. */\nexport interface PolymarketRedeemPrepareInput {\n wallet_address: string;\n condition_id: string;\n neg_risk: boolean;\n}\n\n/** Response from the redeem prepare endpoint. */\nexport interface PolymarketRedeemPrepareResponse {\n /** Active Polymarket wallet kind for redeem execution. */\n wallet_kind?: PolymarketWalletKind;\n /** Active smart-contract wallet that holds the redeemable position. */\n wallet_address?: string;\n /** Legacy Gnosis Safe wallet address, present when wallet_kind is \"safe\". */\n safe_address?: string;\n /** CLOB V2 deposit wallet address, present when wallet_kind is \"deposit\". */\n deposit_wallet_address?: string;\n nonce: string;\n /** Deposit-wallet Batch deadline, present when wallet_kind is \"deposit\". */\n deadline?: string;\n /** Deposit-wallet Batch typed data. Sign with eth_signTypedData_v4. */\n typed_data?: PolymarketTypedData;\n /** Legacy SafeTx hash (0x-prefixed). Sign with personal_sign. */\n message_hash?: string;\n}\n\n/** Input for redeeming tokens — includes the EIP-712 signature. */\nexport interface PolymarketRedeemInput {\n wallet_address: string;\n condition_id: string;\n neg_risk: boolean;\n signature: string;\n nonce: string;\n wallet_kind?: PolymarketWalletKind;\n deadline?: string;\n}\n\n/** Response from the Polymarket redeem endpoint. */\nexport interface PolymarketRedeemResponse {\n transaction_id: string;\n transaction_hash?: string;\n status: string;\n}\n","import { httpGet, httpPost, httpDelete } from \"@liberfi.io/utils\";\nimport { MARKET_STRUCTURE_MEDIA_TYPE_V1 } from \"./types\";\nimport type {\n AvailableSharesResponse,\n BalanceResponse,\n CancelOrderResult,\n Candlestick,\n DepositBuildRequest,\n DepositBuildResponse,\n DepositSubmitRequest,\n DepositSubmitResponse,\n DepositStatusResponse,\n DFlowKYCStatus,\n DFlowQuoteRequest,\n DFlowQuoteResponse,\n DFlowSubmitRequest,\n DFlowSubmitResponse,\n EventStats,\n ListCandlesticksParams,\n ListCommentsParams,\n ListEventsParams,\n ListMarketTradesParams,\n ListOrdersParams,\n ListOrdersMultiParams,\n ListTradesParams,\n ListTradesMultiParams,\n MatchesParams,\n MatchGroup,\n MatchGroupPage,\n MatchMarketParams,\n MatchMarketPage,\n MarketDataMarketKey,\n MarketDataOrderbooksResponse,\n MarketDataQuotesResponse,\n MarketDataWatchRequest,\n MarketDataWatchResponse,\n MarketStructureHttpResponse,\n MarketStructureResponse,\n Orderbook,\n OrderbookBatchItem,\n OrderbookBatchResult,\n OrderbookOutcome,\n OrderbooksBatchResponse,\n PolymarketDepositAddresses,\n PolymarketOrderExecuteRequest,\n PolymarketOrderExecuteResponse,\n PolymarketSupportedAsset,\n PolymarketSupportedAssetsResponse,\n PolymarketSetupStatus,\n PolymarketDepositWalletDeployResponse,\n PolymarketWithdrawBridgeStatusResponse,\n PolymarketWithdrawQuoteRequest,\n PolymarketWithdrawQuoteResponse,\n PolymarketWithdrawRelayBuildRequest,\n PolymarketWithdrawRelayBuildResponse,\n PolymarketWithdrawRelaySubmitRequest,\n PolymarketWithdrawRelaySubmitResponse,\n PolymarketWithdrawPrepareRequest,\n PolymarketWithdrawPrepareResponse,\n PolymarketRedeemPrepareInput,\n PolymarketRedeemPrepareResponse,\n PolymarketRedeemInput,\n PolymarketRedeemResponse,\n PolymarketWithdrawRequest,\n PolymarketWithdrawResponse,\n PredictComment,\n PredictEvent,\n PredictMarket,\n PredictOrder,\n PredictOrdersResponse,\n PredictPage,\n PredictTrade,\n PositionValueResponse,\n PositionsResponse,\n PriceHistoryRange,\n PriceHistoryParams,\n PriceHistoryResponse,\n ProviderSource,\n SimilarEventsParams,\n WithdrawBuildRequest,\n WithdrawBuildResponse,\n WithdrawSubmitRequest,\n WithdrawSubmitResponse,\n WithdrawStatusResponse,\n TickSizeResponse,\n FeeRateResponse,\n RebateConfig,\n EsportsMatchDetailParams,\n EsportsMatchesParams,\n EsportsPropsParams,\n EsportsTaxonomyParams,\n PredictSearchParams,\n PredictSearchResponse,\n SportsMatchDetail,\n SportsMatchDetailParams,\n SportsMatchesParams,\n SportsMatchesResponse,\n SportsPropsParams,\n SportsPropsResponse,\n SportsRoutingParams,\n SportsRoutingResponse,\n SportsTaxonomyParams,\n SportsTaxonomyResponse,\n} from \"./types\";\n\nexport interface PredictClientOptions {\n headers?: HeadersInit | (() => HeadersInit | undefined);\n}\n\nexport class MarketDataHttpError extends Error {\n readonly name = \"MarketDataHttpError\";\n\n constructor(\n message: string,\n readonly status: number,\n readonly code?: string,\n readonly retryAfter?: string,\n readonly body?: unknown,\n ) {\n super(message);\n }\n}\n\n/**\n * Build a URL query string from a params object.\n * `undefined` and `null` values are omitted.\n * Boolean values are serialised as \"true\" / \"false\" strings.\n */\nfunction buildQuery(params: Record<string, unknown>): string {\n const qs = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n qs.set(key, String(value));\n }\n }\n const str = qs.toString();\n return str ? `?${str}` : \"\";\n}\n\n/**\n * HTTP client for the prediction-server REST API.\n *\n * Covers all prediction, market, order, position, and trading endpoints.\n *\n * @example\n * ```ts\n * const client = new PredictClient(\"https://api.example.com\");\n * const page = await client.listEvents({ status: \"open\", limit: 20 });\n * const event = await client.getEvent(\"will-trump-win-2024\");\n * const market = await client.getMarket(\"will-trump-win-2024-yes\");\n * ```\n */\nexport class PredictClient {\n constructor(\n private readonly endpoint: string,\n private readonly options: PredictClientOptions = {},\n ) {}\n\n private requestOptions(options?: RequestInit): RequestInit | undefined {\n const baseHeaders =\n typeof this.options.headers === \"function\"\n ? this.options.headers()\n : this.options.headers;\n if (!baseHeaders && !options) return undefined;\n return {\n ...options,\n headers: {\n ...(baseHeaders ? Object.fromEntries(new Headers(baseHeaders)) : {}),\n ...(options?.headers\n ? Object.fromEntries(new Headers(options.headers))\n : {}),\n },\n };\n }\n\n private async marketDataRequest<R>(\n path: string,\n options: RequestInit,\n ): Promise<R> {\n const response = await fetch(\n `${this.endpoint}${path}`,\n this.requestOptions(options),\n );\n if (response.ok) {\n return (await response.json()) as R;\n }\n const body = await parseMarketDataResponseBody(response);\n const record = isRecord(body) ? body : undefined;\n const code =\n typeof record?.error === \"string\"\n ? record.error\n : typeof record?.code === \"string\"\n ? record.code\n : undefined;\n const message =\n typeof record?.message === \"string\"\n ? record.message\n : (code ?? response.statusText ?? `HTTP ${response.status}`);\n throw new MarketDataHttpError(\n message,\n response.status,\n code,\n response.headers.get(\"Retry-After\") ?? undefined,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Events\n // -------------------------------------------------------------------------\n\n /**\n * List prediction events with optional filtering, sorting, and pagination.\n *\n * Maps to `GET /api/v1/events`.\n *\n * @param params - Optional query parameters (filter, sort, pagination).\n * @returns A paginated page of events.\n */\n async listEvents(\n params?: ListEventsParams,\n ): Promise<PredictPage<PredictEvent>> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/events${query}`;\n return await httpGet<PredictPage<PredictEvent>>(url, this.requestOptions());\n }\n\n /**\n * Fetch a single prediction event by its slug.\n *\n * Maps to `GET /api/v1/events/:slug?source=...`.\n *\n * @param slug - Canonical event slug (e.g. \"will-trump-win-2024\" for Polymarket\n * or \"KXBTCD-25FEB-T68000\" for Kalshi).\n * @param source - Upstream provider (`\"kalshi\"` or `\"polymarket\"`).\n * @returns The matching event.\n * @throws When the server responds with 404 or any other non-2xx status.\n */\n async getEvent(\n slug: string,\n source?: ProviderSource,\n params?: { lang?: string },\n ): Promise<PredictEvent> {\n const query = buildQuery({ source, ...params });\n const url = `${this.endpoint}/api/v1/events/${encodeURIComponent(slug)}${query}`;\n return await httpGet<PredictEvent>(url, this.requestOptions());\n }\n\n /**\n * Fetch aggregate statistics for all open events.\n *\n * Maps to `GET /api/v1/events/stats`.\n */\n async getEventStats(): Promise<EventStats> {\n const url = `${this.endpoint}/api/v1/events/stats`;\n return await httpGet<EventStats>(url);\n }\n\n /**\n * Fetch events similar to the given slug.\n *\n * Maps to `GET /api/v1/events/:slug/similar?source=...`.\n */\n async getSimilarEvents(\n slug: string,\n source: ProviderSource,\n params?: SimilarEventsParams,\n ): Promise<PredictEvent[]> {\n const query = buildQuery({ source, ...params });\n const url = `${this.endpoint}/api/v1/events/${encodeURIComponent(slug)}/similar${query}`;\n return await httpGet<PredictEvent[]>(url);\n }\n\n // -------------------------------------------------------------------------\n // Sports / esports\n // -------------------------------------------------------------------------\n\n /** Maps to `GET /api/v1/sports/taxonomy`. */\n async getSportsTaxonomy(\n params?: SportsTaxonomyParams,\n ): Promise<SportsTaxonomyResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/taxonomy${query}`;\n return await httpGet<SportsTaxonomyResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/matches`. */\n async getSportsMatches(\n params?: SportsMatchesParams,\n ): Promise<SportsMatchesResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/matches${query}`;\n return await httpGet<SportsMatchesResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/props`. */\n async getSportsProps(\n params?: SportsPropsParams,\n ): Promise<SportsPropsResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/props${query}`;\n return await httpGet<SportsPropsResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/esports/taxonomy`. */\n async getEsportsTaxonomy(\n params?: EsportsTaxonomyParams,\n ): Promise<SportsTaxonomyResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/esports/taxonomy${query}`;\n return await httpGet<SportsTaxonomyResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/esports/matches`. */\n async getEsportsMatches(\n params?: EsportsMatchesParams,\n ): Promise<SportsMatchesResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/esports/matches${query}`;\n return await httpGet<SportsMatchesResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/esports/props`. */\n async getEsportsProps(\n params?: EsportsPropsParams,\n ): Promise<SportsPropsResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/esports/props${query}`;\n return await httpGet<SportsPropsResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/routing/:slug`. */\n async getSportsRouting(\n slug: string,\n params?: SportsRoutingParams,\n ): Promise<SportsRoutingResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/routing/${encodeURIComponent(slug)}${query}`;\n return await httpGet<SportsRoutingResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/matches/:match_group_slug`. */\n async getSportsMatchDetail(\n section: \"sports\" | \"esports\",\n matchGroupSlug: string,\n params?: SportsMatchDetailParams,\n ): Promise<SportsMatchDetail> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/${encodeURIComponent(section)}/matches/${encodeURIComponent(matchGroupSlug)}${query}`;\n return await httpGet<SportsMatchDetail>(url, this.requestOptions());\n }\n\n /** Convenience wrapper for `GET /api/v1/esports/matches/:match_group_slug`. */\n async getEsportsMatchDetail(\n matchGroupSlug: string,\n params?: EsportsMatchDetailParams,\n ): Promise<SportsMatchDetail> {\n return this.getSportsMatchDetail(\"esports\", matchGroupSlug, params);\n }\n\n /** Maps to `GET /api/v1/search`. */\n async search(params?: PredictSearchParams): Promise<PredictSearchResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/search${query}`;\n return await httpGet<PredictSearchResponse>(url, this.requestOptions());\n }\n\n /**\n * List comments for a prediction event.\n *\n * Maps to `GET /api/v1/events/:slug/comments`.\n *\n * The server resolves the event to its parent series when one exists\n * (Polymarket attaches discussion at the series level for grouped events such\n * as World Cup matches) and otherwise returns event-level comments. Callers\n * stay unaware of the event-vs-series distinction.\n *\n * @param slug - Canonical event slug.\n * @param params - Query parameters (source, pagination, sort, holders filter).\n * @returns A paginated page of comments.\n */\n async listEventComments(\n slug: string,\n params: ListCommentsParams,\n ): Promise<PredictPage<PredictComment>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/events/${encodeURIComponent(slug)}/comments${query}`;\n return await httpGet<PredictPage<PredictComment>>(url);\n }\n\n // -------------------------------------------------------------------------\n // Markets\n // -------------------------------------------------------------------------\n\n /** Register or refresh the complete provider-neutral market-data demand set. */\n async watchMarketData(\n request: MarketDataWatchRequest,\n ): Promise<MarketDataWatchResponse> {\n return await this.marketDataRequest<MarketDataWatchResponse>(\n \"/api/v1/market-data/watch\",\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n }\n\n /** Read cache-only quote snapshots for at most 500 provider-neutral keys. */\n async getMarketDataQuotes(\n markets: MarketDataMarketKey[],\n ): Promise<MarketDataQuotesResponse> {\n if (markets.length > 500) {\n throw new RangeError(\n \"market data quote request accepts at most 500 markets\",\n );\n }\n return await this.marketDataRequest<MarketDataQuotesResponse>(\n \"/api/v1/markets/quotes\",\n {\n method: \"POST\",\n cache: \"no-store\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ markets }),\n },\n );\n }\n\n /** Read all cached Top20 outcome books for one provider-neutral market. */\n async getMarketDataOrderbooks(\n slug: string,\n source: ProviderSource,\n ): Promise<MarketDataOrderbooksResponse> {\n const path =\n `/api/v1/markets/${encodeURIComponent(slug)}/orderbooks` +\n buildQuery({ source });\n return await this.marketDataRequest<MarketDataOrderbooksResponse>(path, {\n method: \"GET\",\n cache: \"no-store\",\n });\n }\n\n /**\n * Revalidate a page's allowlist-only structure representation.\n *\n * The path must remain inside the prediction API so callers cannot turn a\n * configured authenticated client into a cross-origin request primitive.\n */\n async getMarketStructure(\n path: string,\n ifNoneMatch?: string,\n ): Promise<MarketStructureHttpResponse> {\n if (!path.startsWith(\"/api/v1/\")) {\n throw new TypeError(\"market structure path must start with /api/v1/\");\n }\n const response = await fetch(\n `${this.endpoint}${path}`,\n this.requestOptions({\n method: \"GET\",\n cache: \"no-store\",\n headers: {\n Accept: MARKET_STRUCTURE_MEDIA_TYPE_V1,\n ...(ifNoneMatch ? { \"If-None-Match\": ifNoneMatch } : {}),\n },\n }),\n );\n const etag = response.headers.get(\"ETag\") ?? \"\";\n if (response.status === 304) {\n return { status: 304, etag };\n }\n if (response.ok) {\n return {\n status: 200,\n etag,\n body: (await response.json()) as MarketStructureResponse,\n };\n }\n const body = await parseMarketDataResponseBody(response);\n const record = isRecord(body) ? body : undefined;\n const code = typeof record?.error === \"string\" ? record.error : undefined;\n throw new MarketDataHttpError(\n typeof record?.message === \"string\"\n ? record.message\n : (code ?? response.statusText),\n response.status,\n code,\n response.headers.get(\"Retry-After\") ?? undefined,\n body,\n );\n }\n\n /**\n * Fetch a single prediction market by its slug.\n *\n * Maps to `GET /api/v1/markets/:slug?source=...`.\n *\n * @param slug - Canonical market slug.\n * @param source - Upstream provider (`\"kalshi\"` or `\"polymarket\"`).\n * @returns The matching market.\n * @throws When the server responds with 404 or any other non-2xx status.\n */\n async getMarket(\n slug: string,\n source?: ProviderSource,\n ): Promise<PredictMarket> {\n const query = source ? buildQuery({ source }) : \"\";\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}${query}`;\n return await httpGet<PredictMarket>(url);\n }\n\n /** Maps to `GET /api/v1/markets/:slug/orderbook?source=...&outcome=...`. */\n async getOrderbook(\n slug: string,\n source: ProviderSource,\n outcome?: OrderbookOutcome,\n ): Promise<Orderbook> {\n const query = buildQuery({ source, outcome });\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/orderbook${query}`;\n return await httpGet<Orderbook>(url);\n }\n\n /**\n * Maps to `POST /api/v1/markets/orderbooks`.\n * Fetches order books for many markets in a single request (max 100 items).\n * Results are returned in the same order as `items`; per-item failures are\n * reported via `OrderbookBatchResult.error` and never fail the whole batch.\n */\n async getOrderbooks(\n items: OrderbookBatchItem[],\n ): Promise<OrderbookBatchResult[]> {\n const url = `${this.endpoint}/api/v1/markets/orderbooks`;\n const res = await httpPost<OrderbooksBatchResponse>(url, { items });\n return res.results;\n }\n\n /** Maps to `GET /api/v1/markets/:slug/trades?source=...`. */\n async listMarketTrades(\n slug: string,\n params: ListMarketTradesParams,\n ): Promise<PredictPage<PredictTrade>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/trades${query}`;\n return await httpGet<PredictPage<PredictTrade>>(url);\n }\n\n /** Maps to `GET /api/v1/markets/:slug/price-history?source=...&range=...`. */\n async getPriceHistory(\n slug: string,\n sourceOrParams: ProviderSource | PriceHistoryParams,\n range?: PriceHistoryRange,\n ): Promise<PriceHistoryResponse> {\n const params =\n typeof sourceOrParams === \"string\"\n ? { source: sourceOrParams, range }\n : sourceOrParams;\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/price-history${query}`;\n return await httpGet<PriceHistoryResponse>(url);\n }\n\n /** Maps to `GET /api/v1/markets/:slug/candlesticks?interval=...&limit=...`. */\n async listCandlesticks(\n slug: string,\n params?: ListCandlesticksParams,\n ): Promise<Candlestick[]> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/candlesticks${query}`;\n return await httpGet<Candlestick[]>(url);\n }\n\n // -------------------------------------------------------------------------\n // Positions\n // -------------------------------------------------------------------------\n\n /**\n * Maps to `GET /api/v1/positions`.\n *\n * Single-source: `getPositions(\"addr\", \"kalshi\")`.\n * Multi-wallet: `getPositions({ kalshi_user: \"SOLaddr\", polymarket_user: \"EVMaddr\" })`.\n * Legacy agg: `getPositions(\"addr\")` (same address for all providers).\n */\n async getPositions(\n userOrWallets: string | { kalshi_user?: string; polymarket_user?: string },\n source?: ProviderSource,\n ): Promise<PositionsResponse> {\n let query: string;\n if (typeof userOrWallets === \"string\") {\n query = buildQuery({ source, user: userOrWallets });\n } else {\n query = buildQuery(userOrWallets as Record<string, unknown>);\n }\n const url = `${this.endpoint}/api/v1/positions${query}`;\n return await httpGet<PositionsResponse>(url);\n }\n\n /**\n * Maps to `GET /api/v1/positions/value`.\n *\n * Single-source: `getPositionValue(\"addr\", \"polymarket\")`.\n * Multi-wallet: `getPositionValue({ kalshi_user: \"SOLaddr\", polymarket_user: \"EVMaddr\" })`.\n * Legacy agg: `getPositionValue(\"addr\")` (same address for all providers).\n */\n async getPositionValue(\n userOrWallets: string | { kalshi_user?: string; polymarket_user?: string },\n source?: ProviderSource,\n ): Promise<PositionValueResponse> {\n let query: string;\n if (typeof userOrWallets === \"string\") {\n query = buildQuery({ source, user: userOrWallets });\n } else {\n query = buildQuery(userOrWallets as Record<string, unknown>);\n }\n const url = `${this.endpoint}/api/v1/positions/value${query}`;\n return await httpGet<PositionValueResponse>(url);\n }\n\n // -------------------------------------------------------------------------\n // Available shares (for sell flow)\n // -------------------------------------------------------------------------\n\n /**\n * Get the number of shares available for selling, accounting for active orders.\n *\n * Maps to `GET /api/v1/available-shares?source=...&user=...&market=...&side=...`.\n *\n * @param source - Provider source.\n * @param user - Wallet address.\n * @param market - Market slug.\n * @param side - Position side (\"yes\" or \"no\").\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async getAvailableShares(\n source: ProviderSource,\n user: string,\n market: string,\n side: string,\n headers?: Record<string, string>,\n ): Promise<AvailableSharesResponse> {\n const query = buildQuery({ source, user, market, side });\n const url = `${this.endpoint}/api/v1/available-shares${query}`;\n return await httpGet<AvailableSharesResponse>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n // -------------------------------------------------------------------------\n // Balance\n // -------------------------------------------------------------------------\n\n /**\n * Get the on-chain USDC balance for a wallet.\n *\n * Maps to `GET /api/v1/balance?source=...&user=...`.\n *\n * @param source - Provider source (`\"kalshi\"` for Solana, `\"polymarket\"` for Polygon).\n * @param user - Wallet address.\n */\n async getBalance(\n source: ProviderSource,\n user: string,\n ): Promise<BalanceResponse> {\n const query = buildQuery({ source, user });\n const url = `${this.endpoint}/api/v1/balance${query}`;\n return await httpGet<BalanceResponse>(url);\n }\n\n // -------------------------------------------------------------------------\n // Orders\n // -------------------------------------------------------------------------\n\n /**\n * Maps to `GET /api/v1/orders?source=...&wallet_address=...`.\n *\n * @param params - Query parameters (source, wallet_address, etc.).\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async listOrders(\n params: ListOrdersParams,\n headers?: Record<string, string>,\n ): Promise<PredictPage<PredictOrder>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/orders${query}`;\n return await httpGet<PredictPage<PredictOrder>>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n /**\n * Multi-wallet order listing with enriched market/event context.\n *\n * Maps to `GET /api/v1/orders?kalshi_user=...&polymarket_user=...`.\n *\n * @param params - Per-provider wallet addresses.\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async listOrdersMulti(\n params: ListOrdersMultiParams,\n headers?: Record<string, string>,\n ): Promise<PredictOrdersResponse> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/orders${query}`;\n return await httpGet<PredictOrdersResponse>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n /**\n * Maps to `GET /api/v1/orders/:id?source=...`.\n *\n * @param id - Order ID.\n * @param source - Provider source.\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async getOrder(\n id: string,\n source: ProviderSource,\n headers?: Record<string, string>,\n ): Promise<PredictOrder> {\n const query = buildQuery({ source });\n const url = `${this.endpoint}/api/v1/orders/${encodeURIComponent(id)}${query}`;\n return await httpGet<PredictOrder>(url, headers ? { headers } : undefined);\n }\n\n /**\n * Maps to `DELETE /api/v1/orders/:id?source=...`.\n *\n * @param id - Order ID.\n * @param source - Provider source.\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async cancelOrder(\n id: string,\n source: ProviderSource,\n headers?: Record<string, string>,\n ): Promise<CancelOrderResult> {\n const query = buildQuery({ source });\n const url = `${this.endpoint}/api/v1/orders/${encodeURIComponent(id)}${query}`;\n return await httpDelete<CancelOrderResult>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n // -------------------------------------------------------------------------\n // Polymarket trading\n // -------------------------------------------------------------------------\n\n /**\n * Execute an already signed Polymarket CLOB order through prediction-server.\n *\n * Maps to `POST /api/v1/orders/polymarket/execute`. The server builds the\n * CLOB HMAC headers from the provided L2 credentials, forwards `payload`\n * unchanged to `/order`, and records rebate identity mappings.\n */\n async executePolymarketOrder(\n req: PolymarketOrderExecuteRequest,\n ): Promise<PolymarketOrderExecuteResponse> {\n const url = `${this.endpoint}/api/v1/orders/polymarket/execute`;\n return await httpPost<PolymarketOrderExecuteResponse>(url, req);\n }\n\n /** Maps to `GET /api/v1/polymarket/tick-size?token_id=xxx`. */\n async getPolymarketTickSize(tokenId: string): Promise<TickSizeResponse> {\n const url = `${this.endpoint}/api/v1/polymarket/tick-size?token_id=${encodeURIComponent(tokenId)}`;\n return await httpGet<TickSizeResponse>(url);\n }\n\n /** Maps to `GET /api/v1/polymarket/fee-rate?token_id=xxx`. */\n async getPolymarketFeeRate(tokenId: string): Promise<FeeRateResponse> {\n const url = `${this.endpoint}/api/v1/polymarket/fee-rate?token_id=${encodeURIComponent(tokenId)}`;\n return await httpGet<FeeRateResponse>(url);\n }\n\n /**\n * Builder-attribution / rebate config. Maps to `GET /api/v1/referral/config`.\n * The front-end uses `builder_code` (when `builder_enabled`) to attribute\n * CLOB V2 orders to our builder program.\n */\n async getRebateConfig(): Promise<RebateConfig> {\n const url = `${this.endpoint}/api/v1/referral/config`;\n return await httpGet<RebateConfig>(url);\n }\n\n // -------------------------------------------------------------------------\n // DFlow trading\n // -------------------------------------------------------------------------\n\n /** Maps to `POST /api/v1/orders/kalshi/quote`. */\n async createDFlowQuote(body: DFlowQuoteRequest): Promise<DFlowQuoteResponse> {\n const url = `${this.endpoint}/api/v1/orders/kalshi/quote`;\n return await httpPost<DFlowQuoteResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/orders/kalshi/submit`. */\n async submitDFlowTransaction(\n body: DFlowSubmitRequest,\n ): Promise<DFlowSubmitResponse> {\n const url = `${this.endpoint}/api/v1/orders/kalshi/submit`;\n return await httpPost<DFlowSubmitResponse>(url, body);\n }\n\n // -------------------------------------------------------------------------\n // KYC\n // -------------------------------------------------------------------------\n\n /**\n * Check DFlow KYC verification status for a wallet address.\n *\n * Maps to `GET /api/v1/kyc/kalshi?wallet_address=...`.\n */\n async checkDFlowKYC(walletAddress: string): Promise<DFlowKYCStatus> {\n const query = buildQuery({ wallet_address: walletAddress });\n const url = `${this.endpoint}/api/v1/kyc/kalshi${query}`;\n return await httpGet<DFlowKYCStatus>(url);\n }\n\n // -------------------------------------------------------------------------\n // Polymarket wallet setup\n // -------------------------------------------------------------------------\n\n /**\n * Check Polymarket wallet setup status (Safe deployed + USDC.e approved).\n *\n * Maps to `GET /api/v1/setup/polymarket?wallet_address=...`.\n */\n async checkPolymarketSetup(\n walletAddress: string,\n ): Promise<PolymarketSetupStatus> {\n const query = buildQuery({ wallet_address: walletAddress });\n const url = `${this.endpoint}/api/v1/setup/polymarket${query}`;\n return await httpGet<PolymarketSetupStatus>(url);\n }\n\n /**\n * Run Polymarket wallet setup (deploy Safe + approve USDC.e).\n *\n * Maps to `POST /api/v1/setup/polymarket`.\n */\n async runPolymarketSetup(\n walletAddress: string,\n ): Promise<PolymarketSetupStatus> {\n const url = `${this.endpoint}/api/v1/setup/polymarket`;\n return await httpPost<PolymarketSetupStatus>(url, {\n wallet_address: walletAddress,\n });\n }\n\n /**\n * Deploy a Polymarket CLOB V2 deposit wallet (gasless WALLET-CREATE).\n *\n * No user signature is required — the relayer deploys the per-user\n * ERC-1967 proxy and the server waits until it is confirmed on-chain.\n * Used for new (non-Safe) users on the POLY_1271 path.\n *\n * Maps to `POST /api/v1/setup/polymarket/deposit/deploy`.\n */\n async deployPolymarketDepositWallet(\n walletAddress: string,\n ): Promise<PolymarketDepositWalletDeployResponse> {\n const url = `${this.endpoint}/api/v1/setup/polymarket/deposit/deploy`;\n return await httpPost<PolymarketDepositWalletDeployResponse>(url, {\n wallet_address: walletAddress,\n });\n }\n\n // -------------------------------------------------------------------------\n // Cross-platform matches\n // -------------------------------------------------------------------------\n\n /**\n * List cross-platform matched event groups with inline aggregate stats.\n *\n * Maps to `GET /api/v1/matches`.\n */\n async listMatches(params?: MatchesParams): Promise<MatchGroupPage> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/matches${query}`;\n return await httpGet<MatchGroupPage>(url);\n }\n\n /**\n * Fetch a single match group by ID.\n *\n * Maps to `GET /api/v1/matches/:id`.\n */\n async getMatch(id: number): Promise<MatchGroup> {\n const url = `${this.endpoint}/api/v1/matches/${id}`;\n return await httpGet<MatchGroup>(url);\n }\n\n /**\n * List flattened market pairs across match groups (market-level granularity).\n *\n * Maps to `GET /api/v1/matches/markets`.\n */\n async listMatchMarkets(params?: MatchMarketParams): Promise<MatchMarketPage> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/matches/markets${query}`;\n return await httpGet<MatchMarketPage>(url);\n }\n\n // -------------------------------------------------------------------------\n // Trades by wallet\n // -------------------------------------------------------------------------\n\n /** Maps to `GET /api/v1/trades?source=...&wallet=...`. */\n async listTrades(\n params: ListTradesParams,\n ): Promise<PredictPage<PredictTrade>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/trades${query}`;\n return await httpGet<PredictPage<PredictTrade>>(url);\n }\n\n /** Maps to `GET /api/v1/trades?kalshi_user=...&polymarket_user=...`. */\n async listTradesMulti(\n params: ListTradesMultiParams,\n ): Promise<PredictPage<PredictTrade>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/trades${query}`;\n return await httpGet<PredictPage<PredictTrade>>(url);\n }\n\n // -------------------------------------------------------------------------\n // Withdraw\n // -------------------------------------------------------------------------\n\n /** Maps to `POST /api/v1/withdraw/build`. */\n async withdrawBuild(\n body: WithdrawBuildRequest,\n ): Promise<WithdrawBuildResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/build`;\n return await httpPost<WithdrawBuildResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/withdraw/submit`. */\n async withdrawSubmit(\n body: WithdrawSubmitRequest,\n ): Promise<WithdrawSubmitResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/submit`;\n return await httpPost<WithdrawSubmitResponse>(url, body);\n }\n\n /** Maps to `GET /api/v1/withdraw/status?tx_hash=...&source=...`. */\n async withdrawStatus(\n txHash: string,\n source: ProviderSource,\n ): Promise<WithdrawStatusResponse> {\n const query = buildQuery({ tx_hash: txHash, source });\n const url = `${this.endpoint}/api/v1/withdraw/status${query}`;\n return await httpGet<WithdrawStatusResponse>(url);\n }\n\n // -------------------------------------------------------------------------\n // Deposit (native USDC → USDC.e for Polymarket)\n // -------------------------------------------------------------------------\n\n /**\n * Build unsigned deposit transactions (approve + Uniswap V3 swap).\n *\n * The server checks the Safe's USDC.e balance and returns only\n * the transactions needed to cover the shortfall.\n *\n * Maps to `POST /api/v1/deposit/polymarket/build`.\n */\n async depositBuild(body: DepositBuildRequest): Promise<DepositBuildResponse> {\n const url = `${this.endpoint}/api/v1/deposit/polymarket/build`;\n return await httpPost<DepositBuildResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/deposit/polymarket/submit`. */\n async depositSubmit(\n body: DepositSubmitRequest,\n ): Promise<DepositSubmitResponse> {\n const url = `${this.endpoint}/api/v1/deposit/polymarket/submit`;\n return await httpPost<DepositSubmitResponse>(url, body);\n }\n\n /** Maps to `GET /api/v1/deposit/polymarket/status?tx_hash=...&source=...`. */\n async depositStatus(\n txHash: string,\n source: ProviderSource,\n ): Promise<DepositStatusResponse> {\n const query = buildQuery({ tx_hash: txHash, source });\n const url = `${this.endpoint}/api/v1/deposit/polymarket/status${query}`;\n return await httpGet<DepositStatusResponse>(url);\n }\n\n /**\n * Get multi-chain deposit addresses for a Polymarket Safe wallet via Bridge API.\n *\n * Maps to `GET /api/v1/deposit/polymarket/addresses?safe_address=...`.\n */\n async getPolymarketDepositAddresses(\n safeAddress: string,\n ): Promise<PolymarketDepositAddresses> {\n const query = buildQuery({ safe_address: safeAddress });\n const url = `${this.endpoint}/api/v1/deposit/polymarket/addresses${query}`;\n return await httpGet<PolymarketDepositAddresses>(url);\n }\n\n /**\n * List the Polymarket Bridge supported (chain, token) tuples along with\n * the per-asset minimum USD deposit amount.\n *\n * The list is the same for every caller; backend caches it for 15 minutes.\n *\n * Maps to `GET /api/v1/deposit/polymarket/supported-assets`.\n */\n async getPolymarketSupportedAssets(): Promise<PolymarketSupportedAsset[]> {\n const url = `${this.endpoint}/api/v1/deposit/polymarket/supported-assets`;\n const data = await httpGet<PolymarketSupportedAssetsResponse>(url);\n return data.supportedAssets ?? [];\n }\n\n // -------------------------------------------------------------------------\n // Polymarket Relayer Withdraw\n // -------------------------------------------------------------------------\n\n /** Maps to `POST /api/v1/withdraw/polymarket/quote`. */\n async quotePolymarketWithdraw(\n body: PolymarketWithdrawQuoteRequest,\n ): Promise<PolymarketWithdrawQuoteResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/quote`;\n return await httpPost<PolymarketWithdrawQuoteResponse>(url, body);\n }\n\n /**\n * Prepare a Polymarket withdrawal by obtaining a Bridge deposit address.\n *\n * Maps to `POST /api/v1/withdraw/polymarket/prepare`.\n */\n async preparePolymarketWithdraw(\n body: PolymarketWithdrawPrepareRequest,\n ): Promise<PolymarketWithdrawPrepareResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/prepare`;\n return await httpPost<PolymarketWithdrawPrepareResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/withdraw/polymarket/build-relay`. */\n async buildPolymarketWithdrawRelay(\n body: PolymarketWithdrawRelayBuildRequest,\n ): Promise<PolymarketWithdrawRelayBuildResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/build-relay`;\n return await httpPost<PolymarketWithdrawRelayBuildResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/withdraw/polymarket/submit-relay`. */\n async submitPolymarketWithdrawRelay(\n body: PolymarketWithdrawRelaySubmitRequest,\n ): Promise<PolymarketWithdrawRelaySubmitResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/submit-relay`;\n return await httpPost<PolymarketWithdrawRelaySubmitResponse>(url, body);\n }\n\n /** Maps to `GET /api/v1/withdraw/polymarket/status`. */\n async getPolymarketWithdrawStatus(params: {\n bridge_address?: string;\n transaction_id?: string;\n }): Promise<PolymarketWithdrawBridgeStatusResponse> {\n const query = buildQuery(params);\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/status${query}`;\n return await httpGet<PolymarketWithdrawBridgeStatusResponse>(url);\n }\n\n /**\n * Execute a gasless USDC.e withdrawal from a Polymarket Safe wallet via Relayer.\n *\n * Maps to `POST /api/v1/withdraw/polymarket/execute`.\n */\n async executePolymarketWithdraw(\n body: PolymarketWithdrawRequest,\n ): Promise<PolymarketWithdrawResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/execute`;\n return await httpPost<PolymarketWithdrawResponse>(url, body);\n }\n\n // -------------------------------------------------------------------------\n // Redeem (resolved market token redemption)\n // -------------------------------------------------------------------------\n\n /**\n * Prepare the signing payload for a Polymarket redeem transaction.\n * The frontend must sign the returned Safe hash or deposit-wallet typed data\n * and pass the signature to `redeemPolymarket`.\n *\n * Maps to `POST /api/v1/redeem/polymarket/prepare`.\n */\n async prepareRedeemPolymarket(\n body: PolymarketRedeemPrepareInput,\n ): Promise<PolymarketRedeemPrepareResponse> {\n const url = `${this.endpoint}/api/v1/redeem/polymarket/prepare`;\n return await httpPost<PolymarketRedeemPrepareResponse>(url, body);\n }\n\n /**\n * Redeem tokens from a resolved Polymarket market via gasless Relayer.\n * Requires a valid signature for the payload returned by the prepare step.\n *\n * Maps to `POST /api/v1/redeem/polymarket`.\n */\n async redeemPolymarket(\n body: PolymarketRedeemInput,\n ): Promise<PolymarketRedeemResponse> {\n const url = `${this.endpoint}/api/v1/redeem/polymarket`;\n return await httpPost<PolymarketRedeemResponse>(url, body);\n }\n}\n\n/**\n * Factory function for `PredictClient`.\n *\n * @param endpoint - Base URL of the prediction-server, without a trailing slash.\n */\nexport function createPredictClient(\n endpoint: string,\n options?: PredictClientOptions,\n): PredictClient {\n return new PredictClient(endpoint, options);\n}\n\nasync function parseMarketDataResponseBody(\n response: Response,\n): Promise<unknown> {\n const text = await response.text().catch(() => \"\");\n if (!text) return undefined;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/**\n * PredictWsClient — WebSocket client for prediction-server real-time data.\n *\n * Connects to `GET /api/v1/ws` (RFC 6455) and supports three channels:\n * `orderbook`, `prices`, and `trades`.\n *\n * Features:\n * - Auto-reconnect with exponential backoff\n * - Application-level ping/pong keepalive\n * - Subscription state tracking with automatic restore after reconnect\n * - Event-emitter pattern for typed message dispatch\n */\nimport type {\n WsChannel,\n WsChannelEvent,\n WsClientMessage,\n WsConnectionStatus,\n WsDataMessage,\n WsErrorCode,\n WsOrderbookEvent,\n WsPriceEvent,\n WsTradeEvent,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\n/** Configuration for `PredictWsClient`. */\nexport interface PredictWsClientConfig {\n /** Full WebSocket URL, e.g. `\"wss://api.example.com/api/v1/ws\"`. */\n wsUrl: string;\n /** Connect immediately on construction. Default: `true`. */\n autoConnect?: boolean;\n /** Reconnect automatically on unexpected close. Default: `true`. */\n autoReconnect?: boolean;\n /** Base delay (ms) for exponential backoff. Default: `1000`. */\n reconnectIntervalBase?: number;\n /** Maximum reconnect delay (ms). Default: `30000`. */\n reconnectMaxInterval?: number;\n /** Interval (ms) between application-level pings. Default: `30000`. */\n pingInterval?: number;\n /**\n * How long (ms) to wait for a pong after sending a ping before\n * considering the connection dead. Default: `10000`.\n * Must be less than `pingInterval`.\n */\n pongTimeout?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_RECONNECT_BASE = 1000;\nconst DEFAULT_RECONNECT_MAX = 30000;\nconst DEFAULT_PING_INTERVAL = 20000;\nconst DEFAULT_PONG_TIMEOUT = 10000;\n\n/**\n * Maximum serialized byte size for a single subscribe/unsubscribe frame.\n *\n * The server enforces a read limit (4096 bytes) and closes the connection\n * with code 1009 (\"message too big\") on any frame that exceeds it. A page\n * subscribing to hundreds of market slugs at once would otherwise produce a\n * single oversized frame, get disconnected, and loop forever on reconnect\n * (restoreSubscriptions resends the same oversized frame). We chunk slugs so\n * every frame stays comfortably under the server limit.\n */\nconst MAX_SUBSCRIPTION_FRAME_BYTES = 3500;\n\n// ---------------------------------------------------------------------------\n// Internal event-emitter types\n// ---------------------------------------------------------------------------\n\n/** UTF-8 byte length of a string (slugs are ASCII in practice). */\nfunction byteLength(str: string): number {\n if (typeof TextEncoder !== \"undefined\") {\n return new TextEncoder().encode(str).length;\n }\n // Fallback: assume single-byte chars (slugs are ASCII).\n return str.length;\n}\n\ntype EventCallback<T = unknown> = (data: T) => void;\n\ninterface EventListeners {\n connect: EventCallback<void>[];\n disconnect: EventCallback<{ code?: number; reason?: string }>[];\n reconnecting: EventCallback<{ attempt: number; delay: number }>[];\n error: EventCallback<{ code: WsErrorCode; message: string }>[];\n status: EventCallback<WsConnectionStatus>[];\n subscribed: EventCallback<{\n channels: WsChannel[];\n market_slugs: string[];\n }>[];\n orderbook: EventCallback<WsDataMessage<WsOrderbookEvent>>[];\n prices: EventCallback<WsDataMessage<WsPriceEvent>>[];\n trades: EventCallback<WsDataMessage<WsTradeEvent>>[];\n}\n\ntype WsEventType = keyof EventListeners;\n\n// ---------------------------------------------------------------------------\n// Subscription tracking\n// ---------------------------------------------------------------------------\n\ninterface SubscriptionState {\n /** channel → Set<market_slug> */\n channels: Map<WsChannel, Set<string>>;\n}\n\n// ---------------------------------------------------------------------------\n// PredictWsClient\n// ---------------------------------------------------------------------------\n\nexport class PredictWsClient {\n private ws: WebSocket | null = null;\n private readonly wsUrl: string;\n private readonly autoReconnect: boolean;\n private readonly reconnectBase: number;\n private readonly reconnectMax: number;\n private readonly pingMs: number;\n private readonly pongTimeoutMs: number;\n\n private status: WsConnectionStatus = \"disconnected\";\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n private pongTimer: ReturnType<typeof setTimeout> | null = null;\n private shouldReconnect = true;\n\n private listeners: EventListeners = {\n connect: [],\n disconnect: [],\n reconnecting: [],\n error: [],\n status: [],\n subscribed: [],\n orderbook: [],\n prices: [],\n trades: [],\n };\n\n private subs: SubscriptionState = {\n channels: new Map([\n [\"orderbook\", new Set()],\n [\"prices\", new Set()],\n [\"trades\", new Set()],\n ]),\n };\n\n constructor(config: PredictWsClientConfig) {\n this.wsUrl = config.wsUrl;\n this.autoReconnect = config.autoReconnect ?? true;\n this.reconnectBase = config.reconnectIntervalBase ?? DEFAULT_RECONNECT_BASE;\n this.reconnectMax = config.reconnectMaxInterval ?? DEFAULT_RECONNECT_MAX;\n this.pingMs = config.pingInterval ?? DEFAULT_PING_INTERVAL;\n this.pongTimeoutMs = config.pongTimeout ?? DEFAULT_PONG_TIMEOUT;\n\n if (config.autoConnect !== false && typeof window !== \"undefined\") {\n this.connect();\n }\n }\n\n // -------------------------------------------------------------------------\n // Connection management\n // -------------------------------------------------------------------------\n\n connect(): void {\n if (typeof window === \"undefined\") return;\n if (\n this.ws &&\n (this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n this.shouldReconnect = true;\n this.setStatus(\"connecting\");\n\n try {\n this.ws = new WebSocket(this.wsUrl);\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.setStatus(\"connected\");\n this.emit(\"connect\", undefined);\n this.restoreSubscriptions();\n this.startPing();\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data as string);\n };\n\n this.ws.onerror = () => {\n // The close event fires immediately after, which handles reconnect.\n };\n\n this.ws.onclose = (event) => {\n this.stopPing();\n this.setStatus(\"disconnected\");\n this.emit(\"disconnect\", { code: event.code, reason: event.reason });\n if (this.shouldReconnect && this.autoReconnect) {\n this.scheduleReconnect();\n }\n };\n } catch {\n if (this.shouldReconnect && this.autoReconnect) {\n this.scheduleReconnect();\n }\n }\n }\n\n disconnect(): void {\n this.shouldReconnect = false;\n this.stopPing();\n this.clearReconnectTimer();\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n this.setStatus(\"disconnected\");\n }\n\n /** Disconnect and clear all subscription state and listeners. */\n destroy(): void {\n this.disconnect();\n for (const ch of this.subs.channels.values()) ch.clear();\n for (const key of Object.keys(this.listeners)) {\n (this.listeners[key as WsEventType] as unknown[]).length = 0;\n }\n }\n\n getStatus(): WsConnectionStatus {\n return this.status;\n }\n\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\n }\n\n // -------------------------------------------------------------------------\n // Subscription — low-level (multi-channel, multi-slug)\n // -------------------------------------------------------------------------\n\n /**\n * Subscribe to one or more channels for the given market slugs.\n * The server acknowledges with a `subscribed` message.\n */\n subscribe(channels: WsChannel[], marketSlugs: string[]): void {\n for (const ch of channels) {\n const set = this.subs.channels.get(ch)!;\n for (const slug of marketSlugs) set.add(slug);\n }\n this.sendChunkedSubscription(\"subscribe\", channels, marketSlugs);\n }\n\n /**\n * Unsubscribe from one or more channels for the given market slugs.\n */\n unsubscribe(channels: WsChannel[], marketSlugs: string[]): void {\n for (const ch of channels) {\n const set = this.subs.channels.get(ch)!;\n for (const slug of marketSlugs) set.delete(slug);\n }\n this.sendChunkedSubscription(\"unsubscribe\", channels, marketSlugs);\n }\n\n // -------------------------------------------------------------------------\n // Subscription — convenience (single channel)\n // -------------------------------------------------------------------------\n\n /**\n * Subscribe to price updates for the given slugs.\n * Returns an unsubscribe function.\n */\n subscribePrices(\n slugs: string[],\n onUpdate: (msg: WsDataMessage<WsPriceEvent>) => void,\n ): () => void {\n this.subscribe([\"prices\"], slugs);\n const off = this.on(\"prices\", onUpdate);\n return () => {\n off();\n this.unsubscribe([\"prices\"], slugs);\n };\n }\n\n /**\n * Subscribe to orderbook snapshots for the given slugs.\n * Returns an unsubscribe function.\n */\n subscribeOrderbook(\n slugs: string[],\n onUpdate: (msg: WsDataMessage<WsOrderbookEvent>) => void,\n ): () => void {\n this.subscribe([\"orderbook\"], slugs);\n const off = this.on(\"orderbook\", onUpdate);\n return () => {\n off();\n this.unsubscribe([\"orderbook\"], slugs);\n };\n }\n\n /**\n * Subscribe to trade events for the given slugs.\n * Returns an unsubscribe function.\n */\n subscribeTrades(\n slugs: string[],\n onUpdate: (msg: WsDataMessage<WsTradeEvent>) => void,\n ): () => void {\n this.subscribe([\"trades\"], slugs);\n const off = this.on(\"trades\", onUpdate);\n return () => {\n off();\n this.unsubscribe([\"trades\"], slugs);\n };\n }\n\n // -------------------------------------------------------------------------\n // Status observation\n // -------------------------------------------------------------------------\n\n /** Register a callback for connection status changes. Returns unsubscribe. */\n onStatusChange(cb: (status: WsConnectionStatus) => void): () => void {\n return this.on(\"status\", cb);\n }\n\n /** Register a callback for server-sent errors. Returns unsubscribe. */\n onError(\n cb: (err: { code: WsErrorCode; message: string }) => void,\n ): () => void {\n return this.on(\"error\", cb);\n }\n\n // -------------------------------------------------------------------------\n // Event emitter\n // -------------------------------------------------------------------------\n\n on<T extends WsEventType>(\n event: T,\n callback: EventListeners[T][number],\n ): () => void {\n const list = this.listeners[event] as EventCallback<unknown>[];\n list.push(callback as EventCallback<unknown>);\n return () => this.off(event, callback);\n }\n\n off<T extends WsEventType>(\n event: T,\n callback: EventListeners[T][number],\n ): void {\n const list = this.listeners[event] as EventCallback<unknown>[];\n const idx = list.indexOf(callback as EventCallback<unknown>);\n if (idx !== -1) list.splice(idx, 1);\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n private emit<T extends WsEventType>(\n event: T,\n data: Parameters<EventListeners[T][number]>[0],\n ): void {\n const list = this.listeners[event] as EventCallback<typeof data>[];\n for (const cb of list) {\n try {\n cb(data);\n } catch (e) {\n console.error(`[PredictWsClient] Error in \"${event}\" listener:`, e);\n }\n }\n }\n\n private send(msg: WsClientMessage): boolean {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;\n try {\n this.ws.send(JSON.stringify(msg));\n return true;\n } catch {\n return false;\n }\n }\n\n private setStatus(next: WsConnectionStatus): void {\n if (this.status !== next) {\n this.status = next;\n this.emit(\"status\", next);\n }\n }\n\n private handleMessage(raw: string): void {\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return;\n }\n\n // Control messages (have `type`)\n if (msg.type) {\n switch (msg.type) {\n case \"pong\":\n this.clearPongTimer();\n return;\n case \"subscribed\":\n this.emit(\"subscribed\", {\n channels: msg.channels as WsChannel[],\n market_slugs: msg.market_slugs as string[],\n });\n return;\n case \"error\":\n this.emit(\"error\", {\n code: msg.code as WsErrorCode,\n message: msg.message as string,\n });\n return;\n }\n }\n\n // Data messages (have `channel` + `data`)\n if (msg.channel && msg.data) {\n const dataMsg = msg as unknown as WsDataMessage<WsChannelEvent>;\n switch (dataMsg.channel) {\n case \"orderbook\":\n this.emit(\"orderbook\", dataMsg as WsDataMessage<WsOrderbookEvent>);\n break;\n case \"prices\":\n this.emit(\"prices\", dataMsg as WsDataMessage<WsPriceEvent>);\n break;\n case \"trades\":\n this.emit(\"trades\", dataMsg as WsDataMessage<WsTradeEvent>);\n break;\n }\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) return;\n\n const delay = Math.min(\n this.reconnectBase * Math.pow(2, this.reconnectAttempts),\n this.reconnectMax,\n );\n\n this.setStatus(\"reconnecting\");\n this.emit(\"reconnecting\", { attempt: this.reconnectAttempts + 1, delay });\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.reconnectAttempts++;\n this.connect();\n }, delay);\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n private restoreSubscriptions(): void {\n for (const [channel, slugs] of this.subs.channels.entries()) {\n if (slugs.size > 0) {\n this.sendChunkedSubscription(\"subscribe\", [channel], Array.from(slugs));\n }\n }\n }\n\n /**\n * Send a subscribe/unsubscribe message, splitting `marketSlugs` across\n * multiple frames so no single frame exceeds the server read limit.\n */\n private sendChunkedSubscription(\n type: \"subscribe\" | \"unsubscribe\",\n channels: WsChannel[],\n marketSlugs: string[],\n ): void {\n if (marketSlugs.length === 0) {\n this.send({ type, channels, market_slugs: [] });\n return;\n }\n\n const envelopeBytes = byteLength(\n JSON.stringify({ type, channels, market_slugs: [] }),\n );\n const budget = MAX_SUBSCRIPTION_FRAME_BYTES - envelopeBytes;\n\n let chunk: string[] = [];\n let chunkBytes = 0;\n const flush = () => {\n if (chunk.length > 0) {\n this.send({ type, channels, market_slugs: chunk });\n chunk = [];\n chunkBytes = 0;\n }\n };\n\n for (const slug of marketSlugs) {\n // serialized slug plus a comma separator\n const slugBytes = byteLength(JSON.stringify(slug)) + 1;\n if (chunk.length > 0 && chunkBytes + slugBytes > budget) flush();\n chunk.push(slug);\n chunkBytes += slugBytes;\n }\n flush();\n }\n\n private startPing(): void {\n this.stopPing();\n this.pingTimer = setInterval(() => {\n this.send({ type: \"ping\" });\n this.armPongTimeout();\n }, this.pingMs);\n }\n\n private stopPing(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n this.clearPongTimer();\n }\n\n /**\n * Start a timer that fires if the server does not reply with pong\n * within `pongTimeoutMs`. On timeout the socket is closed so\n * the normal reconnect flow kicks in.\n */\n private armPongTimeout(): void {\n this.clearPongTimer();\n this.pongTimer = setTimeout(() => {\n this.pongTimer = null;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close(4000, \"pong timeout\");\n }\n }, this.pongTimeoutMs);\n }\n\n private clearPongTimer(): void {\n if (this.pongTimer) {\n clearTimeout(this.pongTimer);\n this.pongTimer = null;\n }\n }\n}\n\n/**\n * Factory function for `PredictWsClient`.\n *\n * @param config - WebSocket client configuration.\n */\nexport function createPredictWsClient(\n config: PredictWsClientConfig,\n): PredictWsClient {\n return new PredictWsClient(config);\n}\n","/**\n * Polymarket L2 HMAC-SHA256 signing utilities.\n *\n * Uses the Web Crypto API (available in all modern browsers and Node ≥18) to\n * avoid taking a dependency on Node.js `crypto` or any third-party library.\n *\n * References:\n * https://docs.polymarket.com/#authentication\n * https://github.com/Polymarket/clob-client/blob/main/src/headers/index.ts\n */\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Encode a string to a Uint8Array using UTF-8. */\nfunction encode(str: string): Uint8Array {\n return new TextEncoder().encode(str);\n}\n\n/** Decode a Uint8Array as a UTF-8 string. */\nfunction decode(buf: ArrayBuffer): string {\n return new TextDecoder().decode(buf);\n}\n\n/**\n * Convert a base64 or base64url string to a Uint8Array.\n * Normalises base64url (`-`, `_`, no padding) to standard base64 before decoding.\n */\nfunction base64ToBytes(b64: string): Uint8Array {\n let std = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n while (std.length % 4 !== 0) std += \"=\";\n const binary = atob(std);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/** Convert a Uint8Array to a base64 string. */\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n// ---------------------------------------------------------------------------\n// HMAC-SHA256\n// ---------------------------------------------------------------------------\n\n/**\n * Compute an HMAC-SHA256 signature using the Web Crypto API.\n *\n * @param secretBase64 - The signing secret encoded as base64.\n * @param message - The plaintext message to sign.\n * @returns The signature as a base64 string.\n */\nexport async function hmacSha256Base64(\n secretBase64: string,\n message: string,\n): Promise<string> {\n const keyBytes = base64ToBytes(secretBase64);\n const cryptoKey = await crypto.subtle.importKey(\n \"raw\",\n keyBytes.buffer as ArrayBuffer,\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const msgBytes = encode(message);\n const signature = await crypto.subtle.sign(\n \"HMAC\",\n cryptoKey,\n msgBytes.buffer as ArrayBuffer,\n );\n const b64 = bytesToBase64(new Uint8Array(signature));\n // Polymarket requires base64url encoding (keep trailing '=')\n return b64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\");\n}\n\n// ---------------------------------------------------------------------------\n// Polymarket L2 auth headers\n// ---------------------------------------------------------------------------\n\n/** HTTP method values accepted by Polymarket CLOB. */\nexport type HttpMethod = \"GET\" | \"DELETE\" | \"POST\" | \"PUT\";\n\nexport interface PolymarketL2HeadersInput {\n /** L2 API key (from credential exchange). */\n apiKey: string;\n /** L2 HMAC secret (base64-encoded). */\n secret: string;\n /** L2 passphrase. */\n passphrase: string;\n /** HTTP method of the request. */\n method: HttpMethod;\n /** Request path without host, e.g. \"/order\". */\n requestPath: string;\n /** Raw JSON request body string; empty string for GET/DELETE. */\n body?: string;\n}\n\nexport interface PolymarketL2Headers {\n POLY_ADDRESS: string;\n POLY_SIGNATURE: string;\n POLY_TIMESTAMP: string;\n POLY_API_KEY: string;\n POLY_PASSPHRASE: string;\n}\n\n/**\n * Build Polymarket L2 HMAC authentication headers for a CLOB API request.\n *\n * The signature is `HMAC-SHA256(secret, timestamp + method + requestPath + body)`.\n *\n * @param address - EVM wallet address (owner of the credentials).\n * @param input - Credential and request details.\n * @returns An object containing all required `POLY_*` headers.\n */\nexport async function buildPolymarketL2Headers(\n address: string,\n input: PolymarketL2HeadersInput,\n): Promise<PolymarketL2Headers> {\n const timestamp = Math.floor(Date.now() / 1000).toString();\n const body = input.body ?? \"\";\n const message = `${timestamp}${input.method}${input.requestPath}${body}`;\n\n const signature = await hmacSha256Base64(input.secret, message);\n\n return {\n POLY_ADDRESS: address,\n POLY_SIGNATURE: signature,\n POLY_TIMESTAMP: timestamp,\n POLY_API_KEY: input.apiKey,\n POLY_PASSPHRASE: input.passphrase,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Polymarket L1 auth (credential derivation)\n// ---------------------------------------------------------------------------\n\n/** EIP-712 domain used by Polymarket CLOB for L1 authentication. */\nexport const CLOB_AUTH_DOMAIN = {\n name: \"ClobAuthDomain\",\n version: \"1\",\n chainId: 137,\n} as const;\n\n/** EIP-712 types for the `ClobAuth` struct. */\nexport const CLOB_AUTH_TYPES = {\n ClobAuth: [\n { name: \"address\", type: \"address\" },\n { name: \"timestamp\", type: \"string\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"message\", type: \"string\" },\n ],\n} as const;\n\nexport interface BuildClobAuthMessageInput {\n /** EVM wallet address. */\n address: string;\n /** Unix seconds string. */\n timestamp: string;\n /** Credential nonce. Use `0` for a permanent / deterministic credential. */\n nonce: number;\n}\n\n/**\n * Build the EIP-712 typed data value for a `ClobAuth` message.\n * The resulting object is passed to `eth_signTypedData_v4`.\n */\nexport function buildClobAuthMessage(\n input: BuildClobAuthMessageInput,\n): Record<string, unknown> {\n return {\n address: input.address,\n timestamp: input.timestamp,\n nonce: input.nonce,\n message: \"This message attests that I control the given wallet\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// Credential exchange\n// ---------------------------------------------------------------------------\n\ntype ApiKeyCreds = { apiKey: string; secret: string; passphrase: string };\n\nfunction buildL1Headers(\n address: string,\n signature: string,\n timestamp: string,\n nonce: number,\n): Record<string, string> {\n return {\n POLY_ADDRESS: address,\n POLY_SIGNATURE: signature,\n POLY_TIMESTAMP: timestamp,\n POLY_NONCE: String(nonce),\n };\n}\n\n/**\n * Create or derive Polymarket L2 API credentials from an L1 EIP-712 signature.\n *\n * Polymarket exposes two endpoints:\n * - `POST /auth/api-key` — create new credentials (required for first-time wallets)\n * - `GET /auth/derive-api-key` — derive existing credentials\n *\n * This function tries to derive first; on failure it creates, matching the\n * official `createOrDeriveApiKey()` behaviour from `@polymarket/clob-client`.\n *\n * @returns `{ apiKey, secret, passphrase }`.\n */\nexport async function derivePolymarketApiKey(\n address: string,\n signature: string,\n timestamp: string,\n nonce: number,\n): Promise<ApiKeyCreds> {\n const headers = buildL1Headers(address, signature, timestamp, nonce);\n\n // Try deriving existing credentials first.\n const deriveRes = await fetch(\n `https://clob.polymarket.com/auth/derive-api-key?nonce=${nonce}`,\n { method: \"GET\", headers },\n );\n\n if (deriveRes.ok) {\n return deriveRes.json() as Promise<ApiKeyCreds>;\n }\n\n // Derive failed — wallet likely has no API key yet; create one.\n const createRes = await fetch(\"https://clob.polymarket.com/auth/api-key\", {\n method: \"POST\",\n headers,\n });\n\n if (createRes.ok) {\n return createRes.json() as Promise<ApiKeyCreds>;\n }\n\n const text = await createRes.text().catch(() => createRes.statusText);\n throw new Error(\n `Polymarket credential exchange failed (${createRes.status}): ${text}`,\n );\n}\n","/**\n * Polymarket CTF Exchange order construction utilities.\n *\n * Implements EIP-712 signing for `Order` structs on the CTF Exchange and\n * Neg-Risk CTF Exchange contracts (Polygon mainnet).\n *\n * References:\n * - Official docs (order creation):\n * https://docs.polymarket.com/trading/orders/create\n * - Official TS CLOB client (order builder / helpers):\n * https://github.com/Polymarket/clob-client/blob/main/src/order-builder/builder.ts\n * https://github.com/Polymarket/clob-client/blob/main/src/order-builder/helpers.ts\n * - Official Python CLOB client (order builder — has `get_market_order_amounts`):\n * https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/order_builder/builder.py\n *\n * Market order (FOK/FAK) precision limits — NOT documented in official docs,\n * enforced server-side and discovered via API error messages:\n * - makerAmount: max 2 decimal places (human-readable)\n * - takerAmount: max 4 decimal places (human-readable)\n * - GitHub issues tracking this undocumented constraint:\n * https://github.com/Polymarket/py-clob-client/issues/121\n * https://github.com/Polymarket/py-clob-client/issues/253\n * https://github.com/Polymarket/rs-clob-client/issues/261\n */\nimport type { CreateOrderInput, PolymarketTickSize } from \"../client/types\";\n\n// ---------------------------------------------------------------------------\n// Contract addresses (Polygon mainnet)\n// ---------------------------------------------------------------------------\n\n/** Polymarket CTF Exchange contract (standard markets). */\nexport const CTF_EXCHANGE_ADDRESS =\n \"0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E\" as const;\n\n/** Polymarket Neg-Risk CTF Exchange contract (neg-risk markets). */\nexport const NEG_RISK_CTF_EXCHANGE_ADDRESS =\n \"0xC5d563A36AE78145C45a50134d48A1215220f80a\" as const;\n\n/** USDC.e (Bridged USDC) on Polygon — the only collateral token on Polymarket. */\nexport const USDC_ADDRESS =\n \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\" as const;\n\n/** Chain ID for Polygon mainnet. */\nexport const POLYGON_CHAIN_ID = 137;\n\n// ---------------------------------------------------------------------------\n// EIP-712 domain and types\n// ---------------------------------------------------------------------------\n\n/**\n * Build the EIP-712 domain for the CTF Exchange.\n *\n * @param negRisk - When `true`, use the Neg-Risk exchange address.\n */\nexport function buildCtfExchangeDomain(negRisk = false) {\n return {\n name: \"Polymarket CTF Exchange\",\n version: \"1\",\n chainId: POLYGON_CHAIN_ID,\n verifyingContract: negRisk\n ? NEG_RISK_CTF_EXCHANGE_ADDRESS\n : CTF_EXCHANGE_ADDRESS,\n };\n}\n\n/** EIP-712 type definitions for the Polymarket `Order` struct. */\nexport const CTF_ORDER_TYPES = {\n Order: [\n { name: \"salt\", type: \"uint256\" },\n { name: \"maker\", type: \"address\" },\n { name: \"signer\", type: \"address\" },\n { name: \"taker\", type: \"address\" },\n { name: \"tokenId\", type: \"uint256\" },\n { name: \"makerAmount\", type: \"uint256\" },\n { name: \"takerAmount\", type: \"uint256\" },\n { name: \"expiration\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"feeRateBps\", type: \"uint256\" },\n { name: \"side\", type: \"uint8\" },\n { name: \"signatureType\", type: \"uint8\" },\n ],\n} as const;\n\n// ---------------------------------------------------------------------------\n// Order type constants\n// ---------------------------------------------------------------------------\n\n/** Order type enum matching CTFExchange.sol. */\nexport const ORDER_TYPE = {\n GTC: 0, // Good-Till-Cancelled\n FOK: 1, // Fill-Or-Kill\n GTD: 2, // Good-Till-Date\n FAK: 3, // Fill-And-Kill\n} as const;\n\n/** Side enum matching CTFExchange.sol (0 = BUY, 1 = SELL). */\nexport const SIDE = { BUY: 0, SELL: 1 } as const;\n\n// ---------------------------------------------------------------------------\n// Amount calculation — matches official Polymarket CLOB client rounding\n// ---------------------------------------------------------------------------\n//\n// Terminology:\n// maker = the order creator (you). Provides `makerAmount` of an asset.\n// taker = the counterparty. Provides `takerAmount` of an asset.\n//\n// BUY: makerAmount = USDC spent, takerAmount = shares received\n// SELL: makerAmount = shares sold, takerAmount = USDC received\n//\n// Implied price = USDC amount / shares amount\n// BUY: price = makerAmount / takerAmount\n// SELL: price = takerAmount / makerAmount\n//\n// Order types and amount computation:\n// ┌──────────────┬─────────────────────────────┬──────────────────────────────┐\n// │ │ Market (FOK / FAK) │ Limit (GTC / GTD) │\n// ├──────────────┼─────────────────────────────┼──────────────────────────────┤\n// │ BUY input │ size = USDC to spend │ size = shares to buy │\n// │ BUY maker │ floor(size, 2) → USDC │ round(size × price, amt) │\n// │ BUY taker │ floor(USDC/price, 4) →shares│ round(size, sz) → shares │\n// ├──────────────┼─────────────────────────────┼──────────────────────────────┤\n// │ SELL input │ size = shares to sell │ size = shares to sell │\n// │ SELL maker │ floor(size, 2) → shares │ floor(size, sz) → shares │\n// │ SELL taker │ ceil(shares×price, 4)→ USDC │ round(size × price, amt) │\n// └──────────────┴─────────────────────────────┴──────────────────────────────┘\n// (sz = rc.size, amt = rc.amount; market orders cap at 2 / 4 decimals)\n//\n// ---------------------------------------------------------------------------\n\n/**\n * Rounding configuration per tick size, aligned with the official\n * Polymarket CLOB client (`@polymarket/clob-client`).\n *\n * Each field is the **max decimal places** allowed for that dimension:\n * - `price`: price per share (e.g. 0.86 → 2 decimals for tick \"0.01\")\n * - `size`: number of shares (e.g. 11.63 → 2 decimals for tick \"0.01\")\n * - `amount`: total cost = size × price (e.g. 10.0018 → 4 decimals)\n *\n * Key invariant: `amount = size + price` decimal places.\n * This guarantees `round(size × price, amount) / round(size, size)` has\n * exactly `price` decimal places → the implied price is tick-aligned.\n *\n * NOTE: `size` is always 2 across all tick sizes in the official client.\n * The `amount` field equals `size + price` (e.g. \"0.001\": 2 + 3 = 5).\n *\n * Example with tick \"0.01\": { size: 2, price: 2, amount: 4 }\n * 11.63 (2dp) × 0.86 (2dp) = 10.0018 (4dp)\n * 10.0018 / 11.63 = 0.86 ← exactly 2dp, valid tick ✓\n *\n * @see https://github.com/Polymarket/clob-client/blob/main/src/order-builder/helpers.ts\n */\nconst ROUNDING_CONFIG: Record<\n string,\n { size: number; price: number; amount: number }\n> = {\n \"0.1\": { size: 2, price: 1, amount: 3 },\n \"0.01\": { size: 2, price: 2, amount: 4 },\n \"0.005\": { size: 2, price: 3, amount: 5 },\n \"0.0025\": { size: 2, price: 4, amount: 6 },\n \"0.001\": { size: 2, price: 3, amount: 5 },\n \"0.0001\": { size: 2, price: 4, amount: 6 },\n};\n\nconst DEFAULT_ROUNDING = { size: 2, price: 2, amount: 4 };\n\n/**\n * Normalise a raw `minimum_tick_size` value (number or string, e.g. from the\n * `/tick-size` endpoint) to one of the tick sizes known to the CLOB clients'\n * rounding configs.\n *\n * The official `@polymarket/clob-client-v2` OrderBuilder indexes its\n * `ROUNDING_CONFIG` by the tick-size string without any fallback — an unknown\n * key crashes order building with \"Cannot read properties of undefined\n * (reading 'price')\". Funnelling every caller through this helper guarantees\n * we only ever hand the builder a supported tick size (unknown values fall\n * back to the CLOB-default \"0.01\").\n */\nexport function normalizePolymarketTickSize(\n raw: number | string | null | undefined,\n): PolymarketTickSize {\n const value = typeof raw === \"string\" ? parseFloat(raw) : raw;\n if (value == null || !Number.isFinite(value) || value <= 0) return \"0.01\";\n for (const tick of Object.keys(ROUNDING_CONFIG) as PolymarketTickSize[]) {\n if (Math.abs(parseFloat(tick) - value) < 1e-9) return tick;\n }\n return \"0.01\";\n}\n\n/**\n * Round a number to `d` decimal places (round-half-away-from-zero via toFixed).\n * Mirrors the official `decimalPlaces()` / `roundNormal()` helpers.\n */\nfunction decimalPlaces(n: number, d: number): number {\n return parseFloat(n.toFixed(d));\n}\n\n/**\n * Floor a number to `d` decimal places (never rounds up).\n * Used for SELL size to prevent exceeding actual holdings.\n */\nfunction floorDecimalPlaces(n: number, d: number): number {\n const factor = 10 ** d;\n return Math.floor(n * factor) / factor;\n}\n\n/**\n * Ceil a number to `d` decimal places (never rounds down).\n * Used for market SELL taker amount to avoid under-quoting.\n */\nfunction ceilDecimalPlaces(n: number, d: number): number {\n const factor = 10 ** d;\n return Math.ceil(n * factor) / factor;\n}\n\n/**\n * Count the number of decimal places in a number's string representation.\n */\nfunction countDecimalPlaces(n: number): number {\n const s = n.toString();\n const dot = s.indexOf(\".\");\n if (dot === -1) return 0;\n return s.length - dot - 1;\n}\n\n/**\n * Convert a human-readable amount to micro-USDC (6 decimals).\n * Polymarket contracts use USDC.e with 6 decimals.\n */\nfunction toMicroUsdc(amount: number): bigint {\n return BigInt(Math.round(amount * 1_000_000));\n}\n\n/**\n * Normalise a token ID to a decimal string.\n * Polymarket's CLOB API requires decimal representation, but market metadata\n * may store token IDs as hex strings (0x-prefixed).\n */\nfunction normalizeTokenId(tokenId: string): string {\n if (tokenId.startsWith(\"0x\") || tokenId.startsWith(\"0X\")) {\n return BigInt(tokenId).toString(10);\n }\n return tokenId;\n}\n\n// ---------------------------------------------------------------------------\n// Order message builder\n// ---------------------------------------------------------------------------\n\nexport interface BuildOrderMessageInput extends CreateOrderInput {\n /** Signer / owner address. */\n signerAddress: string;\n /** Signature type (0 = EOA, 1 = Magic, 2 = Poly Proxy). */\n signatureType: 0 | 1 | 2;\n /** Fee rate in basis points from the CLOB fee-rate endpoint. Defaults to \"0\". */\n feeRateBps?: string;\n}\n\nexport interface OrderMessage {\n salt: string;\n /** Funder address that holds the collateral (USDC.e or outcome tokens). */\n maker: string;\n /** Signer address that signs the EIP-712 order. */\n signer: string;\n /** Taker address (0x0 = any counterparty). */\n taker: string;\n tokenId: string;\n /**\n * Amount the maker provides (micro-USDC, 6 decimals).\n * BUY: USDC spent. SELL: shares sold.\n */\n makerAmount: string;\n /**\n * Amount the taker provides (micro-USDC, 6 decimals).\n * BUY: shares received. SELL: USDC received.\n */\n takerAmount: string;\n expiration: string;\n nonce: string;\n feeRateBps: string;\n /** 0 = BUY, 1 = SELL (matches CTFExchange.sol). */\n side: number;\n /** 0 = EOA, 1 = POLY_PROXY, 2 = POLY_GNOSIS_SAFE. */\n signatureType: number;\n}\n\n/**\n * Polymarket API precision limits for market orders (FOK / FAK).\n *\n * With the corrected ROUNDING_CONFIG (size=2 for all tick sizes, matching the\n * official CLOB client), `rc.size` already equals MARKET_MAKER_MAX_DECIMALS.\n * These constants are kept as safety guards — if ROUNDING_CONFIG is ever\n * changed, `Math.min(rc.size, MARKET_MAKER_MAX_DECIMALS)` will still enforce\n * the API limit.\n *\n * The constraint is NOT documented in the official Polymarket docs — it is\n * enforced server-side and surfaced only via the error message:\n * \"invalid amounts, the market buy orders maker amount supports a max\n * accuracy of 2 decimals, taker amount a max of 4 decimals\"\n *\n * @see https://github.com/Polymarket/py-clob-client/issues/121\n * @see https://github.com/Polymarket/py-clob-client/issues/253\n * @see https://github.com/Polymarket/rs-clob-client/issues/261\n */\nconst MARKET_MAKER_MAX_DECIMALS = 2;\nconst MARKET_TAKER_MAX_DECIMALS = 4;\n\n/**\n * Compute makerAmount / takerAmount for a **market order** (FOK / FAK).\n *\n * Follows the official Polymarket Python CLOB client `get_market_order_amounts`.\n * The official docs describe market order input semantics here:\n * https://docs.polymarket.com/trading/orders/create#market-orders\n * - BUY: \"specify the dollar amount you want to spend\"\n * - SELL: \"specify the number of shares you want to sell\"\n *\n * Calculation (BUY):\n * makerAmount (USDC) = floor(size, min(rc.size, 2)) → ≤ 2 decimals\n * takerAmount (shares) = floor(makerAmt / price, min(rc.amount, 4)) → ≤ 4 decimals\n *\n * Calculation (SELL):\n * makerAmount (shares) = floor(size, min(rc.size, 2)) → ≤ 2 decimals\n * takerAmount (USDC) = ceil(makerAmt × price, min(rc.amount, 4)) → ≤ 4 decimals\n *\n * @see https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/order_builder/builder.py\n * @see https://github.com/Polymarket/py-clob-client/issues/121 (FOK decimal error)\n * @see https://github.com/Polymarket/py-clob-client/issues/253 (amount decimal bug)\n */\nfunction getMarketOrderAmounts(\n side: number,\n size: number,\n price: number,\n rc: { size: number; price: number; amount: number },\n): { makerAmount: string; takerAmount: string } {\n const rawPrice = decimalPlaces(price, rc.price);\n const makerDecimals = Math.min(rc.size, MARKET_MAKER_MAX_DECIMALS);\n const takerDecimals = Math.min(rc.amount, MARKET_TAKER_MAX_DECIMALS);\n\n if (side === SIDE.BUY) {\n const rawMakerAmt = floorDecimalPlaces(size, makerDecimals);\n let rawTakerAmt = rawMakerAmt / rawPrice;\n if (countDecimalPlaces(rawTakerAmt) > takerDecimals) {\n rawTakerAmt = floorDecimalPlaces(rawTakerAmt, takerDecimals);\n }\n return {\n makerAmount: toMicroUsdc(rawMakerAmt).toString(),\n takerAmount: toMicroUsdc(rawTakerAmt).toString(),\n };\n }\n\n // SELL\n const rawMakerAmt = floorDecimalPlaces(size, makerDecimals);\n let rawTakerAmt = rawMakerAmt * rawPrice;\n if (countDecimalPlaces(rawTakerAmt) > takerDecimals) {\n rawTakerAmt = ceilDecimalPlaces(rawTakerAmt, takerDecimals);\n }\n return {\n makerAmount: toMicroUsdc(rawMakerAmt).toString(),\n takerAmount: toMicroUsdc(rawTakerAmt).toString(),\n };\n}\n\n/**\n * Compute makerAmount / takerAmount for a **limit order** (GTC / GTD).\n *\n * `size` is always shares (for both BUY and SELL).\n *\n * Amount rounding follows the official Polymarket CLOB client to guarantee\n * that `makerAmount / takerAmount` produces a tick-aligned price.\n * The key invariant: `amountDecimals = sizeDecimals + priceDecimals`, so\n * `round(size × price, amountDecimals) / round(size, sizeDecimals)` has\n * exactly `priceDecimals` decimal places.\n *\n * Since `rc.size` is always 2 in the official ROUNDING_CONFIG, limit orders\n * naturally satisfy the same 2-decimal makerAmount constraint as market orders.\n *\n * BUY: makerAmount = round(size × price, rc.amount) → USDC\n * takerAmount = round(size, rc.size) → shares\n * SELL: makerAmount = floor(size, rc.size) → shares (floor to avoid overselling)\n * takerAmount = round(size × price, rc.amount) → USDC\n */\nfunction getLimitOrderAmounts(\n side: number,\n size: number,\n price: number,\n rc: { size: number; price: number; amount: number },\n): { makerAmount: string; takerAmount: string } {\n const rawPrice = decimalPlaces(price, rc.price);\n\n const rawSize =\n side === SIDE.SELL\n ? floorDecimalPlaces(size, rc.size)\n : decimalPlaces(size, rc.size);\n const sizeInMicro = toMicroUsdc(rawSize);\n const rawAmount = decimalPlaces(rawSize * rawPrice, rc.amount);\n const amountInMicro = toMicroUsdc(rawAmount);\n\n const makerAmount =\n side === SIDE.BUY ? amountInMicro.toString() : sizeInMicro.toString();\n const takerAmount =\n side === SIDE.BUY ? sizeInMicro.toString() : amountInMicro.toString();\n\n return { makerAmount, takerAmount };\n}\n\n/**\n * Build the EIP-712 typed data value for a Polymarket order.\n *\n * All amounts are in micro-USDC / micro-shares (1 unit = 1 000 000).\n *\n * Maker/taker semantics:\n * BUY: makerAmount = USDC spent, takerAmount = shares received\n * SELL: makerAmount = shares sold, takerAmount = USDC received\n *\n * Input `size` semantics depend on order type:\n * Market BUY (FOK/FAK): size = USDC dollar amount to spend\n * Market SELL (FOK/FAK): size = number of shares to sell\n * Limit BUY (GTC/GTD): size = number of shares to buy\n * Limit SELL (GTC/GTD): size = number of shares to sell\n *\n * Precision (rc.size is always 2 in the official ROUNDING_CONFIG):\n * Market orders → makerAmount ≤ 2 decimals, takerAmount ≤ 4 decimals\n * Limit orders → makerAmount ≤ rc.size (2) decimals, takerAmount ≤ rc.amount\n *\n * Rounding direction:\n * Market BUY: maker = floor (spend less), taker = floor (fewer shares)\n * Market SELL: maker = floor (sell fewer), taker = ceil (receive more)\n * Limit BUY: size = round (tick-align), amount = round\n * Limit SELL: size = floor (avoid overselling), amount = round\n */\nexport function buildOrderMessage(input: BuildOrderMessageInput): OrderMessage {\n const side = input.side === \"BUY\" ? SIDE.BUY : SIDE.SELL;\n const rc = ROUNDING_CONFIG[input.tickSize] ?? DEFAULT_ROUNDING;\n\n const isMarketOrder = input.orderType === \"FOK\" || input.orderType === \"FAK\";\n\n const { makerAmount, takerAmount } = isMarketOrder\n ? getMarketOrderAmounts(side, input.size, input.price, rc)\n : getLimitOrderAmounts(side, input.size, input.price, rc);\n\n const maker = input.funderAddress ?? input.signerAddress;\n\n return {\n salt: Math.floor(Math.random() * 1e15).toString(),\n maker,\n signer: input.signerAddress,\n taker: \"0x0000000000000000000000000000000000000000\",\n tokenId: normalizeTokenId(input.tokenId),\n makerAmount,\n takerAmount,\n expiration: String(input.expiration ?? 0),\n nonce: \"0\",\n feeRateBps: input.feeRateBps ?? \"0\",\n side,\n signatureType: input.signatureType,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Signed order payload builder\n// ---------------------------------------------------------------------------\n\nexport interface SignedOrder extends OrderMessage {\n signature: string;\n orderType: string;\n}\n\n/**\n * Attach a signature (and optional orderType) to an already-built order message\n * to produce the final payload for the Polymarket CLOB.\n *\n * IMPORTANT: always pass the SAME `OrderMessage` that was used for EIP-712\n * signing. Do NOT rebuild it — `buildOrderMessage` generates a random salt\n * each time, so a second call would produce a different message and the\n * signature would be invalid.\n */\nexport function buildSignedOrder(\n orderMessage: OrderMessage,\n signature: string,\n orderType?: string,\n): SignedOrder {\n return {\n ...orderMessage,\n signature,\n orderType: orderType ?? \"GTC\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// CLOB payload builder (orderToJson equivalent)\n// ---------------------------------------------------------------------------\n\n/**\n * CLOB order payload as expected by Polymarket's `POST /order` endpoint.\n *\n * Key format differences from the EIP-712 `OrderMessage`:\n * - `salt` is a **number** (not a string)\n * - `side` is `\"BUY\"` / `\"SELL\"` (not 0 / 1)\n * - `deferExec` is required (defaults to `false`)\n *\n * @see https://github.com/Polymarket/clob-client/blob/main/src/utilities.ts\n */\nexport interface ClobOrderPayload {\n order: {\n salt: number;\n maker: string;\n signer: string;\n taker: string;\n tokenId: string;\n makerAmount: string;\n takerAmount: string;\n expiration: string;\n nonce: string;\n feeRateBps: string;\n side: \"BUY\" | \"SELL\";\n signatureType: number;\n signature: string;\n };\n owner: string;\n orderType: string;\n deferExec: boolean;\n}\n\n/**\n * Convert a `SignedOrder` into the JSON payload format that Polymarket's\n * CLOB API expects. Mirrors the official `orderToJson()` utility.\n */\nexport function buildClobPayload(\n signedOrder: SignedOrder,\n owner: string,\n): ClobOrderPayload {\n const { orderType: ot, ...order } = signedOrder;\n return {\n order: {\n ...order,\n salt: parseInt(order.salt, 10),\n side: order.side === SIDE.BUY ? \"BUY\" : \"SELL\",\n },\n owner,\n orderType: ot ?? \"GTC\",\n deferExec: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Precision helper for UI\n// ---------------------------------------------------------------------------\n\n/**\n * Return the maximum number of decimal places allowed for share quantities\n * on Polymarket, given the market's tick size.\n *\n * In the official CLOB client, `ROUNDING_CONFIG[tickSize].size` is always 2.\n * This function encapsulates that lookup so UI layers don't need to know about\n * the internal rounding config.\n */\nexport function getPolymarketSharesPrecision(tickSize: string): number {\n const rc = ROUNDING_CONFIG[tickSize] ?? DEFAULT_ROUNDING;\n return rc.size;\n}\n"]}
1
+ {"version":3,"sources":["../src/hooks/predict/events.params.ts","../src/hooks/predict/market.params.ts","../src/hooks/predict/matches.params.ts","../src/hooks/predict/matchMarkets.params.ts","../src/hooks/predict/sports.params.ts","../src/hooks/predict/esports.params.ts","../src/hooks/predict/sports-routing.params.ts","../src/hooks/predict/sports-match-detail.params.ts","../src/hooks/predict/search.params.ts","../src/client/types.ts","../src/client/client.ts","../src/client/ws.ts","../src/utils/polymarket-hmac.ts","../src/utils/polymarket-order.ts"],"names":["rawMakerAmt","rawTakerAmt"],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * Server-safe pure functions for events query parameters.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictClient,\n PredictEvent,\n EventSortField,\n EventStatus,\n ListEventsParams,\n PredictPage,\n ProviderSource,\n} from \"../../client\";\n\nexport type { ProviderSource };\n\n/** Default page size for list queries. */\nexport const DEFAULT_PAGE_SIZE = 24;\n\n/**\n * Selection emitted by a categories/tag selector widget.\n * Duplicated here to avoid pulling in UI component barrel into server-only bundles.\n */\nexport interface TagSlugSelection {\n categorySlug: string | null;\n tagSlug: string | null;\n}\n\n/**\n * Resolve a `TagSlugSelection` to a single `tag_slug` string for the API.\n */\nexport function resolveTagSlug(\n selection: TagSlugSelection | null | undefined,\n): string | undefined {\n if (!selection) return undefined;\n return selection.tagSlug ?? selection.categorySlug ?? undefined;\n}\n\n/**\n * Input accepted by {@link resolveEventsParams}. All fields optional;\n * defaults match the client-side `useInfiniteEvents` hook's initial state.\n */\nexport interface ResolveEventsParamsInput {\n tagSlugSelection?: TagSlugSelection | null;\n limit?: number;\n status?: EventStatus;\n sort_by?: EventSortField;\n sort_asc?: boolean;\n source?: ProviderSource;\n with_markets?: boolean;\n /**\n * Minimum total volume in USD (numeric string or number).\n * Converted to `min_volume` in the API request.\n */\n minVolume?: string | number;\n /**\n * Minimum liquidity in USD (numeric string or number).\n * Converted to `min_liquidity` in the API request.\n */\n minLiquidity?: string | number;\n /**\n * Time-remaining bucket. Converts to an `end_before` RFC 3339 timestamp.\n * \"1d\" = events closing within 24 h, \"7d\" = 7 days, \"30d\" = 30 days.\n */\n timeRemaining?: string;\n /**\n * Max number of markets per event (sorted by volume DESC).\n * Defaults to `3` in `resolveEventsParams`.\n */\n markets_limit?: number;\n /**\n * Resolved UI language. Included in the API query and query key so localized\n * payloads are not shared across languages.\n */\n lang?: string;\n}\n\n/**\n * Convert a time-remaining bucket string to an RFC 3339 `end_before` timestamp.\n * Returns `undefined` when `timeRemaining` is not set.\n */\nfunction resolveEndBefore(\n timeRemaining: string | undefined,\n): string | undefined {\n if (!timeRemaining) return undefined;\n const days = timeRemaining === \"1d\" ? 1 : timeRemaining === \"7d\" ? 7 : 30;\n return new Date(Date.now() + days * 24 * 60 * 60 * 1000).toISOString();\n}\n\n/**\n * Build a clean `ListEventsParams` from loose user inputs.\n *\n * Server-side `prefetchInfiniteQuery` and client-side `useInfiniteEvents` must\n * both use this function to guarantee identical query keys.\n */\nexport function resolveEventsParams(\n input: ResolveEventsParamsInput = {},\n): ListEventsParams {\n const {\n tagSlugSelection,\n limit = DEFAULT_PAGE_SIZE,\n status = \"open\",\n with_markets = true,\n source,\n sort_by,\n sort_asc,\n minVolume,\n minLiquidity,\n timeRemaining,\n markets_limit = 3,\n lang,\n } = input;\n const tag_slug = resolveTagSlug(tagSlugSelection);\n\n const min_volume =\n minVolume !== undefined && minVolume !== \"\" ? Number(minVolume) : undefined;\n const min_liquidity =\n minLiquidity !== undefined && minLiquidity !== \"\"\n ? Number(minLiquidity)\n : undefined;\n const end_before = resolveEndBefore(timeRemaining);\n\n return {\n limit,\n status,\n with_markets,\n ...(source ? { source } : {}),\n ...(tag_slug ? { tag_slug } : {}),\n ...(sort_by ? { sort_by } : {}),\n ...(sort_asc !== undefined ? { sort_asc } : {}),\n ...(min_volume !== undefined && !isNaN(min_volume) ? { min_volume } : {}),\n ...(min_liquidity !== undefined && !isNaN(min_liquidity)\n ? { min_liquidity }\n : {}),\n ...(end_before ? { end_before } : {}),\n ...(markets_limit ? { markets_limit } : {}),\n ...(lang ? { lang } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Events infinite query (server-safe)\n// ---------------------------------------------------------------------------\n\n/** Stable TanStack Query key for the events infinite query. */\nexport function infiniteEventsQueryKey(params: ListEventsParams): unknown[] {\n return [\"predict\", \"events-infinite\", params];\n}\n\n/**\n * Fetch a single page of events. Can be used outside of React\n * (e.g. in Server Components, loaders, or tests).\n */\nexport async function fetchEventsPage(\n client: PredictClient,\n params: ListEventsParams,\n): Promise<PredictPage<PredictEvent>> {\n return client.listEvents(params);\n}\n\n// ---------------------------------------------------------------------------\n// Single event (server-safe)\n// ---------------------------------------------------------------------------\n\n/** Stable TanStack Query key for a single event. */\nexport function eventQueryKey(\n slug: string,\n source?: ProviderSource,\n lang?: string,\n): unknown[] {\n return [\"predict\", \"event\", slug, source, lang];\n}\n\n/**\n * Fetch a single event. Can be used outside of React\n * (e.g. in Server Components, loaders, or tests).\n */\nexport async function fetchEvent(\n client: PredictClient,\n slug: string,\n source?: ProviderSource,\n lang?: string,\n): Promise<PredictEvent> {\n return client.getEvent(slug, source, { lang });\n}\n\nexport type { PredictEvent, ListEventsParams, PredictPage };\n","/**\n * Server-safe pure functions for market query helpers.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictMarket,\n ProviderSource,\n PredictClient,\n} from \"../../client\";\n\n/** Stable TanStack Query key for a single market. */\nexport function marketQueryKey(\n slug: string,\n source?: ProviderSource,\n): unknown[] {\n return [\"predict\", \"market\", slug, source];\n}\n\n/**\n * Fetch function usable outside React (e.g. in loaders or tests).\n */\nexport async function fetchMarket(\n client: PredictClient,\n slug: string,\n source?: ProviderSource,\n): Promise<PredictMarket> {\n return client.getMarket(slug, source);\n}\n","/**\n * Server-safe pure functions for matches query parameters.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictClient,\n MatchesParams,\n MatchGroupPage,\n} from \"../../client\";\n\n/** Query key for match group list queries. */\nexport function matchesQueryKey(params?: MatchesParams): unknown[] {\n return [\"predict\", \"matches\", params];\n}\n\n/** Query key for a single match group. */\nexport function matchQueryKey(id: number): unknown[] {\n return [\"predict\", \"match\", id];\n}\n\n/** Fetch a page of matches (usable in both client and server contexts). */\nexport async function fetchMatchesPage(\n client: PredictClient,\n params: MatchesParams,\n): Promise<MatchGroupPage> {\n return client.listMatches(params);\n}\n","/**\n * Server-safe pure functions for match markets query parameters.\n *\n * This module contains NO React imports and can be used in Server Components,\n * route handlers, or any non-browser context.\n */\nimport type {\n PredictClient,\n MatchMarketParams,\n MatchMarketPage,\n} from \"../../client\";\n\n/** Query key for market-level match queries. */\nexport function matchMarketsQueryKey(params?: MatchMarketParams): unknown[] {\n return [\"predict\", \"matchMarkets\", params];\n}\n\n/** Fetch a page of match markets (usable in both client and server contexts). */\nexport async function fetchMatchMarketsPage(\n client: PredictClient,\n params: MatchMarketParams,\n): Promise<MatchMarketPage> {\n return client.listMatchMarkets(params);\n}\n","import type {\n PredictClient,\n SportsMatchesParams,\n SportsMatchesResponse,\n SportsPropsParams,\n SportsPropsResponse,\n SportsTaxonomyParams,\n SportsTaxonomyResponse,\n} from \"../../client\";\n\nexport function sportsTaxonomyQueryKey(\n params?: SportsTaxonomyParams,\n): unknown[] {\n return [\"predict\", \"sports\", \"taxonomy\", params];\n}\n\nexport function sportsMatchesQueryKey(params?: SportsMatchesParams): unknown[] {\n return [\"predict\", \"sports\", \"matches\", params];\n}\n\nexport function sportsPropsQueryKey(params?: SportsPropsParams): unknown[] {\n return [\"predict\", \"sports\", \"props\", params];\n}\n\nexport function resolveSportsTaxonomyParams(\n params: SportsTaxonomyParams = {},\n): SportsTaxonomyParams {\n return { ...params, section: \"sports\" };\n}\n\nexport function resolveSportsMatchesParams(\n params: SportsMatchesParams = {},\n): SportsMatchesParams {\n return params;\n}\n\nexport function resolveSportsPropsParams(\n params: SportsPropsParams = {},\n): SportsPropsParams {\n return params;\n}\n\nexport async function fetchSportsTaxonomy(\n client: PredictClient,\n params?: SportsTaxonomyParams,\n): Promise<SportsTaxonomyResponse> {\n return client.getSportsTaxonomy(resolveSportsTaxonomyParams(params));\n}\n\nexport async function fetchSportsMatches(\n client: PredictClient,\n params?: SportsMatchesParams,\n): Promise<SportsMatchesResponse> {\n return client.getSportsMatches(resolveSportsMatchesParams(params));\n}\n\nexport async function fetchSportsProps(\n client: PredictClient,\n params?: SportsPropsParams,\n): Promise<SportsPropsResponse> {\n return client.getSportsProps(resolveSportsPropsParams(params));\n}\n","import type {\n EsportsMatchesParams,\n EsportsPropsParams,\n EsportsTaxonomyParams,\n PredictClient,\n SportsMatchesResponse,\n SportsPropsResponse,\n SportsTaxonomyResponse,\n} from \"../../client\";\n\nexport function esportsTaxonomyQueryKey(\n params?: EsportsTaxonomyParams,\n): unknown[] {\n return [\"predict\", \"esports\", \"taxonomy\", params];\n}\n\nexport function esportsMatchesQueryKey(\n params?: EsportsMatchesParams,\n): unknown[] {\n return [\"predict\", \"esports\", \"matches\", params];\n}\n\nexport function esportsPropsQueryKey(params?: EsportsPropsParams): unknown[] {\n return [\"predict\", \"esports\", \"props\", params];\n}\n\nexport function resolveEsportsTaxonomyParams(\n params: EsportsTaxonomyParams = {},\n): EsportsTaxonomyParams {\n return params;\n}\n\nexport function resolveEsportsMatchesParams(\n params: EsportsMatchesParams = {},\n): EsportsMatchesParams {\n return params;\n}\n\nexport function resolveEsportsPropsParams(\n params: EsportsPropsParams = {},\n): EsportsPropsParams {\n return params;\n}\n\nexport async function fetchEsportsTaxonomy(\n client: PredictClient,\n params?: EsportsTaxonomyParams,\n): Promise<SportsTaxonomyResponse> {\n return client.getEsportsTaxonomy(resolveEsportsTaxonomyParams(params));\n}\n\nexport async function fetchEsportsMatches(\n client: PredictClient,\n params?: EsportsMatchesParams,\n): Promise<SportsMatchesResponse> {\n return client.getEsportsMatches(resolveEsportsMatchesParams(params));\n}\n\nexport async function fetchEsportsProps(\n client: PredictClient,\n params?: EsportsPropsParams,\n): Promise<SportsPropsResponse> {\n return client.getEsportsProps(resolveEsportsPropsParams(params));\n}\n","import type {\n PredictClient,\n SportsRoutingParams,\n SportsRoutingResponse,\n} from \"../../client\";\n\nexport function sportsRoutingQueryKey(\n slug: string,\n params?: SportsRoutingParams,\n): unknown[] {\n return [\"predict\", \"sports\", \"routing\", slug, params];\n}\n\nexport function resolveSportsRoutingParams(\n params: SportsRoutingParams = {},\n): SportsRoutingParams {\n return params;\n}\n\nexport async function fetchSportsRouting(\n client: PredictClient,\n slug: string,\n params?: SportsRoutingParams,\n): Promise<SportsRoutingResponse> {\n return client.getSportsRouting(slug, resolveSportsRoutingParams(params));\n}\n","import type {\n EsportsMatchDetailParams,\n PredictClient,\n SportsMatchDetail,\n SportsMatchDetailParams,\n SportsSection,\n} from \"../../client\";\n\nexport function sportsMatchDetailQueryKey(\n section: SportsSection,\n matchGroupSlug: string,\n params?: SportsMatchDetailParams,\n): unknown[] {\n return [\"predict\", section, \"match-detail\", matchGroupSlug, params];\n}\n\nexport function esportsMatchDetailQueryKey(\n matchGroupSlug: string,\n params?: EsportsMatchDetailParams,\n): unknown[] {\n return sportsMatchDetailQueryKey(\"esports\", matchGroupSlug, params);\n}\n\nexport function resolveSportsMatchDetailParams(\n params: SportsMatchDetailParams = {},\n): SportsMatchDetailParams {\n return params;\n}\n\nexport function resolveEsportsMatchDetailParams(\n params: EsportsMatchDetailParams = {},\n): EsportsMatchDetailParams {\n return params;\n}\n\nexport async function fetchSportsMatchDetail(\n client: PredictClient,\n section: SportsSection,\n matchGroupSlug: string,\n params?: SportsMatchDetailParams,\n): Promise<SportsMatchDetail> {\n return client.getSportsMatchDetail(\n section,\n matchGroupSlug,\n resolveSportsMatchDetailParams(params),\n );\n}\n\nexport async function fetchEsportsMatchDetail(\n client: PredictClient,\n matchGroupSlug: string,\n params?: EsportsMatchDetailParams,\n): Promise<SportsMatchDetail> {\n return client.getEsportsMatchDetail(\n matchGroupSlug,\n resolveEsportsMatchDetailParams(params),\n );\n}\n","import type {\n PredictClient,\n PredictSearchParams,\n PredictSearchResponse,\n} from \"../../client\";\n\nexport function predictSearchQueryKey(params?: PredictSearchParams): unknown[] {\n return [\"predict\", \"search-documents\", params];\n}\n\nexport function resolvePredictSearchParams(\n params: PredictSearchParams = {},\n): PredictSearchParams {\n const q = params.q ?? \"\";\n return {\n ...params,\n q,\n sort_by: params.sort_by ?? (q ? \"relevance\" : \"volume\"),\n sort_asc: params.sort_asc ?? (q ? undefined : false),\n };\n}\n\nexport async function fetchPredictSearch(\n client: PredictClient,\n params?: PredictSearchParams,\n): Promise<PredictSearchResponse> {\n return client.search(resolvePredictSearchParams(params));\n}\n","/**\n * Domain types for the prediction-server REST API.\n *\n * Mirrors: github.com/liberfi-io/prediction-server/internal/domain\n */\n\n// ---------------------------------------------------------------------------\n// Shared / provider\n// ---------------------------------------------------------------------------\n\n/** Upstream data provider that produced a domain object. */\nexport type ProviderSource = \"kalshi\" | \"polymarket\";\n\n/**\n * Provider-specific metadata attached to every domain aggregate.\n * Keys are namespaced field paths, e.g. \"polymarket.conditionId\" or \"dflow.yesMint\".\n * Values are raw JSON-decoded values.\n */\nexport type ProviderMeta = Record<string, unknown>;\n\n// ---------------------------------------------------------------------------\n// Tags\n// ---------------------------------------------------------------------------\n\n/** Provider-sourced label attached to an Event. */\nexport interface PredictTag {\n slug: string;\n label: string;\n source: ProviderSource;\n provider_meta?: ProviderMeta;\n}\n\n// ---------------------------------------------------------------------------\n// Event\n// ---------------------------------------------------------------------------\n\n/** Lifecycle status of a prediction event (normalised across all providers). */\nexport type EventStatus = \"pending\" | \"open\" | \"closed\" | \"voided\";\n\n/** Settlement / resolution data source for an event. */\nexport interface SettlementSource {\n url: string;\n name?: string;\n}\n\n/** Root aggregate for a prediction event from the prediction-server API. */\nexport interface PredictEvent {\n /** Internal database surrogate key (absent when not yet persisted). */\n id?: number;\n /**\n * Canonical business key shared across all providers.\n * - DFlow: ticker (e.g. \"KXBTCD-25FEB-T68000\")\n * - Polymarket: slug (e.g. \"will-trump-win-2024\")\n */\n slug: string;\n\n title: string;\n /** Localized title for the request language. Falls back to `title` when absent. */\n title_trans?: string;\n subtitle?: string;\n /** Localized subtitle for the request language. Falls back to `subtitle` when absent. */\n subtitle_trans?: string;\n description?: string;\n /** Localized description for the request language. Falls back to `description` when absent. */\n description_trans?: string;\n image_url?: string;\n\n status: EventStatus;\n /** ISO 8601 timestamp; absent if the provider does not supply it. */\n start_at?: string;\n end_at?: string;\n created_at?: string;\n updated_at?: string;\n\n /** Provider-sourced labels for display only. */\n tags?: PredictTag[];\n\n /** All values are USD amounts. */\n volume?: number;\n volume_24h?: number;\n liquidity?: number;\n open_interest?: number;\n\n settlement_sources?: SettlementSource[];\n\n /** Nested markets; omitted when the request used `with_markets=false`. */\n markets?: PredictMarket[];\n /** Cache-only quote snapshot embedded when the market-data contract is enabled. */\n initial_quotes?: MarketDataInitialQuotes;\n\n source: ProviderSource;\n provider_meta?: ProviderMeta;\n}\n\n// ---------------------------------------------------------------------------\n// Market\n// ---------------------------------------------------------------------------\n\n/** Lifecycle status of a prediction market (normalised across all providers). */\nexport type MarketStatus = \"pending\" | \"open\" | \"closed\" | \"voided\";\n\n/** Final resolution of a closed market. Empty string means unresolved. */\nexport type MarketResult = \"yes\" | \"no\" | \"voided\" | \"\";\n\n/** One possible outcome in a binary (or multi-outcome) prediction market. */\nexport interface MarketOutcome {\n /** Provider-neutral structural identity; unique within the parent market. */\n key: string;\n /** Display name, e.g. \"Yes\" or \"No\". */\n label: string;\n /** Localized label for the request language. Falls back to `label` when absent. */\n label_trans?: string;\n /** Current implied probability [0, 1]. */\n price?: number;\n best_bid?: number;\n best_ask?: number;\n}\n\n/** Tradeable prediction outcome within an Event. */\nexport interface PredictMarket {\n id?: number;\n event_id?: number;\n\n slug: string;\n event_slug: string;\n\n question: string;\n /** Localized question for the request language. Falls back to `question` when absent. */\n question_trans?: string;\n description?: string;\n /** Localized description for the request language. Falls back to `description` when absent. */\n description_trans?: string;\n image_url?: string;\n /** Resolution/settlement rules in order. */\n rules?: string[];\n\n status: MarketStatus;\n result?: MarketResult;\n\n start_at?: string;\n end_at?: string;\n expires_at?: string;\n closed_at?: string;\n created_at?: string;\n updated_at?: string;\n\n /** Always present; binary markets have exactly 2 outcomes (YES at [0], NO at [1]). */\n outcomes: MarketOutcome[];\n\n volume?: number;\n volume_24h?: number;\n liquidity?: number;\n open_interest?: number;\n\n source: ProviderSource;\n provider_meta?: ProviderMeta;\n}\n\n// ---------------------------------------------------------------------------\n// Provider-neutral market data\n// ---------------------------------------------------------------------------\n\nexport const MARKET_STRUCTURE_MEDIA_TYPE_V1 =\n \"application/vnd.liberfi.market-structure+json;v=1\";\n\nexport type MarketDataSchemaVersion = 1;\nexport type MarketDataMarketView = \"summary\" | \"full\";\n\nexport interface MarketDataMarketKey {\n source: ProviderSource;\n market_slug: string;\n}\n\nexport interface MarketDataEventWatch {\n source: ProviderSource;\n event_slug: string;\n market_view: MarketDataMarketView;\n}\n\nexport interface MarketDataWatchRequest {\n quote_events?: MarketDataEventWatch[];\n quote_markets?: MarketDataMarketKey[];\n orderbook_market?: MarketDataMarketKey;\n}\n\nexport interface MarketDataWatchResponse {\n refresh_after_ms: number;\n}\n\nexport interface MarketDataQuotesRequest {\n markets: MarketDataMarketKey[];\n}\n\nexport interface MarketDataValueComponent {\n available: boolean;\n value?: number;\n provider_timestamp?: string;\n observed_at?: string;\n}\n\nexport interface MarketDataBBAComponent {\n available: boolean;\n empty: boolean;\n best_bid?: number;\n best_ask?: number;\n midpoint?: number;\n provider_timestamp?: string;\n observed_at?: string;\n}\n\nexport interface MarketDataOutcomeQuote extends MarketDataMarketKey {\n outcome: string;\n bba: MarketDataBBAComponent;\n last_trade: MarketDataValueComponent;\n tick_size: MarketDataValueComponent;\n}\n\nexport interface MarketDataMarketQuoteResult extends MarketDataMarketKey {\n realtime_supported: boolean;\n outcomes: MarketDataOutcomeQuote[];\n}\n\nexport interface MarketDataQuotesResponse {\n schema_version: MarketDataSchemaVersion;\n markets: MarketDataMarketQuoteResult[];\n}\n\nexport type MarketDataInitialQuotes = MarketDataQuotesResponse;\n\nexport interface MarketDataBookLevel {\n price: string;\n size: string;\n}\n\nexport interface MarketDataOutcomeOrderbook {\n outcome: string;\n provider_timestamp?: string;\n observed_at: string;\n bids: MarketDataBookLevel[];\n asks: MarketDataBookLevel[];\n}\n\nexport interface MarketDataOrderbooksResponse extends MarketDataMarketKey {\n schema_version: MarketDataSchemaVersion;\n orderbooks: MarketDataOutcomeOrderbook[];\n}\n\nexport type MarketStructureResourceType = \"event\" | \"match\" | \"prop\";\n\nexport interface MarketStructureOutcome {\n key: string;\n label: string;\n label_trans?: string;\n quote_capable: boolean;\n orderbook_capable: boolean;\n price_history_supported: boolean;\n book_channel?: string;\n}\n\nexport interface MarketStructureMarket extends MarketDataMarketKey {\n question: string;\n question_trans?: string;\n status: MarketStatus;\n realtime_supported: boolean;\n realtime_book_supported: boolean;\n outcomes: MarketStructureOutcome[];\n}\n\nexport interface MarketStructureItem {\n resource_type: MarketStructureResourceType;\n source?: ProviderSource;\n resource_slug: string;\n section?: SportsSection;\n title: string;\n title_trans?: string;\n status: string;\n market_view: MarketDataMarketView;\n markets_included: boolean;\n item_channel?: string;\n markets: MarketStructureMarket[];\n}\n\nexport interface MarketStructureResponse {\n representation_schema_version: 1;\n initial_quotes_contract_enabled: boolean;\n items: MarketStructureItem[];\n}\n\nexport type MarketStructureHttpResponse =\n | {\n status: 200;\n etag: string;\n body: MarketStructureResponse;\n }\n | {\n status: 304;\n etag: string;\n body?: never;\n };\n\n// ---------------------------------------------------------------------------\n// Pagination\n// ---------------------------------------------------------------------------\n\n/** Generic paginated result set returned by the prediction-server list endpoints. */\nexport interface PredictPage<T> {\n items: T[];\n next_cursor?: string;\n has_more?: boolean;\n limit?: number;\n /** Not all backends support total count. */\n total?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Request parameters\n// ---------------------------------------------------------------------------\n\n/** Valid sort fields accepted by `GET /api/v1/events`. */\nexport type EventSortField =\n | \"volume\"\n | \"volume_24h\"\n | \"liquidity\"\n | \"open_interest\"\n | \"end_at\"\n | \"start_at\"\n | \"created_at\";\n\n/** Query parameters for `listEvents`. All fields are optional. */\nexport interface ListEventsParams {\n /** Page size. Server default: 20. */\n limit?: number;\n /** Opaque pagination cursor returned by the previous page's `next_cursor`. */\n cursor?: string;\n /** Filter by event lifecycle status. */\n status?: EventStatus;\n /** Filter by upstream provider. */\n source?: ProviderSource;\n /** Unified navigation tag slug (e.g. \"politics\", \"sports\"). */\n tag_slug?: string;\n /** Full-text search query. */\n search?: string;\n /** Field to sort by. */\n sort_by?: EventSortField;\n /** When `true`, sort ascending. Defaults to descending. */\n sort_asc?: boolean;\n /**\n * When `false`, markets are omitted from each event for lighter payloads.\n * Defaults to `true` on the server.\n */\n with_markets?: boolean;\n /** Keep only events whose total volume (USD) is >= this value. */\n min_volume?: number;\n /** Keep only events whose liquidity (USD) is >= this value. */\n min_liquidity?: number;\n /**\n * RFC 3339 timestamp. Keep only events whose `end_at` is before this deadline\n * (i.e. the event closes within the specified window).\n */\n end_before?: string;\n /**\n * Max number of markets per event (sorted by volume DESC).\n * `0` means no limit. Defaults to `3` when set via `resolveEventsParams`.\n */\n markets_limit?: number;\n /**\n * Resolved UI language. Sent as `?lang=` so localized event/market fields are\n * returned and TanStack Query keys remain language-specific.\n */\n lang?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Orderbook\n// ---------------------------------------------------------------------------\n\n/** Single price level in an order book. */\nexport interface OrderbookLevel {\n price: number;\n size: number;\n}\n\n/** Binary outcome side for per-outcome order books. */\nexport type OrderbookOutcome = \"yes\" | \"no\";\n\n/** Aggregated order book for a market. */\nexport interface Orderbook {\n market_id: string;\n /** Outcome side this book belongs to. */\n outcome?: OrderbookOutcome;\n /** Sorted by price descending. */\n bids: OrderbookLevel[];\n /** Sorted by price ascending. */\n asks: OrderbookLevel[];\n /** best_ask − best_bid; absent when either side is empty. */\n spread?: number;\n}\n\n/** One market to fetch in a batch order book request. */\nexport interface OrderbookBatchItem {\n slug: string;\n source: ProviderSource;\n /** Outcome side; defaults to `\"yes\"`. */\n outcome?: OrderbookOutcome;\n}\n\n/** Request body for `POST /api/v1/markets/orderbooks`. */\nexport interface OrderbooksBatchRequest {\n /** Up to 100 markets to fetch in one call. */\n items: OrderbookBatchItem[];\n}\n\n/**\n * One result of a batch order book response, aligned with the request order.\n * `orderbook` is `null` when the item failed (see `error`); per-item failures\n * never fail the whole batch.\n */\nexport interface OrderbookBatchResult {\n slug: string;\n source: ProviderSource;\n outcome: OrderbookOutcome;\n orderbook: Orderbook | null;\n /** Present only when this item failed. */\n error?: string;\n}\n\n/** Response from `POST /api/v1/markets/orderbooks`. */\nexport interface OrderbooksBatchResponse {\n results: OrderbookBatchResult[];\n}\n\n// ---------------------------------------------------------------------------\n// Sports / esports\n// ---------------------------------------------------------------------------\n\n/** Top-level evergreen sports section. */\nexport type SportsSection = \"sports\" | \"esports\";\n\n/** Sports provider used by orderbook keys and search results. */\nexport type SportsProviderSource = ProviderSource;\n\n/** Public Sports event card type. */\nexport type SportsEventType = \"match\" | \"prop\";\n\n/** Sports event route result kind. */\nexport type SportsRouteType =\n | \"match\"\n | \"prop\"\n | \"child_redirect\"\n | \"not_sports\";\n\n/** Taxonomy node kind. */\nexport type SportsTaxonomyNodeType =\n | \"sport\"\n | \"game\"\n | \"league\"\n | \"tournament\"\n | \"category\";\n\n/** Binary outcome side accepted by existing Predict orderbook APIs. */\nexport type SportsBinaryOutcome = OrderbookOutcome;\n\nexport interface SportsTaxonomyNode {\n section?: SportsSection;\n node_type: SportsTaxonomyNodeType;\n slug: string;\n label: string;\n children?: SportsTaxonomyNode[];\n}\n\nexport interface SportsTaxonomySection {\n section: SportsSection;\n children: SportsTaxonomyNode[];\n}\n\nexport interface SportsTaxonomyResponse {\n sections: SportsTaxonomySection[];\n}\n\nexport interface SportsParticipant {\n name: string;\n role?: string;\n slug?: string;\n logo_url?: string;\n abbreviation?: string;\n}\n\nexport interface SportsLiveState {\n status?: string;\n status_text?: string;\n clock?: string | null;\n period?: string | null;\n score?: unknown;\n score_state?: unknown;\n observed_at_unix_ms?: number;\n}\n\nexport interface SportsOrderbookKey {\n market_slug: string;\n source: SportsProviderSource;\n outcome: SportsBinaryOutcome;\n}\n\nexport interface SportsMarketOutcome {\n outcome: SportsBinaryOutcome;\n label: string;\n price?: number;\n best_bid?: number;\n best_ask?: number;\n last_trade_price?: number;\n orderbook?: SportsOrderbookKey;\n}\n\nexport interface SportsInlineMarket {\n market_slug: string;\n market_type?: string;\n label: string;\n outcomes: SportsMarketOutcome[];\n}\n\nexport interface SportsMarket extends SportsInlineMarket {\n condition_id?: string;\n market_category?: string;\n period?: string;\n line?: number;\n active?: boolean;\n closed?: boolean;\n accepting_orders?: boolean;\n volume?: number;\n liquidity?: number;\n}\n\nexport interface SportsMarketGroup {\n market_category: string;\n label: string;\n markets: SportsMarket[];\n}\n\nexport interface SportsMatchCard {\n match_group_slug: string;\n section: SportsSection;\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n title: string;\n status: string;\n start_time?: string;\n participants?: SportsParticipant[];\n market_count?: number;\n live_state?: SportsLiveState;\n inline_markets?: SportsInlineMarket[];\n initial_quotes?: MarketDataInitialQuotes;\n}\n\nexport type SportsMatchesResponse = PredictPage<SportsMatchCard>;\n\nexport interface SportsPropEventCard {\n event_slug: string;\n event_type: SportsEventType;\n prop_type?: \"futures\" | \"outright\" | \"player_prop\" | \"all\" | string;\n section: SportsSection;\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n title: string;\n status?: string;\n start_time?: string;\n parent_match_group_slug?: string;\n markets?: SportsInlineMarket[];\n initial_quotes?: MarketDataInitialQuotes;\n}\n\nexport type SportsPropsResponse = PredictPage<SportsPropEventCard>;\n\nexport interface SportsRoutingResponse {\n route_type: SportsRouteType;\n slug: string;\n section?: SportsSection;\n match_group_slug?: string;\n event_slug?: string;\n redirect_to?: string;\n status?: number;\n}\n\nexport interface SportsMatchDetail extends SportsMatchCard {\n market_groups: SportsMarketGroup[];\n}\n\nexport interface SportsTaxonomyParams {\n section?: SportsSection;\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n lang?: string;\n}\n\nexport interface SportsMatchesParams {\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n status?: string;\n limit?: number;\n cursor?: string;\n lang?: string;\n}\n\nexport interface SportsPropsParams {\n sport_slug?: string;\n game_slug?: string;\n league_slug?: string;\n tournament_slug?: string;\n prop_type?: \"futures\" | \"outright\" | \"player_prop\" | \"all\";\n limit?: number;\n cursor?: string;\n lang?: string;\n}\n\nexport interface SportsRoutingParams {\n lang?: string;\n}\n\nexport interface SportsMatchDetailParams {\n lang?: string;\n}\n\nexport type EsportsTaxonomyParams = Omit<SportsTaxonomyParams, \"section\">;\nexport type EsportsMatchesParams = SportsMatchesParams;\nexport type EsportsPropsParams = SportsPropsParams;\nexport type EsportsMatchDetailParams = SportsMatchDetailParams;\n\n// ---------------------------------------------------------------------------\n// Mixed search\n// ---------------------------------------------------------------------------\n\nexport type PredictSearchResultType =\n | \"event\"\n | \"match_group\"\n | \"prop_event\"\n | \"market\";\n\nexport type PredictSearchSortField =\n | \"relevance\"\n | \"volume\"\n | \"start_time\"\n | \"updated_at\";\n\nexport interface PredictSearchParams {\n q?: string;\n result_type?: PredictSearchResultType | PredictSearchResultType[] | string;\n source?: ProviderSource;\n section?: SportsSection | string;\n include_closed?: boolean;\n sort_by?: PredictSearchSortField;\n sort_asc?: boolean;\n limit?: number;\n cursor?: string;\n lang?: string;\n}\n\nexport interface PredictSearchResult {\n result_type: PredictSearchResultType;\n document_id: string;\n title: string;\n source?: ProviderSource;\n section?: SportsSection | string;\n event_slug?: string;\n match_group_slug?: string;\n market_slug?: string;\n detail_url: string;\n status?: string;\n score?: number;\n}\n\nexport type PredictSearchResponse = PredictPage<PredictSearchResult>;\n\n// ---------------------------------------------------------------------------\n// Trade\n// ---------------------------------------------------------------------------\n\n/** On-chain trade type. */\nexport type TradeType =\n | \"TRADE\"\n | \"SPLIT\"\n | \"MERGE\"\n | \"REDEEM\"\n | \"REWARD\"\n | \"CONVERSION\"\n | \"MAKER_REBATE\"\n | \"REFERRAL_REWARD\";\n\n/** Lightweight event summary embedded in a trade. */\nexport interface EventSummary {\n slug: string;\n title: string;\n image_url?: string;\n status: EventStatus;\n}\n\n/** Lightweight market summary embedded in a trade or order. */\nexport interface MarketSummary {\n slug: string;\n question: string;\n image_url?: string;\n status: MarketStatus;\n}\n\n/** A single trade record. */\nexport interface PredictTrade {\n id: string;\n source: ProviderSource;\n side?: string;\n outcome?: string;\n outcome_index?: number;\n price?: number;\n size: number;\n usd_size?: number;\n /** Unix seconds. */\n timestamp: number;\n tx_hash?: string;\n wallet?: string;\n type: TradeType;\n event?: EventSummary;\n market?: MarketSummary;\n provider_meta?: ProviderMeta;\n}\n\n/** Query parameters for `GET /api/v1/markets/{slug}/trades`. */\nexport interface ListMarketTradesParams {\n source: ProviderSource;\n limit?: number;\n cursor?: string;\n /** Filter by side: `\"BUY\"` or `\"SELL\"`. */\n side?: string;\n}\n\n/** Query parameters for `GET /api/v1/trades` (by wallet). */\nexport interface ListTradesParams {\n /** Provider source. Omit to aggregate all providers. */\n source?: ProviderSource;\n wallet: string;\n limit?: number;\n cursor?: string;\n /** Comma-separated trade types. */\n type?: string;\n side?: string;\n}\n\n/**\n * Query parameters for `GET /api/v1/trades` in multi-wallet mode.\n * Each provider uses its own wallet address (e.g. Solana for Kalshi, EVM for Polymarket).\n */\nexport interface ListTradesMultiParams {\n kalshi_user?: string;\n polymarket_user?: string;\n limit?: number;\n cursor?: string;\n /** Comma-separated trade types. */\n type?: string;\n side?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Comments\n// ---------------------------------------------------------------------------\n\n/** Public profile of a comment author. */\nexport interface PredictCommentProfile {\n /** Display name, when the author set one. */\n name?: string;\n /** Generated pseudonym, shown when `name` is empty. */\n pseudonym?: string;\n /** Avatar image URL. */\n profile_image?: string;\n /** Provider proxy wallet (e.g. Polymarket Safe). */\n proxy_wallet?: string;\n /** Author wallet address; falls back to the base address upstream. */\n user_address?: string;\n}\n\n/** A single user comment on a prediction event (or its parent series). */\nexport interface PredictComment {\n id: string;\n body: string;\n /** Present when the comment is a reply to another comment. */\n parent_comment_id?: string;\n /** ISO-8601 timestamp. */\n created_at: string;\n reaction_count: number;\n profile: PredictCommentProfile;\n}\n\n/**\n * Query parameters for `GET /api/v1/events/{slug}/comments`.\n * `slug` is passed positionally to {@link PredictClient.listEventComments}.\n */\nexport interface ListCommentsParams {\n /** Provider source. Only `\"polymarket\"` is supported today. */\n source: ProviderSource;\n limit?: number;\n /** Opaque pagination cursor (offset string) from the previous page. */\n cursor?: string;\n /** Order field, e.g. `\"createdAt\"` or `\"reactionCount\"`. */\n order?: string;\n /** When true, sort ascending (requires `order`). */\n ascending?: boolean;\n /** When true, only comments from position holders. */\n holders_only?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Price history\n// ---------------------------------------------------------------------------\n\n/** A single price-history data point. */\nexport interface PricePoint {\n /** Unix seconds. */\n t: number;\n /** Price [0, 1]. */\n p: number;\n}\n\n/** Response from `GET /api/v1/markets/{slug}/price-history`. */\nexport interface PriceHistoryResponse {\n points: PricePoint[];\n}\n\n/** Accepted values for the `range` query parameter. */\nexport type PriceHistoryRange = \"1h\" | \"6h\" | \"1d\" | \"1w\" | \"1m\" | \"all\";\n\n/** Query parameters for `GET /api/v1/markets/{slug}/price-history`. */\nexport interface PriceHistoryParams {\n source: ProviderSource;\n range?: PriceHistoryRange;\n /** Unix seconds. Mirrors Polymarket `startTs`. */\n startTs?: number;\n /** Unix seconds. Mirrors Polymarket `endTs`. */\n endTs?: number;\n /** Data accuracy in minutes. Mirrors Polymarket `fidelity`. */\n fidelity?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Candlestick\n// ---------------------------------------------------------------------------\n\n/** OHLCV candlestick data point. */\nexport interface Candlestick {\n timestamp: string;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n}\n\n/** Query parameters for `GET /api/v1/markets/{slug}/candlesticks`. */\nexport interface ListCandlesticksParams {\n /** Candle interval (e.g. `\"1m\"`, `\"5m\"`, `\"1h\"`, `\"1d\"`). Default: `\"1h\"`. */\n interval?: string;\n /** Number of candles. Default: 100. */\n limit?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Similar events\n// ---------------------------------------------------------------------------\n\n/** Query parameters for `GET /api/v1/events/{slug}/similar`. */\nexport interface SimilarEventsParams {\n /** Number of results (default 5, max 20). */\n limit?: number;\n /** When true, only return events from the same provider. */\n same_source?: boolean;\n /**\n * Resolved UI language. Sent as `?lang=` so localized event/market fields are\n * returned.\n */\n lang?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Cross-platform matches\n// ---------------------------------------------------------------------------\n\n/** Match group lifecycle status. */\nexport type MatchStatus = \"active\" | \"expired\";\n\n/** One provider's event within a MatchGroup. */\nexport interface MatchGroupEntry {\n id: number;\n group_id: number;\n source: ProviderSource;\n event: PredictEvent;\n}\n\n/** Pairwise market comparison within a MatchGroup. */\nexport interface MatchGroupMarket {\n id: number;\n group_id: number;\n source_a: ProviderSource;\n market_a: PredictMarket;\n source_b: ProviderSource;\n market_b: PredictMarket;\n /**\n * v1.1: now `|a − b|` absolute YES-side gap, no longer fee-adjusted\n * arbitrage edge. Range [0, 1].\n */\n spread?: number;\n /** v1.1: `|a − b| × 100`. */\n spread_percent?: number;\n /** @deprecated PRD v1.1 removed the arbitrage framing. Always `0`. */\n arb_profit?: number;\n /**\n * v1.1: pair quality classification. Mirrors backend signal.go.\n * - `liquid_gap`: both legs vol_24h ≥ vol_active_usd, fresh.\n * - `active_gap`: at least one leg vol_24h ≥ vol_stale_usd, fresh.\n * - `stale_gap`: both legs vol_24h < vol_stale_usd, fresh data.\n * - `stale_data`: snapshot age > stale_age_seconds (data freshness wins).\n */\n signal_tag?: SignalTag;\n /** Pre-filter rejection reason (not surfaced to UI when set). */\n reject_reason?: string;\n}\n\n/**\n * A group of matched events across N providers referring to the same\n * real-world prediction. `entries.length >= 2`.\n */\nexport interface MatchGroup {\n id: number;\n title: string;\n entries: MatchGroupEntry[];\n matched_markets?: MatchGroupMarket[];\n confidence: number;\n max_spread?: number;\n combined_volume?: number;\n combined_volume_24h?: number;\n status: MatchStatus;\n created_at: string;\n updated_at: string;\n}\n\n/** Valid sort fields for the matches list endpoint. */\nexport type MatchSortField = \"spread\" | \"volume\" | \"confidence\";\n\n/** Query parameters for `GET /api/v1/matches`. */\nexport interface MatchesParams {\n sort_by?: MatchSortField;\n sort_asc?: boolean;\n min_spread?: number;\n /** Minimum combined volume (USD) filter. */\n min_volume?: number;\n /** Comma-separated provider sources, e.g. `\"kalshi,polymarket\"`. */\n sources?: string;\n status?: MatchStatus;\n search?: string;\n limit?: number;\n cursor?: string;\n}\n\n/** Aggregate statistics returned inline with the matches listing. */\nexport interface MatchesStats {\n total_matches: number;\n avg_spread: number;\n max_spread: number;\n matches_over_5_percent: number;\n matches_over_3_percent: number;\n total_volume: number;\n total_volume_24h: number;\n}\n\n/** Paginated match group result with inline aggregate stats. */\nexport interface MatchGroupPage {\n items: MatchGroup[];\n next_cursor?: string;\n has_more?: boolean;\n limit?: number;\n total?: number;\n stats?: MatchesStats;\n}\n\n/**\n * Confidence tier for match quality.\n * @deprecated v1.1 — UI surfaces `signal_tag` instead. Kept on the wire\n * for one release for backwards compatibility.\n */\nexport type MatchConfidenceTier = \"high\" | \"medium\" | \"low\";\n\n/**\n * v1.1 pair-quality classification (PRD §5.3). Empty string is never\n * emitted by the server — it's just here to silence narrowing on legacy\n * cached responses that predate the migration.\n */\nexport type SignalTag =\n | \"liquid_gap\"\n | \"active_gap\"\n | \"stale_gap\"\n | \"stale_data\";\n\n/**\n * v1.1 per-leg projection of a market in a matched pair (PRD §5).\n * Renders one side of the MatchMarketCard.\n */\nexport interface MatchLeg {\n source: ProviderSource;\n event_title: string;\n event_slug: string;\n market_id: number;\n market_slug: string;\n question: string;\n status: MarketStatus;\n outcomes?: MarketOutcome[];\n /**\n * YES-side effective best price used for the gap. Mid (bid+ask)/2\n * when both sides exist, else best_ask, else best_bid, else\n * outcome.price. Always in [0, 1] when set.\n */\n best_price?: number;\n /** Per-leg 24h notional in USD. Liquidity proxy now that depth is deferred. */\n vol_24h_usd?: number;\n /**\n * Deep link to this market on the original provider. Surfaced as the\n * small \"view on Polymarket / Kalshi\" icon next to the leg.\n */\n external_url?: string;\n /** now − markets.synced_at for THIS leg, in whole seconds. */\n age_seconds?: number;\n}\n\n/**\n * Flattened market pair from a match group (market-level granularity).\n *\n * v1.1: prefer reading `legs[0]` / `legs[1]` and `signal_tag`. The\n * legacy `market_a` / `market_b` / `spread_percent` fields are still\n * emitted for one release window so existing cached SDK responses do\n * not 500 — they will be removed in v1.2.\n */\nexport interface MatchMarketFlat {\n match_id: number;\n similarity_score: number;\n /** @deprecated v1.1 — prefer `signal_tag`. */\n confidence_tier: MatchConfidenceTier;\n status: MatchStatus;\n\n /** v1.1 primary projection — always length 2, ordered same as source_a/source_b. */\n legs: MatchLeg[];\n /** v1.1 pair quality (see SignalTag). */\n signal_tag?: SignalTag;\n /** v1.1 max(legs[*].age_seconds) — used for the pair-level freshness pill. */\n age_seconds?: number;\n\n source_a: ProviderSource;\n event_a_title: string;\n market_a: PredictMarket;\n source_b: ProviderSource;\n event_b_title: string;\n market_b: PredictMarket;\n /** v1.1 semantics: `|a − b|` absolute gap (0..1). */\n spread?: number;\n /** v1.1 semantics: `|a − b| × 100`. */\n spread_percent?: number;\n /** @deprecated PRD v1.1 removed arbitrage framing. */\n arb_profit?: number;\n combined_volume?: number;\n combined_volume_24h?: number;\n reject_reason?: string;\n}\n\n/** Paginated result for flattened market pairs. */\nexport interface MatchMarketPage {\n items: MatchMarketFlat[];\n total: number;\n limit: number;\n offset: number;\n}\n\n/** Query parameters for `GET /api/v1/matches/markets`. */\nexport interface MatchMarketParams {\n sort_by?: MatchSortField;\n sort_asc?: boolean;\n min_spread?: number;\n min_volume?: number;\n sources?: string;\n status?: MatchStatus;\n search?: string;\n /**\n * v1.1: comma-separated `SignalTag` values, e.g. `\"liquid_gap,active_gap\"`.\n * Pass `\"any\"` (or omit) to disable signal filtering.\n */\n signal?: string;\n limit?: number;\n offset?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Positions\n// ---------------------------------------------------------------------------\n\n/** A single user position in a prediction market. */\nexport interface PredictPosition {\n source: ProviderSource;\n side: string;\n size: number;\n avg_price?: number;\n current_price?: number;\n current_value?: number;\n initial_value?: number;\n pnl?: number;\n pnl_percent?: number;\n realized_pnl?: number;\n redeemable: boolean;\n event?: PredictEvent;\n market?: PredictMarket;\n /**\n * Position-level provider metadata.\n * DFlow positions carry `dflow.outcomeMint` and `dflow.collateralMint`.\n */\n provider_meta?: ProviderMeta;\n}\n\n/** Response from `GET /api/v1/positions`. */\nexport interface PositionsResponse {\n /** Populated for single-source or legacy aggregate queries. */\n user?: string;\n /** Populated for multi-wallet queries (keys are external source names). */\n wallets?: Record<string, string>;\n positions: PredictPosition[];\n}\n\n/** Lightweight current-value summary for one provider wallet. */\nexport interface PositionValue {\n source: ProviderSource;\n user: string;\n /** Current position value in {@link currency}, returned as a decimal string. */\n value: string;\n currency: string;\n}\n\n/** Provider-specific failure returned by aggregate position value queries. */\nexport interface PositionValueError {\n source: ProviderSource;\n user?: string;\n code: string;\n message: string;\n}\n\n/** Response from `GET /api/v1/positions/value`. */\nexport interface PositionValueResponse {\n /** Populated for single-source or legacy aggregate queries. */\n user?: string;\n /** Populated for multi-wallet queries (keys are external source names). */\n wallets?: Record<string, string>;\n /** Populated for single-source queries. */\n source?: ProviderSource;\n /** Aggregate current position value in {@link currency}. */\n value: string;\n currency: string;\n /** Per-provider values for multi-wallet or aggregate queries. */\n values?: PositionValue[];\n /** True when at least one provider failed but others returned values. */\n partial?: boolean;\n errors?: PositionValueError[];\n}\n\n// ---------------------------------------------------------------------------\n// Balance\n// ---------------------------------------------------------------------------\n\n/** Response from `GET /api/v1/balance`. */\nexport interface BalanceResponse {\n user: string;\n source: ProviderSource;\n /** Token symbol (e.g. \"USDC\"). */\n token: string;\n /** Human-readable balance (e.g. \"125.50\"). */\n balance: string;\n /** Raw balance in smallest unit (e.g. \"125500000\"). */\n raw_balance: string;\n /** Token decimals (e.g. 6 for USDC). */\n decimals: number;\n}\n\n// ---------------------------------------------------------------------------\n// Withdraw\n// ---------------------------------------------------------------------------\n\n/** Request body for `POST /api/v1/withdraw/build`. */\nexport interface WithdrawBuildRequest {\n source: ProviderSource;\n from: string;\n to: string;\n /** Human-readable amount (e.g. \"10.5\"). */\n amount: string;\n}\n\n/** Response from `POST /api/v1/withdraw/build`. */\nexport interface WithdrawBuildResponse {\n /** Base64 (Solana) or JSON tx params (Polygon). */\n serialized_tx: string;\n /** Unix timestamp; 0 means no expiry. */\n expires_at: number;\n}\n\n/** Request body for `POST /api/v1/withdraw/submit`. */\nexport interface WithdrawSubmitRequest {\n source: ProviderSource;\n signed_tx: string;\n}\n\n/** Response from `POST /api/v1/withdraw/submit`. */\nexport interface WithdrawSubmitResponse {\n tx_hash: string;\n status: string;\n}\n\n/** Response from `GET /api/v1/withdraw/status`. */\nexport interface WithdrawStatusResponse {\n tx_hash: string;\n /** \"submitted\" | \"confirmed\" | \"failed\" */\n status: \"submitted\" | \"confirmed\" | \"failed\";\n}\n\n// ---------------------------------------------------------------------------\n// Deposit (native USDC → USDC.e for Polymarket)\n// ---------------------------------------------------------------------------\n\n/** Request body for `POST /api/v1/deposit/polymarket/build`. */\nexport interface DepositBuildRequest {\n source: ProviderSource;\n from: string;\n safe_address: string;\n /** Total USDC needed (human-readable, e.g. \"50.0\"). */\n amount: string;\n}\n\n/** A single unsigned EVM transaction in the deposit build response. */\nexport interface UnsignedTx {\n /** \"approve\" or \"swap\" */\n type: \"approve\" | \"swap\";\n /** Transaction params: {from, to, data, value, chainId, gas} */\n params: Record<string, string>;\n}\n\n/** Response from `POST /api/v1/deposit/polymarket/build`. */\nexport interface DepositBuildResponse {\n transactions: UnsignedTx[];\n /** USDC amount that needs to be swapped (human-readable). */\n shortfall: string;\n /** Current Safe USDC.e balance (human-readable). */\n safe_balance: string;\n}\n\n/** Request body for `POST /api/v1/deposit/polymarket/submit`. */\nexport interface DepositSubmitRequest {\n source: ProviderSource;\n signed_tx: string;\n}\n\n/** Response from `POST /api/v1/deposit/polymarket/submit`. */\nexport interface DepositSubmitResponse {\n tx_hash: string;\n status: string;\n}\n\n/** Response from `GET /api/v1/deposit/polymarket/status`. */\nexport interface DepositStatusResponse {\n tx_hash: string;\n /** \"submitted\" | \"confirmed\" | \"failed\" */\n status: \"submitted\" | \"confirmed\" | \"failed\";\n}\n\n/** Multi-chain deposit addresses from the Polymarket Bridge API. */\nexport interface PolymarketDepositAddresses {\n /** EVM bridge address — accepts USDC/USDT on Ethereum, Polygon, Base, Arbitrum, Optimism, BNB, etc. */\n evm: string;\n /** Solana bridge address — accepts USDC on Solana. */\n svm: string;\n /** Bitcoin bridge address — accepts BTC. */\n btc: string;\n /** Tron bridge address — accepts USDT-TRC20 (optional, may be absent). */\n tron?: string;\n}\n\n/**\n * A single ERC20-style token entry returned by the Polymarket Bridge\n * `/supported-assets` endpoint.\n */\nexport interface PolymarketBridgeToken {\n /** Full token name, e.g. \"USD Coin\". */\n name: string;\n /** Token symbol, e.g. \"USDC\". */\n symbol: string;\n /** On-chain token contract address. May be a native-token sentinel for non-EVM chains. */\n address: string;\n /** Token decimals. */\n decimals: number;\n}\n\n/**\n * A single (chain, token) tuple supported by the Polymarket Bridge,\n * carrying the minimum USD amount that the Bridge will process for\n * deposits / withdrawals.\n */\nexport interface PolymarketSupportedAsset {\n /** Chain ID as a string (numeric for EVM, \"solana\"/\"bitcoin\"/\"tron\" for non-EVM, mirrors upstream). */\n chainId: string;\n /** Human-readable chain name, e.g. \"Ethereum\", \"Polygon\", \"Solana\". */\n chainName: string;\n /** Token metadata for this entry. */\n token: PolymarketBridgeToken;\n /** Minimum USD amount accepted by the bridge for this asset. */\n minCheckoutUsd: number;\n}\n\n/**\n * Response shape of `GET /api/v1/deposit/polymarket/supported-assets`.\n *\n * `supportedAssets` is the full list; consumers usually filter by `chainId`.\n */\nexport interface PolymarketSupportedAssetsResponse {\n supportedAssets: PolymarketSupportedAsset[];\n}\n\n/** Request body for `POST /api/v1/withdraw/polymarket/prepare`. */\nexport interface PolymarketWithdrawPrepareRequest {\n safe_address?: string;\n to?: string;\n wallet_address?: string;\n to_chain_id?: string;\n to_token_address?: string;\n recipient_address?: string;\n quote_id?: string;\n}\n\n/** Response from `POST /api/v1/withdraw/polymarket/prepare`. */\nexport interface PolymarketWithdrawPrepareResponse {\n deposit_address: string;\n bridge_address?: string;\n address_type?: \"evm\" | \"svm\" | \"tron\" | \"btc\" | string;\n quote_id?: string;\n}\n\n/** Request body for `POST /api/v1/withdraw/polymarket/execute`. */\nexport interface PolymarketWithdrawRequest {\n wallet_address: string;\n safe_address: string;\n to: string;\n /** Human-readable amount (e.g. \"10.5\"). */\n amount: string;\n}\n\n/** Response from `POST /api/v1/withdraw/polymarket/execute`. */\nexport interface PolymarketWithdrawResponse {\n transaction_id: string;\n status: string;\n}\n\nexport interface PolymarketWithdrawQuoteRequest {\n wallet_address: string;\n amount: string;\n to_chain_id: string;\n to_token_address: string;\n recipient_address: string;\n}\n\nexport interface PolymarketWithdrawQuoteResponse {\n quote_id: string;\n from_amount_base_unit: string;\n est_checkout_time_ms: number;\n est_input_usd: number;\n est_output_usd: number;\n est_to_token_base_unit: string;\n to_token_decimals: number;\n to_token_symbol: string;\n min_checkout_usd: number;\n est_fee_breakdown?: Record<string, unknown>;\n raw_bridge_quote?: Record<string, unknown>;\n}\n\nexport interface PolymarketTypedDataArg {\n name: string;\n type: string;\n}\n\nexport interface PolymarketTypedData {\n domain: Record<string, unknown>;\n types: Record<string, PolymarketTypedDataArg[]>;\n primaryType: string;\n message: Record<string, unknown>;\n}\n\nexport interface PolymarketWithdrawRelayBuildRequest {\n owner_address: string;\n wallet_address: string;\n bridge_address: string;\n amount: string;\n}\n\nexport interface PolymarketWithdrawRelayBuildResponse {\n typed_data: PolymarketTypedData;\n nonce: string;\n deadline: string;\n}\n\nexport interface PolymarketWithdrawRelaySubmitRequest {\n owner_address: string;\n wallet_address: string;\n bridge_address: string;\n amount: string;\n nonce: string;\n deadline: string;\n signature: string;\n}\n\nexport interface PolymarketWithdrawRelaySubmitResponse {\n transaction_id: string;\n status: string;\n bridge_address: string;\n}\n\nexport interface PolymarketWithdrawBridgeStatusResponse {\n bridge_address: string;\n transaction_id?: string;\n relayer_status?: string;\n transaction_hash?: string;\n bridge_status?: string;\n raw_bridge_status?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Orders\n// ---------------------------------------------------------------------------\n\n/** Lifecycle status of a user order. */\nexport type OrderStatus =\n | \"live\"\n | \"matched\"\n | \"cancelled\"\n | \"invalid\"\n | \"submitted\"\n | \"pending\"\n | \"open\"\n | \"pending_close\"\n | \"closed\"\n | \"failed\"\n | \"expired\";\n\n/** Order direction. */\nexport type OrderSide = \"BUY\" | \"SELL\";\n\n/** A single user order record. */\nexport interface PredictOrder {\n id: string;\n source: ProviderSource;\n status: OrderStatus;\n market_id?: string;\n asset_id?: string;\n side?: OrderSide;\n outcome?: string;\n price?: string;\n original_size?: string;\n size_matched?: string;\n in_amount?: string;\n out_amount?: string;\n order_type?: string;\n /** Unix seconds. */\n created_at?: number;\n expires_at?: number;\n provider_meta?: ProviderMeta;\n\n /** Enriched event context (populated by multi-wallet endpoint). */\n event?: EventSummary;\n /** Enriched market context (populated by multi-wallet endpoint). */\n market?: MarketSummary;\n}\n\n/** Query parameters for `GET /api/v1/orders`. */\nexport interface ListOrdersParams {\n /** Provider source. Omit to aggregate all providers. */\n source?: ProviderSource;\n wallet_address?: string;\n market_id?: string;\n asset_id?: string;\n next_cursor?: string;\n}\n\n/** Query parameters for multi-wallet `GET /api/v1/orders` mode. */\nexport interface ListOrdersMultiParams {\n kalshi_user?: string;\n polymarket_user?: string;\n}\n\n/** Response from multi-wallet `GET /api/v1/orders`. */\nexport interface PredictOrdersResponse {\n user?: string;\n wallets?: Record<string, string>;\n orders: PredictOrder[];\n}\n\n/** Result of `DELETE /api/v1/orders/{id}`. */\nexport interface CancelOrderResult {\n cancelled: string[];\n not_cancelled: Record<string, string>;\n}\n\n// ---------------------------------------------------------------------------\n// DFlow trading\n// ---------------------------------------------------------------------------\n\n/** Request body for `POST /api/v1/orders/kalshi/quote`. */\nexport interface DFlowQuoteRequest {\n inputMint: string;\n outputMint: string;\n amount: string;\n userPublicKey: string;\n slippageBps?: number;\n}\n\n/** Raw upstream response from DFlow quote (transparent passthrough). */\nexport type DFlowQuoteResponse = Record<string, unknown>;\n\n/** Context stored alongside a DFlow order for later enrichment. */\nexport interface DFlowOrderContext {\n user_public_key: string;\n input_mint: string;\n output_mint: string;\n amount: string;\n price: string;\n side: string;\n outcome: string;\n market_slug: string;\n slippage_bps: number;\n}\n\n/** Request body for `POST /api/v1/orders/kalshi/submit`. */\nexport interface DFlowSubmitRequest {\n signedTransaction: string;\n orderContext: DFlowOrderContext;\n}\n\n/** Response from `POST /api/v1/orders/kalshi/submit`. */\nexport interface DFlowSubmitResponse {\n signature: string;\n status: OrderStatus;\n}\n\n// ---------------------------------------------------------------------------\n// Polymarket trading\n// ---------------------------------------------------------------------------\n\n/** Order type for Polymarket CLOB. */\nexport type PolymarketOrderType = \"GTC\" | \"FOK\" | \"GTD\" | \"FAK\";\n\n/**\n * Known Polymarket minimum tick sizes. Must stay in sync with the\n * `ROUNDING_CONFIG` of `@polymarket/clob-client-v2` — sports markets use the\n * finer `0.005` / `0.0025` ticks introduced alongside CLOB V2.\n */\nexport type PolymarketTickSize =\n | \"0.1\"\n | \"0.01\"\n | \"0.005\"\n | \"0.0025\"\n | \"0.001\"\n | \"0.0001\";\n\n/**\n * Input for creating a Polymarket order (limit or market).\n * @see https://docs.polymarket.com/trading/orders/create\n */\nexport interface CreateOrderInput {\n /** Token ID (outcome asset ID) from market provider_meta. */\n tokenId: string;\n /** Price in range [0.01, 0.99]. */\n price: number;\n /**\n * Order size — meaning depends on order type:\n * - **Market BUY (FOK/FAK)**: USDC dollar amount to spend.\n * - **Market SELL (FOK/FAK)**: Number of shares to sell.\n * - **Limit BUY/SELL (GTC/GTD)**: Number of shares.\n *\n * This matches the official Polymarket SDK where `createMarketOrder` takes\n * `amount` (USDC for buy, shares for sell), while `createOrder` (limit)\n * takes `size` (always shares).\n * @see https://docs.polymarket.com/trading/orders/create#market-orders\n */\n size: number;\n side: OrderSide;\n orderType?: PolymarketOrderType;\n /** Minimum tick size for this market (from Polymarket gamma API). */\n tickSize: PolymarketTickSize;\n /** Whether this is a neg-risk market (uses different exchange contract). */\n negRisk?: boolean;\n /** Expiration timestamp (Unix seconds). Required for GTD orders. */\n expiration?: number;\n /**\n * The funder address that holds the USDC (proxy/Gnosis Safe wallet).\n * Defaults to the signer address when not provided.\n */\n funderAddress?: string;\n /**\n * Builder code (bytes32 hex, 0x-prefixed) for builder-rebate attribution.\n * Only honoured on CLOB V2 (POLY_1271 / deposit-wallet) orders — the V2\n * order struct carries a native `builder` field. Legacy V1 orders have no\n * builder field, so this is ignored there.\n */\n builderCode?: string;\n}\n\n/** Request body for `POST /api/v1/orders/polymarket/execute`. */\nexport interface PolymarketOrderExecuteRequest {\n /** Already signed Polymarket CLOB `/order` payload. */\n payload: unknown;\n /** L2 API key used as the CLOB order owner. */\n l2_api_key: string;\n /** L2 HMAC secret. */\n l2_secret: string;\n /** L2 HMAC passphrase. */\n l2_passphrase: string;\n /** L1 EVM signer address that owns the L2 credentials. */\n signer_address: string;\n /** Optional explicit owner override; defaults to l2_api_key server-side. */\n owner?: string;\n}\n\n/** Response from `POST /api/v1/orders/polymarket/execute`. */\nexport interface PolymarketOrderExecuteResponse {\n raw: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// KYC\n// ---------------------------------------------------------------------------\n\n/** Response from `GET /api/v1/kyc/kalshi?wallet_address=...`. */\nexport interface DFlowKYCStatus {\n wallet_address: string;\n verified: boolean;\n /** URL to redirect the user to for KYC onboarding (provided by server config). */\n kyc_url: string;\n}\n\n/**\n * Which Polymarket wallet model a user is on.\n * - `safe`: legacy Gnosis Safe (signatureType=2, USDC.e, V1 exchanges).\n * - `deposit`: CLOB V2 deposit wallet / ERC-1967 proxy\n * (signatureType=3 / POLY_1271, pUSD, V2 exchanges).\n */\nexport type PolymarketWalletKind = \"safe\" | \"deposit\";\n\n/** Response from `GET /api/v1/setup/polymarket?wallet_address=...`. */\nexport interface PolymarketSetupStatus {\n wallet_address: string;\n /** Active wallet model the caller should drive. */\n wallet_kind: PolymarketWalletKind;\n\n /** Legacy Safe fields. */\n safe_address?: string;\n safe_deployed: boolean;\n\n /** Deposit wallet (CLOB V2) fields. */\n deposit_wallet_address?: string;\n deposit_wallet_deployed: boolean;\n\n token_approved: boolean;\n /** True when the active wallet is deployed && token_approved. */\n verified: boolean;\n}\n\n/** Request body for `POST /api/v1/setup/polymarket/deposit/deploy`. */\nexport interface PolymarketDepositWalletDeployRequest {\n wallet_address: string;\n}\n\n/** Response from `POST /api/v1/setup/polymarket/deposit/deploy`. */\nexport interface PolymarketDepositWalletDeployResponse {\n deposit_wallet_address: string;\n deposit_wallet_deployed: boolean;\n transaction_id?: string;\n /** Relayer transaction state, e.g. \"STATE_CONFIRMED\". */\n status: string;\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket — mirrors prediction-server internal/domain/ws.go + protocol.go\n// ---------------------------------------------------------------------------\n\n/** WebSocket subscription channel. */\nexport type WsChannel = \"orderbook\" | \"prices\" | \"trades\";\n\n/** WebSocket connection lifecycle status. */\nexport type WsConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"disconnected\"\n | \"reconnecting\";\n\n/**\n * Full orderbook snapshot pushed via the `orderbook` channel.\n * Always a complete replacement — no delta merging required.\n */\nexport interface WsOrderbookEvent {\n market_slug: string;\n /** Outcome side this snapshot belongs to. */\n outcome?: OrderbookOutcome;\n bids: OrderbookLevel[];\n asks: OrderbookLevel[];\n spread?: number;\n}\n\n/** Latest bid/ask prices pushed via the `prices` channel. */\nexport interface WsPriceEvent {\n market_slug: string;\n yes_bid?: number;\n yes_ask?: number;\n no_bid?: number;\n no_ask?: number;\n spread?: number;\n}\n\n/** Single trade execution pushed via the `trades` channel. */\nexport interface WsTradeEvent {\n market_slug: string;\n trade_id?: string;\n side: string;\n price: number;\n size: number;\n outcome?: string;\n}\n\n/** Union of all channel data payloads. */\nexport type WsChannelEvent = WsOrderbookEvent | WsPriceEvent | WsTradeEvent;\n\n// -- Client → Server --------------------------------------------------------\n\n/** Subscribe or unsubscribe message sent to the server. */\nexport interface WsSubscribeMessage {\n type: \"subscribe\" | \"unsubscribe\";\n channels: WsChannel[];\n market_slugs: string[];\n}\n\n/** Client ping (application-level keepalive). */\nexport interface WsPingMessage {\n type: \"ping\";\n}\n\n/** Union of all messages the client can send. */\nexport type WsClientMessage = WsSubscribeMessage | WsPingMessage;\n\n// -- Server → Client --------------------------------------------------------\n\n/** Pong response to a client ping. */\nexport interface WsPongMessage {\n type: \"pong\";\n}\n\n/** Subscription confirmation. */\nexport interface WsSubscribedMessage {\n type: \"subscribed\";\n channels: WsChannel[];\n market_slugs: string[];\n}\n\n/** Error codes the server may return. */\nexport type WsErrorCode =\n | \"invalid_message\"\n | \"market_not_found\"\n | \"provider_unavailable\"\n | \"provider_reconnecting\";\n\n/** Error message from the server. */\nexport interface WsErrorMessage {\n type: \"error\";\n code: WsErrorCode;\n message: string;\n}\n\n/** Data message carrying a channel event payload. */\nexport interface WsDataMessage<T extends WsChannelEvent = WsChannelEvent> {\n channel: WsChannel;\n market_slug: string;\n data: T;\n ts: number;\n}\n\n/** Union of all messages the server can send. */\nexport type WsServerMessage =\n | WsPongMessage\n | WsSubscribedMessage\n | WsErrorMessage\n | WsDataMessage;\n\n// ---------------------------------------------------------------------------\n// Polymarket tick size\n// ---------------------------------------------------------------------------\n\n/** Response from the Polymarket tick-size endpoint. */\nexport interface TickSizeResponse {\n minimum_tick_size: number;\n}\n\n/** Response from the Polymarket fee-rate endpoint. */\nexport interface FeeRateResponse {\n base_fee: number;\n}\n\n// ---------------------------------------------------------------------------\n// Rebate / builder config\n// ---------------------------------------------------------------------------\n\n/**\n * Builder-attribution config from `GET /api/v1/referral/config`. The front-end\n * attaches {@link RebateConfig.builder_code} to CLOB V2 orders (when\n * {@link RebateConfig.builder_enabled}) so fills are credited to our builder\n * program for rebates.\n */\nexport interface RebateConfig {\n builder_enabled: boolean;\n /** Builder code (bytes32 hex, 0x-prefixed). Empty when not configured. */\n builder_code: string;\n builder_taker_fee_bps: number;\n builder_maker_fee_bps: number;\n commission_ratio: number;\n}\n\n// ---------------------------------------------------------------------------\n// Event stats (aggregate)\n// ---------------------------------------------------------------------------\n\n/** Aggregate statistics for all open prediction events. */\nexport interface EventStats {\n total_events: number;\n total_volume_24h: number;\n avg_liquidity: number;\n active_sources: number;\n}\n\n// ---------------------------------------------------------------------------\n// Available shares (for sell flow)\n// ---------------------------------------------------------------------------\n\n/** Response from the available-shares endpoint. */\nexport interface AvailableSharesResponse {\n source: ProviderSource;\n market: string;\n side: string;\n total_shares: number;\n active_order_shares: number;\n available_shares: number;\n precision: number;\n}\n\n// ---------------------------------------------------------------------------\n// Redeem (resolved market redemption)\n// ---------------------------------------------------------------------------\n\n/** Input for the redeem prepare endpoint — returns EIP-712 typed data to sign. */\nexport interface PolymarketRedeemPrepareInput {\n wallet_address: string;\n condition_id: string;\n neg_risk: boolean;\n}\n\n/** Response from the redeem prepare endpoint. */\nexport interface PolymarketRedeemPrepareResponse {\n /** Active Polymarket wallet kind for redeem execution. */\n wallet_kind?: PolymarketWalletKind;\n /** Active smart-contract wallet that holds the redeemable position. */\n wallet_address?: string;\n /** Legacy Gnosis Safe wallet address, present when wallet_kind is \"safe\". */\n safe_address?: string;\n /** CLOB V2 deposit wallet address, present when wallet_kind is \"deposit\". */\n deposit_wallet_address?: string;\n nonce: string;\n /** Deposit-wallet Batch deadline, present when wallet_kind is \"deposit\". */\n deadline?: string;\n /** Deposit-wallet Batch typed data. Sign with eth_signTypedData_v4. */\n typed_data?: PolymarketTypedData;\n /** Legacy SafeTx hash (0x-prefixed). Sign with personal_sign. */\n message_hash?: string;\n}\n\n/** Input for redeeming tokens — includes the EIP-712 signature. */\nexport interface PolymarketRedeemInput {\n wallet_address: string;\n condition_id: string;\n neg_risk: boolean;\n signature: string;\n nonce: string;\n wallet_kind?: PolymarketWalletKind;\n deadline?: string;\n}\n\n/** Response from the Polymarket redeem endpoint. */\nexport interface PolymarketRedeemResponse {\n transaction_id: string;\n transaction_hash?: string;\n status: string;\n}\n","import { httpGet, httpPost, httpDelete } from \"@liberfi.io/utils\";\nimport { MARKET_STRUCTURE_MEDIA_TYPE_V1 } from \"./types\";\nimport type {\n AvailableSharesResponse,\n BalanceResponse,\n CancelOrderResult,\n Candlestick,\n DepositBuildRequest,\n DepositBuildResponse,\n DepositSubmitRequest,\n DepositSubmitResponse,\n DepositStatusResponse,\n DFlowKYCStatus,\n DFlowQuoteRequest,\n DFlowQuoteResponse,\n DFlowSubmitRequest,\n DFlowSubmitResponse,\n EventStats,\n ListCandlesticksParams,\n ListCommentsParams,\n ListEventsParams,\n ListMarketTradesParams,\n ListOrdersParams,\n ListOrdersMultiParams,\n ListTradesParams,\n ListTradesMultiParams,\n MatchesParams,\n MatchGroup,\n MatchGroupPage,\n MatchMarketParams,\n MatchMarketPage,\n MarketDataMarketKey,\n MarketDataOrderbooksResponse,\n MarketDataQuotesResponse,\n MarketDataWatchRequest,\n MarketDataWatchResponse,\n MarketStructureHttpResponse,\n MarketStructureResponse,\n Orderbook,\n OrderbookBatchItem,\n OrderbookBatchResult,\n OrderbookOutcome,\n OrderbooksBatchResponse,\n PolymarketDepositAddresses,\n PolymarketOrderExecuteRequest,\n PolymarketOrderExecuteResponse,\n PolymarketSupportedAsset,\n PolymarketSupportedAssetsResponse,\n PolymarketSetupStatus,\n PolymarketDepositWalletDeployResponse,\n PolymarketWithdrawBridgeStatusResponse,\n PolymarketWithdrawQuoteRequest,\n PolymarketWithdrawQuoteResponse,\n PolymarketWithdrawRelayBuildRequest,\n PolymarketWithdrawRelayBuildResponse,\n PolymarketWithdrawRelaySubmitRequest,\n PolymarketWithdrawRelaySubmitResponse,\n PolymarketWithdrawPrepareRequest,\n PolymarketWithdrawPrepareResponse,\n PolymarketRedeemPrepareInput,\n PolymarketRedeemPrepareResponse,\n PolymarketRedeemInput,\n PolymarketRedeemResponse,\n PolymarketWithdrawRequest,\n PolymarketWithdrawResponse,\n PredictComment,\n PredictEvent,\n PredictMarket,\n PredictOrder,\n PredictOrdersResponse,\n PredictPage,\n PredictTrade,\n PositionValueResponse,\n PositionsResponse,\n PriceHistoryRange,\n PriceHistoryParams,\n PriceHistoryResponse,\n ProviderSource,\n SimilarEventsParams,\n WithdrawBuildRequest,\n WithdrawBuildResponse,\n WithdrawSubmitRequest,\n WithdrawSubmitResponse,\n WithdrawStatusResponse,\n TickSizeResponse,\n FeeRateResponse,\n RebateConfig,\n EsportsMatchDetailParams,\n EsportsMatchesParams,\n EsportsPropsParams,\n EsportsTaxonomyParams,\n PredictSearchParams,\n PredictSearchResponse,\n SportsMatchDetail,\n SportsMatchDetailParams,\n SportsMatchesParams,\n SportsMatchesResponse,\n SportsPropsParams,\n SportsPropsResponse,\n SportsRoutingParams,\n SportsRoutingResponse,\n SportsTaxonomyParams,\n SportsTaxonomyResponse,\n} from \"./types\";\n\nexport interface PredictClientOptions {\n headers?: HeadersInit | (() => HeadersInit | undefined);\n}\n\nexport class MarketDataHttpError extends Error {\n readonly name = \"MarketDataHttpError\";\n\n constructor(\n message: string,\n readonly status: number,\n readonly code?: string,\n readonly retryAfter?: string,\n readonly body?: unknown,\n ) {\n super(message);\n }\n}\n\n/**\n * Build a URL query string from a params object.\n * `undefined` and `null` values are omitted.\n * Boolean values are serialised as \"true\" / \"false\" strings.\n */\nfunction buildQuery(params: Record<string, unknown>): string {\n const qs = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n qs.set(key, String(value));\n }\n }\n const str = qs.toString();\n return str ? `?${str}` : \"\";\n}\n\n/**\n * HTTP client for the prediction-server REST API.\n *\n * Covers all prediction, market, order, position, and trading endpoints.\n *\n * @example\n * ```ts\n * const client = new PredictClient(\"https://api.example.com\");\n * const page = await client.listEvents({ status: \"open\", limit: 20 });\n * const event = await client.getEvent(\"will-trump-win-2024\");\n * const market = await client.getMarket(\"will-trump-win-2024-yes\");\n * ```\n */\nexport class PredictClient {\n constructor(\n private readonly endpoint: string,\n private readonly options: PredictClientOptions = {},\n ) {}\n\n private requestOptions(options?: RequestInit): RequestInit | undefined {\n const baseHeaders =\n typeof this.options.headers === \"function\"\n ? this.options.headers()\n : this.options.headers;\n if (!baseHeaders && !options) return undefined;\n return {\n ...options,\n headers: {\n ...(baseHeaders ? Object.fromEntries(new Headers(baseHeaders)) : {}),\n ...(options?.headers\n ? Object.fromEntries(new Headers(options.headers))\n : {}),\n },\n };\n }\n\n private async marketDataRequest<R>(\n path: string,\n options: RequestInit,\n ): Promise<R> {\n const response = await fetch(\n `${this.endpoint}${path}`,\n this.requestOptions(options),\n );\n if (response.ok) {\n return (await response.json()) as R;\n }\n const body = await parseMarketDataResponseBody(response);\n const record = isRecord(body) ? body : undefined;\n const code =\n typeof record?.error === \"string\"\n ? record.error\n : typeof record?.code === \"string\"\n ? record.code\n : undefined;\n const message =\n typeof record?.message === \"string\"\n ? record.message\n : (code ?? response.statusText ?? `HTTP ${response.status}`);\n throw new MarketDataHttpError(\n message,\n response.status,\n code,\n response.headers.get(\"Retry-After\") ?? undefined,\n body,\n );\n }\n\n // -------------------------------------------------------------------------\n // Events\n // -------------------------------------------------------------------------\n\n /**\n * List prediction events with optional filtering, sorting, and pagination.\n *\n * Maps to `GET /api/v1/events`.\n *\n * @param params - Optional query parameters (filter, sort, pagination).\n * @returns A paginated page of events.\n */\n async listEvents(\n params?: ListEventsParams,\n ): Promise<PredictPage<PredictEvent>> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/events${query}`;\n return await httpGet<PredictPage<PredictEvent>>(url, this.requestOptions());\n }\n\n /**\n * Fetch a single prediction event by its slug.\n *\n * Maps to `GET /api/v1/events/:slug?source=...`.\n *\n * @param slug - Canonical event slug (e.g. \"will-trump-win-2024\" for Polymarket\n * or \"KXBTCD-25FEB-T68000\" for Kalshi).\n * @param source - Upstream provider (`\"kalshi\"` or `\"polymarket\"`).\n * @returns The matching event.\n * @throws When the server responds with 404 or any other non-2xx status.\n */\n async getEvent(\n slug: string,\n source?: ProviderSource,\n params?: { lang?: string },\n ): Promise<PredictEvent> {\n const query = buildQuery({ source, ...params });\n const url = `${this.endpoint}/api/v1/events/${encodeURIComponent(slug)}${query}`;\n return await httpGet<PredictEvent>(url, this.requestOptions());\n }\n\n /**\n * Fetch aggregate statistics for all open events.\n *\n * Maps to `GET /api/v1/events/stats`.\n */\n async getEventStats(): Promise<EventStats> {\n const url = `${this.endpoint}/api/v1/events/stats`;\n return await httpGet<EventStats>(url);\n }\n\n /**\n * Fetch events similar to the given slug.\n *\n * Maps to `GET /api/v1/events/:slug/similar?source=...`.\n */\n async getSimilarEvents(\n slug: string,\n source: ProviderSource,\n params?: SimilarEventsParams,\n ): Promise<PredictEvent[]> {\n const query = buildQuery({ source, ...params });\n const url = `${this.endpoint}/api/v1/events/${encodeURIComponent(slug)}/similar${query}`;\n return await httpGet<PredictEvent[]>(url);\n }\n\n // -------------------------------------------------------------------------\n // Sports / esports\n // -------------------------------------------------------------------------\n\n /** Maps to `GET /api/v1/sports/taxonomy`. */\n async getSportsTaxonomy(\n params?: SportsTaxonomyParams,\n ): Promise<SportsTaxonomyResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/taxonomy${query}`;\n return await httpGet<SportsTaxonomyResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/matches`. */\n async getSportsMatches(\n params?: SportsMatchesParams,\n ): Promise<SportsMatchesResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/matches${query}`;\n return await httpGet<SportsMatchesResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/props`. */\n async getSportsProps(\n params?: SportsPropsParams,\n ): Promise<SportsPropsResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/props${query}`;\n return await httpGet<SportsPropsResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/esports/taxonomy`. */\n async getEsportsTaxonomy(\n params?: EsportsTaxonomyParams,\n ): Promise<SportsTaxonomyResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/esports/taxonomy${query}`;\n return await httpGet<SportsTaxonomyResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/esports/matches`. */\n async getEsportsMatches(\n params?: EsportsMatchesParams,\n ): Promise<SportsMatchesResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/esports/matches${query}`;\n return await httpGet<SportsMatchesResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/esports/props`. */\n async getEsportsProps(\n params?: EsportsPropsParams,\n ): Promise<SportsPropsResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/esports/props${query}`;\n return await httpGet<SportsPropsResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/routing/:slug`. */\n async getSportsRouting(\n slug: string,\n params?: SportsRoutingParams,\n ): Promise<SportsRoutingResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/sports/routing/${encodeURIComponent(slug)}${query}`;\n return await httpGet<SportsRoutingResponse>(url, this.requestOptions());\n }\n\n /** Maps to `GET /api/v1/sports/matches/:match_group_slug`. */\n async getSportsMatchDetail(\n section: \"sports\" | \"esports\",\n matchGroupSlug: string,\n params?: SportsMatchDetailParams,\n ): Promise<SportsMatchDetail> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/${encodeURIComponent(section)}/matches/${encodeURIComponent(matchGroupSlug)}${query}`;\n return await httpGet<SportsMatchDetail>(url, this.requestOptions());\n }\n\n /** Convenience wrapper for `GET /api/v1/esports/matches/:match_group_slug`. */\n async getEsportsMatchDetail(\n matchGroupSlug: string,\n params?: EsportsMatchDetailParams,\n ): Promise<SportsMatchDetail> {\n return this.getSportsMatchDetail(\"esports\", matchGroupSlug, params);\n }\n\n /** Maps to `GET /api/v1/search`. */\n async search(params?: PredictSearchParams): Promise<PredictSearchResponse> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/search${query}`;\n return await httpGet<PredictSearchResponse>(url, this.requestOptions());\n }\n\n /**\n * List comments for a prediction event.\n *\n * Maps to `GET /api/v1/events/:slug/comments`.\n *\n * The server resolves the event to its parent series when one exists\n * (Polymarket attaches discussion at the series level for grouped events such\n * as World Cup matches) and otherwise returns event-level comments. Callers\n * stay unaware of the event-vs-series distinction.\n *\n * @param slug - Canonical event slug.\n * @param params - Query parameters (source, pagination, sort, holders filter).\n * @returns A paginated page of comments.\n */\n async listEventComments(\n slug: string,\n params: ListCommentsParams,\n ): Promise<PredictPage<PredictComment>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/events/${encodeURIComponent(slug)}/comments${query}`;\n return await httpGet<PredictPage<PredictComment>>(url);\n }\n\n // -------------------------------------------------------------------------\n // Markets\n // -------------------------------------------------------------------------\n\n /** Register or refresh the complete provider-neutral market-data demand set. */\n async watchMarketData(\n request: MarketDataWatchRequest,\n ): Promise<MarketDataWatchResponse> {\n return await this.marketDataRequest<MarketDataWatchResponse>(\n \"/api/v1/market-data/watch\",\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n }\n\n /** Read cache-only quote snapshots for at most 500 provider-neutral keys. */\n async getMarketDataQuotes(\n markets: MarketDataMarketKey[],\n ): Promise<MarketDataQuotesResponse> {\n if (markets.length > 500) {\n throw new RangeError(\n \"market data quote request accepts at most 500 markets\",\n );\n }\n return await this.marketDataRequest<MarketDataQuotesResponse>(\n \"/api/v1/markets/quotes\",\n {\n method: \"POST\",\n cache: \"no-store\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ markets }),\n },\n );\n }\n\n /** Read all cached Top20 outcome books for one provider-neutral market. */\n async getMarketDataOrderbooks(\n slug: string,\n source: ProviderSource,\n ): Promise<MarketDataOrderbooksResponse> {\n const path =\n `/api/v1/markets/${encodeURIComponent(slug)}/orderbooks` +\n buildQuery({ source });\n return await this.marketDataRequest<MarketDataOrderbooksResponse>(path, {\n method: \"GET\",\n cache: \"no-store\",\n });\n }\n\n /**\n * Revalidate a page's allowlist-only structure representation.\n *\n * The path must remain inside the prediction API so callers cannot turn a\n * configured authenticated client into a cross-origin request primitive.\n */\n async getMarketStructure(\n path: string,\n ifNoneMatch?: string,\n ): Promise<MarketStructureHttpResponse> {\n if (!path.startsWith(\"/api/v1/\")) {\n throw new TypeError(\"market structure path must start with /api/v1/\");\n }\n const response = await fetch(\n `${this.endpoint}${path}`,\n this.requestOptions({\n method: \"GET\",\n cache: \"no-store\",\n headers: {\n Accept: MARKET_STRUCTURE_MEDIA_TYPE_V1,\n ...(ifNoneMatch ? { \"If-None-Match\": ifNoneMatch } : {}),\n },\n }),\n );\n const etag = response.headers.get(\"ETag\") ?? \"\";\n if (response.status === 304) {\n return { status: 304, etag };\n }\n if (response.ok) {\n return {\n status: 200,\n etag,\n body: (await response.json()) as MarketStructureResponse,\n };\n }\n const body = await parseMarketDataResponseBody(response);\n const record = isRecord(body) ? body : undefined;\n const code = typeof record?.error === \"string\" ? record.error : undefined;\n throw new MarketDataHttpError(\n typeof record?.message === \"string\"\n ? record.message\n : (code ?? response.statusText),\n response.status,\n code,\n response.headers.get(\"Retry-After\") ?? undefined,\n body,\n );\n }\n\n /**\n * Fetch a single prediction market by its slug.\n *\n * Maps to `GET /api/v1/markets/:slug?source=...`.\n *\n * @param slug - Canonical market slug.\n * @param source - Upstream provider (`\"kalshi\"` or `\"polymarket\"`).\n * @returns The matching market.\n * @throws When the server responds with 404 or any other non-2xx status.\n */\n async getMarket(\n slug: string,\n source?: ProviderSource,\n ): Promise<PredictMarket> {\n const query = source ? buildQuery({ source }) : \"\";\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}${query}`;\n return await httpGet<PredictMarket>(url);\n }\n\n /** Maps to `GET /api/v1/markets/:slug/orderbook?source=...&outcome=...`. */\n async getOrderbook(\n slug: string,\n source: ProviderSource,\n outcome?: OrderbookOutcome,\n ): Promise<Orderbook> {\n const query = buildQuery({ source, outcome });\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/orderbook${query}`;\n return await httpGet<Orderbook>(url);\n }\n\n /**\n * Maps to `POST /api/v1/markets/orderbooks`.\n * Fetches order books for many markets in a single request (max 100 items).\n * Results are returned in the same order as `items`; per-item failures are\n * reported via `OrderbookBatchResult.error` and never fail the whole batch.\n */\n async getOrderbooks(\n items: OrderbookBatchItem[],\n ): Promise<OrderbookBatchResult[]> {\n const url = `${this.endpoint}/api/v1/markets/orderbooks`;\n const res = await httpPost<OrderbooksBatchResponse>(url, { items });\n return res.results;\n }\n\n /** Maps to `GET /api/v1/markets/:slug/trades?source=...`. */\n async listMarketTrades(\n slug: string,\n params: ListMarketTradesParams,\n ): Promise<PredictPage<PredictTrade>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/trades${query}`;\n return await httpGet<PredictPage<PredictTrade>>(url);\n }\n\n /** Maps to `GET /api/v1/markets/:slug/price-history?source=...&range=...`. */\n async getPriceHistory(\n slug: string,\n sourceOrParams: ProviderSource | PriceHistoryParams,\n range?: PriceHistoryRange,\n ): Promise<PriceHistoryResponse> {\n const params =\n typeof sourceOrParams === \"string\"\n ? { source: sourceOrParams, range }\n : sourceOrParams;\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/price-history${query}`;\n return await httpGet<PriceHistoryResponse>(url);\n }\n\n /** Maps to `GET /api/v1/markets/:slug/candlesticks?interval=...&limit=...`. */\n async listCandlesticks(\n slug: string,\n params?: ListCandlesticksParams,\n ): Promise<Candlestick[]> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/candlesticks${query}`;\n return await httpGet<Candlestick[]>(url);\n }\n\n // -------------------------------------------------------------------------\n // Positions\n // -------------------------------------------------------------------------\n\n /**\n * Maps to `GET /api/v1/positions`.\n *\n * Single-source: `getPositions(\"addr\", \"kalshi\")`.\n * Multi-wallet: `getPositions({ kalshi_user: \"SOLaddr\", polymarket_user: \"EVMaddr\" })`.\n * Legacy agg: `getPositions(\"addr\")` (same address for all providers).\n */\n async getPositions(\n userOrWallets: string | { kalshi_user?: string; polymarket_user?: string },\n source?: ProviderSource,\n ): Promise<PositionsResponse> {\n let query: string;\n if (typeof userOrWallets === \"string\") {\n query = buildQuery({ source, user: userOrWallets });\n } else {\n query = buildQuery(userOrWallets as Record<string, unknown>);\n }\n const url = `${this.endpoint}/api/v1/positions${query}`;\n return await httpGet<PositionsResponse>(url);\n }\n\n /**\n * Maps to `GET /api/v1/positions/value`.\n *\n * Single-source: `getPositionValue(\"addr\", \"polymarket\")`.\n * Multi-wallet: `getPositionValue({ kalshi_user: \"SOLaddr\", polymarket_user: \"EVMaddr\" })`.\n * Legacy agg: `getPositionValue(\"addr\")` (same address for all providers).\n */\n async getPositionValue(\n userOrWallets: string | { kalshi_user?: string; polymarket_user?: string },\n source?: ProviderSource,\n ): Promise<PositionValueResponse> {\n let query: string;\n if (typeof userOrWallets === \"string\") {\n query = buildQuery({ source, user: userOrWallets });\n } else {\n query = buildQuery(userOrWallets as Record<string, unknown>);\n }\n const url = `${this.endpoint}/api/v1/positions/value${query}`;\n return await httpGet<PositionValueResponse>(url);\n }\n\n // -------------------------------------------------------------------------\n // Available shares (for sell flow)\n // -------------------------------------------------------------------------\n\n /**\n * Get the number of shares available for selling, accounting for active orders.\n *\n * Maps to `GET /api/v1/available-shares?source=...&user=...&market=...&side=...`.\n *\n * @param source - Provider source.\n * @param user - Wallet address.\n * @param market - Market slug.\n * @param side - Position side (\"yes\" or \"no\").\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async getAvailableShares(\n source: ProviderSource,\n user: string,\n market: string,\n side: string,\n headers?: Record<string, string>,\n ): Promise<AvailableSharesResponse> {\n const query = buildQuery({ source, user, market, side });\n const url = `${this.endpoint}/api/v1/available-shares${query}`;\n return await httpGet<AvailableSharesResponse>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n // -------------------------------------------------------------------------\n // Balance\n // -------------------------------------------------------------------------\n\n /**\n * Get the on-chain USDC balance for a wallet.\n *\n * Maps to `GET /api/v1/balance?source=...&user=...`.\n *\n * @param source - Provider source (`\"kalshi\"` for Solana, `\"polymarket\"` for Polygon).\n * @param user - Wallet address.\n */\n async getBalance(\n source: ProviderSource,\n user: string,\n ): Promise<BalanceResponse> {\n const query = buildQuery({ source, user });\n const url = `${this.endpoint}/api/v1/balance${query}`;\n return await httpGet<BalanceResponse>(url);\n }\n\n // -------------------------------------------------------------------------\n // Orders\n // -------------------------------------------------------------------------\n\n /**\n * Maps to `GET /api/v1/orders?source=...&wallet_address=...`.\n *\n * @param params - Query parameters (source, wallet_address, etc.).\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async listOrders(\n params: ListOrdersParams,\n headers?: Record<string, string>,\n ): Promise<PredictPage<PredictOrder>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/orders${query}`;\n return await httpGet<PredictPage<PredictOrder>>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n /**\n * Multi-wallet order listing with enriched market/event context.\n *\n * Maps to `GET /api/v1/orders?kalshi_user=...&polymarket_user=...`.\n *\n * @param params - Per-provider wallet addresses.\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async listOrdersMulti(\n params: ListOrdersMultiParams,\n headers?: Record<string, string>,\n ): Promise<PredictOrdersResponse> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/orders${query}`;\n return await httpGet<PredictOrdersResponse>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n /**\n * Maps to `GET /api/v1/orders/:id?source=...`.\n *\n * @param id - Order ID.\n * @param source - Provider source.\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async getOrder(\n id: string,\n source: ProviderSource,\n headers?: Record<string, string>,\n ): Promise<PredictOrder> {\n const query = buildQuery({ source });\n const url = `${this.endpoint}/api/v1/orders/${encodeURIComponent(id)}${query}`;\n return await httpGet<PredictOrder>(url, headers ? { headers } : undefined);\n }\n\n /**\n * Maps to `DELETE /api/v1/orders/:id?source=...`.\n *\n * @param id - Order ID.\n * @param source - Provider source.\n * @param headers - Optional extra headers (e.g. Polymarket POLY_* HMAC headers).\n */\n async cancelOrder(\n id: string,\n source: ProviderSource,\n headers?: Record<string, string>,\n ): Promise<CancelOrderResult> {\n const query = buildQuery({ source });\n const url = `${this.endpoint}/api/v1/orders/${encodeURIComponent(id)}${query}`;\n return await httpDelete<CancelOrderResult>(\n url,\n headers ? { headers } : undefined,\n );\n }\n\n // -------------------------------------------------------------------------\n // Polymarket trading\n // -------------------------------------------------------------------------\n\n /**\n * Execute an already signed Polymarket CLOB order through prediction-server.\n *\n * Maps to `POST /api/v1/orders/polymarket/execute`. The server builds the\n * CLOB HMAC headers from the provided L2 credentials, forwards `payload`\n * unchanged to `/order`, and records rebate identity mappings.\n */\n async executePolymarketOrder(\n req: PolymarketOrderExecuteRequest,\n ): Promise<PolymarketOrderExecuteResponse> {\n const url = `${this.endpoint}/api/v1/orders/polymarket/execute`;\n return await httpPost<PolymarketOrderExecuteResponse>(url, req);\n }\n\n /** Maps to `GET /api/v1/polymarket/tick-size?token_id=xxx`. */\n async getPolymarketTickSize(tokenId: string): Promise<TickSizeResponse> {\n const url = `${this.endpoint}/api/v1/polymarket/tick-size?token_id=${encodeURIComponent(tokenId)}`;\n return await httpGet<TickSizeResponse>(url);\n }\n\n /** Maps to `GET /api/v1/polymarket/fee-rate?token_id=xxx`. */\n async getPolymarketFeeRate(tokenId: string): Promise<FeeRateResponse> {\n const url = `${this.endpoint}/api/v1/polymarket/fee-rate?token_id=${encodeURIComponent(tokenId)}`;\n return await httpGet<FeeRateResponse>(url);\n }\n\n /**\n * Builder-attribution / rebate config. Maps to `GET /api/v1/referral/config`.\n * The front-end uses `builder_code` (when `builder_enabled`) to attribute\n * CLOB V2 orders to our builder program.\n */\n async getRebateConfig(): Promise<RebateConfig> {\n const url = `${this.endpoint}/api/v1/referral/config`;\n return await httpGet<RebateConfig>(url);\n }\n\n // -------------------------------------------------------------------------\n // DFlow trading\n // -------------------------------------------------------------------------\n\n /** Maps to `POST /api/v1/orders/kalshi/quote`. */\n async createDFlowQuote(body: DFlowQuoteRequest): Promise<DFlowQuoteResponse> {\n const url = `${this.endpoint}/api/v1/orders/kalshi/quote`;\n return await httpPost<DFlowQuoteResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/orders/kalshi/submit`. */\n async submitDFlowTransaction(\n body: DFlowSubmitRequest,\n ): Promise<DFlowSubmitResponse> {\n const url = `${this.endpoint}/api/v1/orders/kalshi/submit`;\n return await httpPost<DFlowSubmitResponse>(url, body);\n }\n\n // -------------------------------------------------------------------------\n // KYC\n // -------------------------------------------------------------------------\n\n /**\n * Check DFlow KYC verification status for a wallet address.\n *\n * Maps to `GET /api/v1/kyc/kalshi?wallet_address=...`.\n */\n async checkDFlowKYC(walletAddress: string): Promise<DFlowKYCStatus> {\n const query = buildQuery({ wallet_address: walletAddress });\n const url = `${this.endpoint}/api/v1/kyc/kalshi${query}`;\n return await httpGet<DFlowKYCStatus>(url);\n }\n\n // -------------------------------------------------------------------------\n // Polymarket wallet setup\n // -------------------------------------------------------------------------\n\n /**\n * Check Polymarket wallet setup status (Safe deployed + USDC.e approved).\n *\n * Maps to `GET /api/v1/setup/polymarket?wallet_address=...`.\n */\n async checkPolymarketSetup(\n walletAddress: string,\n ): Promise<PolymarketSetupStatus> {\n const query = buildQuery({ wallet_address: walletAddress });\n const url = `${this.endpoint}/api/v1/setup/polymarket${query}`;\n return await httpGet<PolymarketSetupStatus>(url);\n }\n\n /**\n * Run Polymarket wallet setup (deploy Safe + approve USDC.e).\n *\n * Maps to `POST /api/v1/setup/polymarket`.\n */\n async runPolymarketSetup(\n walletAddress: string,\n ): Promise<PolymarketSetupStatus> {\n const url = `${this.endpoint}/api/v1/setup/polymarket`;\n return await httpPost<PolymarketSetupStatus>(url, {\n wallet_address: walletAddress,\n });\n }\n\n /**\n * Deploy a Polymarket CLOB V2 deposit wallet (gasless WALLET-CREATE).\n *\n * No user signature is required — the relayer deploys the per-user\n * ERC-1967 proxy and the server waits until it is confirmed on-chain.\n * Used for new (non-Safe) users on the POLY_1271 path.\n *\n * Maps to `POST /api/v1/setup/polymarket/deposit/deploy`.\n */\n async deployPolymarketDepositWallet(\n walletAddress: string,\n ): Promise<PolymarketDepositWalletDeployResponse> {\n const url = `${this.endpoint}/api/v1/setup/polymarket/deposit/deploy`;\n return await httpPost<PolymarketDepositWalletDeployResponse>(url, {\n wallet_address: walletAddress,\n });\n }\n\n // -------------------------------------------------------------------------\n // Cross-platform matches\n // -------------------------------------------------------------------------\n\n /**\n * List cross-platform matched event groups with inline aggregate stats.\n *\n * Maps to `GET /api/v1/matches`.\n */\n async listMatches(params?: MatchesParams): Promise<MatchGroupPage> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/matches${query}`;\n return await httpGet<MatchGroupPage>(url);\n }\n\n /**\n * Fetch a single match group by ID.\n *\n * Maps to `GET /api/v1/matches/:id`.\n */\n async getMatch(id: number): Promise<MatchGroup> {\n const url = `${this.endpoint}/api/v1/matches/${id}`;\n return await httpGet<MatchGroup>(url);\n }\n\n /**\n * List flattened market pairs across match groups (market-level granularity).\n *\n * Maps to `GET /api/v1/matches/markets`.\n */\n async listMatchMarkets(params?: MatchMarketParams): Promise<MatchMarketPage> {\n const query = buildQuery((params ?? {}) as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/matches/markets${query}`;\n return await httpGet<MatchMarketPage>(url);\n }\n\n // -------------------------------------------------------------------------\n // Trades by wallet\n // -------------------------------------------------------------------------\n\n /** Maps to `GET /api/v1/trades?source=...&wallet=...`. */\n async listTrades(\n params: ListTradesParams,\n ): Promise<PredictPage<PredictTrade>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/trades${query}`;\n return await httpGet<PredictPage<PredictTrade>>(url);\n }\n\n /** Maps to `GET /api/v1/trades?kalshi_user=...&polymarket_user=...`. */\n async listTradesMulti(\n params: ListTradesMultiParams,\n ): Promise<PredictPage<PredictTrade>> {\n const query = buildQuery(params as unknown as Record<string, unknown>);\n const url = `${this.endpoint}/api/v1/trades${query}`;\n return await httpGet<PredictPage<PredictTrade>>(url);\n }\n\n // -------------------------------------------------------------------------\n // Withdraw\n // -------------------------------------------------------------------------\n\n /** Maps to `POST /api/v1/withdraw/build`. */\n async withdrawBuild(\n body: WithdrawBuildRequest,\n ): Promise<WithdrawBuildResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/build`;\n return await httpPost<WithdrawBuildResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/withdraw/submit`. */\n async withdrawSubmit(\n body: WithdrawSubmitRequest,\n ): Promise<WithdrawSubmitResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/submit`;\n return await httpPost<WithdrawSubmitResponse>(url, body);\n }\n\n /** Maps to `GET /api/v1/withdraw/status?tx_hash=...&source=...`. */\n async withdrawStatus(\n txHash: string,\n source: ProviderSource,\n ): Promise<WithdrawStatusResponse> {\n const query = buildQuery({ tx_hash: txHash, source });\n const url = `${this.endpoint}/api/v1/withdraw/status${query}`;\n return await httpGet<WithdrawStatusResponse>(url);\n }\n\n // -------------------------------------------------------------------------\n // Deposit (native USDC → USDC.e for Polymarket)\n // -------------------------------------------------------------------------\n\n /**\n * Build unsigned deposit transactions (approve + Uniswap V3 swap).\n *\n * The server checks the Safe's USDC.e balance and returns only\n * the transactions needed to cover the shortfall.\n *\n * Maps to `POST /api/v1/deposit/polymarket/build`.\n */\n async depositBuild(body: DepositBuildRequest): Promise<DepositBuildResponse> {\n const url = `${this.endpoint}/api/v1/deposit/polymarket/build`;\n return await httpPost<DepositBuildResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/deposit/polymarket/submit`. */\n async depositSubmit(\n body: DepositSubmitRequest,\n ): Promise<DepositSubmitResponse> {\n const url = `${this.endpoint}/api/v1/deposit/polymarket/submit`;\n return await httpPost<DepositSubmitResponse>(url, body);\n }\n\n /** Maps to `GET /api/v1/deposit/polymarket/status?tx_hash=...&source=...`. */\n async depositStatus(\n txHash: string,\n source: ProviderSource,\n ): Promise<DepositStatusResponse> {\n const query = buildQuery({ tx_hash: txHash, source });\n const url = `${this.endpoint}/api/v1/deposit/polymarket/status${query}`;\n return await httpGet<DepositStatusResponse>(url);\n }\n\n /**\n * Get multi-chain deposit addresses for a Polymarket Safe wallet via Bridge API.\n *\n * Maps to `GET /api/v1/deposit/polymarket/addresses?safe_address=...`.\n */\n async getPolymarketDepositAddresses(\n safeAddress: string,\n ): Promise<PolymarketDepositAddresses> {\n const query = buildQuery({ safe_address: safeAddress });\n const url = `${this.endpoint}/api/v1/deposit/polymarket/addresses${query}`;\n return await httpGet<PolymarketDepositAddresses>(url);\n }\n\n /**\n * List the Polymarket Bridge supported (chain, token) tuples along with\n * the per-asset minimum USD deposit amount.\n *\n * The list is the same for every caller; backend caches it for 15 minutes.\n *\n * Maps to `GET /api/v1/deposit/polymarket/supported-assets`.\n */\n async getPolymarketSupportedAssets(): Promise<PolymarketSupportedAsset[]> {\n const url = `${this.endpoint}/api/v1/deposit/polymarket/supported-assets`;\n const data = await httpGet<PolymarketSupportedAssetsResponse>(url);\n return data.supportedAssets ?? [];\n }\n\n // -------------------------------------------------------------------------\n // Polymarket Relayer Withdraw\n // -------------------------------------------------------------------------\n\n /** Maps to `POST /api/v1/withdraw/polymarket/quote`. */\n async quotePolymarketWithdraw(\n body: PolymarketWithdrawQuoteRequest,\n ): Promise<PolymarketWithdrawQuoteResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/quote`;\n return await httpPost<PolymarketWithdrawQuoteResponse>(url, body);\n }\n\n /**\n * Prepare a Polymarket withdrawal by obtaining a Bridge deposit address.\n *\n * Maps to `POST /api/v1/withdraw/polymarket/prepare`.\n */\n async preparePolymarketWithdraw(\n body: PolymarketWithdrawPrepareRequest,\n ): Promise<PolymarketWithdrawPrepareResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/prepare`;\n return await httpPost<PolymarketWithdrawPrepareResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/withdraw/polymarket/build-relay`. */\n async buildPolymarketWithdrawRelay(\n body: PolymarketWithdrawRelayBuildRequest,\n ): Promise<PolymarketWithdrawRelayBuildResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/build-relay`;\n return await httpPost<PolymarketWithdrawRelayBuildResponse>(url, body);\n }\n\n /** Maps to `POST /api/v1/withdraw/polymarket/submit-relay`. */\n async submitPolymarketWithdrawRelay(\n body: PolymarketWithdrawRelaySubmitRequest,\n ): Promise<PolymarketWithdrawRelaySubmitResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/submit-relay`;\n return await httpPost<PolymarketWithdrawRelaySubmitResponse>(url, body);\n }\n\n /** Maps to `GET /api/v1/withdraw/polymarket/status`. */\n async getPolymarketWithdrawStatus(params: {\n bridge_address?: string;\n transaction_id?: string;\n }): Promise<PolymarketWithdrawBridgeStatusResponse> {\n const query = buildQuery(params);\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/status${query}`;\n return await httpGet<PolymarketWithdrawBridgeStatusResponse>(url);\n }\n\n /**\n * Execute a gasless USDC.e withdrawal from a Polymarket Safe wallet via Relayer.\n *\n * Maps to `POST /api/v1/withdraw/polymarket/execute`.\n */\n async executePolymarketWithdraw(\n body: PolymarketWithdrawRequest,\n ): Promise<PolymarketWithdrawResponse> {\n const url = `${this.endpoint}/api/v1/withdraw/polymarket/execute`;\n return await httpPost<PolymarketWithdrawResponse>(url, body);\n }\n\n // -------------------------------------------------------------------------\n // Redeem (resolved market token redemption)\n // -------------------------------------------------------------------------\n\n /**\n * Prepare the signing payload for a Polymarket redeem transaction.\n * The frontend must sign the returned Safe hash or deposit-wallet typed data\n * and pass the signature to `redeemPolymarket`.\n *\n * Maps to `POST /api/v1/redeem/polymarket/prepare`.\n */\n async prepareRedeemPolymarket(\n body: PolymarketRedeemPrepareInput,\n ): Promise<PolymarketRedeemPrepareResponse> {\n const url = `${this.endpoint}/api/v1/redeem/polymarket/prepare`;\n return await httpPost<PolymarketRedeemPrepareResponse>(url, body);\n }\n\n /**\n * Redeem tokens from a resolved Polymarket market via gasless Relayer.\n * Requires a valid signature for the payload returned by the prepare step.\n *\n * Maps to `POST /api/v1/redeem/polymarket`.\n */\n async redeemPolymarket(\n body: PolymarketRedeemInput,\n ): Promise<PolymarketRedeemResponse> {\n const url = `${this.endpoint}/api/v1/redeem/polymarket`;\n return await httpPost<PolymarketRedeemResponse>(url, body);\n }\n}\n\n/**\n * Factory function for `PredictClient`.\n *\n * @param endpoint - Base URL of the prediction-server, without a trailing slash.\n */\nexport function createPredictClient(\n endpoint: string,\n options?: PredictClientOptions,\n): PredictClient {\n return new PredictClient(endpoint, options);\n}\n\nasync function parseMarketDataResponseBody(\n response: Response,\n): Promise<unknown> {\n const text = await response.text().catch(() => \"\");\n if (!text) return undefined;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/**\n * PredictWsClient — WebSocket client for prediction-server real-time data.\n *\n * Connects to `GET /api/v1/ws` (RFC 6455) and supports three channels:\n * `orderbook`, `prices`, and `trades`.\n *\n * Features:\n * - Auto-reconnect with exponential backoff\n * - Application-level ping/pong keepalive\n * - Subscription state tracking with automatic restore after reconnect\n * - Event-emitter pattern for typed message dispatch\n */\nimport type {\n WsChannel,\n WsChannelEvent,\n WsClientMessage,\n WsConnectionStatus,\n WsDataMessage,\n WsErrorCode,\n WsOrderbookEvent,\n WsPriceEvent,\n WsTradeEvent,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\n/** Configuration for `PredictWsClient`. */\nexport interface PredictWsClientConfig {\n /** Full WebSocket URL, e.g. `\"wss://api.example.com/api/v1/ws\"`. */\n wsUrl: string;\n /** Connect immediately on construction. Default: `true`. */\n autoConnect?: boolean;\n /** Reconnect automatically on unexpected close. Default: `true`. */\n autoReconnect?: boolean;\n /** Base delay (ms) for exponential backoff. Default: `1000`. */\n reconnectIntervalBase?: number;\n /** Maximum reconnect delay (ms). Default: `30000`. */\n reconnectMaxInterval?: number;\n /** Interval (ms) between application-level pings. Default: `30000`. */\n pingInterval?: number;\n /**\n * How long (ms) to wait for a pong after sending a ping before\n * considering the connection dead. Default: `10000`.\n * Must be less than `pingInterval`.\n */\n pongTimeout?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_RECONNECT_BASE = 1000;\nconst DEFAULT_RECONNECT_MAX = 30000;\nconst DEFAULT_PING_INTERVAL = 20000;\nconst DEFAULT_PONG_TIMEOUT = 10000;\n\n/**\n * Maximum serialized byte size for a single subscribe/unsubscribe frame.\n *\n * The server enforces a read limit (4096 bytes) and closes the connection\n * with code 1009 (\"message too big\") on any frame that exceeds it. A page\n * subscribing to hundreds of market slugs at once would otherwise produce a\n * single oversized frame, get disconnected, and loop forever on reconnect\n * (restoreSubscriptions resends the same oversized frame). We chunk slugs so\n * every frame stays comfortably under the server limit.\n */\nconst MAX_SUBSCRIPTION_FRAME_BYTES = 3500;\n\n// ---------------------------------------------------------------------------\n// Internal event-emitter types\n// ---------------------------------------------------------------------------\n\n/** UTF-8 byte length of a string (slugs are ASCII in practice). */\nfunction byteLength(str: string): number {\n if (typeof TextEncoder !== \"undefined\") {\n return new TextEncoder().encode(str).length;\n }\n // Fallback: assume single-byte chars (slugs are ASCII).\n return str.length;\n}\n\ntype EventCallback<T = unknown> = (data: T) => void;\n\ninterface EventListeners {\n connect: EventCallback<void>[];\n disconnect: EventCallback<{ code?: number; reason?: string }>[];\n reconnecting: EventCallback<{ attempt: number; delay: number }>[];\n error: EventCallback<{ code: WsErrorCode; message: string }>[];\n status: EventCallback<WsConnectionStatus>[];\n subscribed: EventCallback<{\n channels: WsChannel[];\n market_slugs: string[];\n }>[];\n orderbook: EventCallback<WsDataMessage<WsOrderbookEvent>>[];\n prices: EventCallback<WsDataMessage<WsPriceEvent>>[];\n trades: EventCallback<WsDataMessage<WsTradeEvent>>[];\n}\n\ntype WsEventType = keyof EventListeners;\n\n// ---------------------------------------------------------------------------\n// Subscription tracking\n// ---------------------------------------------------------------------------\n\ninterface SubscriptionState {\n /** channel → Set<market_slug> */\n channels: Map<WsChannel, Set<string>>;\n}\n\n// ---------------------------------------------------------------------------\n// PredictWsClient\n// ---------------------------------------------------------------------------\n\nexport class PredictWsClient {\n private ws: WebSocket | null = null;\n private readonly wsUrl: string;\n private readonly autoReconnect: boolean;\n private readonly reconnectBase: number;\n private readonly reconnectMax: number;\n private readonly pingMs: number;\n private readonly pongTimeoutMs: number;\n\n private status: WsConnectionStatus = \"disconnected\";\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n private pongTimer: ReturnType<typeof setTimeout> | null = null;\n private shouldReconnect = true;\n\n private listeners: EventListeners = {\n connect: [],\n disconnect: [],\n reconnecting: [],\n error: [],\n status: [],\n subscribed: [],\n orderbook: [],\n prices: [],\n trades: [],\n };\n\n private subs: SubscriptionState = {\n channels: new Map([\n [\"orderbook\", new Set()],\n [\"prices\", new Set()],\n [\"trades\", new Set()],\n ]),\n };\n\n constructor(config: PredictWsClientConfig) {\n this.wsUrl = config.wsUrl;\n this.autoReconnect = config.autoReconnect ?? true;\n this.reconnectBase = config.reconnectIntervalBase ?? DEFAULT_RECONNECT_BASE;\n this.reconnectMax = config.reconnectMaxInterval ?? DEFAULT_RECONNECT_MAX;\n this.pingMs = config.pingInterval ?? DEFAULT_PING_INTERVAL;\n this.pongTimeoutMs = config.pongTimeout ?? DEFAULT_PONG_TIMEOUT;\n\n if (config.autoConnect !== false && typeof window !== \"undefined\") {\n this.connect();\n }\n }\n\n // -------------------------------------------------------------------------\n // Connection management\n // -------------------------------------------------------------------------\n\n connect(): void {\n if (typeof window === \"undefined\") return;\n if (\n this.ws &&\n (this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n this.shouldReconnect = true;\n this.setStatus(\"connecting\");\n\n try {\n this.ws = new WebSocket(this.wsUrl);\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.setStatus(\"connected\");\n this.emit(\"connect\", undefined);\n this.restoreSubscriptions();\n this.startPing();\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data as string);\n };\n\n this.ws.onerror = () => {\n // The close event fires immediately after, which handles reconnect.\n };\n\n this.ws.onclose = (event) => {\n this.stopPing();\n this.setStatus(\"disconnected\");\n this.emit(\"disconnect\", { code: event.code, reason: event.reason });\n if (this.shouldReconnect && this.autoReconnect) {\n this.scheduleReconnect();\n }\n };\n } catch {\n if (this.shouldReconnect && this.autoReconnect) {\n this.scheduleReconnect();\n }\n }\n }\n\n disconnect(): void {\n this.shouldReconnect = false;\n this.stopPing();\n this.clearReconnectTimer();\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n this.setStatus(\"disconnected\");\n }\n\n /** Disconnect and clear all subscription state and listeners. */\n destroy(): void {\n this.disconnect();\n for (const ch of this.subs.channels.values()) ch.clear();\n for (const key of Object.keys(this.listeners)) {\n (this.listeners[key as WsEventType] as unknown[]).length = 0;\n }\n }\n\n getStatus(): WsConnectionStatus {\n return this.status;\n }\n\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\n }\n\n // -------------------------------------------------------------------------\n // Subscription — low-level (multi-channel, multi-slug)\n // -------------------------------------------------------------------------\n\n /**\n * Subscribe to one or more channels for the given market slugs.\n * The server acknowledges with a `subscribed` message.\n */\n subscribe(channels: WsChannel[], marketSlugs: string[]): void {\n for (const ch of channels) {\n const set = this.subs.channels.get(ch)!;\n for (const slug of marketSlugs) set.add(slug);\n }\n this.sendChunkedSubscription(\"subscribe\", channels, marketSlugs);\n }\n\n /**\n * Unsubscribe from one or more channels for the given market slugs.\n */\n unsubscribe(channels: WsChannel[], marketSlugs: string[]): void {\n for (const ch of channels) {\n const set = this.subs.channels.get(ch)!;\n for (const slug of marketSlugs) set.delete(slug);\n }\n this.sendChunkedSubscription(\"unsubscribe\", channels, marketSlugs);\n }\n\n // -------------------------------------------------------------------------\n // Subscription — convenience (single channel)\n // -------------------------------------------------------------------------\n\n /**\n * Subscribe to price updates for the given slugs.\n * Returns an unsubscribe function.\n */\n subscribePrices(\n slugs: string[],\n onUpdate: (msg: WsDataMessage<WsPriceEvent>) => void,\n ): () => void {\n this.subscribe([\"prices\"], slugs);\n const off = this.on(\"prices\", onUpdate);\n return () => {\n off();\n this.unsubscribe([\"prices\"], slugs);\n };\n }\n\n /**\n * Subscribe to orderbook snapshots for the given slugs.\n * Returns an unsubscribe function.\n */\n subscribeOrderbook(\n slugs: string[],\n onUpdate: (msg: WsDataMessage<WsOrderbookEvent>) => void,\n ): () => void {\n this.subscribe([\"orderbook\"], slugs);\n const off = this.on(\"orderbook\", onUpdate);\n return () => {\n off();\n this.unsubscribe([\"orderbook\"], slugs);\n };\n }\n\n /**\n * Subscribe to trade events for the given slugs.\n * Returns an unsubscribe function.\n */\n subscribeTrades(\n slugs: string[],\n onUpdate: (msg: WsDataMessage<WsTradeEvent>) => void,\n ): () => void {\n this.subscribe([\"trades\"], slugs);\n const off = this.on(\"trades\", onUpdate);\n return () => {\n off();\n this.unsubscribe([\"trades\"], slugs);\n };\n }\n\n // -------------------------------------------------------------------------\n // Status observation\n // -------------------------------------------------------------------------\n\n /** Register a callback for connection status changes. Returns unsubscribe. */\n onStatusChange(cb: (status: WsConnectionStatus) => void): () => void {\n return this.on(\"status\", cb);\n }\n\n /** Register a callback for server-sent errors. Returns unsubscribe. */\n onError(\n cb: (err: { code: WsErrorCode; message: string }) => void,\n ): () => void {\n return this.on(\"error\", cb);\n }\n\n // -------------------------------------------------------------------------\n // Event emitter\n // -------------------------------------------------------------------------\n\n on<T extends WsEventType>(\n event: T,\n callback: EventListeners[T][number],\n ): () => void {\n const list = this.listeners[event] as EventCallback<unknown>[];\n list.push(callback as EventCallback<unknown>);\n return () => this.off(event, callback);\n }\n\n off<T extends WsEventType>(\n event: T,\n callback: EventListeners[T][number],\n ): void {\n const list = this.listeners[event] as EventCallback<unknown>[];\n const idx = list.indexOf(callback as EventCallback<unknown>);\n if (idx !== -1) list.splice(idx, 1);\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n private emit<T extends WsEventType>(\n event: T,\n data: Parameters<EventListeners[T][number]>[0],\n ): void {\n const list = this.listeners[event] as EventCallback<typeof data>[];\n for (const cb of list) {\n try {\n cb(data);\n } catch (e) {\n console.error(`[PredictWsClient] Error in \"${event}\" listener:`, e);\n }\n }\n }\n\n private send(msg: WsClientMessage): boolean {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;\n try {\n this.ws.send(JSON.stringify(msg));\n return true;\n } catch {\n return false;\n }\n }\n\n private setStatus(next: WsConnectionStatus): void {\n if (this.status !== next) {\n this.status = next;\n this.emit(\"status\", next);\n }\n }\n\n private handleMessage(raw: string): void {\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return;\n }\n\n // Control messages (have `type`)\n if (msg.type) {\n switch (msg.type) {\n case \"pong\":\n this.clearPongTimer();\n return;\n case \"subscribed\":\n this.emit(\"subscribed\", {\n channels: msg.channels as WsChannel[],\n market_slugs: msg.market_slugs as string[],\n });\n return;\n case \"error\":\n this.emit(\"error\", {\n code: msg.code as WsErrorCode,\n message: msg.message as string,\n });\n return;\n }\n }\n\n // Data messages (have `channel` + `data`)\n if (msg.channel && msg.data) {\n const dataMsg = msg as unknown as WsDataMessage<WsChannelEvent>;\n switch (dataMsg.channel) {\n case \"orderbook\":\n this.emit(\"orderbook\", dataMsg as WsDataMessage<WsOrderbookEvent>);\n break;\n case \"prices\":\n this.emit(\"prices\", dataMsg as WsDataMessage<WsPriceEvent>);\n break;\n case \"trades\":\n this.emit(\"trades\", dataMsg as WsDataMessage<WsTradeEvent>);\n break;\n }\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) return;\n\n const delay = Math.min(\n this.reconnectBase * Math.pow(2, this.reconnectAttempts),\n this.reconnectMax,\n );\n\n this.setStatus(\"reconnecting\");\n this.emit(\"reconnecting\", { attempt: this.reconnectAttempts + 1, delay });\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.reconnectAttempts++;\n this.connect();\n }, delay);\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n private restoreSubscriptions(): void {\n for (const [channel, slugs] of this.subs.channels.entries()) {\n if (slugs.size > 0) {\n this.sendChunkedSubscription(\"subscribe\", [channel], Array.from(slugs));\n }\n }\n }\n\n /**\n * Send a subscribe/unsubscribe message, splitting `marketSlugs` across\n * multiple frames so no single frame exceeds the server read limit.\n */\n private sendChunkedSubscription(\n type: \"subscribe\" | \"unsubscribe\",\n channels: WsChannel[],\n marketSlugs: string[],\n ): void {\n if (marketSlugs.length === 0) {\n this.send({ type, channels, market_slugs: [] });\n return;\n }\n\n const envelopeBytes = byteLength(\n JSON.stringify({ type, channels, market_slugs: [] }),\n );\n const budget = MAX_SUBSCRIPTION_FRAME_BYTES - envelopeBytes;\n\n let chunk: string[] = [];\n let chunkBytes = 0;\n const flush = () => {\n if (chunk.length > 0) {\n this.send({ type, channels, market_slugs: chunk });\n chunk = [];\n chunkBytes = 0;\n }\n };\n\n for (const slug of marketSlugs) {\n // serialized slug plus a comma separator\n const slugBytes = byteLength(JSON.stringify(slug)) + 1;\n if (chunk.length > 0 && chunkBytes + slugBytes > budget) flush();\n chunk.push(slug);\n chunkBytes += slugBytes;\n }\n flush();\n }\n\n private startPing(): void {\n this.stopPing();\n this.pingTimer = setInterval(() => {\n this.send({ type: \"ping\" });\n this.armPongTimeout();\n }, this.pingMs);\n }\n\n private stopPing(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n this.clearPongTimer();\n }\n\n /**\n * Start a timer that fires if the server does not reply with pong\n * within `pongTimeoutMs`. On timeout the socket is closed so\n * the normal reconnect flow kicks in.\n */\n private armPongTimeout(): void {\n this.clearPongTimer();\n this.pongTimer = setTimeout(() => {\n this.pongTimer = null;\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close(4000, \"pong timeout\");\n }\n }, this.pongTimeoutMs);\n }\n\n private clearPongTimer(): void {\n if (this.pongTimer) {\n clearTimeout(this.pongTimer);\n this.pongTimer = null;\n }\n }\n}\n\n/**\n * Factory function for `PredictWsClient`.\n *\n * @param config - WebSocket client configuration.\n */\nexport function createPredictWsClient(\n config: PredictWsClientConfig,\n): PredictWsClient {\n return new PredictWsClient(config);\n}\n","/**\n * Polymarket L2 HMAC-SHA256 signing utilities.\n *\n * Uses the Web Crypto API (available in all modern browsers and Node ≥18) to\n * avoid taking a dependency on Node.js `crypto` or any third-party library.\n *\n * References:\n * https://docs.polymarket.com/#authentication\n * https://github.com/Polymarket/clob-client/blob/main/src/headers/index.ts\n */\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Encode a string to a Uint8Array using UTF-8. */\nfunction encode(str: string): Uint8Array {\n return new TextEncoder().encode(str);\n}\n\n/**\n * Convert a base64 or base64url string to a Uint8Array.\n * Normalises base64url (`-`, `_`, no padding) to standard base64 before decoding.\n */\nfunction base64ToBytes(b64: string): Uint8Array {\n let std = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n while (std.length % 4 !== 0) std += \"=\";\n const binary = atob(std);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/** Convert a Uint8Array to a base64 string. */\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n// ---------------------------------------------------------------------------\n// HMAC-SHA256\n// ---------------------------------------------------------------------------\n\n/**\n * Compute an HMAC-SHA256 signature using the Web Crypto API.\n *\n * @param secretBase64 - The signing secret encoded as base64.\n * @param message - The plaintext message to sign.\n * @returns The signature as a base64 string.\n */\nexport async function hmacSha256Base64(\n secretBase64: string,\n message: string,\n): Promise<string> {\n const keyBytes = base64ToBytes(secretBase64);\n const cryptoKey = await crypto.subtle.importKey(\n \"raw\",\n keyBytes.buffer as ArrayBuffer,\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const msgBytes = encode(message);\n const signature = await crypto.subtle.sign(\n \"HMAC\",\n cryptoKey,\n msgBytes.buffer as ArrayBuffer,\n );\n const b64 = bytesToBase64(new Uint8Array(signature));\n // Polymarket requires base64url encoding (keep trailing '=')\n return b64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\");\n}\n\n// ---------------------------------------------------------------------------\n// Polymarket L2 auth headers\n// ---------------------------------------------------------------------------\n\n/** HTTP method values accepted by Polymarket CLOB. */\nexport type HttpMethod = \"GET\" | \"DELETE\" | \"POST\" | \"PUT\";\n\nexport interface PolymarketL2HeadersInput {\n /** L2 API key (from credential exchange). */\n apiKey: string;\n /** L2 HMAC secret (base64-encoded). */\n secret: string;\n /** L2 passphrase. */\n passphrase: string;\n /** HTTP method of the request. */\n method: HttpMethod;\n /** Request path without host, e.g. \"/order\". */\n requestPath: string;\n /** Raw JSON request body string; empty string for GET/DELETE. */\n body?: string;\n}\n\nexport interface PolymarketL2Headers {\n POLY_ADDRESS: string;\n POLY_SIGNATURE: string;\n POLY_TIMESTAMP: string;\n POLY_API_KEY: string;\n POLY_PASSPHRASE: string;\n}\n\n/**\n * Build Polymarket L2 HMAC authentication headers for a CLOB API request.\n *\n * The signature is `HMAC-SHA256(secret, timestamp + method + requestPath + body)`.\n *\n * @param address - EVM wallet address (owner of the credentials).\n * @param input - Credential and request details.\n * @returns An object containing all required `POLY_*` headers.\n */\nexport async function buildPolymarketL2Headers(\n address: string,\n input: PolymarketL2HeadersInput,\n): Promise<PolymarketL2Headers> {\n const timestamp = Math.floor(Date.now() / 1000).toString();\n const body = input.body ?? \"\";\n const message = `${timestamp}${input.method}${input.requestPath}${body}`;\n\n const signature = await hmacSha256Base64(input.secret, message);\n\n return {\n POLY_ADDRESS: address,\n POLY_SIGNATURE: signature,\n POLY_TIMESTAMP: timestamp,\n POLY_API_KEY: input.apiKey,\n POLY_PASSPHRASE: input.passphrase,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Polymarket L1 auth (credential derivation)\n// ---------------------------------------------------------------------------\n\n/** EIP-712 domain used by Polymarket CLOB for L1 authentication. */\nexport const CLOB_AUTH_DOMAIN = {\n name: \"ClobAuthDomain\",\n version: \"1\",\n chainId: 137,\n} as const;\n\n/** EIP-712 types for the `ClobAuth` struct. */\nexport const CLOB_AUTH_TYPES = {\n ClobAuth: [\n { name: \"address\", type: \"address\" },\n { name: \"timestamp\", type: \"string\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"message\", type: \"string\" },\n ],\n} as const;\n\nexport interface BuildClobAuthMessageInput {\n /** EVM wallet address. */\n address: string;\n /** Unix seconds string. */\n timestamp: string;\n /** Credential nonce. Use `0` for a permanent / deterministic credential. */\n nonce: number;\n}\n\n/**\n * Build the EIP-712 typed data value for a `ClobAuth` message.\n * The resulting object is passed to `eth_signTypedData_v4`.\n */\nexport function buildClobAuthMessage(\n input: BuildClobAuthMessageInput,\n): Record<string, unknown> {\n return {\n address: input.address,\n timestamp: input.timestamp,\n nonce: input.nonce,\n message: \"This message attests that I control the given wallet\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// Credential exchange\n// ---------------------------------------------------------------------------\n\ntype ApiKeyCreds = { apiKey: string; secret: string; passphrase: string };\n\nfunction buildL1Headers(\n address: string,\n signature: string,\n timestamp: string,\n nonce: number,\n): Record<string, string> {\n return {\n POLY_ADDRESS: address,\n POLY_SIGNATURE: signature,\n POLY_TIMESTAMP: timestamp,\n POLY_NONCE: String(nonce),\n };\n}\n\n/**\n * Create or derive Polymarket L2 API credentials from an L1 EIP-712 signature.\n *\n * Polymarket exposes two endpoints:\n * - `POST /auth/api-key` — create new credentials (required for first-time wallets)\n * - `GET /auth/derive-api-key` — derive existing credentials\n *\n * This function tries to derive first; on failure it creates, matching the\n * official `createOrDeriveApiKey()` behaviour from `@polymarket/clob-client`.\n *\n * @returns `{ apiKey, secret, passphrase }`.\n */\nexport async function derivePolymarketApiKey(\n address: string,\n signature: string,\n timestamp: string,\n nonce: number,\n): Promise<ApiKeyCreds> {\n const headers = buildL1Headers(address, signature, timestamp, nonce);\n\n // Try deriving existing credentials first.\n const deriveRes = await fetch(\n `https://clob.polymarket.com/auth/derive-api-key?nonce=${nonce}`,\n { method: \"GET\", headers },\n );\n\n if (deriveRes.ok) {\n return deriveRes.json() as Promise<ApiKeyCreds>;\n }\n\n // Derive failed — wallet likely has no API key yet; create one.\n const createRes = await fetch(\"https://clob.polymarket.com/auth/api-key\", {\n method: \"POST\",\n headers,\n });\n\n if (createRes.ok) {\n return createRes.json() as Promise<ApiKeyCreds>;\n }\n\n const text = await createRes.text().catch(() => createRes.statusText);\n throw new Error(\n `Polymarket credential exchange failed (${createRes.status}): ${text}`,\n );\n}\n","/**\n * Polymarket CTF Exchange order construction utilities.\n *\n * Implements EIP-712 signing for `Order` structs on the CTF Exchange and\n * Neg-Risk CTF Exchange contracts (Polygon mainnet).\n *\n * References:\n * - Official docs (order creation):\n * https://docs.polymarket.com/trading/orders/create\n * - Official TS CLOB client (order builder / helpers):\n * https://github.com/Polymarket/clob-client/blob/main/src/order-builder/builder.ts\n * https://github.com/Polymarket/clob-client/blob/main/src/order-builder/helpers.ts\n * - Official Python CLOB client (order builder — has `get_market_order_amounts`):\n * https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/order_builder/builder.py\n *\n * Market order (FOK/FAK) precision limits — NOT documented in official docs,\n * enforced server-side and discovered via API error messages:\n * - makerAmount: max 2 decimal places (human-readable)\n * - takerAmount: max 4 decimal places (human-readable)\n * - GitHub issues tracking this undocumented constraint:\n * https://github.com/Polymarket/py-clob-client/issues/121\n * https://github.com/Polymarket/py-clob-client/issues/253\n * https://github.com/Polymarket/rs-clob-client/issues/261\n */\nimport type { CreateOrderInput, PolymarketTickSize } from \"../client/types\";\n\n// ---------------------------------------------------------------------------\n// Contract addresses (Polygon mainnet)\n// ---------------------------------------------------------------------------\n\n/** Polymarket CTF Exchange contract (standard markets). */\nexport const CTF_EXCHANGE_ADDRESS =\n \"0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E\" as const;\n\n/** Polymarket Neg-Risk CTF Exchange contract (neg-risk markets). */\nexport const NEG_RISK_CTF_EXCHANGE_ADDRESS =\n \"0xC5d563A36AE78145C45a50134d48A1215220f80a\" as const;\n\n/** USDC.e (Bridged USDC) on Polygon — the only collateral token on Polymarket. */\nexport const USDC_ADDRESS =\n \"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174\" as const;\n\n/** Chain ID for Polygon mainnet. */\nexport const POLYGON_CHAIN_ID = 137;\n\n// ---------------------------------------------------------------------------\n// EIP-712 domain and types\n// ---------------------------------------------------------------------------\n\n/**\n * Build the EIP-712 domain for the CTF Exchange.\n *\n * @param negRisk - When `true`, use the Neg-Risk exchange address.\n */\nexport function buildCtfExchangeDomain(negRisk = false) {\n return {\n name: \"Polymarket CTF Exchange\",\n version: \"1\",\n chainId: POLYGON_CHAIN_ID,\n verifyingContract: negRisk\n ? NEG_RISK_CTF_EXCHANGE_ADDRESS\n : CTF_EXCHANGE_ADDRESS,\n };\n}\n\n/** EIP-712 type definitions for the Polymarket `Order` struct. */\nexport const CTF_ORDER_TYPES = {\n Order: [\n { name: \"salt\", type: \"uint256\" },\n { name: \"maker\", type: \"address\" },\n { name: \"signer\", type: \"address\" },\n { name: \"taker\", type: \"address\" },\n { name: \"tokenId\", type: \"uint256\" },\n { name: \"makerAmount\", type: \"uint256\" },\n { name: \"takerAmount\", type: \"uint256\" },\n { name: \"expiration\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"feeRateBps\", type: \"uint256\" },\n { name: \"side\", type: \"uint8\" },\n { name: \"signatureType\", type: \"uint8\" },\n ],\n} as const;\n\n// ---------------------------------------------------------------------------\n// Order type constants\n// ---------------------------------------------------------------------------\n\n/** Order type enum matching CTFExchange.sol. */\nexport const ORDER_TYPE = {\n GTC: 0, // Good-Till-Cancelled\n FOK: 1, // Fill-Or-Kill\n GTD: 2, // Good-Till-Date\n FAK: 3, // Fill-And-Kill\n} as const;\n\n/** Side enum matching CTFExchange.sol (0 = BUY, 1 = SELL). */\nexport const SIDE = { BUY: 0, SELL: 1 } as const;\n\n// ---------------------------------------------------------------------------\n// Amount calculation — matches official Polymarket CLOB client rounding\n// ---------------------------------------------------------------------------\n//\n// Terminology:\n// maker = the order creator (you). Provides `makerAmount` of an asset.\n// taker = the counterparty. Provides `takerAmount` of an asset.\n//\n// BUY: makerAmount = USDC spent, takerAmount = shares received\n// SELL: makerAmount = shares sold, takerAmount = USDC received\n//\n// Implied price = USDC amount / shares amount\n// BUY: price = makerAmount / takerAmount\n// SELL: price = takerAmount / makerAmount\n//\n// Order types and amount computation:\n// ┌──────────────┬─────────────────────────────┬──────────────────────────────┐\n// │ │ Market (FOK / FAK) │ Limit (GTC / GTD) │\n// ├──────────────┼─────────────────────────────┼──────────────────────────────┤\n// │ BUY input │ size = USDC to spend │ size = shares to buy │\n// │ BUY maker │ floor(size, 2) → USDC │ round(size × price, amt) │\n// │ BUY taker │ floor(USDC/price, 4) →shares│ round(size, sz) → shares │\n// ├──────────────┼─────────────────────────────┼──────────────────────────────┤\n// │ SELL input │ size = shares to sell │ size = shares to sell │\n// │ SELL maker │ floor(size, 2) → shares │ floor(size, sz) → shares │\n// │ SELL taker │ ceil(shares×price, 4)→ USDC │ round(size × price, amt) │\n// └──────────────┴─────────────────────────────┴──────────────────────────────┘\n// (sz = rc.size, amt = rc.amount; market orders cap at 2 / 4 decimals)\n//\n// ---------------------------------------------------------------------------\n\n/**\n * Rounding configuration per tick size, aligned with the official\n * Polymarket CLOB client (`@polymarket/clob-client`).\n *\n * Each field is the **max decimal places** allowed for that dimension:\n * - `price`: price per share (e.g. 0.86 → 2 decimals for tick \"0.01\")\n * - `size`: number of shares (e.g. 11.63 → 2 decimals for tick \"0.01\")\n * - `amount`: total cost = size × price (e.g. 10.0018 → 4 decimals)\n *\n * Key invariant: `amount = size + price` decimal places.\n * This guarantees `round(size × price, amount) / round(size, size)` has\n * exactly `price` decimal places → the implied price is tick-aligned.\n *\n * NOTE: `size` is always 2 across all tick sizes in the official client.\n * The `amount` field equals `size + price` (e.g. \"0.001\": 2 + 3 = 5).\n *\n * Example with tick \"0.01\": { size: 2, price: 2, amount: 4 }\n * 11.63 (2dp) × 0.86 (2dp) = 10.0018 (4dp)\n * 10.0018 / 11.63 = 0.86 ← exactly 2dp, valid tick ✓\n *\n * @see https://github.com/Polymarket/clob-client/blob/main/src/order-builder/helpers.ts\n */\nconst ROUNDING_CONFIG: Record<\n string,\n { size: number; price: number; amount: number }\n> = {\n \"0.1\": { size: 2, price: 1, amount: 3 },\n \"0.01\": { size: 2, price: 2, amount: 4 },\n \"0.005\": { size: 2, price: 3, amount: 5 },\n \"0.0025\": { size: 2, price: 4, amount: 6 },\n \"0.001\": { size: 2, price: 3, amount: 5 },\n \"0.0001\": { size: 2, price: 4, amount: 6 },\n};\n\nconst DEFAULT_ROUNDING = { size: 2, price: 2, amount: 4 };\n\n/**\n * Normalise a raw `minimum_tick_size` value (number or string, e.g. from the\n * `/tick-size` endpoint) to one of the tick sizes known to the CLOB clients'\n * rounding configs.\n *\n * The official `@polymarket/clob-client-v2` OrderBuilder indexes its\n * `ROUNDING_CONFIG` by the tick-size string without any fallback — an unknown\n * key crashes order building with \"Cannot read properties of undefined\n * (reading 'price')\". Funnelling every caller through this helper guarantees\n * we only ever hand the builder a supported tick size (unknown values fall\n * back to the CLOB-default \"0.01\").\n */\nexport function normalizePolymarketTickSize(\n raw: number | string | null | undefined,\n): PolymarketTickSize {\n const value = typeof raw === \"string\" ? parseFloat(raw) : raw;\n if (value == null || !Number.isFinite(value) || value <= 0) return \"0.01\";\n for (const tick of Object.keys(ROUNDING_CONFIG) as PolymarketTickSize[]) {\n if (Math.abs(parseFloat(tick) - value) < 1e-9) return tick;\n }\n return \"0.01\";\n}\n\n/**\n * Round a number to `d` decimal places (round-half-away-from-zero via toFixed).\n * Mirrors the official `decimalPlaces()` / `roundNormal()` helpers.\n */\nfunction decimalPlaces(n: number, d: number): number {\n return parseFloat(n.toFixed(d));\n}\n\n/**\n * Floor a number to `d` decimal places (never rounds up).\n * Used for SELL size to prevent exceeding actual holdings.\n */\nfunction floorDecimalPlaces(n: number, d: number): number {\n const factor = 10 ** d;\n return Math.floor(n * factor) / factor;\n}\n\n/**\n * Ceil a number to `d` decimal places (never rounds down).\n * Used for market SELL taker amount to avoid under-quoting.\n */\nfunction ceilDecimalPlaces(n: number, d: number): number {\n const factor = 10 ** d;\n return Math.ceil(n * factor) / factor;\n}\n\n/**\n * Count the number of decimal places in a number's string representation.\n */\nfunction countDecimalPlaces(n: number): number {\n const s = n.toString();\n const dot = s.indexOf(\".\");\n if (dot === -1) return 0;\n return s.length - dot - 1;\n}\n\n/**\n * Convert a human-readable amount to micro-USDC (6 decimals).\n * Polymarket contracts use USDC.e with 6 decimals.\n */\nfunction toMicroUsdc(amount: number): bigint {\n return BigInt(Math.round(amount * 1_000_000));\n}\n\n/**\n * Normalise a token ID to a decimal string.\n * Polymarket's CLOB API requires decimal representation, but market metadata\n * may store token IDs as hex strings (0x-prefixed).\n */\nfunction normalizeTokenId(tokenId: string): string {\n if (tokenId.startsWith(\"0x\") || tokenId.startsWith(\"0X\")) {\n return BigInt(tokenId).toString(10);\n }\n return tokenId;\n}\n\n// ---------------------------------------------------------------------------\n// Order message builder\n// ---------------------------------------------------------------------------\n\nexport interface BuildOrderMessageInput extends CreateOrderInput {\n /** Signer / owner address. */\n signerAddress: string;\n /** Signature type (0 = EOA, 1 = Magic, 2 = Poly Proxy). */\n signatureType: 0 | 1 | 2;\n /** Fee rate in basis points from the CLOB fee-rate endpoint. Defaults to \"0\". */\n feeRateBps?: string;\n}\n\nexport interface OrderMessage {\n salt: string;\n /** Funder address that holds the collateral (USDC.e or outcome tokens). */\n maker: string;\n /** Signer address that signs the EIP-712 order. */\n signer: string;\n /** Taker address (0x0 = any counterparty). */\n taker: string;\n tokenId: string;\n /**\n * Amount the maker provides (micro-USDC, 6 decimals).\n * BUY: USDC spent. SELL: shares sold.\n */\n makerAmount: string;\n /**\n * Amount the taker provides (micro-USDC, 6 decimals).\n * BUY: shares received. SELL: USDC received.\n */\n takerAmount: string;\n expiration: string;\n nonce: string;\n feeRateBps: string;\n /** 0 = BUY, 1 = SELL (matches CTFExchange.sol). */\n side: number;\n /** 0 = EOA, 1 = POLY_PROXY, 2 = POLY_GNOSIS_SAFE. */\n signatureType: number;\n}\n\n/**\n * Polymarket API precision limits for market orders (FOK / FAK).\n *\n * With the corrected ROUNDING_CONFIG (size=2 for all tick sizes, matching the\n * official CLOB client), `rc.size` already equals MARKET_MAKER_MAX_DECIMALS.\n * These constants are kept as safety guards — if ROUNDING_CONFIG is ever\n * changed, `Math.min(rc.size, MARKET_MAKER_MAX_DECIMALS)` will still enforce\n * the API limit.\n *\n * The constraint is NOT documented in the official Polymarket docs — it is\n * enforced server-side and surfaced only via the error message:\n * \"invalid amounts, the market buy orders maker amount supports a max\n * accuracy of 2 decimals, taker amount a max of 4 decimals\"\n *\n * @see https://github.com/Polymarket/py-clob-client/issues/121\n * @see https://github.com/Polymarket/py-clob-client/issues/253\n * @see https://github.com/Polymarket/rs-clob-client/issues/261\n */\nconst MARKET_MAKER_MAX_DECIMALS = 2;\nconst MARKET_TAKER_MAX_DECIMALS = 4;\n\n/**\n * Compute makerAmount / takerAmount for a **market order** (FOK / FAK).\n *\n * Follows the official Polymarket Python CLOB client `get_market_order_amounts`.\n * The official docs describe market order input semantics here:\n * https://docs.polymarket.com/trading/orders/create#market-orders\n * - BUY: \"specify the dollar amount you want to spend\"\n * - SELL: \"specify the number of shares you want to sell\"\n *\n * Calculation (BUY):\n * makerAmount (USDC) = floor(size, min(rc.size, 2)) → ≤ 2 decimals\n * takerAmount (shares) = floor(makerAmt / price, min(rc.amount, 4)) → ≤ 4 decimals\n *\n * Calculation (SELL):\n * makerAmount (shares) = floor(size, min(rc.size, 2)) → ≤ 2 decimals\n * takerAmount (USDC) = ceil(makerAmt × price, min(rc.amount, 4)) → ≤ 4 decimals\n *\n * @see https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/order_builder/builder.py\n * @see https://github.com/Polymarket/py-clob-client/issues/121 (FOK decimal error)\n * @see https://github.com/Polymarket/py-clob-client/issues/253 (amount decimal bug)\n */\nfunction getMarketOrderAmounts(\n side: number,\n size: number,\n price: number,\n rc: { size: number; price: number; amount: number },\n): { makerAmount: string; takerAmount: string } {\n const rawPrice = decimalPlaces(price, rc.price);\n const makerDecimals = Math.min(rc.size, MARKET_MAKER_MAX_DECIMALS);\n const takerDecimals = Math.min(rc.amount, MARKET_TAKER_MAX_DECIMALS);\n\n if (side === SIDE.BUY) {\n const rawMakerAmt = floorDecimalPlaces(size, makerDecimals);\n let rawTakerAmt = rawMakerAmt / rawPrice;\n if (countDecimalPlaces(rawTakerAmt) > takerDecimals) {\n rawTakerAmt = floorDecimalPlaces(rawTakerAmt, takerDecimals);\n }\n return {\n makerAmount: toMicroUsdc(rawMakerAmt).toString(),\n takerAmount: toMicroUsdc(rawTakerAmt).toString(),\n };\n }\n\n // SELL\n const rawMakerAmt = floorDecimalPlaces(size, makerDecimals);\n let rawTakerAmt = rawMakerAmt * rawPrice;\n if (countDecimalPlaces(rawTakerAmt) > takerDecimals) {\n rawTakerAmt = ceilDecimalPlaces(rawTakerAmt, takerDecimals);\n }\n return {\n makerAmount: toMicroUsdc(rawMakerAmt).toString(),\n takerAmount: toMicroUsdc(rawTakerAmt).toString(),\n };\n}\n\n/**\n * Compute makerAmount / takerAmount for a **limit order** (GTC / GTD).\n *\n * `size` is always shares (for both BUY and SELL).\n *\n * Amount rounding follows the official Polymarket CLOB client to guarantee\n * that `makerAmount / takerAmount` produces a tick-aligned price.\n * The key invariant: `amountDecimals = sizeDecimals + priceDecimals`, so\n * `round(size × price, amountDecimals) / round(size, sizeDecimals)` has\n * exactly `priceDecimals` decimal places.\n *\n * Since `rc.size` is always 2 in the official ROUNDING_CONFIG, limit orders\n * naturally satisfy the same 2-decimal makerAmount constraint as market orders.\n *\n * BUY: makerAmount = round(size × price, rc.amount) → USDC\n * takerAmount = round(size, rc.size) → shares\n * SELL: makerAmount = floor(size, rc.size) → shares (floor to avoid overselling)\n * takerAmount = round(size × price, rc.amount) → USDC\n */\nfunction getLimitOrderAmounts(\n side: number,\n size: number,\n price: number,\n rc: { size: number; price: number; amount: number },\n): { makerAmount: string; takerAmount: string } {\n const rawPrice = decimalPlaces(price, rc.price);\n\n const rawSize =\n side === SIDE.SELL\n ? floorDecimalPlaces(size, rc.size)\n : decimalPlaces(size, rc.size);\n const sizeInMicro = toMicroUsdc(rawSize);\n const rawAmount = decimalPlaces(rawSize * rawPrice, rc.amount);\n const amountInMicro = toMicroUsdc(rawAmount);\n\n const makerAmount =\n side === SIDE.BUY ? amountInMicro.toString() : sizeInMicro.toString();\n const takerAmount =\n side === SIDE.BUY ? sizeInMicro.toString() : amountInMicro.toString();\n\n return { makerAmount, takerAmount };\n}\n\n/**\n * Build the EIP-712 typed data value for a Polymarket order.\n *\n * All amounts are in micro-USDC / micro-shares (1 unit = 1 000 000).\n *\n * Maker/taker semantics:\n * BUY: makerAmount = USDC spent, takerAmount = shares received\n * SELL: makerAmount = shares sold, takerAmount = USDC received\n *\n * Input `size` semantics depend on order type:\n * Market BUY (FOK/FAK): size = USDC dollar amount to spend\n * Market SELL (FOK/FAK): size = number of shares to sell\n * Limit BUY (GTC/GTD): size = number of shares to buy\n * Limit SELL (GTC/GTD): size = number of shares to sell\n *\n * Precision (rc.size is always 2 in the official ROUNDING_CONFIG):\n * Market orders → makerAmount ≤ 2 decimals, takerAmount ≤ 4 decimals\n * Limit orders → makerAmount ≤ rc.size (2) decimals, takerAmount ≤ rc.amount\n *\n * Rounding direction:\n * Market BUY: maker = floor (spend less), taker = floor (fewer shares)\n * Market SELL: maker = floor (sell fewer), taker = ceil (receive more)\n * Limit BUY: size = round (tick-align), amount = round\n * Limit SELL: size = floor (avoid overselling), amount = round\n */\nexport function buildOrderMessage(input: BuildOrderMessageInput): OrderMessage {\n const side = input.side === \"BUY\" ? SIDE.BUY : SIDE.SELL;\n const rc = ROUNDING_CONFIG[input.tickSize] ?? DEFAULT_ROUNDING;\n\n const isMarketOrder = input.orderType === \"FOK\" || input.orderType === \"FAK\";\n\n const { makerAmount, takerAmount } = isMarketOrder\n ? getMarketOrderAmounts(side, input.size, input.price, rc)\n : getLimitOrderAmounts(side, input.size, input.price, rc);\n\n const maker = input.funderAddress ?? input.signerAddress;\n\n return {\n salt: Math.floor(Math.random() * 1e15).toString(),\n maker,\n signer: input.signerAddress,\n taker: \"0x0000000000000000000000000000000000000000\",\n tokenId: normalizeTokenId(input.tokenId),\n makerAmount,\n takerAmount,\n expiration: String(input.expiration ?? 0),\n nonce: \"0\",\n feeRateBps: input.feeRateBps ?? \"0\",\n side,\n signatureType: input.signatureType,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Signed order payload builder\n// ---------------------------------------------------------------------------\n\nexport interface SignedOrder extends OrderMessage {\n signature: string;\n orderType: string;\n}\n\n/**\n * Attach a signature (and optional orderType) to an already-built order message\n * to produce the final payload for the Polymarket CLOB.\n *\n * IMPORTANT: always pass the SAME `OrderMessage` that was used for EIP-712\n * signing. Do NOT rebuild it — `buildOrderMessage` generates a random salt\n * each time, so a second call would produce a different message and the\n * signature would be invalid.\n */\nexport function buildSignedOrder(\n orderMessage: OrderMessage,\n signature: string,\n orderType?: string,\n): SignedOrder {\n return {\n ...orderMessage,\n signature,\n orderType: orderType ?? \"GTC\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// CLOB payload builder (orderToJson equivalent)\n// ---------------------------------------------------------------------------\n\n/**\n * CLOB order payload as expected by Polymarket's `POST /order` endpoint.\n *\n * Key format differences from the EIP-712 `OrderMessage`:\n * - `salt` is a **number** (not a string)\n * - `side` is `\"BUY\"` / `\"SELL\"` (not 0 / 1)\n * - `deferExec` is required (defaults to `false`)\n *\n * @see https://github.com/Polymarket/clob-client/blob/main/src/utilities.ts\n */\nexport interface ClobOrderPayload {\n order: {\n salt: number;\n maker: string;\n signer: string;\n taker: string;\n tokenId: string;\n makerAmount: string;\n takerAmount: string;\n expiration: string;\n nonce: string;\n feeRateBps: string;\n side: \"BUY\" | \"SELL\";\n signatureType: number;\n signature: string;\n };\n owner: string;\n orderType: string;\n deferExec: boolean;\n}\n\n/**\n * Convert a `SignedOrder` into the JSON payload format that Polymarket's\n * CLOB API expects. Mirrors the official `orderToJson()` utility.\n */\nexport function buildClobPayload(\n signedOrder: SignedOrder,\n owner: string,\n): ClobOrderPayload {\n const { orderType: ot, ...order } = signedOrder;\n return {\n order: {\n ...order,\n salt: parseInt(order.salt, 10),\n side: order.side === SIDE.BUY ? \"BUY\" : \"SELL\",\n },\n owner,\n orderType: ot ?? \"GTC\",\n deferExec: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Precision helper for UI\n// ---------------------------------------------------------------------------\n\n/**\n * Return the maximum number of decimal places allowed for share quantities\n * on Polymarket, given the market's tick size.\n *\n * In the official CLOB client, `ROUNDING_CONFIG[tickSize].size` is always 2.\n * This function encapsulates that lookup so UI layers don't need to know about\n * the internal rounding config.\n */\nexport function getPolymarketSharesPrecision(tickSize: string): number {\n const rc = ROUNDING_CONFIG[tickSize] ?? DEFAULT_ROUNDING;\n return rc.size;\n}\n"]}