@agg-build/sdk 4.27.5 → 4.27.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agg-websocket-DGxWY0XM.d.mts → agg-websocket-DJiCnnfa.d.mts} +41 -6
- package/dist/agg-websocket-DJiCnnfa.d.mts.map +1 -0
- package/dist/{agg-websocket-DGxWY0XM.d.ts → agg-websocket-DJiCnnfa.d.ts} +41 -6
- package/dist/agg-websocket-DJiCnnfa.d.ts.map +1 -0
- package/dist/browser.d.mts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +22 -10
- package/dist/index.mjs +22 -10
- package/dist/index.mjs.map +1 -1
- package/dist/market-data.d.mts +1 -1
- package/dist/market-data.d.ts +1 -1
- package/package.json +1 -1
- package/dist/agg-websocket-DGxWY0XM.d.mts.map +0 -1
- package/dist/agg-websocket-DGxWY0XM.d.ts.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["computeBestSplitsByAmount","computeBestSplitsByAmountFromCommon"],"sources":["../../common/src/enums/venue.ts","../../common/src/enums/image-size.ts","../../common/src/enums/account.ts","../../common/src/enums/chain.ts","../../common/src/enums/market-status.ts","../../common/src/enums/trading.ts","../../common/src/utils/format-market-display.ts","../../common/src/utils/auth.ts","../../common/src/utils/validate.ts","../../common/src/utils/trading-splits.ts","../../common/src/utils/image-url.ts","../../common/src/utils/venue-market-cluster.ts","../../common/src/utils/sort-venues.ts","../../common/src/utils/venue-url.ts","../../common/src/utils/limit-price-ticks.ts","../../common/src/utils/balance-refill.ts","../src/retry-after.ts","../src/errors.ts","../src/eip55.ts","../src/types.ts","../src/client.ts","../src/best-split.ts","../src/market-aggregator.ts","../src/hosted-venue-funding.ts","../src/index.ts"],"sourcesContent":["/** Use these constants instead of hardcoding \"kalshi\" or \"polymarket\". */\nexport enum Venue {\n kalshi = \"kalshi\",\n polymarket = \"polymarket\",\n limitless = \"limitless\",\n opinion = \"opinion\",\n predict = \"predict\",\n pred = \"pred\",\n tiprun = \"tiprun\",\n probable = \"probable\",\n myriad = \"myriad\",\n hyperliquid = \"hyperliquid\",\n novig = \"novig\",\n prophetx = \"prophetx\",\n betdex = \"betdex\",\n}\n\n/** Single source of truth for venue identifiers. */\nexport const VENUES = [\n Venue.kalshi,\n Venue.polymarket,\n Venue.limitless,\n Venue.opinion,\n Venue.predict,\n Venue.pred,\n Venue.tiprun,\n Venue.probable,\n Venue.myriad,\n Venue.hyperliquid,\n Venue.novig,\n Venue.prophetx,\n Venue.betdex,\n] as const;\n\n/** Canonical destination chain for venues with on-chain funding or settlement. */\nexport const VENUE_CHAIN_IDS: Partial<Record<Venue, number>> = {\n [Venue.kalshi]: 792703809,\n [Venue.polymarket]: 137,\n [Venue.limitless]: 8453,\n [Venue.predict]: 56,\n [Venue.pred]: 8453,\n [Venue.tiprun]: 42161,\n [Venue.myriad]: 56,\n [Venue.hyperliquid]: 1337,\n [Venue.novig]: 792703809,\n [Venue.prophetx]: 792703809,\n};\n\n/**\n * Venues that participate in new discovery, market-data, and execution flows.\n *\n * Keep retired venues in {@link Venue} and {@link VENUES}: historical orders,\n * positions, settlement, and redemption still rely on those identifiers.\n * Re-activating a venue is therefore an intentional code change here rather\n * than a runtime configuration toggle.\n */\nexport const ACTIVE_VENUES = [\n Venue.kalshi,\n Venue.polymarket,\n Venue.limitless,\n Venue.opinion,\n Venue.predict,\n Venue.pred,\n Venue.tiprun,\n Venue.probable,\n Venue.myriad,\n Venue.hyperliquid,\n Venue.novig,\n Venue.prophetx,\n Venue.betdex,\n] as const;\n\n/**\n * Venues excluded from new user-facing activity. BETDEX is active at the\n * compile-time boundary now that discovery and execution are implemented;\n * partner rollout remains controlled by app policy and runtime flags.\n */\nexport const INACTIVE_VENUES = [] as const;\n\n/**\n * Venues hidden from an app that has no explicit venue configuration of its\n * own — and the value stamped onto every new App via the `disabledVenues`\n * schema default.\n *\n * Deliberately SEPARATE from {@link INACTIVE_VENUES}. `INACTIVE_VENUES` answers \"has this venue\n * launched?\" — a compile-time fact that also drives {@link isVenueInactive},\n * the published SDK contract and the UI's tab-flash guard. This answers \"what\n * does an unconfigured caller see?\", which an App row is allowed to override\n * in both directions. PRED, Novig and ProphetX are globally launched but remain off\n * by default until a super admin opts a specific app in.\n *\n * A venue leaves this set only when it should become visible to apps that\n * never opted in — which is a data migration, not a constant edit.\n */\nexport const DEFAULT_DISABLED_VENUES = [\n Venue.pred,\n Venue.tiprun,\n Venue.novig,\n Venue.prophetx,\n Venue.betdex,\n] as const;\n\nconst ACTIVE_VENUE_SET = new Set<string>(ACTIVE_VENUES);\nconst INACTIVE_VENUE_SET = new Set<string>(INACTIVE_VENUES);\n\nfunction normalizeVenue(venue: string): string {\n return venue.trim().toLowerCase();\n}\n\n/** Whether a venue may participate in new user-facing activity. */\nexport function isVenueActive(venue: string): boolean {\n // Engine and API wire values are already canonical lowercase strings. Keep\n // that realtime path allocation-free; only normalize compatibility inputs.\n if (ACTIVE_VENUE_SET.has(venue)) return true;\n if (INACTIVE_VENUE_SET.has(venue)) return false;\n return ACTIVE_VENUE_SET.has(normalizeVenue(venue));\n}\n\n/** Whether a venue is intentionally retained only for wind-down/history flows. */\nexport function isVenueInactive(venue: string): boolean {\n if (INACTIVE_VENUE_SET.has(venue)) return true;\n if (ACTIVE_VENUE_SET.has(venue)) return false;\n return INACTIVE_VENUE_SET.has(normalizeVenue(venue));\n}\n\n/**\n * Data-plane visibility (listings/search/orderbook DISPLAY). Distinct from\n * {@link isVenueActive} (execution/routing) — this predicate never affects\n * whether a venue can trade. `dataVisibleOverride` un-hides specific venues\n * for DATA surfaces only; callers pass an env-derived list.\n */\nexport function isVenueDataVisible(\n venue: string,\n dataVisibleOverride: readonly Venue[] = [],\n): boolean {\n if (isVenueActive(venue)) return true;\n const n = normalizeVenue(venue);\n return dataVisibleOverride.some((v) => normalizeVenue(v) === n);\n}\n\n/**\n * Merge app-specific disabled venues with the compile-time retired set, then\n * remove any venue explicitly opted into data visibility via\n * `dataVisibleVenues` (see {@link isVenueDataVisible}). Results use the\n * canonical {@link VENUES} order and ignore unknown values.\n */\nexport function getEffectiveDisabledVenues(\n disabledVenues?: readonly (Venue | string)[],\n dataVisibleVenues: readonly Venue[] = [],\n): Venue[] {\n // `undefined` means NO APP CONTEXT — an admin-tier or authless discovery\n // call, or a global cron. There is no App row to consult and none to\n // backfill, so fall back to the platform default rather than showing\n // everything. The env override still applies here, which is what lets\n // staging verify a venue before any app opts in.\n if (disabledVenues === undefined) {\n const disabled = new Set<string>(DEFAULT_DISABLED_VENUES);\n for (const venue of dataVisibleVenues) disabled.delete(normalizeVenue(venue));\n return VENUES.filter((venue) => disabled.has(venue));\n }\n\n // An App row is authoritative in BOTH directions. It may reveal a venue the\n // platform hides by default (a super admin opted this app in) and it may hide\n // one the platform shows. Notably the env override is NOT applied here: it\n // used to delete from this set unconditionally, which erased an app's own\n // entry and made per-app hiding impossible wherever the override was set.\n const disabled = new Set(disabledVenues.map(normalizeVenue));\n return VENUES.filter((venue) => disabled.has(venue));\n}\n","export enum ImageSize {\n sm = 44,\n md = 48,\n lg = 60,\n // Retina (2x) variants. The processor Lambda has emitted these since\n // 2026-07-31; older assets lack them until the backfill runs, so consumers\n // must fall back to a 1x variant when one 404s.\n xl = 80,\n xxl = 96,\n xxxl = 120,\n original = 0,\n}\n\n// Keep in sync with SIZES in infra/src/handlers/image-processor.ts.\nexport const IMAGE_SIZES = [\n ImageSize.sm,\n ImageSize.md,\n ImageSize.lg,\n ImageSize.xl,\n ImageSize.xxl,\n ImageSize.xxxl,\n] as const;\n\n/** Variants sized for 2x displays. */\nexport const RETINA_IMAGE_SIZES = [ImageSize.xl, ImageSize.xxl, ImageSize.xxxl] as const;\n","export enum AccountType {\n oauth = \"oauth\",\n siwe = \"siwe\",\n siws = \"siws\",\n email = \"email\",\n}\n\nexport enum AccountProvider {\n wallet = \"wallet\",\n solana_wallet = \"solana_wallet\",\n google = \"google\",\n twitter = \"twitter\",\n apple = \"apple\",\n email = \"email\",\n}\n","export enum Chain {\n evm = \"evm\",\n svm = \"svm\",\n}\n","export enum MatchStatus {\n pending = \"pending\",\n unmatched = \"unmatched\",\n review = \"review\",\n matched = \"matched\",\n verified = \"verified\",\n rejected = \"rejected\",\n}\n\nexport enum MatchType {\n manual = \"manual\",\n llm = \"llm\",\n}\n\n/** Match statuses considered \"confirmed\" for user-facing data (orderbooks, listings, aggregation). */\nexport const CONFIRMED_MATCH_STATUSES: MatchStatus[] = [MatchStatus.matched, MatchStatus.verified];\n\nexport enum MarketStatus {\n open = \"open\",\n closed = \"closed\",\n resolved = \"resolved\",\n unopened = \"unopened\",\n paused = \"paused\",\n}\n","export enum OrderStatus {\n pending = \"pending\",\n signing = \"signing\",\n pending_bridge = \"pending_bridge\",\n submitting = \"submitting\",\n submitted = \"submitted\",\n open = \"open\",\n partially_filled_open = \"partially_filled_open\",\n cancel_pending = \"cancel_pending\",\n filled = \"filled\",\n partial_fill = \"partial_fill\",\n failed = \"failed\",\n expired = \"expired\",\n cancelled = \"cancelled\",\n}\n\nexport enum TradeSide {\n Buy = \"buy\",\n Sell = \"sell\",\n}\n\nexport enum OrderType {\n Market = \"market\",\n Limit = \"limit\",\n}\n\nexport enum TimeInForce {\n GTC = \"GTC\",\n GTD = \"GTD\",\n FOK = \"FOK\",\n FAK = \"FAK\",\n IOC = \"IOC\",\n ALO = \"ALO\",\n}\n","import { Venue } from \"../enums/venue\";\n\n/**\n * API response-boundary formatters for market display fields.\n *\n * Called by the response mappers (mapVenueMarketRow, toVenueEventDto) to\n * produce display-ready text before it reaches the client. Internal code\n * (matching, sorting, DB) uses the raw DB values.\n */\n\n/**\n * Resolve the display label for a VenueMarketOutcome.\n *\n * - **Kalshi:** Always return `label`. Kalshi's label IS the canonical\n * display text (\"Yes\"/\"No\"); `title` is a subtitle shown elsewhere.\n * - **All other venues:** Return `title` if present and non-empty,\n * otherwise `label`. Polymarket normalizes binary outcomes to\n * \"Yes\"/\"No\" labels and stores the original descriptive text in `title`\n * (e.g. label=\"Yes\", title=\"Trump Wins\").\n *\n * When `market` context is provided and the outcome's `title` duplicates\n * the market's `question` (a known Limitless group-sub-market quirk where\n * the driver name lands on every outcome's title), fall back to `label`\n * so \"Yes\"/\"No\" remain distinguishable instead of both collapsing to the\n * market subject.\n */\nexport function formatOutcomeLabel(\n venue: Venue,\n outcome: { label: string; title?: string | null },\n _market?: { question?: string | null },\n): string {\n // ON FE we check at places where label is Yes or No so we should return the label directly\n // and then on FE display we would use title instead of label directly so user sees it clearly.\n return outcome.label;\n\n // @deprecated\n // if (venue === Venue.kalshi) return outcome.label;\n // const title = outcome.title?.trim();\n // if (!title) return outcome.label;\n // const question = market?.question?.trim();\n // if (question && title === question) return outcome.label;\n // return title;\n}\n\n/**\n * Resolve the display question for a VenueMarket.\n *\n * - **Kalshi:** Return the first outcome's `title` if available. Kalshi\n * market tickers (e.g. \"INXD-26APR08-T7563.43\") are stored in\n * `question` but the human-readable text is in the outcome's `title`\n * (e.g. \"S&P 500 closes above 7,563.43\"). Falls back to `question` if\n * no outcome title exists.\n * - **All other venues:** Return `question` as-is (already human-readable).\n */\nexport function formatMarketQuestion(\n venue: Venue,\n market: {\n question: string;\n shortTitle?: string | null;\n venueMarketOutcomes?: Array<{ label: string; title?: string | null }>;\n },\n): string {\n if (market.shortTitle?.trim()) return market.shortTitle.trim();\n if (venue === Venue.kalshi) {\n const firstTitle = market.venueMarketOutcomes?.[0]?.title?.trim();\n if (firstTitle) return firstTitle;\n }\n return market.question.trim();\n}\n\n/**\n * Resolve the display title for a VenueMarketOutcome.\n *\n * Returns `null` when every outcome on the market shares the same `title`\n * (Kalshi binary markets often store the same human-readable phrase on\n * both Yes/No outcomes — repeating it on each option is redundant). The\n * frontend should fall back to `label` in that case.\n *\n * Otherwise returns the outcome's stored `title` verbatim (or `null` when\n * unset). The DB `label` is always returned untouched by this helper.\n *\n * Polymarket player-prop fallback: when a binary Yes/No outcome has no\n * stored title (Gamma sends `outcomes=[\"Yes\",\"No\"]` for these markets,\n * e.g. *\"Mikal Bridges: Rebounds O/U 2.5\"*), derive `Over`/`Under` from\n * the question's `O/U <n>` token so the FE has something meaningful to\n * show. Sports-totals (`[\"Over\",\"Under\"]`) and spread markets\n * (`[\"<TeamA>\",\"<TeamB>\"]`) already get titles from upstream and are\n * unaffected.\n */\nexport function formatOutcomeTitle(\n _venue: Venue,\n outcome: { label: string; title?: string | null },\n market: {\n question?: string | null;\n venueMarketOutcomes?: Array<{ label: string; title?: string | null }>;\n },\n): string | null {\n const outcomes = market.venueMarketOutcomes ?? [];\n if (outcomes.length >= 2) {\n const normalized = outcomes.map((o) => o.title?.trim() ?? \"\");\n const hasAnyTitle = normalized.some((t) => t.length > 0);\n // Kalshi shape: every outcome carries the same non-empty title — fall\n // back to label so Yes/No stay distinguishable. We only short-circuit\n // here when at least one title is populated; if all are empty, fall\n // through to the O/U derivation below.\n if (hasAnyTitle && normalized.every((t) => t === normalized[0])) return null;\n }\n const title = outcome.title?.trim();\n if (title) return title;\n return deriveOverUnderTitle(outcome.label, market.question);\n}\n\nconst OVER_UNDER_QUESTION = /\\bO\\/U\\s+\\d/i;\n\nfunction deriveOverUnderTitle(label: string, question: string | null | undefined): string | null {\n if (!question || !OVER_UNDER_QUESTION.test(question)) return null;\n const normalized = label.trim().toLowerCase();\n if (normalized === \"yes\") return \"Over\";\n if (normalized === \"no\") return \"Under\";\n return null;\n}\n","import type { UserProfile } from \"../types-standalone\";\nimport { AccountType } from \"../enums/account\";\n\nexport function getWalletAddressFromUserProfile(user: UserProfile | undefined): string | undefined {\n // Prefer explicit wallet oauth account if present\n const oauthWallet =\n user?.accounts?.find(\n (a) => a.type === AccountType.oauth && String(a.provider).toLowerCase() === \"wallet\",\n ) ?? null;\n if (oauthWallet?.providerAccountId) return oauthWallet.providerAccountId;\n\n // Fallback to SIWE account\n const siweAccount = user?.accounts?.find((a) => a.type === AccountType.siwe) ?? null;\n return siweAccount?.providerAccountId ?? undefined;\n}\n","/**\n * Lightweight runtime validation utilities — zero dependencies.\n * Replaces Zod's safeParse/parse for simple type-guard-based validation.\n */\n\n// ── safeParse ────────────────────────────────────────────────────────\n\nexport type SafeParseSuccess<T> = { success: true; data: T };\nexport type SafeParseFailure = { success: false; error?: { issues: Array<{ message: string }> } };\nexport type SafeParseResult<T> = SafeParseSuccess<T> | SafeParseFailure;\n\n/** Generic safeParse — drop-in replacement for zod's schema.safeParse(). */\nexport function safeParse<T>(value: unknown, guard: (v: unknown) => v is T): SafeParseResult<T> {\n if (guard(value)) return { success: true, data: value };\n return { success: false };\n}\n\n/** Throwing parse — drop-in replacement for zod's schema.parse(). */\nexport function parse<T>(\n value: unknown,\n guard: (v: unknown) => v is T,\n message = \"Validation failed\",\n): T {\n if (guard(value)) return value;\n const err = new Error(message);\n (err as any).issues = [{ message }];\n throw err;\n}\n\n// ── Guard factories ──────────────────────────────────────────────────\n\n/** Creates a type guard for a set of string values (enums, string unions). */\nexport function isEnum<T extends string>(values: ReadonlySet<string>): (v: unknown) => v is T {\n return (v: unknown): v is T => typeof v === \"string\" && values.has(v);\n}\n\n/** Creates a type guard for a set of string values from an enum or array. */\nexport function enumGuard<T extends string>(\n source: Record<string, T> | readonly T[],\n): (v: unknown) => v is T {\n const values = new Set<string>(Array.isArray(source) ? source : Object.values(source));\n return isEnum<T>(values);\n}\n\n// ── Built-in guards ──────────────────────────────────────────────────\n\n/** Finite, non-negative number. */\nexport function isFiniteNonNeg(v: unknown): v is number {\n return typeof v === \"number\" && Number.isFinite(v) && v >= 0;\n}\n\n/** Non-empty string. */\nexport function isNonEmptyString(v: unknown): v is string {\n return typeof v === \"string\" && v.length > 0;\n}\n\n/** Object with specific keys present and of the right primitive type. */\nexport function hasShape<T>(v: unknown, checks: Record<string, (val: unknown) => boolean>): v is T {\n if (typeof v !== \"object\" || v === null) return false;\n const obj = v as Record<string, unknown>;\n for (const [key, check] of Object.entries(checks)) {\n if (!(key in obj) || !check(obj[key])) return false;\n }\n return true;\n}\n\n// ── Email validation ─────────────────────────────────────────────────\n\nconst EMAIL_MSG = \"Enter a valid email address.\";\nconst EMAIL_MAX_LEN = 254; // RFC 5321\n\n/**\n * Linear-scan email check matching /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/ semantics\n * without polynomial-regex backtracking. Exported so the API's TypeBox\n * FormatRegistry can share the same implementation.\n */\nexport function isEmail(v: string): boolean {\n const n = v.length;\n if (n === 0 || n > EMAIL_MAX_LEN) return false;\n let atIdx = -1;\n for (let i = 0; i < n; i++) {\n const c = v.charCodeAt(i);\n if (c === 32 || (c >= 9 && c <= 13)) return false;\n if (c === 0x40 /* @ */) {\n if (atIdx !== -1) return false;\n atIdx = i;\n }\n }\n if (atIdx <= 0 || atIdx === n - 1) return false;\n for (let i = atIdx + 2; i < n - 1; i++) {\n if (v.charCodeAt(i) === 0x2e /* . */) return true;\n }\n return false;\n}\n\n/** Validates + trims email. Returns safeParse-compatible result with error.issues shape. */\nexport function parseEmail(raw: string): SafeParseResult<{ email: string }> {\n const email = raw.trim();\n if (!isEmail(email)) {\n return { success: false, error: { issues: [{ message: EMAIL_MSG }] } };\n }\n return { success: true, data: { email } };\n}\n\n/** Strict email parse — throws with .issues for catch-block compat. */\nexport function parseEmailStrict(raw: string): { email: string } {\n const result = parseEmail(raw);\n if (!result.success) {\n const err = new Error(EMAIL_MSG);\n (err as any).issues = result.error?.issues;\n throw err;\n }\n return result.data;\n}\n","import type { Orderbook, TradeSplit, VenueMarket, VenueMarketOutcome } from \"../types-standalone\";\nimport type { Venue } from \"../enums/venue\";\nimport { TradeSide } from \"../enums/trading\";\n\ninterface Level {\n venue: Venue;\n venueMarketOutcomeId: string;\n outcomeExternalIdentifier: string | undefined;\n price: number;\n size: number;\n negRisk: boolean;\n}\n\nexport interface SplitsByAmountResult {\n splits: TradeSplit[];\n totalSize: number;\n totalCost: number;\n}\n\nexport function computeBestSplitsByAmount(\n selections: Array<{\n market: VenueMarket;\n outcome: VenueMarketOutcome;\n orderbook: Orderbook;\n }>,\n side: TradeSide,\n maxDollarAmount: number,\n): SplitsByAmountResult {\n if (selections.length === 0 || maxDollarAmount <= 0) {\n return { splits: [], totalSize: 0, totalCost: 0 };\n }\n\n const levels: Level[] = [];\n for (const o of selections) {\n const venue = o.market.venue as Venue;\n const venueMarketOutcomeId = o.outcome.id;\n const outcomeExternalIdentifier = o.outcome.externalIdentifier ?? undefined;\n if (side === TradeSide.Buy) {\n [...o.orderbook.asks]\n .sort((a, b) => a.price - b.price)\n .forEach((l) =>\n levels.push({\n venue,\n venueMarketOutcomeId,\n outcomeExternalIdentifier,\n price: l.price,\n size: l.size,\n negRisk: o.orderbook.negRisk ?? false,\n }),\n );\n } else {\n [...o.orderbook.bids]\n .sort((a, b) => b.price - a.price)\n .forEach((l) =>\n levels.push({\n venue,\n venueMarketOutcomeId,\n outcomeExternalIdentifier,\n price: 1 - l.price,\n size: l.size,\n negRisk: o.orderbook.negRisk ?? false,\n }),\n );\n }\n }\n\n levels.sort((a, b) => a.price - b.price);\n\n let totalCost = 0;\n const fills: Level[] = [];\n for (const l of levels) {\n if (totalCost >= maxDollarAmount) break;\n const remainingBudget = maxDollarAmount - totalCost;\n const maxSizeAtLevel = Math.min(l.size, remainingBudget / l.price);\n if (maxSizeAtLevel <= 0) continue;\n const take = maxSizeAtLevel;\n fills.push({\n venue: l.venue,\n venueMarketOutcomeId: l.venueMarketOutcomeId,\n outcomeExternalIdentifier: l.outcomeExternalIdentifier,\n price: l.price,\n size: take,\n negRisk: l.negRisk,\n });\n totalCost += l.price * take;\n }\n\n if (fills.length === 0) {\n return { splits: [], totalSize: 0, totalCost: 0 };\n }\n\n const byOutcome: Record<\n string,\n {\n size: number;\n venue: Venue;\n venueMarketOutcomeId: string;\n outcomeExternalIdentifier: string | undefined;\n negRisk: boolean;\n }\n > = {};\n for (const f of fills) {\n const key = `${f.venue}:${f.venueMarketOutcomeId}`;\n const existing = byOutcome[key];\n if (!existing) {\n byOutcome[key] = {\n size: f.size,\n venue: f.venue,\n venueMarketOutcomeId: f.venueMarketOutcomeId,\n outcomeExternalIdentifier: f.outcomeExternalIdentifier,\n negRisk: f.negRisk,\n };\n } else {\n existing.size += f.size;\n }\n }\n\n const splits: TradeSplit[] = [];\n let totalSize = 0;\n for (const key in byOutcome) {\n const { size, venue, venueMarketOutcomeId, outcomeExternalIdentifier, negRisk } =\n byOutcome[key];\n totalSize += size;\n let price = 0;\n if (size > 0) {\n const outcomeFills = fills.filter(\n (f) => f.venue === venue && f.venueMarketOutcomeId === venueMarketOutcomeId,\n );\n if (side === TradeSide.Buy) {\n const rawPrice = Math.max(...outcomeFills.map((f) => f.price));\n price = Math.ceil(rawPrice * 100) / 100;\n } else {\n const rawPrice = Math.min(...outcomeFills.map((f) => 1 - f.price));\n price = Math.floor(rawPrice * 100) / 100;\n }\n }\n splits.push({\n venue,\n venueMarketOutcomeId,\n side,\n price,\n size,\n negRisk,\n outcomeExternalIdentifier,\n });\n }\n return {\n splits,\n totalSize,\n totalCost,\n };\n}\n","import { ImageSize, RETINA_IMAGE_SIZES } from \"../enums/image-size\";\n\n/**\n * Pick the smallest pre-processed variant that covers the requested pixel size.\n * Falls back to `original` when no pre-processed size is large enough.\n */\nfunction pickVariant(px: number): ImageSize {\n if (px <= ImageSize.sm) return ImageSize.sm; // 44\n if (px <= ImageSize.md) return ImageSize.md; // 48\n if (px <= ImageSize.lg) return ImageSize.lg; // 60\n return ImageSize.original;\n}\n\nconst VARIANT_RE = /\\/(original|raw|\\d+)\\.webp$/;\n\n/**\n * Rewrite a CDN image URL to use the pre-processed variant closest to `maxPx`.\n *\n * - CDN URLs ending in `/original.webp` or `/{size}.webp` are rewritten.\n * - External URLs (venue logos, non-CDN) pass through unchanged.\n * - Falsy inputs return `undefined`.\n *\n * @param url Full image URL from the API (e.g. `https://assets.agg.market/users/.../original.webp`)\n * @param maxPx Largest dimension the image will be rendered at, in CSS pixels.\n * Pass the **largest** responsive breakpoint size (e.g. 60 for `size-10 md:size-[60px]`).\n */\nexport function optimizedImageUrl(\n url: string | null | undefined,\n maxPx: number,\n): string | undefined {\n if (!url) return undefined;\n if (!VARIANT_RE.test(url)) return url;\n const variant = pickVariant(maxPx);\n const filename = variant === ImageSize.original ? \"original.webp\" : `${variant}.webp`;\n return url.replace(VARIANT_RE, `/${filename}`);\n}\n\n/**\n * Rewrite a CDN image URL to the retina variant covering `maxPx` at 2x density,\n * for use as the `2x` candidate beside {@link optimizedImageUrl}.\n *\n * Returns `undefined` for external URLs, falsy inputs, or when `maxPx * 2`\n * exceeds the largest retina variant (the 1x URL is then the only candidate).\n * Assets processed before 2026-07-31 may not have retina variants yet, so\n * callers must fall back to the 1x URL when this one fails to load.\n */\nexport function retinaImageUrl(url: string | null | undefined, maxPx: number): string | undefined {\n if (!url) return undefined;\n if (!VARIANT_RE.test(url)) return undefined;\n const variant = RETINA_IMAGE_SIZES.find((size) => size >= maxPx * 2);\n if (variant == null) return undefined;\n return url.replace(VARIANT_RE, `/${variant}.webp`);\n}\n","export type VenueMarketClusterNode<TMarket = unknown> = {\n id: string;\n venue: string;\n matchedVenueMarkets?: readonly TMarket[] | null;\n matchEntry?:\n | {\n targetVenueMarketId?: string | null;\n targetVenueMarket?: TMarket | null;\n }\n | null\n | undefined;\n venues?: readonly string[] | null;\n venueCount?: number | null;\n};\n\nconst toNonEmptyString = (value: string | null | undefined): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n\n const trimmedValue = value.trim();\n return trimmedValue ? trimmedValue : undefined;\n};\n\nconst addGraphEdge = (\n adjacencyById: Map<string, Set<string>>,\n fromMarketId: string,\n toMarketId: string,\n): void => {\n if (fromMarketId === toMarketId) return;\n\n const fromNeighbors = adjacencyById.get(fromMarketId) ?? new Set<string>();\n fromNeighbors.add(toMarketId);\n adjacencyById.set(fromMarketId, fromNeighbors);\n\n const toNeighbors = adjacencyById.get(toMarketId) ?? new Set<string>();\n toNeighbors.add(fromMarketId);\n adjacencyById.set(toMarketId, toNeighbors);\n};\n\nconst collectDirectRelationMarkets = <TMarket extends VenueMarketClusterNode<TMarket>>(\n market: TMarket,\n): TMarket[] => {\n const relationMarkets: TMarket[] = [];\n const seenRelationIds = new Set<string>();\n\n const addRelationMarket = (relationMarket: TMarket | null | undefined): void => {\n if (!relationMarket) return;\n if (seenRelationIds.has(relationMarket.id)) return;\n\n seenRelationIds.add(relationMarket.id);\n relationMarkets.push(relationMarket);\n };\n\n for (const matchedVenueMarket of market.matchedVenueMarkets ?? []) {\n addRelationMarket(matchedVenueMarket);\n }\n\n addRelationMarket(market.matchEntry?.targetVenueMarket ?? undefined);\n\n return relationMarkets;\n};\n\nconst dedupeSourceMarketsById = <TMarket extends VenueMarketClusterNode<TMarket>>(\n markets: readonly TMarket[],\n): TMarket[] => {\n const seenMarketIds = new Set<string>();\n\n return markets.filter((market) => {\n if (seenMarketIds.has(market.id)) {\n return false;\n }\n\n seenMarketIds.add(market.id);\n return true;\n });\n};\n\nconst collectUniqueRelatedMarkets = <TMarket extends VenueMarketClusterNode<TMarket>>(\n markets: readonly TMarket[],\n sourceMarketsById: Map<string, TMarket>,\n): TMarket[] => {\n const relatedMarketsById = new Map<string, TMarket>();\n\n for (const market of markets) {\n for (const relatedMarket of collectDirectRelationMarkets(market)) {\n if (sourceMarketsById.has(relatedMarket.id) || relatedMarketsById.has(relatedMarket.id)) {\n continue;\n }\n\n relatedMarketsById.set(relatedMarket.id, relatedMarket);\n }\n }\n\n return Array.from(relatedMarketsById.values());\n};\n\nexport const normalizeVenueMarketCluster = <TMarket extends VenueMarketClusterNode<TMarket>>(\n markets: readonly TMarket[],\n selectedMarketId?: string | null,\n): TMarket[] => {\n if (markets.length === 0) return [];\n\n const orderedSourceMarkets = dedupeSourceMarketsById(markets);\n const sourceMarketsById = new Map(orderedSourceMarkets.map((market) => [market.id, market]));\n const orderedRelatedMarkets = collectUniqueRelatedMarkets(\n orderedSourceMarkets,\n sourceMarketsById,\n );\n const relatedMarketsById = new Map(orderedRelatedMarkets.map((market) => [market.id, market]));\n\n const resolvedSelectedMarketId = toNonEmptyString(selectedMarketId);\n if (!resolvedSelectedMarketId) {\n return [...orderedSourceMarkets, ...orderedRelatedMarkets];\n }\n\n const adjacencyById = new Map<string, Set<string>>();\n\n for (const market of orderedSourceMarkets) {\n for (const relatedMarket of collectDirectRelationMarkets(market)) {\n addGraphEdge(adjacencyById, market.id, relatedMarket.id);\n }\n\n const targetVenueMarketId = toNonEmptyString(market.matchEntry?.targetVenueMarketId);\n if (targetVenueMarketId) {\n addGraphEdge(adjacencyById, market.id, targetVenueMarketId);\n }\n }\n\n if (\n !sourceMarketsById.has(resolvedSelectedMarketId) &&\n !relatedMarketsById.has(resolvedSelectedMarketId)\n ) {\n return [];\n }\n\n const visitedMarketIds = new Set<string>();\n const queue = [resolvedSelectedMarketId];\n\n while (queue.length > 0) {\n const currentMarketId = queue.shift();\n if (!currentMarketId || visitedMarketIds.has(currentMarketId)) {\n continue;\n }\n\n visitedMarketIds.add(currentMarketId);\n\n const neighborMarketIds = adjacencyById.get(currentMarketId);\n for (const neighborMarketId of Array.from(neighborMarketIds ?? new Set<string>())) {\n if (!visitedMarketIds.has(neighborMarketId)) {\n queue.push(neighborMarketId);\n }\n }\n }\n\n const orderedClusterMarkets: TMarket[] = [];\n const appendedMarketIds = new Set<string>();\n\n const appendMarket = (market: TMarket | undefined): void => {\n if (!market) return;\n if (!visitedMarketIds.has(market.id)) return;\n if (appendedMarketIds.has(market.id)) return;\n\n appendedMarketIds.add(market.id);\n orderedClusterMarkets.push(market);\n };\n\n appendMarket(\n sourceMarketsById.get(resolvedSelectedMarketId) ??\n relatedMarketsById.get(resolvedSelectedMarketId),\n );\n\n for (const market of orderedSourceMarkets) {\n appendMarket(market);\n }\n\n for (const market of orderedRelatedMarkets) {\n appendMarket(market);\n }\n\n return orderedClusterMarkets;\n};\n","import { Venue } from \"../enums/venue\";\n\n/**\n * Canonical venue display order — the single source of truth for every surface\n * that lists venues (event cards, orderbook columns, chart tie-breaks, and the\n * admin Settings venue list).\n *\n * Admin's drag-to-reorder is LOCAL STATE ONLY: no App column, contract field or\n * endpoint persists a per-app order, so a drag is discarded on save. Changing\n * the order is a code change here until that lands.\n */\nconst VENUE_SORT_ORDER: readonly string[] = [\n Venue.polymarket,\n Venue.hyperliquid,\n Venue.predict,\n Venue.prophetx,\n Venue.betdex,\n Venue.kalshi,\n Venue.limitless,\n Venue.myriad,\n Venue.pred,\n Venue.tiprun,\n Venue.probable,\n Venue.novig,\n Venue.opinion,\n];\n\nconst venueOrderIndex = new Map(VENUE_SORT_ORDER.map((v, i) => [v, i]));\n\nconst getVenueOrder = (venue: string): number =>\n venueOrderIndex.get(venue) ?? VENUE_SORT_ORDER.length;\n\nexport const sortVenues = <T extends string>(venues: readonly T[]): T[] =>\n [...venues].sort((a, b) => getVenueOrder(a) - getVenueOrder(b));\n","/**\n * Build an external URL to a venue's event/market page.\n *\n * Single source of truth — used by API services AND by the admin Matched\n * Events page to deep-link rows out to the venue's UI.\n *\n * Returns `null` when there isn't enough data to construct a working URL.\n * Callers should hide the link button rather than render a broken href.\n *\n * Per-venue URL conventions are kept here so any future change (e.g.\n * Kalshi moves to a new path, Polymarket rebrands) is a one-file edit.\n */\nexport interface BuildVenueUrlOpts {\n /** VenueEvent.slug — preferred input for venues that use slug-style URLs. */\n eventSlug?: string | null;\n /** VenueEvent.externalIdentifier — used by Kalshi (with series) and as a fallback. */\n eventExternalId?: string | null;\n /** VenueEvent.series.externalIdentifier — required for Kalshi's canonical URL. */\n seriesExternalId?: string | null;\n /** VenueMarket.conditionId — used as a fallback for Polymarket when slug is missing. */\n conditionId?: string | null;\n /**\n * Novig outcome id — the per-side (Yes/No) id, e.g.\n * `DiscoveredOutcome.external_identifier` / `o.id` in\n * agg-venue-novig/src/convert.rs. NOT the same id as `eventExternalId`\n * (Novig's event id, `ev.id`) or a market id (`m.id`) — Novig's deeplink\n * template takes the outcome, one level more specific than either. Not\n * currently plumbed from any caller.\n */\n outcomeExternalId?: string | null;\n /**\n * Novig-issued partner id, required by Novig's deeplink URL structure for\n * attribution tracking (https://docs.novig.com/llms-full.txt,\n * \"Deeplinking\"). Not currently plumbed from any caller — no Novig case\n * builds a URL without it, so pass it explicitly once we have one.\n */\n partnerId?: string | null;\n /**\n * Which of Novig's two documented deeplink schemes to build — Novig's docs\n * say to detect the caller's platform via User-Agent and pick accordingly.\n * Defaults to `\"web\"`. Ignored by every other venue.\n */\n platform?: \"web\" | \"native\";\n}\n\nexport function buildVenueUrl(venue: string, opts: BuildVenueUrlOpts): string | null {\n switch (venue) {\n case \"kalshi\": {\n // Kalshi canonical: /markets/<series>/<event>. Both lowercased.\n // Without the series id we can't build a URL that resolves, so we\n // return null and the FE hides the link button.\n const series = opts.seriesExternalId;\n const event = opts.eventExternalId;\n if (series && event) {\n return `https://kalshi.com/markets/${series.toLowerCase()}/${event.toLowerCase()}`;\n }\n return null;\n }\n case \"polymarket\": {\n if (opts.eventSlug) return `https://polymarket.com/event/${opts.eventSlug}`;\n if (opts.conditionId) return `https://polymarket.com/market/${opts.conditionId}`;\n return null;\n }\n case \"predict\": {\n if (opts.eventSlug) return `https://predict.fun/market/${opts.eventSlug}`;\n return null;\n }\n case \"pred\": {\n // PRED's SPA routes fixture-level canonical names through /trade/:canonicalName.\n // Discovery stores that canonical name as VenueEvent.slug, so the event\n // slug is the only safe identifier here; child market ids do not resolve\n // as standalone public pages.\n if (opts.eventSlug) return `https://www.pred.app/trade/${opts.eventSlug}`;\n return null;\n }\n case \"limitless\": {\n if (opts.eventSlug) return `https://limitless.exchange/markets/${opts.eventSlug}`;\n return null;\n }\n case \"opinion\": {\n if (opts.eventSlug) return `https://www.opinion.trade/market/${opts.eventSlug}`;\n return null;\n }\n case \"myriad\": {\n // https://myriad.markets/markets/<slug>\n if (opts.eventSlug) return `https://myriad.markets/markets/${opts.eventSlug}`;\n return null;\n }\n case \"hyperliquid\": {\n // https://app.hyperliquid.xyz/trade/<slug>\n // Hyperliquid uses slug-style market names, NOT the numeric externalId.\n if (opts.eventSlug) return `https://app.hyperliquid.xyz/trade/${opts.eventSlug}`;\n return null;\n }\n case \"probable\": {\n if (opts.eventSlug) return `https://probable.markets/event/${opts.eventSlug}`;\n return null;\n }\n case \"novig\": {\n // Documented formats (docs.novig.com/llms-full.txt, \"Deeplinking\"):\n // web: novig.com/events/<outcome_id>/<partner_id>/<wager_amount>?referralCode=YOUR_CODE\n // native: novigapp://events/<outcome_id>/<partner_id>?referralCode=YOUR_CODE\n // outcome_id and partner_id are both required — Novig's docs state\n // partner_id must \"always\" be included for attribution tracking, with\n // no documented fallback URL that omits either.\n //\n // INTENTIONALLY INERT today: no caller supplies partnerId (no Novig\n // partner/affiliate id is plumbed anywhere in this codebase yet), so\n // this always returns null — same \"insufficient data, hide the link\"\n // pattern as every other case above. Left in (not deleted) so the\n // mapping is correct and ready the moment a partnerId source exists,\n // rather than being reintroduced from scratch and re-risking a wrong\n // id mapping.\n if (opts.outcomeExternalId && opts.partnerId) {\n return opts.platform === \"native\"\n ? `novigapp://events/${opts.outcomeExternalId}/${opts.partnerId}`\n : `https://novig.com/events/${opts.outcomeExternalId}/${opts.partnerId}`;\n }\n return null;\n }\n default:\n return null;\n }\n}\n","export const LIMIT_PRICE_RAW_SCALE = BigInt(1_000_000);\n\nexport type LimitPriceSide = \"buy\" | \"sell\";\n\nexport type LimitPriceTickAdjustment = {\n adjusted: boolean;\n adjustedPriceRaw: string;\n originalPriceRaw: string;\n tickSizeRaw: string | null;\n};\n\nconst resolveTickSizeRaw = (tickSize: number): bigint => {\n const scaledTick = tickSize * Number(LIMIT_PRICE_RAW_SCALE);\n const roundedTick = Math.round(scaledTick);\n\n if (\n !Number.isFinite(scaledTick) ||\n roundedTick <= 0 ||\n Math.abs(scaledTick - roundedTick) > 1e-6\n ) {\n throw new RangeError(`Unsupported limit-order tick size: ${tickSize}`);\n }\n\n return BigInt(roundedTick);\n};\n\n/**\n * Aligns a six-decimal limit price to a venue tick in the user's favor.\n * All rounding is performed with integers after the venue tick is scaled.\n */\nexport const adjustLimitPriceRawToTick = ({\n limitPriceRaw,\n side,\n tickSize,\n}: {\n limitPriceRaw: string;\n side: LimitPriceSide;\n tickSize?: number | null;\n}): LimitPriceTickAdjustment => {\n const originalPrice = BigInt(limitPriceRaw);\n const originalPriceRaw = originalPrice.toString();\n if (tickSize == null) {\n return {\n adjusted: false,\n adjustedPriceRaw: originalPriceRaw,\n originalPriceRaw,\n tickSizeRaw: null,\n };\n }\n\n const tickSizeRaw = resolveTickSizeRaw(tickSize);\n const remainder = originalPrice % tickSizeRaw;\n if (remainder === BigInt(0)) {\n return {\n adjusted: false,\n adjustedPriceRaw: originalPriceRaw,\n originalPriceRaw,\n tickSizeRaw: tickSizeRaw.toString(),\n };\n }\n\n const adjustedPrice =\n side === \"buy\" ? originalPrice - remainder : originalPrice + (tickSizeRaw - remainder);\n\n return {\n adjusted: true,\n adjustedPriceRaw: adjustedPrice.toString(),\n originalPriceRaw,\n tickSizeRaw: tickSizeRaw.toString(),\n };\n};\n","export const DEFAULT_BALANCE_REFILL_DAILY_CAP_RAW = \"1002000000\";\nexport const DEFAULT_BALANCE_REFILL_MAX_FEE_RAW = \"2000000\";\n\nexport const getBalanceRefillMaximumRaw = (dailyCapRaw: string, maxFeeRaw: string): string => {\n const dailyCap = BigInt(dailyCapRaw);\n const maximumFee = BigInt(maxFeeRaw);\n if (dailyCap <= maximumFee) return \"0\";\n\n return (dailyCap - maximumFee).toString();\n};\n\nexport const isBalanceRefillWithinDailyCap = (\n minimumRaw: string,\n refillAmountRaw: string,\n dailyCapRaw: string,\n maxFeeRaw: string,\n): boolean => {\n const maximum = BigInt(getBalanceRefillMaximumRaw(dailyCapRaw, maxFeeRaw));\n return BigInt(minimumRaw) <= maximum && BigInt(refillAmountRaw) <= maximum;\n};\n","/** Convert explicit retry hints to milliseconds without treating arbitrary strings as dates. */\nexport function parseRetryAfterSeconds(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) return undefined;\n const milliseconds = value * 1000;\n return Number.isSafeInteger(milliseconds) ? milliseconds : undefined;\n}\n\nexport function parseRetryAfterHeader(\n value: string | null | undefined,\n now = Date.now(),\n): number | undefined {\n if (!value) return undefined;\n const text = value.trim();\n if (/^\\d+$/.test(text)) return parseRetryAfterSeconds(Number(text));\n // HTTP-date uses GMT; accepting Date.parse's additional formats would turn malformed\n // numeric or locale-specific hints into unrelated dates. Verify calendar/weekday too.\n if (\n !/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \\d{2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d{4} \\d{2}:\\d{2}:\\d{2} GMT$/.test(\n text,\n )\n )\n return undefined;\n const timestamp = Date.parse(text);\n if (!Number.isFinite(timestamp) || new Date(timestamp).toUTCString() !== text) return undefined;\n const milliseconds = timestamp - now;\n return Number.isSafeInteger(milliseconds) && milliseconds >= 0 ? milliseconds : undefined;\n}\n","/**\n * Thrown when the server returns `challenge_required` during auth start.\n * The client should render a Cloudflare Turnstile widget using `siteKey`,\n * then retry the auth flow with the resulting `turnstileToken`.\n */\nexport class TurnstileChallengeError extends Error {\n readonly siteKey: string;\n\n constructor(siteKey: string) {\n super(\"Bot protection challenge required. Render Turnstile widget and retry.\");\n this.name = \"TurnstileChallengeError\";\n this.siteKey = siteKey;\n }\n}\n\n/** Public 429 body. Optional fields preserve compatibility with message-only rate limiters. */\nexport interface AggRateLimitResponse {\n message: string;\n statusCode?: 429;\n code?: \"rate_limited\" | \"venue_rate_limited\";\n /** Present when the upstream account, rather than Agg admission, is throttled. */\n venue?: \"prophetx\";\n /** Retry delay in seconds; the SDK exposes parsed error hints as retryAfterMs. */\n retryAfter?: number;\n}\n\n/** Field-level validation detail returned by the API on 400 responses. */\nexport interface AggApiFieldError {\n field: string;\n message: string;\n}\n\nexport interface AggApiErrorInit {\n code?: string;\n retryable?: boolean;\n /** Server-requested delay before a retry, in milliseconds. Does not enable automatic SDK retries. */\n retryAfterMs?: number;\n errors?: AggApiFieldError[];\n}\n\n/**\n * Thrown for every non-2xx response from the AGG API.\n *\n * Branch on `status` and `code` rather than matching `message` text —\n * messages are human-facing and may be reworded without a major bump.\n *\n * ```ts\n * try {\n * await client.getPositions();\n * } catch (err) {\n * if (isAggApiError(err) && err.status === 401) {\n * // session lapsed — prompt reconnect\n * }\n * }\n * ```\n */\nexport class AggApiError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly retryable?: boolean;\n readonly retryAfterMs?: number;\n readonly errors?: AggApiFieldError[];\n\n constructor(message: string, status: number, init: AggApiErrorInit = {}) {\n super(message);\n this.name = \"AggApiError\";\n this.status = status;\n if (init.code !== undefined) this.code = init.code;\n if (init.retryable !== undefined) this.retryable = init.retryable;\n if (init.retryAfterMs !== undefined) this.retryAfterMs = init.retryAfterMs;\n if (init.errors !== undefined) this.errors = init.errors;\n // Required for `instanceof` to survive the ES5 downlevel target.\n Object.setPrototypeOf(this, AggApiError.prototype);\n }\n}\n\n/** Type guard for {@link AggApiError}, safe across bundle boundaries. */\nexport function isAggApiError(value: unknown): value is AggApiError {\n return value instanceof AggApiError;\n}\n","/**\n * EIP-55 address checksumming, self-contained.\n *\n * EIP-4361 (SIWE) requires the address line of the message to be EIP-55\n * checksummed, and wallets routinely hand back a lowercase address —\n * `eth_requestAccounts` does. Every SIWE client library (viem, ethers, `siwe`)\n * checksums inside `buildMessage`; this package has no runtime dependencies,\n * so it carries the one primitive that needs: Keccak-256.\n *\n * The permutation below is a port of `keccakP` from @noble/hashes (MIT,\n * Copyright (c) 2022 Paul Miller — https://github.com/paulmillr/noble-hashes),\n * reduced to the single Keccak-256 instance EIP-55 needs. Lanes are held as\n * `[low32, high32]` pairs in a Uint32Array; bytes are absorbed and squeezed\n * little-endian explicitly, so nothing here depends on platform endianness.\n * `eip55.test.ts` pins it to the classic Keccak vectors and the EIP-55 examples.\n */\n\n// The 24 round constants, split into 32-bit halves.\nconst IOTA_LO = [\n 0x00000001, 0x00008082, 0x0000808a, 0x80008000, 0x0000808b, 0x80000001, 0x80008081, 0x00008009,\n 0x0000008a, 0x00000088, 0x80008009, 0x8000000a, 0x8000808b, 0x0000008b, 0x00008089, 0x00008003,\n 0x00008002, 0x00000080, 0x0000800a, 0x8000000a, 0x80008081, 0x00008080, 0x80000001, 0x80008008,\n];\nconst IOTA_HI = [\n 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000,\n 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000,\n 0x80000000, 0x80000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000, 0x00000000, 0x80000000,\n];\n\n// Rho rotation offsets and Pi lane permutation, in the order the round applies\n// them. None of the offsets is 0 or 32, which matters: a JS shift by 32 is a\n// no-op, so the rotate helpers below never have to special-case it.\nconst PI: number[] = [];\nconst ROTL: number[] = [];\nfor (let round = 0, x = 1, y = 0; round < 24; round++) {\n [x, y] = [y, (2 * x + 3 * y) % 5];\n PI.push(2 * (5 * y + x));\n ROTL.push((((round + 1) * (round + 2)) / 2) % 64);\n}\n\n// 64-bit rotate-left on a (lo, hi) pair, one half at a time.\nconst rotlLo = (lo: number, hi: number, s: number) =>\n s > 32 ? (hi << (s - 32)) | (lo >>> (64 - s)) : (lo << s) | (hi >>> (32 - s));\nconst rotlHi = (lo: number, hi: number, s: number) =>\n s > 32 ? (lo << (s - 32)) | (hi >>> (64 - s)) : (hi << s) | (lo >>> (32 - s));\n\n/** Keccak-f[1600] on a 25-lane state stored as 50 little-endian u32 halves. */\nfunction keccakP(s: Uint32Array): void {\n const B = new Uint32Array(10);\n for (let round = 0; round < 24; round++) {\n // Theta\n for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];\n for (let x = 0; x < 10; x += 2) {\n const idx1 = (x + 8) % 10;\n const idx0 = (x + 2) % 10;\n const B0 = B[idx0];\n const B1 = B[idx0 + 1];\n const Tlo = rotlLo(B0, B1, 1) ^ B[idx1];\n const Thi = rotlHi(B0, B1, 1) ^ B[idx1 + 1];\n for (let y = 0; y < 50; y += 10) {\n s[x + y] ^= Tlo;\n s[x + y + 1] ^= Thi;\n }\n }\n // Rho + Pi\n let curLo = s[2];\n let curHi = s[3];\n for (let t = 0; t < 24; t++) {\n const shift = ROTL[t];\n const Tlo = rotlLo(curLo, curHi, shift);\n const Thi = rotlHi(curLo, curHi, shift);\n const pi = PI[t];\n curLo = s[pi];\n curHi = s[pi + 1];\n s[pi] = Tlo;\n s[pi + 1] = Thi;\n }\n // Chi\n for (let y = 0; y < 50; y += 10) {\n for (let x = 0; x < 10; x++) B[x] = s[y + x];\n for (let x = 0; x < 10; x++) s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];\n }\n // Iota\n s[0] ^= IOTA_LO[round];\n s[1] ^= IOTA_HI[round];\n }\n}\n\n/** Rate of Keccak-256 in bytes: 1600 − 2·256 bits. */\nconst RATE = 136;\n\n/** Keccak-256 (the Ethereum flavour: `0x01` padding, not NIST SHA3's `0x06`). */\nexport function keccak256(data: Uint8Array): Uint8Array {\n const s = new Uint32Array(50);\n let pos = 0;\n for (let i = 0; i < data.length; i++) {\n s[pos >> 2] ^= data[i] << ((pos & 3) * 8);\n if (++pos === RATE) {\n keccakP(s);\n pos = 0;\n }\n }\n // pad10*1: first bit after the message, last bit of the block. When the\n // message ends one byte short of the rate the two land on the same byte.\n s[pos >> 2] ^= 0x01 << ((pos & 3) * 8);\n s[(RATE - 1) >> 2] ^= 0x80 << (((RATE - 1) & 3) * 8);\n keccakP(s);\n\n const out = new Uint8Array(32);\n for (let i = 0; i < 32; i++) out[i] = (s[i >> 2] >>> ((i & 3) * 8)) & 0xff;\n return out;\n}\n\n/**\n * EIP-55 checksum an EVM address.\n *\n * Accepts any casing — lowercase, uppercase, or an already-checksummed\n * address — and returns the canonical mixed-case form. A mixed-case input\n * with a WRONG checksum is corrected, not rejected: this is a message\n * builder, and the wallet's signature is what authenticates the address\n * downstream. Throws only when the input is not a 20-byte hex address at all.\n */\nexport function toChecksumAddress(address: string): string {\n if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {\n throw new Error(`\"${address}\" is not a 20-byte hex address`);\n }\n const lower = address.slice(2).toLowerCase();\n // The hash is over the ASCII of the lowercase hex, not the address bytes.\n const hash = keccak256(Uint8Array.from(lower, (c) => c.charCodeAt(0)));\n\n let out = \"0x\";\n for (let i = 0; i < 40; i++) {\n const nibble = i % 2 === 0 ? hash[i >> 1] >> 4 : hash[i >> 1] & 0x0f;\n out += nibble >= 8 ? lower[i].toUpperCase() : lower[i];\n }\n return out;\n}\n","import type {\n AuthUser,\n VenueEvent,\n VenueMarket,\n GetOrdersQuery,\n GetPositionsQuery,\n Orderbook,\n OrderListItem,\n MarketStatus,\n PositionGroup,\n UnifiedBalanceResponse,\n UserProfile,\n Venue,\n} from \"@agg/common/types-only\";\n\n/** App-level paper/live mode. An app is one or the other, never both. */\nexport type AppTradingMode = \"live\" | \"paper\";\n\nexport interface AppClientConfigResponse {\n prophetxExecutionMode?: \"clearinghouse\" | \"direct\";\n novigExecutionMode?: \"clearinghouse\" | \"direct\";\n disabledVenues: Venue[];\n disabledCategoryPresets: string[];\n earlyAccessEnabled: boolean;\n authOptions: AppClientAuthOption[];\n /**\n * Server-owned execution mode. Prefer this over any locally-configured\n * `trading.executionMode` — the API enforces it regardless of what the\n * client sends, and end users cannot change it.\n */\n tradingMode: AppTradingMode;\n /**\n * One-time simulated balance granted on first paper use, in dollars.\n * Interpolate this into paper copy rather than hardcoding a figure.\n */\n paperStartingBalance: number;\n}\n\nexport interface VenueGeoPolicyEntry {\n venue: Venue;\n /** ISO 3166-1 alpha-2, upper-case. Empty means no country restriction. */\n blockedCountries: string[];\n /**\n * ISO 3166-1 alpha-2, upper-case. When present, this venue is ALLOWLIST\n * mode: ONLY these countries are permitted (`blockedCountries` is always\n * `[]` alongside this and must be ignored). Absent/undefined ⇒ ordinary\n * denylist mode, use `blockedCountries` as before. Only Novig uses this\n * today — a client that reads only `blockedCountries` sees an allowlisted\n * venue as unrestricted, which is exactly the misread this field closes.\n */\n allowedCountries?: string[];\n}\n\nexport interface VenueGeoPolicyResponse {\n venues: VenueGeoPolicyEntry[];\n}\n\nexport interface RpcTokenResponse {\n token: string;\n expiresAt: number;\n}\n\nexport type AggAuthProviderType = \"siwe\" | \"siws\" | \"google\" | \"twitter\" | \"apple\" | \"email\";\nexport interface AppClientAuthOption {\n provider: AggAuthProviderType;\n type: \"oauth\" | \"email\" | \"wallet\";\n enabled: boolean;\n callbackUrl?: string;\n statement?: string;\n}\nexport type AggAuthDeliveryMode = \"body\" | \"cookie-refresh\";\n\nexport interface AggClientAuthOptions {\n getEarlyAccessCode?: () => string | null;\n}\n\nexport type AggAuthStartBody =\n | {\n provider: Exclude<AggAuthProviderType, \"email\">;\n redirectUrl?: string;\n /** Cloudflare Turnstile token — required when a prior authStart returned `challenge_required`. */\n turnstileToken?: string;\n earlyAccessCode?: string;\n }\n | {\n provider: \"email\";\n email: string;\n redirectUrl?: string;\n /** Cloudflare Turnstile token — required when a prior authStart returned `challenge_required`. */\n turnstileToken?: string;\n earlyAccessCode?: string;\n };\n\n/** SIWE / SIWS sign-in. `kind` is optional so callers that predate the discriminator still compile. */\nexport interface AggAuthWalletVerifyBody {\n kind?: \"wallet\";\n message: string;\n signature: string;\n earlyAccessCode?: string;\n}\n\n/** Privy sign-in. Requires the app's wallet provider to be Privy; the token must come from that Privy app. */\nexport interface AggAuthPrivyVerifyBody {\n kind: \"privy\";\n privyToken: string;\n earlyAccessCode?: string;\n}\n\n/** Body for `POST /auth/verify` — mirrors the API's union on `kind`. */\nexport type AggAuthVerifyBody = AggAuthWalletVerifyBody | AggAuthPrivyVerifyBody;\n\nexport type AggAuthStartResult =\n | { type: \"nonce\"; nonce: string; statement?: string }\n | { type: \"redirect\"; url: string }\n | { type: \"magic_link\"; success: true }\n | { type: \"challenge_required\"; siteKey: string };\n\n/**\n * Body for `POST /users/me/link-account/start` — authenticated account linking.\n *\n * `redirectUrl` is required for OAuth/email providers: the callback / magic-link\n * verify hands the partner a `link_confirm_token` by redirecting to `redirectUrl`,\n * and the partner app completes the flow by calling `/confirm` from that page.\n *\n * Wallet providers (`siwe`/`siws`) instead return a `wallet_challenge` with a\n * `message` the user signs VERBATIM; the signature is then confirmed with\n * `{ kind: \"wallet_signature\", message, signature }`.\n */\nexport type AggLinkAccountBody =\n | { provider: \"google\" | \"twitter\" | \"apple\"; redirectUrl: string }\n | { provider: \"email\"; email: string; redirectUrl: string }\n | { provider: \"siwe\" | \"siws\"; address: string };\n\nexport type AggLinkAccountResult =\n | { type: \"redirect\"; url: string }\n | { type: \"magic_link\"; success: true }\n | { type: \"wallet_challenge\"; message: string };\n\n/**\n * Wallet branch of `POST /users/me/link-account/confirm`. Requires `kind` so it\n * can never be confused with the `token` branch. `message` MUST be the exact\n * `message` returned by `/start`'s `wallet_challenge` — the server compares it\n * byte-for-byte, so do not reconstruct or edit it client-side.\n */\nexport type AggLinkAccountWalletConfirmBody = {\n kind: \"wallet_signature\";\n message: string;\n signature: string;\n};\n\n/**\n * Success result of /users/me/link-account/confirm.\n * - `linked` — new Account row written.\n * - `already_linked_same` — identity was already attached to the caller's Principal\n * (idempotent; safe to retry).\n *\n * Collisions with a different Principal surface as HTTP 409 and are thrown by the\n * SDK's request layer — catch them at the call site, don't expect them here.\n */\nexport type AggLinkAccountConfirmResult = {\n status: \"linked\" | \"already_linked_same\";\n provider: string;\n};\n\nexport type AggSessionUser = AuthUser | UserProfile;\n\nexport interface AggClientSessionInput {\n accessToken: string;\n refreshToken?: string;\n user?: AggSessionUser;\n}\n\n/** Non-sensitive auth snapshot persisted to localStorage for UI bootstrapping.\n * Tokens are NEVER included — they exist only in process memory. */\nexport interface PersistedAuthSnapshot {\n user: {\n id: string;\n username: string | null;\n avatarUrl: string | null;\n walletAddress?: string | null;\n } | null;\n authHint: { wasAuthenticated: boolean };\n}\n\n/** Auth lifecycle status for UI state machines. */\nexport type AuthStatus = \"unknown\" | \"authenticated\" | \"unauthenticated\";\n\n// ── Self-custodial fills ──\n\nexport type SignatureRequestType =\n | \"eip712\"\n | \"personal_sign\"\n /** EVM transaction — bridge legs and approvals. secp256k1. */\n | \"transaction\"\n /** Solana transaction — bridge legs on SVM. ed25519, NOT secp256k1. */\n | \"solana_transaction\"\n | \"hl_l1_action\"\n /**\n * EIP-7702 authorization over `{ contractAddress, chainId, nonce }`.\n *\n * A signature over a RAW digest — `keccak(0x05 ‖ rlp([chainId, delegate,\n * nonce]))` — not EIP-191 and not EIP-712. Many wallets do not expose this,\n * and that is expected: reject it and the server falls back to asking the\n * user to broadcast a plain approve instead.\n */\n | \"eip7702_authorization\"\n /**\n * A Gnosis Safe transaction relayed through Polymarket — a legacy Polymarket\n * wallet funding a fill. The payload is the SafeTx as EIP-712 typed data,\n * but the wallet must `personal_sign` the RAW 32 bytes of\n * `hashTypedData(payload)` (`signMessage({ message: { raw: hash } })`):\n * Polymarket's relayer only accepts that shape. `payload.safeTxHash` carries\n * the digest for convenience; the server recomputes it from the typed data.\n */\n | \"safe_tx\";\n\n/** One payload the client must sign before a fill can proceed. */\nexport interface SignatureRequest {\n /** Echo this back with the signature. */\n stepId: string;\n /** Payload shape. Discriminates how to sign — not which venue. */\n type: SignatureRequestType;\n venue: string;\n /** The address that must produce this signature. Sign with this key, not another. */\n signerAddress: string;\n /** Absent for non-EVM payloads (e.g. Hyperliquid L1 actions). */\n chainId?: number;\n /** Sign verbatim. */\n payload: unknown;\n expiresAt: string;\n /** Why this signature is being asked for, when the server knows (e.g. `\"fee\"`, `\"funding_and_fee\"`). Display only. */\n purpose?: string;\n /**\n * The fill proceeds without this one (e.g. `purpose: \"hl_referral\"`, a\n * partner referral parked beside a Hyperliquid order). `fillSelfCustody`\n * skips it if your signer throws or it has expired, instead of failing the\n * fill.\n */\n optional?: boolean;\n}\n\n/**\n * Supplied by the partner. Receives a payload, returns a signature. The SDK\n * never sees the key.\n *\n * Return a 0x-prefixed hex string for anything the wallet SIGNS:\n *\n * - `eip712` — `signTypedData` over `payload`.\n * - `personal_sign` — EIP-191 over `payload`: a UTF-8 string or `{ raw: \"0x…\" }\n * bytes (Polymarket proxy batches). Pass it directly as viem `message`.\n * - `safe_tx` — `personal_sign` over the RAW 32 bytes of\n * `hashTypedData(payload)` (viem: `signMessage({ message: { raw: hash } })`,\n * MetaMask: `personal_sign` with the hex hash). The wallet shows a hash, not\n * a structured prompt — that is what Polymarket's own relayer requires.\n * - `hl_l1_action` — Hyperliquid L1 action, EIP-712 in phantom-agent form.\n * - `eip7702_authorization` — an EIP-7702 authorization over\n * `{ contractAddress, chainId, nonce }`. This is a signature over a RAW\n * digest, not EIP-191 and not EIP-712, and many wallets do not expose it.\n * **Throwing here does not help**: there is no reject verb, so a thrown\n * signer is indistinguishable from a slow user — the request simply expires\n * and the fill dies. If your wallet cannot produce this signature, declare\n * `approveMode: \"user_broadcast\"` on the fill instead and the approve is\n * requested as a `transaction` the user sends themselves. Handling this\n * request is what makes funding gasless.\n *\n * Return `{ txHash }` for anything the wallet BROADCASTS:\n *\n * - `transaction` — send it, then return the hash **immediately, without\n * awaiting the receipt**. The server watches for the mined receipt itself\n * and will not resume until it matches the request byte-for-byte.\n */\nexport type SignerFn = (req: SignatureRequest) => Promise<string | { txHash: string }>;\n\n/**\n * How long `fillSelfCustody` will keep waiting before giving up.\n *\n * Covers a first-time user: sign the wallet-setup batch, wait for it on-chain,\n * then sign the order. Generous because the wait is a relayer transaction\n * confirming, not a human deciding.\n */\nexport const SELF_CUSTODY_FILL_TIMEOUT_MS = 5 * 60_000;\n\n/** Gap between re-reads while an on-chain step is in flight. */\nexport const SELF_CUSTODY_POLL_INTERVAL_MS = 2_000;\n\n/**\n * How long `fillSelfCustody` waits on the `signer` for ONE optional request\n * signed by a wallet other than the user's — e.g. a partner's activation\n * sponsor. Such a request can delay the batch's submission by at most this long,\n * after which it is declined and the required signatures go out without it.\n * Required requests, and optional ones the user's own wallet signs (the fill's\n * `signingAddress` or any required request's `signerAddress`, e.g. a referral\n * code), are never bounded by this.\n */\nexport const OPTIONAL_SIGNATURE_TIMEOUT_MS = 15_000;\n\n/**\n * How long `fillSelfCustody` waits on an optional Polymarket buy fee pre-sign\n * (`purpose: \"app_fee\"`). It never holds the order (that round is already\n * posted), so it can wait for a slow wallet: just under the server's 60s grace,\n * after which the request is expired and a post-fill signature asked instead.\n */\nexport const OPTIONAL_FEE_SIGNATURE_TIMEOUT_MS = 55_000;\n\n/**\n * States a run never leaves. Everything else means \"still working\".\n *\n * Typed against `ExecutionOverallState` so a typo'd or renamed literal (e.g.\n * `cancelled` drifting to `canceled`) is a compile error instead of a state\n * that silently stops being treated as terminal. Mirrors\n * `ExecutionOverallStateTB` in the contract; keep the two in step.\n */\nexport const TERMINAL_EXECUTION_STATES: ReadonlySet<ExecutionOverallState> =\n new Set<ExecutionOverallState>([\"filled\", \"partially_filled\", \"failed\", \"cancelled\", \"expired\"]);\nexport type SportsGameStatus =\n | \"scheduled\"\n | \"live\"\n | \"paused\"\n | \"finished\"\n | \"cancelled\"\n | \"postponed\"\n | \"unknown\";\n\nexport interface SportsLiveParticipant {\n position: \"first\" | \"second\";\n name: string;\n shortName: string | null;\n imageUrl: string | null;\n score: string | null;\n}\n\nexport interface SportsLiveState {\n eventId: string;\n sport: string;\n status: SportsGameStatus;\n participants: [SportsLiveParticipant, SportsLiveParticipant];\n period: string | null;\n clock: string | null;\n updatedAt: string | null;\n}\n\nexport interface SportsLiveResponse {\n data: SportsLiveState[];\n missingEventIds: string[];\n}\n\n// SDK-specific types (not in common).\nexport interface AggClientOptions {\n /** Browser adapters can inject a Worker transport; other runtimes keep the native client. */\n webSocketFactory?: (\n options: import(\"./agg-websocket\").AggWebSocketOptions,\n ) => import(\"./agg-websocket\").AggWebSocket;\n baseUrl: string;\n /** Public App ID — sent as x-app-id header. For client-side partner usage. */\n appId?: string;\n /** Secret admin key — sent as x-admin-key header. Server-side only. */\n adminKey?: string;\n /**\n * Partner API key for server-side use. Sent as `x-app-api-key`. NEVER embed\n * in browser bundles, source maps, or logs. Keys start with `agg_<appId>_`.\n */\n apiKey?: string;\n /** WebSocket URL for real-time feeds. Must be set explicitly to use createWebSocket(). */\n wsUrl?: string;\n /** Opt in after immutable history publication/CDN rollout. Defaults false. */\n preferImmutableHistory?: boolean;\n /**\n * @deprecated Kalshi live discovery and trading are retired. This ignored\n * compatibility option remains to avoid breaking existing SDK consumers.\n */\n kalshiDemo?: boolean;\n /** Optional auth request hooks used to enrich auth payloads. */\n auth?: AggClientAuthOptions;\n /** Move refresh delivery to an HttpOnly cookie on auth endpoints. Defaults to \"body\". */\n authDelivery?: AggAuthDeliveryMode;\n /** Persist a non-sensitive auth hint to localStorage for UI bootstrapping.\n * Tokens are NEVER persisted — they exist only in process memory.\n * When authDelivery is \"body\", refresh tokens are lost on page reload.\n * When authDelivery is \"cookie-refresh\", refresh tokens survive via HttpOnly cookies\n * and the SDK attempts a silent refresh on cold start. Defaults to true. */\n persistSession?: boolean;\n /**\n * Supplies signatures for self-custodial fills. Required whenever\n * `fillSelfCustody()` is called with `signingAddress` — the SDK never\n * holds a key itself, so without this option a fill that needs a\n * client-side signature cannot proceed. The signature requests never\n * come back on `POST /execution/fill` itself: `fillSelfCustody()` polls\n * `GET /execution/status` for them (`pendingSignatures`), signs each one\n * with this function, and posts the result to\n * `POST /execution/fill/:quoteId/signatures`.\n */\n signer?: SignerFn;\n}\n\nexport interface SiweMessageParams {\n domain: string;\n address: string;\n uri: string;\n nonce: string;\n chainId?: number;\n statement?: string;\n issuedAt?: string;\n}\n\nexport interface SiwsMessageParams {\n domain: string;\n /** Base58-encoded Solana public key. */\n address: string;\n uri: string;\n nonce: string;\n /** Solana chain ID: \"mainnet\", \"devnet\", \"testnet\", or \"localnet\". Defaults to \"mainnet\". */\n chainId?: string;\n statement?: string;\n issuedAt?: string;\n}\n\n/** OHLCV bar point for chart rendering. */\nexport interface ChartCandle {\n /** Venue average; distinct from OHLC close. */\n mean?: number;\n /** Open time in Unix milliseconds. */\n t: number;\n /** Open price (0-1). */\n o: number;\n /** High price (0-1). */\n h: number;\n /** Low price (0-1). */\n l: number;\n /** Close price (0-1). */\n c: number;\n /** Volume (null if unavailable). */\n v: number | null;\n}\n\n/** @deprecated Historical chart bars are canonical per outcome. Use ChartBarsResponse instead. */\nexport interface ChartVenueCandles {\n venue: string;\n candles: ChartCandle[];\n}\n\nexport type ChartResolution = \"1m\" | \"5m\" | \"1h\" | \"1d\";\n\n/**\n * Freshness signal embedded in every chart response. Compare\n * `staleSeconds` against the resolution to decide whether to show a\n * \"delayed\" badge on the chart.\n */\nexport interface ChartBarsMeta {\n state?: \"ready\" | \"warming\" | \"unsupported\" | \"failed\" | \"empty\";\n complete?: boolean;\n retryAfterMs?: number;\n /** Agg fetch/publication time. Does not measure upstream delivery latency. */\n fetchedAtMs?: number;\n /** Server-side wall clock when the response was assembled, in milliseconds. */\n serverTime: number;\n /** `open_time` of the most-recent bar in `data`, in milliseconds. Null if `data` is empty. */\n lastBarOpenTime: number | null;\n /** `serverTime - lastBarOpenTime` in seconds. Null if `data` is empty. */\n staleSeconds: number | null;\n}\n\n/** Response from GET /charts/bars. */\nexport interface ChartBarsResponse {\n /** VenueMarketOutcome.id requested by the caller. */\n venueMarketOutcomeId: string;\n /** Venue of the canonical historical series. */\n venue: string;\n /** Resolution returned by the backend. */\n resolution: ChartResolution;\n /** Bars sorted in ascending open time. */\n data: ChartCandle[];\n /** Freshness signal — see {@link ChartBarsMeta}. */\n meta: ChartBarsMeta;\n}\n\nexport interface ChartHistoryManifest {\n version: 1;\n revision: string | null;\n venueMarketOutcomeId: string;\n venue: string;\n resolution: ChartResolution;\n semantics: \"venue-ohlcv-v1\" | \"polymarket-price-samples-v1\" | \"kalshi-ohlcv-quote-fallback-v2\";\n from: number;\n to: number;\n finalizedThrough: number;\n chunks: Array<{\n key: string;\n url: string;\n sha256: string;\n from: number;\n to: number;\n points: number;\n }>;\n meta: ChartBarsMeta;\n}\n\n/** @deprecated Use ChartBarsResponse. */\nexport type ChartCandlestickResponse = ChartBarsResponse;\n\n/** Matched market reference returned by batch/aggregate endpoints. */\nexport interface VenueMarketRef {\n venue: string;\n venueMarketId: string;\n}\n\nexport type OrderbookBatchItemStatus =\n | \"ok\"\n | \"market_not_found\"\n | \"market_resolved\"\n | \"market_closed\"\n | \"market_paused\"\n | \"market_unopened\"\n | \"book_not_loaded\";\n\nexport type OrderbookBatchItemErrorCode =\n | \"market_not_found\"\n | \"market_resolved\"\n | \"market_closed\"\n | \"market_paused\"\n | \"market_unopened\"\n | \"book_not_loaded\";\n\nexport interface OrderbookBatchItemError {\n code: OrderbookBatchItemErrorCode;\n message: string;\n retryable: boolean;\n}\n\nexport interface OrderbooksOnlyError {\n code: \"use_orderbooks_endpoint\";\n message: string;\n retryable: boolean;\n}\n\nexport interface OrderbookServiceUnavailableError {\n code: \"orderbook_service_unavailable\";\n message: string;\n retryable: boolean;\n}\n\nexport interface RequestedOrderbookMarket {\n venueMarketId: string;\n venue: string;\n marketStatus: \"open\" | \"closed\" | \"resolved\" | \"unopened\" | \"paused\";\n tickSize: number | null;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this market, raw 6-dec shares.\n * Absent means no known minimum. */\n minSizeRaw?: string;\n endDate: string | null;\n resolutionDate: string | null;\n}\n\nexport interface MatchedOrderbookMarket extends VenueMarketRef {\n marketStatus: \"open\" | \"closed\" | \"resolved\" | \"unopened\" | \"paused\";\n tickSize: number | null;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this market, raw 6-dec shares.\n * Absent means no known minimum. */\n minSizeRaw?: string;\n hasOrderbook: boolean;\n /**\n * Hyperliquid HIP-4 deployer namespace this member belongs to (e.g. \"ap\").\n * `null` for every other venue and for Hyperliquid members without one.\n * Names which deployer this cluster member is — distinct from whether its\n * book was published (see `hasOrderbook`).\n */\n deployerVenue?: string | null;\n}\n\n/**\n * Provenance of a published `midpoint`. Mirrors the engine's `MarkSource`.\n *\n * - `local` — true two-sided midpoint from the venue's own book\n * - `local_merged` — midpoint from the cross-venue merged book\n * - `local_one_sided` — only one side present; mark is the live side, NOT a midpoint\n * - `sibling` — derived from the complementary outcome (e.g. NO from YES)\n * - `local_boundary` — clamped to the [tick, 1-tick] boundary\n * - `none` — no mark available\n */\nexport type MarkSource =\n | \"local\"\n | \"local_merged\"\n | \"local_one_sided\"\n | \"sibling\"\n | \"local_boundary\"\n | \"none\";\n\nexport const RECURRENCE_CADENCES = [\n \"PT5M\",\n \"PT10M\",\n \"PT15M\",\n \"PT30M\",\n \"PT1H\",\n \"PT4H\",\n \"P1D\",\n \"P1W\",\n \"P1M\",\n \"P1Y\",\n] as const;\nexport type RecurrenceCadence = (typeof RECURRENCE_CADENCES)[number];\nexport type RecurrenceFilter = RecurrenceCadence | \"null\";\n\nexport type RecurringCryptoDuration = \"PT5M\" | \"PT15M\" | \"PT30M\" | \"PT1H\" | \"PT4H\" | \"P1D\";\nexport type RecurringCryptoDurationInput =\n | RecurringCryptoDuration\n | \"5m\"\n | \"15m\"\n | \"30m\"\n | \"1h\"\n | \"4h\"\n | \"1d\";\nexport type RecurringCryptoSourceConfidence = \"verified\" | \"inferred\" | \"missing\";\n\nexport interface ListRecurringCryptoMarketsOptions {\n assets?: string[];\n durations?: RecurringCryptoDurationInput[];\n interval?: RecurringCryptoDurationInput;\n window?: \"current\";\n venues?: Venue[];\n status?: MarketStatus[];\n windowStartFrom?: string;\n windowStartTo?: string;\n cursor?: string;\n limit?: number;\n includeOrderbookPrices?: boolean;\n includeReferencePrices?: boolean;\n includeDirectVenueMarkets?: boolean;\n includeOrderbookDepth?: boolean;\n orderbookDepth?: number;\n orderbookDepthAmountUsd?: number;\n}\n\nexport interface RecurringCryptoOrderbookDepthLevel {\n price: number;\n size: number;\n notionalUsd: number;\n cumulativeSize: number;\n cumulativeNotionalUsd: number;\n fillSize: number | null;\n fillNotionalUsd: number | null;\n}\n\nexport interface RecurringCryptoOrderbookDepthSide {\n levels: RecurringCryptoOrderbookDepthLevel[];\n totalSize: number;\n totalNotionalUsd: number;\n requestedNotionalUsd: number | null;\n filledSize: number | null;\n filledNotionalUsd: number | null;\n unfilledNotionalUsd: number | null;\n avgPrice: number | null;\n worstPrice: number | null;\n fillsComplete: boolean | null;\n}\n\nexport interface RecurringCryptoOutcomeOrderbookDepth {\n currency: \"USD\";\n amountUsd: number | null;\n buy: RecurringCryptoOrderbookDepthSide;\n sell: RecurringCryptoOrderbookDepthSide;\n}\n\nexport interface RecurringCryptoOutcome {\n /**\n * Canonical Agg outcome id. Null for direct live venue rows because those\n * rows are discovery data and cannot be passed to smart order routing.\n */\n venueMarketOutcomeId: string | null;\n /** Venue-native outcome id or synthetic external id for direct live rows. */\n externalOutcomeId: string | null;\n /** False for this endpoint; live crypto markets are not smart-route inputs. */\n routeable: boolean;\n /** False for this endpoint; split-order routing is not supported here. */\n splitOrdersAllowed: boolean;\n label: string;\n title: string | null;\n midpoint: number | null;\n bestBid: number | null;\n bestAsk: number | null;\n markSource: MarkSource | string | null;\n lastKnownPrice: number | null;\n orderbookDepth: RecurringCryptoOutcomeOrderbookDepth | null;\n}\n\nexport interface RecurringCryptoMarketMetrics {\n volume: number | null;\n volume24h: number | null;\n openInterest: number | null;\n liquidity: number | null;\n spread: number | null;\n}\n\nexport interface RecurringCryptoResolution {\n sourceName: string | null;\n sourceUrl: string | null;\n sourceDomain: string | null;\n rawCriteria: unknown;\n confidence: RecurringCryptoSourceConfidence;\n}\n\nexport interface RecurringCryptoReferencePrice {\n asset: string;\n quoteAsset: \"USD\";\n raw: string | null;\n decimals: number | null;\n normalized: number | null;\n timestamp: string | null;\n provider: string | null;\n providerMarketId: string | null;\n confidence: RecurringCryptoSourceConfidence;\n fetchedAt?: string | null;\n ageMs?: number | null;\n refreshing?: boolean;\n stale?: boolean;\n}\n\nexport type CryptoReferencePriceTarget =\n | { type: \"venueMarket\"; venueMarketId: string }\n | { type: \"venueEvent\"; venueEventId: string }\n | { type: \"externalVenueMarket\"; venue: Venue; externalMarketId: string }\n | {\n type: \"market\";\n venue: Venue;\n venueEventId?: string;\n venueMarketId: string;\n externalEventId?: string | null;\n externalMarketId?: string;\n asset: string;\n quoteAsset?: \"USD\";\n resolution: RecurringCryptoResolution;\n };\n\nexport interface CryptoReferencePriceExternalMarketInput {\n venue: Venue;\n externalMarketId: string;\n}\n\nexport interface CryptoReferencePriceMarketInput extends RecurringCryptoVenueMarket {\n asset: string;\n quoteAsset?: \"USD\";\n}\n\nexport interface GetCryptoReferencePricesOptions {\n targets?: CryptoReferencePriceTarget[];\n venueMarketIds?: string[];\n venueEventIds?: string[];\n externalMarkets?: CryptoReferencePriceExternalMarketInput[];\n markets?: CryptoReferencePriceMarketInput[];\n windowMarkets?: RecurringCryptoWindowMarket[];\n signal?: AbortSignal;\n}\n\nexport interface CryptoReferencePriceError {\n code:\n | \"not_found\"\n | \"not_recurring_crypto\"\n | \"reference_feed_missing\"\n | \"price_unavailable\"\n | \"stale_price\";\n message: string;\n}\n\nexport interface CryptoReferencePriceSource {\n provider: string | null;\n providerMarketId: string | null;\n confidence: RecurringCryptoSourceConfidence;\n}\n\nexport interface CryptoReferencePriceResult {\n target: CryptoReferencePriceTarget;\n venue: Venue | null;\n venueEventId: string | null;\n venueMarketId: string | null;\n externalEventId: string | null;\n externalMarketId: string | null;\n asset: string | null;\n quoteAsset: \"USD\" | null;\n raw: string | null;\n decimals: number | null;\n normalized: number | null;\n providerTimestamp: string | null;\n fetchedAt: string | null;\n ageMs: number | null;\n refreshing: boolean;\n stale: boolean;\n source: CryptoReferencePriceSource;\n error: CryptoReferencePriceError | null;\n}\n\nexport interface CryptoReferencePricesResponse {\n data: CryptoReferencePriceResult[];\n softRefreshMs: number;\n hardMaxAgeMs: number;\n}\n\nexport type RecurringCryptoComparisonPriceSource = \"referencePrice\" | \"midpoint\" | \"lastKnownPrice\";\n\nexport interface RecurringCryptoComparisonPoint {\n venue: Venue;\n venueMarketId: string;\n value: number;\n label: string | null;\n source: RecurringCryptoComparisonPriceSource;\n provider: string | null;\n providerMarketId: string | null;\n timestamp: string | null;\n confidence: RecurringCryptoSourceConfidence | null;\n}\n\nexport interface RecurringCryptoPriceComparison {\n count: number;\n min: RecurringCryptoComparisonPoint | null;\n max: RecurringCryptoComparisonPoint | null;\n spread: number | null;\n spreadBps: number | null;\n byVenue: RecurringCryptoComparisonPoint[];\n}\n\nexport interface RecurringCryptoWindowComparisons {\n referencePrice: RecurringCryptoPriceComparison;\n outcomePrices: {\n up: RecurringCryptoPriceComparison;\n down: RecurringCryptoPriceComparison;\n };\n}\n\nexport interface RecurringCryptoVenueMarket {\n venue: Venue;\n venueEventId: string;\n venueMarketId: string;\n externalEventId: string | null;\n externalMarketId: string;\n question: string;\n status: MarketStatus;\n priceSource: \"snag\" | \"direct\";\n /** False for this endpoint; live crypto markets are not smart-route inputs. */\n routeable: boolean;\n /** False for this endpoint; split-order routing is not supported here. */\n splitOrdersAllowed: boolean;\n outcomes: RecurringCryptoOutcome[];\n metrics: RecurringCryptoMarketMetrics;\n resolution: RecurringCryptoResolution;\n referencePrice: RecurringCryptoReferencePrice;\n}\n\nexport interface RecurringCryptoWindowMarket {\n id: string;\n asset: string;\n quoteAsset: \"USD\";\n duration: RecurringCryptoDuration;\n windowStart: string;\n windowEnd: string;\n status: MarketStatus;\n markets: RecurringCryptoVenueMarket[];\n comparisons: RecurringCryptoWindowComparisons;\n}\n\nexport interface RecurringCryptoMarketsResponse {\n data: RecurringCryptoWindowMarket[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n/** Per-venue orderbook entry with native tick spacing. */\nexport interface VenueOrderbookEntry {\n venueMarketId: string;\n tickSize: number | null;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this market, raw 6-dec shares.\n * Absent means no known minimum. */\n minSizeRaw?: string;\n orderbook: Orderbook;\n /**\n * Sticky tick of this venue's book inferred at runtime by the engine. May\n * differ from the seed `tickSize` when the live grid is finer than the DB\n * metadata. Optional — only populated when the engine has emitted runtime\n * metadata for this entry.\n */\n tick?: number | null;\n /** Provenance of this venue book's published midpoint. See {@link MarkSource}. */\n markSource?: MarkSource;\n /**\n * Hyperliquid HIP-4 deployer namespace whose book this entry publishes\n * (e.g. \"ap\"). `null` for every other venue. When a cluster has more than\n * one Hyperliquid deployer member, only one member's book is published per\n * request — this names which one, so a caller never pairs this entry's depth\n * with a different member's `venueMarketId`.\n */\n deployerVenue?: string | null;\n}\n\n/** Response from GET /orderbooks (batch). */\nexport interface BatchOrderbooksResponse {\n data: Array<{\n venueMarketId: string;\n status: OrderbookBatchItemStatus;\n error: OrderbookBatchItemError | null;\n requestedMarket: RequestedOrderbookMarket | null;\n venueOrderbooks: Record<string, VenueOrderbookEntry>;\n matchedMarkets: MatchedOrderbookMarket[];\n }>;\n meta: {\n requestedCount: number;\n okCount: number;\n errorCount: number;\n };\n}\n\n/** A single market midpoint row returned by GET /midpoints. */\nexport interface MidpointRow {\n venueMarketId: string;\n venue: string;\n midpoint: number | null;\n spread: number | null;\n timestamp: number | null;\n arbReturn?: number | null;\n /** Provenance of `midpoint`. */\n markSource?: MarkSource;\n /**\n * When `markSource === \"sibling\"`, the matched venueMarketId whose book\n * supplied the headline mark. Allows the FE to label \"sourced from venue X\"\n * without re-running the matching logic.\n */\n siblingVenueMarketId?: string;\n /** Top-of-book buy-side price. Only present when `bestPrice=true`. */\n bestBid?: number | null;\n /** Top-of-book sell-side price. Only present when `bestPrice=true`. */\n bestAsk?: number | null;\n}\n\n/** Per-outcome midpoint from a live orderbook. */\nexport interface OutcomeMidpointRow {\n venueMarketOutcomeId: string;\n label: string;\n midpoint: number | null;\n /** Provenance of `midpoint`. */\n markSource?: MarkSource;\n /** Top-of-book buy-side price. Only present when `bestPrice=true`. */\n bestBid?: number | null;\n /** Top-of-book sell-side price. Only present when `bestPrice=true`. */\n bestAsk?: number | null;\n}\n\n/** Response from GET /midpoints (batch). */\nexport interface BatchMidpointsResponse {\n data: Array<\n MidpointRow & {\n outcomes: OutcomeMidpointRow[];\n matched: MidpointRow[];\n /**\n * Live, quality-gated cross-venue arbitrage return for this market's\n * cluster as a decimal fraction (`0.0085` = 0.85%), computed fresh by\n * the engine on this request. Prefer it over the `arbReturn` embedded\n * in venue-event listings, which a background sync can leave stale.\n * Only present when the request set `bestPrice=true`.\n */\n arbReturn?: number | null;\n /**\n * DB status of the requested market. Present whenever the id resolves\n * to a known market. Resolved markets never serve a price (see `error`).\n */\n marketStatus?: MarketStatus;\n /**\n * Structured refusal, mirroring GET /orderbooks per-item errors:\n * `market_resolved` for settled markets (prices are nulled instead of\n * serving a stale mark), `market_not_found` for unknown ids.\n */\n error?: {\n code: \"market_resolved\" | \"market_not_found\";\n message: string;\n retryable: boolean;\n };\n }\n >;\n}\n\n/** Response from GET /orderbook/outcome/:id (single outcome). */\nexport interface OutcomeOrderbookResponse {\n /** CRC of returned depth-limited levels; full engine checksum remains unchanged. */\n snapshotChecksum?: number;\n venueMarketOutcomeId: string;\n venueMarketId: string;\n venue: string;\n orderbook: {\n bids: Array<{ price: number; size: number }>;\n asks: Array<{ price: number; size: number }>;\n };\n midpoint: number | null;\n spread: number | null;\n seq: number;\n checksum: number;\n timestamp: number;\n /** Sticky tick of this outcome's book, inferred at runtime. `null` until inferred. */\n tick: number | null;\n /** Provenance of `midpoint`. See {@link MarkSource}. */\n markSource: MarkSource;\n}\n\n/** Standard paginated list response from the API. */\nexport interface PaginatedResponse<T> {\n data: T[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface OrderListQuery {\n userId?: string;\n status?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface TradeExecutorOrder {\n id: string;\n userId: string;\n venue: string;\n status: string;\n marketId: string;\n tokenId: string;\n side: string;\n amountRaw: string;\n quoteId: string | null;\n externalId: string | null;\n clientOrderId: string | null;\n dagRunId: string | null;\n filledAmountRaw: string | null;\n executionPrice: string | null;\n txHash: string | null;\n errorMessage: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface TradeExecutorOrderListResponse {\n orders: TradeExecutorOrder[];\n total: number;\n}\n\n// ── Aggregated orderbook (GET /orderbook/:venueMarketId) ──\n\n/** A single level in the aggregated orderbook with per-venue attribution. */\nexport interface AggregatedOrderbookLevel {\n price: number;\n size: number;\n venues: Record<string, number>;\n}\n\n/** A simple orderbook level without venue attribution. */\nexport interface SimpleOrderbookLevel {\n price: number;\n size: number;\n}\n\n/** Per-venue best-bid/ask info. */\nexport interface VenuePriceInfo {\n bestBid: number | null;\n bestAsk: number | null;\n}\n\n/** Response from GET /orderbook/:venueMarketId — canonical aggregated orderbook. */\nexport interface AggregatedOrderbookResponse {\n venueMarketId: string;\n orderbook: {\n bids: AggregatedOrderbookLevel[];\n asks: AggregatedOrderbookLevel[];\n };\n venueOrderbooks: Record<string, { bids: SimpleOrderbookLevel[]; asks: SimpleOrderbookLevel[] }>;\n venues: Record<string, VenuePriceInfo>;\n midpoint: number | null;\n spread: number | null;\n timestamp: number;\n /** Sequence number (present in live responses). */\n seq?: number;\n /** CRC32 checksum (present in live responses). */\n checksum?: number | null;\n /** Markets matched across venues for this canonical market. */\n matchedMarkets?: Array<{ venue: string; venueMarketId: string }>;\n}\n\n// ── Managed Execution ──\n\nexport interface ExecuteManagedParams {\n quoteId: string;\n /** Trading mode. Defaults to live. */\n mode?: ExecutionMode;\n /**\n * Optional intent fallback. When the supplied `quoteId` has expired in the\n * cache (e.g. user clicked Buy after a tab was inactive), the server\n * resolves the latest quote for this intent and refreshes/executes against\n * that instead of returning 400 `quote_not_found`. Same intent = same buttons\n * the user pressed in the UI; a different `maxSpend`, mode, or venue scope is\n * a different intent and won't match.\n */\n fallbackToLatest?: {\n outcomeId: string;\n side: \"buy\" | \"sell\";\n maxSpend?: number;\n sellShares?: number;\n allowedVenues?: Venue[];\n };\n /**\n * Self-custody: the wallet that will sign this fill. Must be a wallet\n * already linked to this account. Omit for managed custody (the default).\n */\n signingAddress?: string;\n /**\n * Self-custody only: which approve shape a cross-chain fill uses when the\n * bridge needs an ERC20 approve. Omit (the default) for \"sponsored\" — the\n * approve costs the wallet no gas, but the wallet must sign a one-time\n * EIP-7702 authorization over a RAW DIGEST, which many wallets cannot\n * produce. Send \"user_broadcast\" when yours cannot: the user sends the\n * approve from their own wallet and pays its gas. Only your client can know\n * which applies — it is a property of the wallet software, not of the\n * address or the chain.\n *\n * Worth surfacing in your UI: \"user_broadcast\" never establishes the\n * delegation, so an approve is needed on EVERY bridge. \"sponsored\" costs one\n * signature once per chain.\n *\n * Neither mode makes bridging free — the approve is only one of the costs.\n * Relay's fee comes out of the amount delivered on every bridge, and one-time\n * costs apply per route. Quote with `deepEstimate` and read\n * `feeBreakdown.bridgeFees` and `feeBreakdown.setupCosts` rather than\n * inferring cost from the approve mode.\n */\n approveMode?: \"sponsored\" | \"user_broadcast\";\n}\n\nexport interface ExecuteManagedResponse {\n alreadyAccepted?: boolean;\n quoteId: string;\n orderIds: string[];\n status: \"pending\";\n redeemId?: string;\n message?: string;\n /**\n * What this fill is waiting to be signed, if anything. On the immediate\n * `POST /execution/fill` response this is always absent or empty — even\n * for a self-custody fill, the DAG parks asynchronously, after this\n * response has already been sent. Real entries only ever come back from\n * polling `GET /execution/status` or from the next\n * `POST /execution/fill/:quoteId/signatures` response (this same shape,\n * reused). Drive the whole round trip through `fillSelfCustody()` rather\n * than reading this field on the fill response by hand.\n */\n pendingSignatures?: SignatureRequest[];\n}\n\nexport type LimitOrderTimeInForce = \"GTC\" | \"GTD\" | \"FOK\" | \"FAK\" | \"IOC\" | \"ALO\";\n\nexport type CancelOrderSignature =\n | { signature: string; timestamp: number }\n | {\n venue: \"hyperliquid\";\n action: { type: \"cancel\"; cancels: Array<{ a: number; o: number }> };\n nonce: number;\n signature: { r: string; s: string; v: 27 | 28 };\n };\n\nexport interface CancelVenueOrderParams {\n venue: \"polymarket\" | \"hyperliquid\";\n venueOrderId: string;\n signerAddress: string;\n cancelSignature: CancelOrderSignature;\n}\n\nexport interface PlaceLimitOrderParams {\n /** BETDEX uses hosted cash: GTC/IOC only, no signer, post-only or expiry.\n * Native odds are rounded conservatively and stake is rounded down. GTC\n * unmatched liquidity is cancelled at the in-play transition. SELL closes\n * the same For outcome and requires collateral as well as owned inventory.\n */\n venue: Venue;\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n limitPriceRaw: string;\n sizeRaw: string;\n timeInForce: LimitOrderTimeInForce;\n postOnly?: boolean;\n expiresAt?: string;\n clientOrderId?: string;\n /** Linked account EOA. Polymarket supports GTC/GTD buys; Hyperliquid supports GTC/ALO buys and sells. Agent keys stay on the client. Omit for managed custody. */\n signingAddress?: string;\n /** Same bridge approval mode as market fills; defaults to sponsored. */\n approveMode?: ExecuteManagedParams[\"approveMode\"];\n /** Self-custody buys only: other wallets linked to this account whose balances may bridge in to fund the order. Requires signingAddress. */\n fundingAddresses?: string[];\n}\n\nexport interface PlaceLimitOrderResponse {\n orderId: string;\n /** Poll getExecutionStatus and answer submitFillSignatures using this ID. */\n quoteId?: string;\n status:\n | \"pending\"\n | \"submitting\"\n | \"submitted\"\n | \"cancel_pending\"\n | \"partial_fill\"\n | \"open\"\n | \"partially_filled_open\"\n | \"filled\"\n | \"cancelled\"\n | \"expired\"\n | \"failed\";\n venue: Venue;\n venueOrderId?: string | null;\n reservedCostRaw?: string | null;\n limitPriceRaw: string;\n limitSizeRaw: string;\n filledSizeRaw: string;\n remainingSizeRaw: string;\n}\n\nexport interface PlaceOrderParams {\n venue: Venue;\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n /** Buy only. Maximum all-in USD spend, inclusive of app fee. */\n maxSpend?: number;\n /** Sell only. Number of contracts to sell. */\n sellShares?: number;\n /**\n * Your trade id. Required, unique within your app — two different users of\n * the same app cannot share one. A repeat returns 409 instead of trading twice.\n */\n externalId: string;\n /** Slippage cap in bps. Defaults to 500 (5%). Set explicitly on sells. */\n slipCapBps?: number;\n /** Restrict funding to these chain IDs. Omit to allow every funded chain. */\n allowedSourceChainIds?: number[];\n /** USD budgets capped by refreshed wallet balances; omitted chains cannot fund. */\n chainBalances?: Record<string, number>;\n /** Per-trade app fee in bips (0..10000), replacing the app's configured rate. Needs an app API key. Buy only. */\n appFeeBips?: number;\n /** Per-venue app fee in bips (each 0..10000), e.g. `{ polymarket: 20, hyperliquid: 10 }`. Wins over `appFeeBips` on the venues it names; `appFeeBips` still covers the rest. Needs an app API key. Buy only. */\n appFeeBipsByVenue?: Record<string, number>;\n /** Referral: EVM address that receives the referral fee. Needs an app API key. */\n referrer?: string;\n /** Referral fee in bips of routed notional (1..10000). Snag-free. */\n referrerFeeBips?: number;\n /** Per-venue referral fee in bips (each 0..10000; 0 = none on that venue). Wins over `referrerFeeBips` on the venues it names. Needs `referrer` and an app API key. Not for `skipQuote`. */\n referrerFeeBipsByVenue?: Record<string, number>;\n /** Who funds the referral: \"user\" (default) reserves it from maxSpend; \"app\" pays from `referralPayerAddress` after the fill. */\n referralPayer?: \"user\" | \"app\";\n /** Required with `referralPayer: \"app\"`: the wallet that signs the parked payout transaction. */\n referralPayerAddress?: string;\n /**\n * User-paid referral only: a wallet that pays Hyperliquid's one-time 1 USDC\n * activation fee for a referrer with no HyperCore account (self-custody\n * Hyperliquid buys). Before the fill a pending signature with this\n * `signerAddress` and `purpose: \"hl_activation_sponsor\"` is passed to your\n * `signer`; it is `optional`, so declining it — or not answering within\n * `OPTIONAL_SIGNATURE_TIMEOUT_MS` — never costs the trade.\n */\n referralActivationSponsorAddress?: string;\n /**\n * Skip the smart-route solver and send one order straight to `venue` (predict,\n * hyperliquid, novig and prophetx only; others return 400). Requires a `read_write` `x-app-api-key`. No\n * bridging: funds must already sit on the venue's own chain, and `allowedSourceChainIds` /\n * `chainBalances` are ignored alongside it. You own price and minimum\n * checks — an order the venue refuses fails after acceptance and uses up its `externalId`.\n */\n skipQuote?: boolean;\n /**\n * With `skipQuote`, skip the balance check and fund hold on a buy: nothing checks the\n * balance and an underfunded order fails at the venue. Sells still check the position.\n * Without `skipQuote`, skip only the quote-time balance refresh: the route uses the last\n * stored balances, and the fund hold and balance check still run. Faster, but a stale\n * balance can fail the order after it was accepted. Requires a `read_write` `x-app-api-key`.\n */\n skipBalance?: boolean;\n /**\n * With `skipQuote`, the price to trade at (e.g. `0.52`). Optional: if omitted, the best\n * available price at submission is used (best ask to buy, bid to sell). Ignored on\n * prophetx, which prices the order itself within `slipCapBps`.\n */\n price?: number;\n}\n\nexport interface PlaceOrderResponse {\n orderId: string;\n externalId: string;\n venue: Venue;\n status: \"pending\";\n quoteId: string;\n /** `null` if the order row doesn't carry a quoted price. Not zero. */\n quotedPriceRaw: string | null;\n /** `null` under the same conditions as `quotedPriceRaw`. Not zero. */\n quotedCostRaw: string | null;\n /** `null` under the same conditions as `quotedPriceRaw`. Not zero. */\n quotedSharesRaw: string | null;\n}\n\nexport interface ValidateManagedParams {\n venueMarketOutcomeIds: string[];\n side: \"buy\" | \"sell\";\n amount: number;\n}\n\nexport interface ValidateManagedResponse {\n canExecute: boolean;\n availableBalanceRaw: string;\n requiredBalanceRaw: string;\n bridgeSourceChainId?: number;\n bridgeAmountRaw?: string;\n}\n\nexport type BalanceRefillPolicyStatus = \"enabled\" | \"paused\";\nexport type BalanceRefillAttemptStatus = \"reserved\" | \"executing\" | \"completed\" | \"failed\";\n\nexport interface BalanceRefillAttempt {\n id: string;\n policyId: string;\n status: BalanceRefillAttemptStatus;\n /** Target-chain balance when the threshold was crossed, in 6-decimal USD units. */\n triggerBalanceRaw: string;\n /** Minimum amount the refill must deliver, in 6-decimal USD units. */\n requestedDeliveryRaw: string;\n /** Reserved source amount, in 6-decimal USD units. */\n sourceAmountRaw: string;\n completedAmountRaw: string | null;\n sourceChainId: number;\n targetChainId: number;\n feeRaw: string | null;\n errorMessage: string | null;\n startedAt: string | null;\n completedAt: string | null;\n createdAt: string;\n}\n\nexport interface BalanceRefillPolicy {\n id: string;\n targetChainId: number;\n targetTokenAddress: string;\n targetTokenSymbol: \"USDC\";\n /** Balance floor, in 6-decimal USD units. */\n minimumRaw: string;\n /** Minimum delivered amount per refill, in 6-decimal USD units. */\n refillAmountRaw: string;\n dailyCapRaw: string;\n maxFeeRaw: string;\n status: BalanceRefillPolicyStatus;\n cooldownSeconds: number;\n lastObservedRaw: string | null;\n lastEvaluatedAt: string | null;\n nextEligibleAt: string | null;\n consentedAt: string;\n createdAt: string;\n updatedAt: string;\n latestAttempt: BalanceRefillAttempt | null;\n}\n\nexport interface CreateBalanceRefillPolicyParams {\n targetChainId: number;\n targetTokenSymbol?: \"USDC\";\n minimumRaw: string;\n refillAmountRaw: string;\n /** Optional daily refill limit. Defaults to $1,002 in 6-decimal USD units. */\n dailyCapRaw?: string;\n /** Optional per-refill fee limit. Defaults to $2 in 6-decimal USD units. */\n maxFeeRaw?: string;\n}\n\nexport interface UpdateBalanceRefillPolicyParams {\n minimumRaw?: string;\n refillAmountRaw?: string;\n dailyCapRaw?: string;\n maxFeeRaw?: string;\n status?: BalanceRefillPolicyStatus;\n}\n\nexport type WithdrawTokenSymbol = \"USDC\" | \"USDC.e\" | \"USDT\";\nexport type WithdrawalSourceTokenSymbol = WithdrawTokenSymbol | \"pUSD\" | \"USD1\";\n\nexport interface WithdrawManagedParams {\n /** Idempotency key for exact-amount transfers. Retry the same request, never a new key, after a lost response. Not combined with max. */\n requestId?: string;\n /** Positive integer string in the token's native decimals (e.g. \"100000\" = 0.1 USDC). */\n amountRaw: string;\n tokenSymbol: WithdrawTokenSymbol;\n /** Recipient address. EVM destinations use 0x-prefixed 20-byte hex; Solana uses base58. */\n destinationAddress: string;\n /** Chain ID where the recipient should receive funds. Required as of v2026.04. */\n destinationChainId: number;\n /**\n * When `true`, the server caps the withdrawal to the maximum deliverable amount\n * instead of rejecting an over-balance request. Use only when the user explicitly\n * clicked Max — manual over-typed amounts must still surface the unviable state.\n */\n max?: boolean;\n}\n\nexport type WithdrawalLifecycleStatus =\n | \"pending\"\n | \"bridging\"\n | \"transferring\"\n | \"completed\"\n | \"partial\"\n | \"failed\";\n\nexport type WithdrawalSourceStatus = \"pending\" | \"submitted\" | \"confirmed\" | \"failed\";\n\nexport type WithdrawalLegType = \"transfer\" | \"bridge\";\nexport type WithdrawalLegStatus = \"planned\" | \"submitted\" | \"confirmed\" | \"failed\";\n\nexport interface WithdrawalLeg {\n type: WithdrawalLegType;\n status: WithdrawalLegStatus;\n sourceChainId: number;\n destChainId: number;\n amountRaw: string;\n txHash: string | null;\n bridgeOperationId: string | null;\n /** Human-readable failure reason when `status === \"failed\"`. Null when succeeded or in-flight. */\n errorMessage?: string | null;\n}\n\nexport interface WithdrawManagedSourceItem {\n sourceId: string;\n chainId: number;\n tokenSymbol: WithdrawalSourceTokenSymbol;\n /** On-chain token address on `chainId`. */\n tokenAddress: string;\n /**\n * On-chain decimals for `(chainId, tokenAddress)`. Required to interpret\n * `amountRaw`: BNB USDC is 18-dec, EVM USDC is 6-dec.\n */\n decimals: number;\n amountRaw: string;\n /** Smart-wallet or native-account custody; absent for ordinary EOA sources. */\n custodyKind?: \"DEPOSIT_WALLET\" | \"VENUE_ACCOUNT\";\n /** Venue that owns the source (for example, `pred` or `tiprun`). */\n venue?: string;\n sourceVenueAccountId?: string;\n /** Lossless native account ID, not an EVM address. */\n sourceExternalAccountId?: string;\n status: WithdrawalSourceStatus;\n txHash: string | null;\n bridgeOperationId: string | null;\n /**\n * Present only while a venue-account source is submitted but not confirmed:\n * what it is waiting on (`awaiting_venue_approval` = the venue has not\n * approved the withdrawal yet).\n */\n pendingReason?:\n | \"awaiting_venue_submission\"\n | \"awaiting_venue_approval\"\n | \"awaiting_chain\"\n | \"awaiting_venue_balance\"\n | \"rechecking\";\n}\n\n/**\n * `pricingStatus === \"quoted\"` means the response includes a fresh preflight\n * quote; other states may carry null `expected.*` fields. Do NOT treat null\n * fields as missing.\n */\nexport interface WithdrawalExpected {\n outputRaw: string | null;\n feeRaw: string | null;\n etaSeconds: number | null;\n}\n\n/** Body for POST /execution/withdraw/preview — identical to a withdraw request. */\nexport type WithdrawPreviewParams = WithdrawManagedParams;\n\nexport interface WithdrawalQuoteParams {\n tokenSymbol: WithdrawTokenSymbol;\n destinationChainId: number;\n}\n\nexport interface WithdrawalQuoteResponse {\n tokenSymbol: WithdrawTokenSymbol;\n destinationChainId: number;\n maxDeliverableRaw: string;\n rawBalanceRaw: string;\n decimals: number;\n}\n\n/** Response from POST /execution/withdraw/preview. All amounts are raw strings in destination-token native decimals. */\nexport interface WithdrawPreviewResponse {\n receiveAmountRaw: string | null;\n feeRaw: string | null;\n relayFeeRaw: string | null;\n networkFeeRaw: string | null;\n pricingStatus: \"quoted\" | \"unviable\";\n quoteExpiresAt: string | null;\n unviableReason: string | null;\n maxDeliverableRaw: string | null;\n}\n\nexport interface WithdrawManagedResponse {\n withdrawalId: string;\n status: WithdrawalLifecycleStatus;\n requested: { tokenSymbol: WithdrawTokenSymbol; amountRaw: string };\n /**\n * Terminal settled amount in destination-token native decimals.\n * Null until at least one source confirms.\n */\n completedAmountRaw: string | null;\n destination: { chainId: number; address: string; tokenSymbol: WithdrawTokenSymbol };\n legs: WithdrawalLeg[];\n expected: WithdrawalExpected;\n pricingStatus: \"unquoted\" | \"quoting\" | \"quoted\" | \"unviable\";\n /**\n * Persisted terminal-state error reason. Always `null` until the\n * withdrawal reaches `failed` / `partial`. The submit response always\n * returns `null`; populated values arrive via the GET status endpoint or\n * via a terminal `withdrawal_lifecycle` WS event.\n */\n errorMessage: string | null;\n sources: WithdrawManagedSourceItem[];\n}\n\nexport interface DepositAddressesToken {\n symbol: string;\n address: string;\n decimals: number;\n}\n\nexport interface DepositAddressesSupportedChain {\n chainId: number;\n name: string;\n tokens: DepositAddressesToken[];\n}\n\nexport interface DepositAddressesReadyResponse {\n ready: true;\n evmAddress: string;\n svmAddress: string;\n supportedChains: DepositAddressesSupportedChain[];\n}\n\nexport interface DepositAddressesPendingResponse {\n ready: false;\n}\n\nexport type DepositAddressesResponse =\n | DepositAddressesReadyResponse\n | DepositAddressesPendingResponse;\n\nexport interface GetPositionsParams {\n cursor?: string;\n limit?: number;\n status?: \"active\" | \"closed\";\n mode?: ExecutionMode;\n categoryIds?: string[];\n sort?: \"realizedPnl\";\n}\n\nexport interface GetOrdersParams {\n status?: string;\n cursor?: string;\n limit?: number;\n}\n\n// ── Orderbook Quote (GET /orderbook/:marketId/quote) ──\n\nexport interface OrderbookQuoteParams {\n marketId: string;\n side: \"buy\" | \"sell\";\n size: number;\n}\n\nexport interface OrderbookQuoteFill {\n venue: string;\n size: number;\n avgPrice: number;\n cost: number;\n}\n\nexport interface OrderbookQuoteResponse {\n marketId: string;\n side: \"buy\" | \"sell\";\n requestedSize: number;\n filledSize: number;\n avgPrice: number | null;\n totalCost: number;\n slippage: number | null;\n fills: OrderbookQuoteFill[];\n}\nexport type ExecutionOrdersQuery = GetOrdersQuery & { mode?: ExecutionMode };\nexport type ExecutionOrderItem = OrderListItem;\nexport type ExecutionStatusQuery = { quoteId: string; mode?: ExecutionMode };\nexport type ExecutionOverallState =\n | \"created\"\n | \"routing\"\n | \"quoting\"\n | \"placing\"\n | \"confirming\"\n | \"filled\"\n | \"partially_filled\"\n | \"failed\"\n | \"cancelled\"\n | \"expired\";\nexport interface ExecutionDagProgress {\n dagRunId: string;\n totalSteps: number;\n currentSequence: number;\n currentStepType: string | null;\n completedSequences: number[];\n stepTypes: Record<number, string>;\n status: \"running\" | \"completed\" | \"failed\";\n errorReason: string | null;\n}\nexport type ExecutionDisplayStepKind = \"submit\" | \"setup\" | \"bridge\" | \"fill\" | \"internal\";\nexport type ExecutionDisplayGroupStatus =\n | \"pending\"\n | \"in_progress\"\n | \"completed\"\n | \"failed\"\n | \"skipped\";\n\nexport interface ExecutionStatusStep {\n sequence: number;\n stepType: string;\n status: \"pending\" | \"in_progress\" | \"completed\" | \"failed\" | \"skipped\";\n attempt: number;\n startedAt: string | null;\n completedAt: string | null;\n errorReason: string | null;\n\n /** Venue legs this step funds or executes; join to `orders[].orderId`. */\n orderIds: string[];\n /** Display class. `internal` steps are not meant to be rendered. */\n kind: ExecutionDisplayStepKind;\n /** Steps sharing a groupId render as ONE row. */\n groupId: string;\n /** Rolled-up status for the group; identical on every member. */\n groupStatus: ExecutionDisplayGroupStatus;\n /** Row copy, phrased for the current `groupStatus`. */\n label: string;\n /** Set on `kind: \"bridge\"` only. */\n bridge?: {\n amount: string;\n tokenSymbol: string;\n fromChain: string;\n toChain: string;\n };\n}\nexport interface ExecutionStatusOrder {\n orderId: string;\n venue: string;\n status: string;\n event: \"filled\" | \"partial_fill\" | \"failed\" | null;\n filledAmountRaw?: string;\n remainingAmountRaw?: string;\n quotedSharesRaw?: string;\n actualSharesRaw?: string;\n quotedToWinRaw?: string;\n actualToWinRaw?: string;\n quotedPriceRaw?: string;\n executionPriceRaw?: string;\n partialFillReason?: string;\n errorReason?: string;\n venueOrderId?: string;\n txHash?: string;\n updatedAt: string;\n}\nexport interface ExecutionStatusResponse {\n executionId: string | null;\n quoteId: string;\n orderIds: string[];\n overallState: ExecutionOverallState;\n terminal: boolean;\n errorReason: string | null;\n pollAfterMs: number | null;\n dagProgress: ExecutionDagProgress | null;\n steps: ExecutionStatusStep[];\n orders: ExecutionStatusOrder[];\n /**\n * What this run is waiting to be signed, mirroring the fill response's\n * field of the same name. This is the polling route `fillSelfCustody` reads\n * while an on-chain step is in flight — a caller polling this route for\n * progress learns about newly-parked steps here too, not just from the\n * signatures endpoint.\n */\n pendingSignatures?: SignatureRequest[];\n}\nexport type ExecutionPositionsQuery = GetPositionsQuery & { mode?: ExecutionMode };\nexport type ExecutionPositionGroup = PositionGroup;\n/** Whose cash to return: the managed server wallet (default) or the account's linked wallets. */\nexport type BalanceCustody = \"managed\" | \"self\";\nexport type ManagedBalancesParams = { mode?: ExecutionMode; custody?: BalanceCustody };\nexport type ManagedBalancesResponse = UnifiedBalanceResponse;\n\n// ── Paper trading account administration (/apps/:appId/paper-trading) ──\n\nexport interface PaperTradingAppOptions {\n /** App ID for the paper account namespace. Defaults to AggClient appId. */\n appId?: string;\n}\n\nexport interface PaperTradingListParams {\n limit?: number;\n cursor?: string;\n}\n\nexport interface PaperTradingAccountListParams extends PaperTradingListParams {\n externalId?: string;\n}\n\nexport interface CreatePaperTradingAccountParams {\n name?: string;\n externalId?: string;\n initialBalanceRaw?: string;\n initialBalance?: number;\n}\n\nexport interface SetPaperTradingBalanceParams {\n balanceRaw?: string;\n balance?: number;\n reason?: string;\n}\n\nexport interface ResetPaperTradingAccountParams {\n balanceRaw?: string;\n balance?: number;\n reason?: string;\n}\n\nexport interface PlacePaperTradingOrderParams {\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n spendRaw?: string;\n spend?: number;\n shares?: number;\n slippageBps?: number;\n clientOrderId?: string;\n}\n\nexport type PaperTradingMarkSource = \"orderbook_midpoint\" | \"orderbook_best_bid\" | \"catalog_price\";\n\nexport type PaperTradingLiquidityStatus = \"full\" | \"partial\" | \"none\";\n\nexport interface PaperTradingAccount {\n id: string;\n appId: string;\n name: string | null;\n externalId: string | null;\n currency: string;\n startingBalanceRaw: string;\n startingBalance: number;\n cashBalanceRaw: string;\n cashBalance: number;\n realizedPnlRaw: string;\n realizedPnl: number;\n kycStatus: \"verified\";\n kycVerified: true;\n status: \"active\" | \"archived\";\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface PaperTradingPosition {\n id: string;\n accountId: string;\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n marketQuestion: string;\n outcomeLabel: string;\n size: number;\n avgEntryPrice: number;\n markPrice: number;\n markSource: PaperTradingMarkSource;\n markTimestamp: number | null;\n bestBidPrice: number | null;\n bestAskPrice: number | null;\n midpoint: number | null;\n spread: number | null;\n marketValueRaw: string;\n marketValue: number;\n unrealizedPnlRaw: string;\n unrealizedPnl: number;\n liquidationPrice: number | null;\n liquidationValueRaw: string;\n liquidationValue: number;\n liquidationPnlRaw: string;\n liquidationPnl: number;\n liquidityShares: number;\n liquidityStatus: PaperTradingLiquidityStatus;\n realizedPnlRaw: string;\n realizedPnl: number;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface PaperTradingOrder {\n id: string;\n accountId: string;\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n marketQuestion: string;\n outcomeLabel: string;\n side: \"buy\" | \"sell\";\n status: \"filled\" | \"rejected\";\n clientOrderId: string | null;\n requestedSpendRaw: string | null;\n requestedSpend: number | null;\n requestedShares: number | null;\n filledShares: number;\n avgPrice: number | null;\n slippageBps: number | null;\n notionalRaw: string;\n notional: number;\n cashDeltaRaw: string;\n cashDelta: number;\n realizedPnlRaw: string;\n realizedPnl: number;\n rejectionReason: string | null;\n createdAt: string;\n}\n\nexport interface PaperTradingBalanceAdjustment {\n id: string;\n accountId: string;\n type: \"set_balance\" | \"reset\";\n amountRaw: string;\n amount: number;\n previousCashBalanceRaw: string;\n previousCashBalance: number;\n newCashBalanceRaw: string;\n newCashBalance: number;\n reason: string | null;\n createdAt: string;\n}\n\nexport interface PaperTradingPortfolio {\n account: PaperTradingAccount;\n cashBalanceRaw: string;\n cashBalance: number;\n marketValueRaw: string;\n marketValue: number;\n equityRaw: string;\n equity: number;\n realizedPnlRaw: string;\n realizedPnl: number;\n unrealizedPnlRaw: string;\n unrealizedPnl: number;\n liquidationValueRaw: string;\n liquidationValue: number;\n liquidationEquityRaw: string;\n liquidationEquity: number;\n liquidationPnlRaw: string;\n liquidationPnl: number;\n positions: PaperTradingPosition[];\n}\n\nexport interface PaperTradingAccountsPage {\n data: PaperTradingAccount[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface PaperTradingPositionsPage {\n data: PaperTradingPosition[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface PaperTradingOrdersPage {\n data: PaperTradingOrder[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface PaperTradingBalanceResponse {\n account: PaperTradingAccount;\n adjustment: PaperTradingBalanceAdjustment;\n}\n\n// ── Unified user activity feed (/users/activity) ──\n\nexport type UserActivityType = \"trade\" | \"withdrawal\" | \"bridge\" | \"deposit\" | \"user_op\" | \"redeem\";\n\ninterface UserActivityBase {\n id: string;\n createdAt: string;\n updatedAt: string;\n status: string;\n}\n\ninterface UserActivityVenueMarket {\n id: string;\n venueEventId: string;\n question: string | null;\n image: string | null;\n}\n\ninterface UserActivityVenueMarketOutcome {\n id: string;\n label: string;\n title: string | null;\n price: number;\n}\n\nexport interface UserActivityTrade extends UserActivityBase {\n type: \"trade\";\n venue: string;\n side: string;\n amountRaw: string;\n filledAmountRaw: string | null;\n executionPrice: string | null;\n venueMarket: UserActivityVenueMarket | null;\n venueMarketOutcome: UserActivityVenueMarketOutcome | null;\n txHash: string | null;\n errorMessage: string | null;\n /** @deprecated Use venueMarket.question. */\n marketQuestion?: string | null;\n /** @deprecated Use venueMarketOutcome.label/title. */\n outcomeLabel?: string | null;\n}\n\nexport interface UserActivityWithdrawal extends UserActivityBase {\n type: \"withdrawal\";\n tokenSymbol: string;\n amountRaw: string;\n destinationAddress: string;\n destinationChainId: string;\n completedAmountRaw: string | null;\n chainId?: string | null;\n txHash?: string | null;\n errorMessage: string | null;\n}\n\nexport interface UserActivityBridge extends UserActivityBase {\n type: \"bridge\";\n tokenSymbol: string;\n amountRaw: string;\n sourceChainId: string;\n destChainId: string;\n sourceTxHash: string | null;\n destTxHash: string | null;\n}\n\nexport interface UserActivityDeposit extends UserActivityBase {\n type: \"deposit\";\n tokenSymbol: string;\n amountRaw: string;\n chainId: string;\n fromAddress: string;\n txHash: string;\n source: \"connected_wallet\" | \"external_wallet\";\n}\n\nexport interface UserActivityUserOp extends UserActivityBase {\n type: \"user_op\";\n callsId: string;\n chainId: string;\n walletAddress: string;\n txHash: string | null;\n confirmedAt: string | null;\n}\n\nexport interface UserActivityRedeemLeg {\n id: string;\n venueMarketOutcomeId: string;\n venue: string;\n status: string;\n chainId: string;\n payoutTokenSymbol: string;\n payoutAmountRaw: string | null;\n txHash: string | null;\n errorMessage: string | null;\n venueMarket: UserActivityVenueMarket | null;\n venueMarketOutcome: Omit<UserActivityVenueMarketOutcome, \"price\"> | null;\n}\n\nexport interface UserActivityRedeem extends UserActivityBase {\n type: \"redeem\";\n totalPayoutRaw: string | null;\n legs: UserActivityRedeemLeg[];\n}\n\nexport type UserActivityItem =\n | UserActivityTrade\n | UserActivityWithdrawal\n | UserActivityBridge\n | UserActivityDeposit\n | UserActivityUserOp\n | UserActivityRedeem;\n\nexport interface UserActivityQuery {\n type?: UserActivityType;\n cursor?: string;\n limit?: number;\n}\n\n// ── Leaderboard ──────────────────────────────────────────────────────────────\n\n/** Column a leaderboard is ranked by. */\nexport type LeaderboardMetric = \"realizedPnl\" | \"volume\";\n\nexport interface LeaderboardQuery {\n /** Inclusive UTC day `YYYY-MM-DD`. Omit both `from` and `to` for all time. */\n from?: string;\n to?: string;\n metric?: LeaderboardMetric;\n /** 1..100, default 50. */\n limit?: number;\n cursor?: string;\n /** Look up one user (at most one of these four). */\n userId?: string;\n externalId?: string;\n /** Only when the app's `leaderboardIdentity` is `profile`. */\n username?: string;\n /** Not when the app's `leaderboardIdentity` is `anonymous`. */\n walletAddress?: string;\n /** One `Category.id` (a league is a category); includes sub-categories. At most 1. */\n categoryIds?: string[];\n /** Up to 5 event ids, each merged across venues. All time only; not with `categoryIds`. */\n venueEventIds?: string[];\n /**\n * Up to 100 AGG user ids; unpaginated. Not with the single-user lookups or `cursor`.\n * Returns rows only for users that have stats: a requested user with no activity is\n * simply absent (the single-user lookups return a zero row instead).\n */\n userIds?: string[];\n}\n\nexport interface LeaderboardRow {\n /** Exact within the top 100, `null` beyond. */\n rank: number | null;\n userId: string;\n /** Null unless the app's `leaderboardIdentity` is `profile`. */\n username: string | null;\n /** Null unless the app's `leaderboardIdentity` is `profile`. */\n avatarUrl: string | null;\n /** Null under `anonymous`; primary wallet under `wallet` or `profile`. */\n walletAddress: string | null;\n /** Filled orders in the range. */\n orders: number;\n /** USD notional of every filled order in the range, buys and sells. */\n volume: number;\n /** USD notional of filled buy orders only — what the trader put in. */\n spent: number;\n /** Gross realized P&L in USD (sells + settlements, before fees). */\n realizedPnl: number;\n /** Settled position legs whose settlement booked a profit. */\n wins: number;\n /** Settled position legs whose settlement booked a loss. A zero settlement (void, refund) is neither. */\n losses: number;\n /** wins / (wins + losses), 0 to 1; `null` before any settlement. */\n winRate: number | null;\n}\n\n/** At most one of `userId`, `externalId`, `username`, `walletAddress`; none = the whole app. */\nexport interface LeaderboardSeriesQuery {\n /** Inclusive UTC calendar day, `YYYY-MM-DD`. Default: 29 days before `to`. */\n from?: string;\n /** Inclusive UTC calendar day, `YYYY-MM-DD`. Default and maximum: today. */\n to?: string;\n userId?: string;\n externalId?: string;\n /** Only when the app's `leaderboardIdentity` is `profile`. */\n username?: string;\n /** Not when the app's `leaderboardIdentity` is `anonymous`. */\n walletAddress?: string;\n /** One `Category.id`. At most 1. */\n categoryIds?: string[];\n}\n\nexport interface LeaderboardStats {\n orders: number;\n volume: number;\n spent: number;\n realizedPnl: number;\n wins: number;\n losses: number;\n winRate: number | null;\n}\n\nexport interface LeaderboardSeriesPoint extends LeaderboardStats {\n /** UTC calendar day, `YYYY-MM-DD`. */\n day: string;\n /** Running total of `realizedPnl` from `from` through this day. */\n cumulativeRealizedPnl: number;\n /** Win rate over `from` through this day; `null` until a position settles. */\n cumulativeWinRate: number | null;\n}\n\nexport interface LeaderboardSeries {\n /** `null` for an app-wide series (no user given). */\n userId: string | null;\n from: string;\n to: string;\n /** Sums over `[from, to]`. */\n totals: LeaderboardStats;\n /** One point per day in `[from, to]`, oldest first; days without activity are 0. */\n points: LeaderboardSeriesPoint[];\n}\n\n// ── Ramp ──\n\nexport interface RampQuoteRequest {\n sourceAmount: string;\n sourceCurrencyCode: string;\n destinationCurrencyCode: string;\n paymentMethodType?: string;\n}\n\nexport interface RampQuote {\n serviceProvider: string;\n transactionType: string;\n sourceAmount: number;\n sourceCurrencyCode: string;\n destinationAmount: number;\n destinationCurrencyCode: string;\n exchangeRate: number;\n totalFee: number;\n networkFee: number;\n transactionFee: number;\n partnerFee: number;\n fiatAmountWithoutFees: number;\n paymentMethodType: string;\n countryCode: string;\n rampScore: number;\n lowKyc: boolean;\n}\n\nexport interface RampSessionRequest {\n sourceAmount: string;\n sourceCurrencyCode: string;\n destinationCurrencyCode: string;\n serviceProvider: string;\n walletAddress: string;\n redirectUrl?: string;\n}\n\nexport interface RampWidgetSession {\n id: string;\n token: string;\n widgetUrl: string;\n serviceProviderWidgetUrl: string;\n}\n// ── Smart order routing (GET /orderbook/:venueMarketOutcomeId/route) ──\n\nexport type SmartRouteStatus =\n | \"ok\"\n | \"infeasible\"\n | \"checker_rejected\"\n | \"solver_error\"\n | \"invalid_input\"\n | \"no_orderbooks\"\n | \"min_order_size_violated\"\n | \"insufficient_input_amount\"\n | \"engine_unavailable\"\n | \"insufficient_position\"\n | \"insufficient_depth\"\n | \"no_bids_above_min_price\"\n | \"insufficient_balance\";\n\n/** A single fill at a price level within a venue. */\nexport interface SmartRouteFill {\n price: number;\n size: number;\n fill: number;\n}\n\n/** Per-venue routing result with fills and chain info. */\nexport interface SmartRouteVenueFill {\n /** Age of the observed orderbook; absent for native venue quotes. */\n bookAgeMs?: number;\n /** Default (r3) or explicitly enabled relaxed (r4) freshness budget. */\n freshnessRow?: \"r3\" | \"r4\";\n /** CH executable price and normalized input, in micro-USDC. */\n limitPriceMicroUsdc?: string;\n inAmount?: string;\n outAmount?: string;\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n chain: string;\n avgPrice: number;\n yesPrice: number;\n noPrice: number;\n fills: SmartRouteFill[];\n executionBackend?: \"clearinghouse\" | \"direct\";\n venueAccountId?: string;\n venueQty: number;\n /**\n * Builder fee for this fill in USD — the slice paid to a builder code\n * rather than to the venue. Excluded from `venueFee`. Optional so an\n * older engine build that does not emit it still validates.\n */\n builderFee?: number;\n /**\n * What the venue takes from this leg's payout if the outcome wins (USD):\n * Hyperliquid HIP-4's close fee on the $1 settlement, 0 elsewhere. Not a\n * cost at fill; already netted out of `estimatedPayout`.\n */\n settlementFee?: number;\n /** Inclusive fee/reserve funding budget. For fee display, use the route's\n * feeBreakdown.venueFees and executionReserve instead. */\n venueFee?: number;\n}\n\nexport interface SmartRouteAllocation {\n sourceChainId: string;\n venue: string;\n amount: number;\n sourceTokenAddress?: string;\n custodyKind?: \"EOA\" | \"DEPOSIT_WALLET\" | \"POLYMARKET_LEGACY\" | \"VENUE_ACCOUNT\";\n custodyAddress?: string;\n /** Native venue cash identifies an account, not an EVM custody address. */\n sourceVenueAccountId?: string;\n /** Lossless decimal native account ID; never convert this to a JS number. */\n sourceExternalAccountId?: string;\n /** On-chain funding wallet, when present; absent for native venue cash. */\n sourceAddress?: string;\n exactToken?: boolean;\n}\n\nexport interface SmartRouteBridgeStep {\n sourceChainId: string;\n destChainId: string;\n /** Source-side amount sent into the bridge, in USD: the allocations this lane funds plus `cost`. */\n amount: number;\n /**\n * Delivery margin, in USD, sent on top of the allocations so the destination\n * still receives them in full after the bridge takes its fee. A planning\n * reserve, not the expected fee: excluded from `feeBreakdown.bridgeFees` and\n * `totalCost`, and whatever the bridge does not charge arrives at the\n * destination as the user's balance. Read `feeBreakdown.bridgeFees` for the\n * expected bridge fee.\n */\n cost: number;\n sourceTokenAddress?: string;\n destTokenAddress?: string;\n}\n\nexport interface VenueSoloQuote {\n quoteFailure?: { venue: string; code: string; retryAt?: string };\n /**\n * Minted by the API per successful + executable solo; send this to\n * /execution/fill to execute single-venue. `null` when the solo is not\n * executable (status !== \"ok\", filledQty === 0, or venue not in\n * SUPPORTED_FILL_VENUES). FE filters on truthiness.\n */\n quoteId: string | null;\n /** Why this venue cannot execute when quoteId is null (or execution is geo-gated). */\n unavailableReason?: string;\n venue: string;\n /**\n * The outcome this solo is bound to. `venue` alone is NOT unique — one venue\n * can list the same matched outcome more than once (e.g. two Hyperliquid\n * deployers listing the same game), producing two solo cards with the same\n * `venue`. Key on this alongside `venue` when identifying a card.\n */\n venueMarketOutcomeId?: string;\n avgPrice: number | null;\n filledQty: number;\n rawExecCost: number;\n estimatedPayout: number;\n estimatedProfit: number;\n returnPct: number;\n /**\n * `feeBreakdown.totalCost` plus this solo's own user-paid app fee and\n * referral — same composition as the primary route's `totalCostIncFees`.\n * `estimatedProfit`/`returnPct` stay router values, unaffected. Absent\n * when the router sent no `feeBreakdown` for this solo.\n */\n totalCostIncFees?: number;\n status: string;\n /** Per-price-level fills, identical shape to primary fills. Empty for non-ok statuses. */\n fills: SmartRouteVenueFill[];\n allocations?: SmartRouteAllocation[];\n bridgeSteps?: SmartRouteBridgeStep[];\n /**\n * One-time setup costs for this solo's chosen venue + market. Populated\n * only when the originating quote opted in via `deepEstimate=true`; absent\n * on cheap quotes and on non-executable / failed solos. Same shape as the\n * multi-route `feeBreakdown.setupCosts`. The solo's `estimatedProfit` and\n * `returnPct` are recomputed against `cost basis + setupCostsTotal` so\n * per-venue comparisons are setup-inclusive.\n */\n setupCosts?: SmartRouteSetupCostLine[];\n /** Sum of this solo's `setupCosts` entries where `alreadyPaid=false`. */\n setupCostsTotal?: number;\n /**\n * Cost breakdown for executing THIS venue alone. Present when\n * `status === \"ok\"`; absent otherwise.\n *\n * Read this — not the top-level `feeBreakdown` — when rendering fees for a\n * single venue. A solo's bridge lanes and venue fee are its own, so a venue\n * needing no bridge reports `bridgeFees: 0` here even when the multi-route\n * plan bridged.\n */\n feeBreakdown?: SmartRouteFeeBreakdown;\n}\n\n/** @deprecated Smart-route side overrides are kept only for source compatibility. */\nexport type SmartRouteSide = \"yes\" | \"no\";\n\n/** Trade direction for order routing. \"buy\" (default) reads asks, \"sell\" reads bids. */\nexport type TradeSide = \"buy\" | \"sell\";\n\n/** Trading mode for normal execution endpoints. Defaults to live. */\nexport type ExecutionMode = \"live\" | \"paper\";\n\n/** Request params for GET /orderbook/:venueMarketOutcomeId/route. */\nexport interface SmartRouteParams {\n venueMarketOutcomeId?: string;\n /** @deprecated Use venueMarketOutcomeId. */\n venueMarketId?: string;\n /** @deprecated Use venueMarketOutcomeId. */\n outcomeId?: string;\n /** @deprecated Side is ignored for routing and echoed back only for legacy consumers. */\n side?: SmartRouteSide;\n /** Trade direction: \"buy\" (default) or \"sell\". */\n tradeSide?: TradeSide;\n /** Trading mode. Defaults to live. */\n mode?: ExecutionMode;\n maxSpend?: number;\n /** Sell only: target number of contracts to sell. Required for sell unless maxSpend is given. */\n sellShares?: number;\n chainBalances?: Record<string, number>;\n slipCapBps?: number;\n compareVenues?: boolean;\n /** Restrict this quote to one or more executable venues. */\n allowedVenues?: Venue[];\n /**\n * Opt in to the deep cost-estimate surface. When `true`, the response\n * `feeBreakdown` includes `setupCosts` (one-time chain approvals + Kalshi\n * SPL token-account rents) with per-item `alreadyPaid` flags from the\n * user's prior trade history. Buy-only; ignored for sells.\n *\n * Deep quotes also pre-deduct the unpaid setup total from `maxSpend`\n * before routing, so `totalCostIncFees` (and the recomputed\n * `estimatedProfit` / `returnPct`) stay within the partner's stated\n * budget.\n */\n deepEstimate?: boolean;\n /** Per-trade app fee in bips (0..10000), replacing the app's configured rate. Needs an app API key. Buy only. */\n appFeeBips?: number;\n /** Per-venue app fee in bips (each 0..10000), e.g. `{ polymarket: 20, hyperliquid: 10 }`. Wins over `appFeeBips` on the venues it names; `appFeeBips` still covers the rest. Needs an app API key. Buy only. */\n appFeeBipsByVenue?: Record<string, number>;\n /** Referral: EVM address that receives the referral fee. Needs an app API key. */\n referrer?: string;\n /** Referral fee in bips of routed notional (1..10000). Snag-free. */\n referrerFeeBips?: number;\n /** Per-venue referral fee in bips (each 0..10000; 0 = none on that venue). Wins over `referrerFeeBips` on the venues it names. Needs `referrer` and an app API key. Not for `skipQuote`. */\n referrerFeeBipsByVenue?: Record<string, number>;\n /** Who funds the referral: \"user\" (default) reserves it from maxSpend; \"app\" pays from `referralPayerAddress` after the fill. */\n referralPayer?: \"user\" | \"app\";\n /** Required with `referralPayer: \"app\"`: the wallet that signs the parked payout transaction. */\n referralPayerAddress?: string;\n /**\n * User-paid referral only: a wallet that pays Hyperliquid's one-time 1 USDC\n * activation fee for a referrer with no HyperCore account (self-custody\n * Hyperliquid buys). Before the fill a pending signature with this\n * `signerAddress` and `purpose: \"hl_activation_sponsor\"` is passed to your\n * `signer`; it is `optional`, so declining it — or not answering within\n * `OPTIONAL_SIGNATURE_TIMEOUT_MS` — never costs the trade.\n */\n referralActivationSponsorAddress?: string;\n}\n\n/** One-time setup line item — populated only on deep-estimate quotes. */\nexport interface SmartRouteSetupCostLine {\n /** \"chainApproval\" = ERC-20 + venue-contract approvals on the venue's\n * chain (Polymarket / Polygon, Limitless / Base, predict.fun / BNB).\n * \"venueMarketAta\" = Kalshi-on-Solana per-market token-account rent.\n * \"hyperliquidActivation\" = Hyperliquid's one-time 1 USDC fee to activate\n * the user's address on its first deposit; `alreadyPaid` once the address\n * exists on Hyperliquid. Deducted from the bridged amount, not a step. */\n kind: \"chainApproval\" | \"venueMarketAta\" | \"hyperliquidActivation\";\n venue: string;\n /** Set when `kind === \"chainApproval\"`. */\n chainId?: number;\n /** Set when `kind === \"venueMarketAta\"`. */\n venueMarketId?: string;\n /** Per-item cost in USD. Sourced from documented chain-paymaster floors\n * (Polygon/Base/Arbitrum ≈ $0.05, BNB $0.20, Solana ATA ≈ $0.30). */\n costUsd: number;\n /** True if the user has already paid this on a prior fill — render as a\n * strike-through \"first-time fee\" chip rather than charging again. */\n alreadyPaid: boolean;\n}\n\n/** Cost breakdown for a route quote. */\nexport interface SmartRouteFeeBreakdown {\n rawExecCost: number;\n venueFees: number;\n /**\n * Builder fee in USD — the slice paid to a builder code rather than to the\n * venue. Partners with their own builder code see their own rate here;\n * everyone else sees the platform default. Excluded from `venueFees`,\n * included in `totalCost`.\n */\n builderFee?: number;\n /** Additional CH funding reserve for slippage or possible venue charges.\n * Excluded from venueFees and totalCost; included in funding allocations.\n * Only the unused portion is released after execution. */\n executionReserve?: number;\n bridgeFees: number;\n executionGas: number;\n totalCost: number;\n /** Populated only when the request specified `deepEstimate=true`. */\n setupCosts?: SmartRouteSetupCostLine[];\n /** Sum of `setupCosts` entries where `alreadyPaid === false`. */\n setupCostsTotal?: number;\n /**\n * Partner-level execution fee in USD. The worst-case fee the user will\n * pay against the routed buy notional at quote time. Buy-side only —\n * sell quotes don't carry this field.\n *\n * Actual collection happens after the trade fills, against realized\n * notional (which may be less on partial fills). Partner UIs should\n * render this as \"you'll pay up to $X in app fees\".\n *\n * Both `appFee` and `appFeeBips` are present iff `appFee > 0`.\n */\n appFee?: number;\n /** The rate that produced `appFee` — the partner's configured bips, or the request's `appFeeBips`. When the venues this route fills have different rates, the highest of them; see `appFeeBipsByVenue`. */\n appFeeBips?: number;\n /** App fee rate per venue this route fills, in bips. Present only when those rates differ. */\n appFeeBipsByVenue?: Record<string, number>;\n /** Category key the bips resolved against (e.g. \"sports\", \"all\" for the fallback, \"override\" for a per-request `appFeeBips`). */\n appFeeCategory?: string;\n /** The `executionGas` line when it is actually collected with the app fee. Present iff > 0; already inside `totalCost`. */\n gasReimbursement?: number;\n /** Referral fee the USER pays, in USD. Present iff > 0 and `referralPayer` is \"user\"; already inside `totalCostIncFees`. An app-paid referral never appears here. */\n referralFee?: number;\n /** Referral fee rate per venue this route fills, in bips. Present with `referralFee`, only when those rates differ. */\n referralFeeBipsByVenue?: Record<string, number>;\n}\n\n/** Response from GET /orderbook/:venueMarketOutcomeId/route. */\nexport interface SmartRouteSettlementLeg {\n action: \"redeem\";\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n positionId: string;\n size: string;\n redeemPath: \"evm\" | \"svm\";\n}\n\nexport interface SmartRouteSettlementPlan {\n redeemId: string;\n status: \"redeem_only\" | \"partial_redeem\";\n message: string;\n totalRedeemableShares: number;\n totalRedeemShares: number;\n totalSellShares: number;\n redeemLegs: SmartRouteSettlementLeg[];\n}\n\n/** Slippage metrics for the route. Mirrors `SmartRouteResponseTB.slippage`. */\nexport interface SmartRouteSlippage {\n /** Volume-weighted average price. */\n vwap: number;\n /** Reference midpoint used by the optimizer. */\n refMidpoint: number;\n /** Route slippage = max(0, VWAP - refMidpoint). */\n slippage: number;\n /** Slippage in basis points relative to ref midpoint. */\n slippageBps: number;\n}\n\nexport interface SmartRouteResponse {\n /** Accepted worst execution price for protected route legs. */\n legBounds?: Array<{\n venue: string;\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n worstPrice: number;\n effectiveSlippageBps: number;\n }>;\n\n quoteRefreshNotBefore?: string;\n quoteFailure?: { venue: string; code: string; retryAt?: string };\n quoteId: string;\n venueMarketOutcomeId: string;\n venueMarketId: string;\n estimatedCostRaw: string;\n expiresAt: string;\n /**\n * Timestamp at which the quote begins to drift — frontends should refetch\n * a fresh `getSmartRoute` at this point even though the cached quoteId\n * remains executable until `expiresAt`. Always earlier than `expiresAt`.\n */\n refreshAt: string;\n status: SmartRouteStatus;\n fills: SmartRouteVenueFill[];\n totalFilled: number;\n rawExecCost: number;\n solveTimeMs: number;\n verifyTimeMs: number;\n matchedMarkets: Array<{ venue: string; venueMarketId: string }>;\n error?: string;\n message?: string;\n settlementPlan?: SmartRouteSettlementPlan;\n warnings?: Array<{ venue: string; venueMarketOutcomeId: string; reason: string }>;\n venueSoloQuotes?: VenueSoloQuote[];\n allocations?: SmartRouteAllocation[];\n bridgeSteps?: SmartRouteBridgeStep[];\n /**\n * Route slippage metrics. Present on the wire (`SmartRouteResponseTB`) but\n * missing from this mirror until now — `@agg-build/hooks` already reads\n * `slippage.slippageBps` to flag thin liquidity.\n */\n slippage?: SmartRouteSlippage;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Only on a single-venue quote; absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this venue/market, raw 6-dec shares.\n * Only on a single-venue quote; absent means no known minimum. */\n minSizeRaw?: string;\n /** Estimated payout if the outcome wins (= totalFilled shares × $1, less\n * settlement fees — see `fills[].settlementFee`). */\n estimatedPayout?: number;\n /** Total cost including all fees (rawExecCost + venueFees + bridgeFees +\n * executionGas). For deep-estimate quotes, `setupCostsTotal` is folded\n * into this number and `estimatedProfit` / `returnPct` are recomputed\n * against it. */\n totalCostIncFees?: number;\n /** Sell only: gross proceeds minus venue, builder, app, and user-paid\n * referral fees, in USD — what the sell returns. */\n estimatedNetProceeds?: number;\n /** Estimated profit if the outcome wins (= estimatedPayout − totalCostIncFees). */\n estimatedProfit?: number;\n /** Return on investment percentage (= estimatedProfit / totalCostIncFees × 100). */\n returnPct?: number;\n /** Per-route fee breakdown. Always present when the engine produced a\n * feasible plan; omitted on solo / failed quotes. The `setupCosts` and\n * `setupCostsTotal` fields are populated only when the request set\n * `deepEstimate=true`. */\n feeBreakdown?: SmartRouteFeeBreakdown;\n /**\n * Quote-time snapshot of the partner fee configuration that produced\n * `feeBreakdown.appFee`, frozen so config drift between quote and execute\n * cannot change what the user is charged.\n *\n * This is NOT the display number — that is `feeBreakdown.appFee`, in USD.\n * This is the audit record: `quotedAppFeeRaw` is the worst-case charge in\n * 6-decimal USD atoms, and is what a partner reconciles against their\n * `AppFeeCharge` rows. `null` when the app has no fee configured.\n */\n appFee?: {\n /** The route rate: the highest among the venues this route fills. */\n bips: number;\n categoryKey: string;\n quotedAppFeeRaw: string;\n /** Rate per venue this route fills. Present only when those rates differ. */\n bipsByVenue?: Record<string, number>;\n } | null;\n /** Referral snapshot; null/absent when no referrer was accepted. */\n referral?: {\n referrer: string;\n /** The highest rate among the venues this route fills. */\n feeBips: number;\n /** Rate per venue this route fills. Present only when those rates differ. */\n feeBipsByVenue?: Record<string, number>;\n payer: \"user\" | \"app\";\n payerAddress?: string;\n /** Wallet sponsoring the referrer's HyperCore activation, when sent. */\n activationSponsorAddress?: string;\n quotedFeeUsd: number;\n } | null;\n /**\n * Sell quotes only: the user's sellable shares when the quote was built, on\n * the venues the request allows. Returned on `ok` sell quotes too; on\n * `insufficient_position` it says how much can be sold. A snapshot, not a\n * reservation: the fill re-checks the live venue balance.\n */\n positionAvailability?: {\n totalSellableShares: number;\n venueMarketOutcomes: Array<{\n id: string;\n venue: string;\n venueMarketId: string;\n availableShares: number;\n }>;\n };\n /** @deprecated Echoed only when the deprecated request-side override is provided. */\n side?: SmartRouteSide;\n}\n\nexport interface CancelManagedExecutionResponse {\n quoteId: string | null;\n orderIds: string[];\n status: \"cancelled\" | \"cancel_pending\";\n}\n\nexport type PositionRedeemStatus = \"eligible\" | \"pending\" | \"redeemed\" | \"ineligible\";\n\nexport type RedeemLegStatus = \"submitted\" | \"confirmed\" | \"ineligible\" | \"rejected\";\n\nexport interface RedeemLegResult {\n venueMarketOutcomeId: string;\n status: RedeemLegStatus;\n callsId: string | null;\n pendingUserOpId: string | null;\n txHash: string | null;\n reason: string | null;\n}\n\nexport interface RedeemRequest {\n venueMarketOutcomeIds: string[];\n /**\n * Trading mode. Defaults to live, matching the other execution methods.\n * Honoured on a live app; ignored on a paper app, which has no real-money\n * path and always settles on paper.\n */\n mode?: ExecutionMode;\n}\n\nexport interface RedeemResponse {\n redeemId: string;\n results: RedeemLegResult[];\n}\n\n// ── Search ──\n\nexport type SearchType = \"events\" | \"markets\";\n\nexport interface SearchParams {\n mode?: \"instant\" | \"full\";\n q: string;\n type: SearchType;\n categoryIds?: string[];\n /**\n * Filter results by status (e.g. `[\"open\"]` for tradeable-only). Without\n * it the server returns all statuses; recurring series (\"BTC Up or Down -\n * 5 Min\") can then fill a page with resolved history, which a UI that\n * hides non-open rows renders as an empty result.\n */\n status?: MarketStatus[];\n limit?: number;\n cursor?: string;\n /**\n * Opt in to the server-side reranker for higher-quality top results.\n *\n * Send `deep: true` for the final search-results page (submit / Enter) and\n * leave it off for debounced typeahead. Adds ~100–150 ms on a cold rerank\n * cache and ~3 ms on a warm one — typeahead can't afford the cold cost,\n * and the result orderings differ enough that the server gives the two\n * modes separate cache slots.\n *\n * Defaults to `false`.\n */\n deep?: boolean;\n}\n\nexport type SearchResponse<T> = {\n meta?: { complete?: boolean; degradedSignals?: string[] };\n type: SearchType;\n data: T[];\n nextCursor: string | null;\n hasMore: boolean;\n};\n\n// ── News Feed ──\n\nexport interface NewsFeedPageOptions {\n cursor?: string;\n since?: string;\n before?: string;\n limit?: number;\n}\n\nexport interface NewsFeedMarketNewsParams {\n venueMarketIds?: string[];\n venueEventIds?: string[];\n customQuery?: string;\n tbs?: string;\n limit?: number;\n}\n\nexport interface NewsFeedArticleWithSummary {\n title: string;\n url: string;\n snippet: string;\n source: string;\n imageUrl: string | null;\n publishedAt: string | null;\n summary: string;\n relevanceScore: number;\n}\n\nexport interface NewsFeedMarketNewsResult {\n venueMarketId: string;\n venueEventId: string;\n question: string;\n eventTitle: string;\n category: string;\n searchQuery: string;\n timeRange: string;\n timeRangeLabel: string;\n articles: NewsFeedArticleWithSummary[];\n}\n\nexport interface NewsFeedMarketNewsResponse {\n results: NewsFeedMarketNewsResult[];\n}\n\nexport interface NewsFeedLinkedMarket {\n venueMarketId: string;\n question: string;\n venue: string;\n yesPrice: number;\n eventTitle: string;\n eventId: string;\n summary: string;\n relevanceScore: number;\n}\n\nexport interface NewsFeedArticleFeedItem {\n article: {\n id: string;\n title: string;\n url: string;\n snippet: string;\n source: string;\n imageUrl: string | null;\n publishedAt: string | null;\n };\n markets: NewsFeedLinkedMarket[];\n category: string;\n id: string;\n seq: number;\n timestamp: string;\n}\n\nexport interface NewsFeedMarketFeedArticle {\n title: string;\n url: string;\n source: string;\n imageUrl: string | null;\n publishedAt: string | null;\n summary: string;\n relevanceScore: number;\n seq: number;\n addedAt: string;\n}\n\nexport interface NewsFeedMarketFeedItem {\n venueMarketId: string;\n question: string;\n venue: string;\n yesPrice: number;\n eventTitle: string;\n eventId: string;\n category: string;\n articleCount: number;\n articles: NewsFeedMarketFeedArticle[];\n}\n\nexport interface NewsFeedArticleFeedResponse {\n data: NewsFeedArticleFeedItem[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface NewsFeedMarketFeedResponse {\n data: NewsFeedMarketFeedItem[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface NewsFeedListResponse {\n feeds: Array<{\n id: string;\n name: string;\n itemCount: number;\n }>;\n}\n\nexport interface NewsFeedStatusResponse {\n articles: { total: number; today: number };\n feedItems: { total: number; today: number };\n perCategory: Array<{\n category: string;\n todayCount: number;\n dailyLimit: number;\n }>;\n config: {\n cronEnabled: boolean;\n itemsPerDay: number;\n batchSize: number;\n categories: string[];\n };\n}\n\n// ── Correlated Markets ──\n\nexport type CorrelatedMarketSide = \"yes\" | \"no\";\nexport type CorrelatedMarketSignalDirection = \"more_likely\" | \"less_likely\";\n\nexport interface CorrelatedMarketSignal {\n id: string;\n text: string;\n side: CorrelatedMarketSide;\n direction: CorrelatedMarketSignalDirection;\n domain: string;\n}\n\nexport interface CorrelatedMarketSignalBatch {\n id: string;\n venueMarketId: string;\n sourceModel: string;\n promptVersion: number;\n createdAt: string;\n signals: CorrelatedMarketSignal[];\n}\n\nexport interface CorrelatedMarketsStatus {\n markets: {\n total: number;\n processed: number;\n coverage: number;\n };\n signals: {\n total: number;\n withEmbeddings: number;\n missingEmbeddings: number;\n };\n eventTitleEmbeddings: {\n total: number;\n events: number;\n coverage: number;\n };\n config: {\n batchSize: number;\n jobsEnabled: boolean;\n backfillInterval: string;\n reembedInterval: string;\n eventEmbeddingInterval: string;\n };\n}\n\nexport interface CorrelatedMarketQueryResult {\n venueMarketId: string;\n marketQuestion: string;\n marketStatus: MarketStatus;\n marketStartDate: string;\n marketEndDate: string | null;\n eventTitle: string;\n eventStatus: MarketStatus;\n eventStartDate: string;\n eventEndDate: string | null;\n score: number;\n matchedSignal: CorrelatedMarketSignal;\n matchSource: \"signal\" | \"title_fallback\";\n venue: string;\n}\n\nexport interface CorrelatedMarketCascadeItem {\n venueEventId: string;\n eventTitle: string;\n eventStatus: MarketStatus;\n eventStartDate: string;\n eventEndDate: string | null;\n score: number;\n action: string;\n reason: string;\n reasonDomain: string;\n}\n\nexport interface CorrelatedMarketCascadeResponse {\n data: CorrelatedMarketCascadeItem[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface ResolveCorrelatedMarketsParams {\n venue?: string;\n externalId?: string;\n slug?: string;\n conditionId?: string;\n q?: string;\n side?: CorrelatedMarketSide;\n mode?: \"expand\" | \"hedge\";\n limit?: number;\n cursor?: string;\n includeResolved?: boolean;\n}\n\nexport type ResolveCorrelatedMarketsResponse =\n | ({\n market: { id: string; question: string };\n } & CorrelatedMarketCascadeResponse)\n | {\n market: { id: string; question: string };\n status: \"processing\";\n message: string;\n };\n\nexport interface ResolvedCorrelatedMarketsResponse extends CorrelatedMarketCascadeResponse {\n market: { id: string; question: string };\n}\n\n/** Display-first event navigation payload; market pages remain cursor paginated. */\nexport interface EventBootstrapResponse {\n detailsDeferred: true;\n event: VenueEvent;\n markets: PaginatedResponse<VenueMarket>;\n selectedOutcomeIds: string[];\n references: { historyManifestPath: \"/charts/history/manifest\"; liveChannel: \"orderbook\" };\n freshness: { assembledAt: number; marketStatus: \"open\" | null };\n}\n","import type {\n AuthUser,\n Category,\n PositionGroup,\n SyncBalancesResponse,\n UnifiedBalanceResponse,\n UpsertVenueKey,\n UpdateUserBody,\n UserHolding,\n UserProfile,\n VenueEvent,\n VenueMarket,\n VenueKeyStatus,\n VenueKeySummary,\n HostedVenueAccount,\n HostedVenueActivity,\n HostedVenueActivityQuery,\n HostedVenueDepositAddress,\n HostedVenueWithdrawal,\n HostedVenueWithdrawalRequest,\n ProvisionHostedVenueAccountBody,\n VerifyResponse,\n} from \"@agg/common/types-only\";\nimport {\n AccountProvider,\n AccountType,\n getWalletAddressFromUserProfile,\n MarketStatus,\n MatchStatus,\n Venue,\n} from \"@agg/common/types-only\";\nimport { parseRetryAfterHeader, parseRetryAfterSeconds } from \"./retry-after\";\nimport { readChartHistoryText } from \"./market-data/history-decoder\";\nimport { AggApiError } from \"./errors\";\nimport { toChecksumAddress } from \"./eip55\";\nimport {\n SELF_CUSTODY_FILL_TIMEOUT_MS,\n OPTIONAL_SIGNATURE_TIMEOUT_MS,\n OPTIONAL_FEE_SIGNATURE_TIMEOUT_MS,\n SELF_CUSTODY_POLL_INTERVAL_MS,\n TERMINAL_EXECUTION_STATES,\n} from \"./types\";\nimport {\n AggWebSocket,\n type AggWebSocketCallbacks,\n type BookWatchdogOptions,\n} from \"./agg-websocket\";\nimport type {\n SignatureRequest,\n AggAuthDeliveryMode,\n AggAuthVerifyBody,\n AggAuthStartBody,\n AggAuthStartResult,\n AggClientAuthOptions,\n AggLinkAccountBody,\n AggLinkAccountConfirmResult,\n AggLinkAccountResult,\n AggLinkAccountWalletConfirmBody,\n AggClientOptions,\n AggClientSessionInput,\n AppClientConfigResponse,\n RpcTokenResponse,\n VenueGeoPolicyResponse,\n AuthStatus,\n BatchMidpointsResponse,\n BatchOrderbooksResponse,\n BalanceRefillAttempt,\n BalanceRefillPolicy,\n CancelManagedExecutionResponse,\n CancelVenueOrderParams,\n ChartBarsResponse,\n ChartHistoryManifest,\n EventBootstrapResponse,\n ChartResolution,\n CorrelatedMarketCascadeResponse,\n CorrelatedMarketQueryResult,\n CorrelatedMarketsStatus,\n CorrelatedMarketSignalBatch,\n CreateBalanceRefillPolicyParams,\n CryptoReferencePricesResponse,\n CryptoReferencePriceTarget,\n DepositAddressesResponse,\n ExecuteManagedParams,\n ExecuteManagedResponse,\n ExecutionOrderItem,\n ExecutionOrdersQuery,\n ExecutionStatusQuery,\n ExecutionStatusResponse,\n UserActivityItem,\n UserActivityQuery,\n LeaderboardQuery,\n LeaderboardRow,\n LeaderboardSeries,\n LeaderboardSeriesQuery,\n ExecutionPositionGroup,\n ExecutionPositionsQuery,\n GetPositionsParams,\n GetCryptoReferencePricesOptions,\n ManagedBalancesParams,\n ListRecurringCryptoMarketsOptions,\n NewsFeedArticleFeedResponse,\n NewsFeedListResponse,\n NewsFeedMarketFeedResponse,\n NewsFeedMarketNewsParams,\n NewsFeedMarketNewsResponse,\n NewsFeedPageOptions,\n NewsFeedStatusResponse,\n OrderListQuery,\n OutcomeOrderbookResponse,\n PaginatedResponse,\n PaperTradingAccount,\n PaperTradingAccountListParams,\n PaperTradingAccountsPage,\n PaperTradingAppOptions,\n PaperTradingBalanceResponse,\n PaperTradingListParams,\n PaperTradingOrdersPage,\n PaperTradingOrder,\n PaperTradingPortfolio,\n PaperTradingPositionsPage,\n PlaceLimitOrderParams,\n CancelOrderSignature,\n PlaceLimitOrderResponse,\n PlaceOrderParams,\n PlaceOrderResponse,\n PlacePaperTradingOrderParams,\n PersistedAuthSnapshot,\n CreatePaperTradingAccountParams,\n RedeemRequest,\n RedeemResponse,\n ResetPaperTradingAccountParams,\n ResolveCorrelatedMarketsParams,\n ResolveCorrelatedMarketsResponse,\n SetPaperTradingBalanceParams,\n RampQuote,\n RampQuoteRequest,\n RampSessionRequest,\n RampWidgetSession,\n RecurringCryptoMarketsResponse,\n RecurrenceFilter,\n SearchParams,\n SearchResponse,\n SignerFn,\n SiweMessageParams,\n SiwsMessageParams,\n SmartRouteParams,\n SmartRouteResponse,\n SportsLiveResponse,\n TradeExecutorOrderListResponse,\n UpdateBalanceRefillPolicyParams,\n WithdrawManagedParams,\n WithdrawManagedResponse,\n WithdrawalQuoteParams,\n WithdrawalQuoteResponse,\n WithdrawPreviewParams,\n WithdrawPreviewResponse,\n} from \"./types\";\n\ntype AuthStateListener = (authenticated: boolean) => void;\ntype UserAuthResult = { accessToken: string; refreshToken?: string; user: UserProfile };\nconst COOKIE_REFRESH_DELIVERY = \"cookie-refresh\";\nconst DEFAULT_MIDPOINT_IDS_PER_REQUEST = 75;\nconst MAX_MIDPOINT_IDS_PER_REQUEST = 75;\nconst MAX_SPORTS_EVENT_IDS_PER_REQUEST = 25;\n\n/**\n * Bounds on the `pollAfterMs` the server hands back on a non-terminal\n * `/execution/status` response. It is server-supplied and drives a loop, so it\n * is clamped rather than trusted.\n *\n * Floor 250ms: a 0 — from a server bug, or a future backoff scheme that means\n * \"immediately\" — would turn this into a busy-loop hammering `/execution/status`\n * for the whole 5-minute budget.\n *\n * Ceiling 30s: the loop is bounded by `SELF_CUSTODY_FILL_TIMEOUT_MS` (5 min).\n * A longer sleep would leave a parked signature undiscovered for most of that\n * budget; 30s still buys at least ten looks before the deadline.\n */\nconst MIN_POLL_INTERVAL_MS = 250;\nconst MAX_POLL_INTERVAL_MS = 30_000;\n/** Step id prefix of a Polymarket order signature request (`poly-sign-<orderId>`). */\nconst PM_ORDER_SIGNATURE_STEP_PREFIX = \"poly-sign-\";\n\nconst isUserProfile = (user: AuthUser | UserProfile): user is UserProfile => {\n return \"accounts\" in user && \"wallets\" in user && \"avatarUrl\" in user;\n};\n\nconst createPersistedHintUserProfile = (input: {\n id: string;\n username: string | null;\n avatarUrl: string | null;\n walletAddress?: string | null;\n}): UserProfile => {\n const normalizedWalletAddress =\n typeof input.walletAddress === \"string\" && input.walletAddress.trim().length > 0\n ? input.walletAddress\n : null;\n\n return {\n id: input.id,\n username: input.username,\n avatarUrl: input.avatarUrl,\n externalId: null,\n isLocationBlocked: false,\n accounts: normalizedWalletAddress\n ? [\n {\n type: AccountType.siwe,\n provider: AccountProvider.wallet,\n providerAccountId: normalizedWalletAddress,\n },\n ]\n : [],\n wallets: [],\n venueAccounts: [],\n };\n};\n\nconst normalizeSessionUser = (\n user: AuthUser | UserProfile | undefined,\n currentUser: UserProfile | undefined,\n): UserProfile | undefined => {\n if (!user) return undefined;\n if (isUserProfile(user)) return user;\n if (currentUser?.id === user.id) return currentUser;\n\n return createPersistedHintUserProfile({\n id: user.id,\n username: null,\n avatarUrl: null,\n walletAddress: null,\n });\n};\n\nconst resolveMidpointIdsPerRequest = (value: number | undefined): number => {\n if (value == null || !Number.isFinite(value)) return DEFAULT_MIDPOINT_IDS_PER_REQUEST;\n return Math.min(MAX_MIDPOINT_IDS_PER_REQUEST, Math.max(1, Math.floor(value)));\n};\n\nconst chunkArray = <T>(items: T[], size: number): T[][] => {\n const chunks: T[][] = [];\n for (let index = 0; index < items.length; index += size) {\n chunks.push(items.slice(index, index + size));\n }\n return chunks;\n};\n\nconst normalizeRequestedVenueMarketIds = (venueMarketIds: string[]): string[] => {\n const normalizedIds: string[] = [];\n const seenIds = new Set<string>();\n\n for (const venueMarketId of venueMarketIds) {\n const normalizedVenueMarketId = venueMarketId.trim();\n if (!normalizedVenueMarketId || seenIds.has(normalizedVenueMarketId)) continue;\n\n seenIds.add(normalizedVenueMarketId);\n normalizedIds.push(normalizedVenueMarketId);\n }\n\n return normalizedIds;\n};\n\nconst mapChartResolution = (resolution?: ChartResolution): \"1\" | \"5\" | \"60\" | \"1D\" | undefined => {\n switch (resolution) {\n case undefined:\n return undefined;\n case \"1m\":\n return \"1\";\n case \"5m\":\n return \"5\";\n case \"1h\":\n return \"60\";\n case \"1d\":\n return \"1D\";\n }\n};\n\n/** Paths that handle their own auth flow and should never trigger automatic 401 retry. */\nconst AUTH_PATHS = new Set([\n \"/auth/start\",\n \"/auth/verify\",\n \"/auth/token/refresh\",\n \"/auth/token/exchange\",\n \"/auth/sign-out\",\n]);\n\n/** Rejects after `ms`; a late settlement of `p` is ignored. */\nfunction withTimeout<T>(p: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);\n p.then(\n (v) => {\n clearTimeout(timer);\n resolve(v);\n },\n (e) => {\n clearTimeout(timer);\n reject(e);\n },\n );\n });\n}\n\nexport class AggClient {\n private _appId?: string;\n private adminKey?: string;\n private apiKey?: string;\n private baseUrl: string;\n private accessToken?: string;\n /** Identity verified for the current token, when supplied with the session/profile. */\n private accessTokenUserId?: string;\n private refreshTokenValue?: string;\n private currentUser?: UserProfile;\n private listeners: Set<AuthStateListener> = new Set();\n private readonly webSocketAuthCleanups = new Set<() => void>();\n private storageKey: string;\n private shouldPersistSession: boolean;\n private authDelivery: AggAuthDeliveryMode;\n private wsUrl?: string;\n readonly preferImmutableHistory: boolean;\n private readonly webSocketFactory?: AggClientOptions[\"webSocketFactory\"];\n private _authStatus: AuthStatus = \"unauthenticated\";\n private authChannel: BroadcastChannel | null = null;\n private authOptions?: AggClientAuthOptions;\n /** In-flight refresh promise — serializes concurrent 401 retries so only one refresh runs. */\n private pendingRefresh: Promise<string> | null = null;\n /** Partner-supplied signature callback for self-custodial fills. The SDK never sees a key. */\n private readonly signer?: SignerFn;\n\n constructor(options: AggClientOptions) {\n if (!options.appId && !options.adminKey) {\n throw new Error(\"AggClient requires at least one of appId or adminKey\");\n }\n this._appId = options.appId;\n this.adminKey = options.adminKey;\n this.apiKey = options.apiKey;\n this.signer = options.signer;\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.wsUrl = options.wsUrl;\n this.preferImmutableHistory = options.preferImmutableHistory ?? false;\n this.webSocketFactory = options.webSocketFactory;\n this.authOptions = options.auth;\n this.storageKey = `agg_auth_${this._appId ?? \"default\"}`;\n this.authDelivery = options.authDelivery ?? \"body\";\n this.shouldPersistSession = options.persistSession !== false;\n this.restoreSession();\n this.initAuthChannel();\n }\n\n private resolvePaperTradingAppId(appId?: string): string {\n const resolvedAppId = appId ?? this._appId;\n if (!resolvedAppId) {\n throw new Error(\n \"Paper trading account methods require appId in client options or method options\",\n );\n }\n return encodeURIComponent(resolvedAppId);\n }\n\n private paperTradingAccountsPath(appId?: string): string {\n return `/apps/${this.resolvePaperTradingAppId(appId)}/paper-trading/accounts`;\n }\n\n private paperTradingAccountPath(accountId: string, appId?: string): string {\n return `${this.paperTradingAccountsPath(appId)}/${encodeURIComponent(accountId)}`;\n }\n\n private paperTradingListQuery(\n params: PaperTradingListParams = {},\n ): Record<string, string> | undefined {\n const query: Record<string, string> = {};\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n return Object.keys(query).length ? query : undefined;\n }\n\n private paperTradingAccountListQuery(\n params: PaperTradingAccountListParams = {},\n ): Record<string, string> | undefined {\n const query = this.paperTradingListQuery(params) ?? {};\n if (params.externalId) query.externalId = params.externalId;\n return Object.keys(query).length ? query : undefined;\n }\n\n private withAuthPayload<T extends { earlyAccessCode?: string }>(payload: T): T {\n if (typeof payload.earlyAccessCode === \"string\" && payload.earlyAccessCode.trim().length > 0) {\n return payload;\n }\n\n const earlyAccessCode = this.authOptions?.getEarlyAccessCode?.()?.trim();\n if (!earlyAccessCode) {\n return payload;\n }\n\n return {\n ...payload,\n earlyAccessCode,\n };\n }\n\n // --- Session persistence (tokens are NEVER persisted — only a sanitized UI hint) ---\n\n private restoreSession(): void {\n if (!this.shouldPersistSession || typeof globalThis.localStorage === \"undefined\") return;\n try {\n const raw = localStorage.getItem(this.storageKey);\n if (!raw) return;\n const data = JSON.parse(raw) as Record<string, unknown>;\n\n // Discard any legacy format that contained tokens.\n if (\"accessToken\" in data) {\n localStorage.removeItem(this.storageKey);\n return;\n }\n\n // Current format: PersistedAuthSnapshot.\n const snapshot = data as unknown as PersistedAuthSnapshot;\n if (snapshot.authHint?.wasAuthenticated && snapshot.user?.id) {\n this.currentUser = createPersistedHintUserProfile({\n id: snapshot.user.id,\n username: snapshot.user.username,\n avatarUrl: snapshot.user.avatarUrl,\n walletAddress: snapshot.user.walletAddress ?? null,\n });\n this._authStatus = \"unknown\";\n }\n } catch {\n localStorage.removeItem(this.storageKey);\n }\n }\n\n private persistSession(): void {\n if (!this.shouldPersistSession || typeof globalThis.localStorage === \"undefined\") return;\n if (this.accessToken && this.currentUser) {\n const snapshot: PersistedAuthSnapshot = {\n user: {\n id: this.currentUser.id,\n username: this.currentUser.username,\n avatarUrl: this.currentUser.avatarUrl,\n walletAddress: getWalletAddressFromUserProfile(this.currentUser) ?? null,\n },\n authHint: { wasAuthenticated: true },\n };\n localStorage.setItem(this.storageKey, JSON.stringify(snapshot));\n } else {\n localStorage.removeItem(this.storageKey);\n }\n }\n\n // --- Cross-tab auth sync via BroadcastChannel ---\n\n private initAuthChannel(): void {\n if (typeof globalThis.BroadcastChannel === \"undefined\") return;\n try {\n this.authChannel = new BroadcastChannel(`agg_auth_${this._appId ?? \"default\"}`);\n this.authChannel.onmessage = (event: MessageEvent) => {\n const { type } = event.data ?? {};\n if (type === \"logout\") {\n this.accessToken = undefined;\n this.accessTokenUserId = undefined;\n this.refreshTokenValue = undefined;\n this.currentUser = undefined;\n this._authStatus = \"unauthenticated\";\n this.persistSession();\n this.notifyListeners();\n } else if (type === \"login\") {\n // Another tab signed in — attempt silent refresh so this tab picks up\n // the session. Works in cookie-refresh mode (cookie is shared across tabs).\n // In body mode this will fail gracefully (no refresh token available).\n this.refreshAccessToken()\n .then(() => this.getCurrentUser())\n .catch(() => {\n // Silent failure — user can manually refresh or sign in.\n });\n }\n };\n } catch {\n this.authChannel = null;\n }\n }\n\n /** Release resources (BroadcastChannel, etc.). Safe to call multiple times. */\n destroy(): void {\n this.authChannel?.close();\n this.authChannel = null;\n for (const cleanup of this.webSocketAuthCleanups) cleanup();\n }\n\n // --- Core HTTP helper ---\n\n /**\n * Generic HTTP method with automatic header injection and 401 retry.\n * Attaches `x-app-id`, `Authorization: Bearer`, and `x-admin-key` headers as appropriate.\n * On 401, attempts a single token refresh and retries the request.\n * @param path - API path (e.g. `/venue-events`)\n * @param init - Fetch init options, plus optional `query` object for URL search params\n */\n public async request<T>(\n path: string,\n init?: RequestInit & { query?: Record<string, string | string[]> },\n decode?: (response: Response) => Promise<T>,\n ): Promise<T> {\n const response = await this.rawFetch(path, init);\n\n // On 401 for non-auth endpoints, attempt a single token refresh + retry.\n if (response.status === 401 && this.accessToken && !AUTH_PATHS.has(path)) {\n try {\n await this.refreshWithDedup();\n // Retry the original request with the new token.\n const retryResponse = await this.rawFetch(path, init);\n if (!retryResponse.ok) {\n return this.throwResponseError(retryResponse);\n }\n if (retryResponse.status === 204) return undefined as T;\n return decode ? decode(retryResponse) : (retryResponse.json() as Promise<T>);\n } catch {\n // Refresh failed — sign out and throw the original 401.\n this.clearAccessToken();\n return this.throwResponseError(response);\n }\n }\n\n if (!response.ok) {\n return this.throwResponseError(response);\n }\n\n if (response.status === 204) return undefined as T;\n return decode ? decode(response) : (response.json() as Promise<T>);\n }\n\n private async rawFetch(\n path: string,\n init?: RequestInit & { query?: Record<string, string | string[]> },\n ): Promise<Response> {\n const headers: Record<string, string> =\n init?.body != null ? { \"Content-Type\": \"application/json\" } : {};\n\n if (this._appId) {\n headers[\"x-app-id\"] = this._appId;\n }\n if (this.adminKey) {\n headers[\"x-admin-key\"] = this.adminKey;\n }\n if (this.apiKey) {\n headers[\"x-app-api-key\"] = this.apiKey;\n }\n if (this.accessToken) {\n headers[\"authorization\"] = `Bearer ${this.accessToken}`;\n }\n\n const url = new URL(`${this.baseUrl}${path}`);\n if (init?.query) {\n for (const [key, value] of Object.entries(init.query)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n v !== undefined && url.searchParams.append(key, v?.toString());\n }\n } else {\n value !== undefined && url.searchParams.set(key, value?.toString());\n }\n }\n }\n\n return fetch(url, {\n ...init,\n headers: {\n ...headers,\n ...init?.headers,\n },\n });\n }\n\n private async throwResponseError(response: Response): Promise<never> {\n let message =\n response.status === 404\n ? \"Market not found\"\n : `AGG API error: ${response.status} ${response.statusText}`;\n let code: string | undefined;\n let retryable: boolean | undefined;\n let retryAfterMs = parseRetryAfterHeader(response.headers?.get(\"Retry-After\"));\n let errors: { field: string; message: string }[] | undefined;\n\n try {\n const body = (await response.json()) as {\n message?: string;\n code?: string;\n retryable?: boolean;\n retryAfter?: unknown;\n errors?: { field?: unknown; message?: unknown }[];\n };\n retryAfterMs ??= parseRetryAfterSeconds(body?.retryAfter);\n if (typeof body.message === \"string\" && body.message.length > 0) {\n message = body.message;\n }\n if (typeof body.code === \"string\" && body.code.length > 0) {\n code = body.code;\n }\n if (typeof body.retryable === \"boolean\") {\n retryable = body.retryable;\n }\n if (Array.isArray(body.errors)) {\n const parsed = body.errors\n .map((e) => ({\n field: typeof e?.field === \"string\" ? e.field : \"\",\n message: typeof e?.message === \"string\" ? e.message : \"\",\n }))\n .filter((e) => e.message.length > 0);\n if (parsed.length > 0) errors = parsed;\n }\n } catch {\n // Best-effort parse only — fall back to the status text message above.\n }\n\n throw new AggApiError(message, response.status, { code, retryable, retryAfterMs, errors });\n }\n\n /**\n * Deduplicates concurrent refresh attempts — if multiple requests hit 401 at the same time,\n * only one refresh call is made and the rest wait for it.\n */\n private refreshWithDedup(): Promise<string> {\n if (!this.pendingRefresh) {\n this.pendingRefresh = this.refreshAccessToken().finally(() => {\n this.pendingRefresh = null;\n });\n }\n return this.pendingRefresh;\n }\n\n private buildAuthRequestInit(\n init: RequestInit,\n options?: { includeDeliveryHeader?: boolean },\n ): RequestInit {\n if (this.authDelivery !== COOKIE_REFRESH_DELIVERY) {\n return init;\n }\n\n const headers = {\n ...(init.headers as Record<string, string> | undefined),\n };\n\n if (options?.includeDeliveryHeader !== false) {\n headers[\"x-auth-delivery\"] = COOKIE_REFRESH_DELIVERY;\n }\n\n return {\n ...init,\n credentials: \"include\",\n headers,\n };\n }\n\n private buildUserAuthResult(response: VerifyResponse, user: UserProfile): UserAuthResult {\n return response.refreshToken === undefined\n ? { accessToken: response.accessToken, user }\n : {\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n user,\n };\n }\n\n private async performSignOutRequest(): Promise<void> {\n await this.request(\n \"/auth/sign-out\",\n this.buildAuthRequestInit({ method: \"POST\", body: \"{}\" }, { includeDeliveryHeader: false }),\n );\n }\n\n // --- Auth & session state ---\n /** Set the user access token (for future user-tier auth). */\n setAccessToken(token: string): void {\n if (this.accessToken !== token) this.accessTokenUserId = undefined;\n this.accessToken = token;\n this._authStatus = \"authenticated\";\n this.persistSession();\n this.notifyListeners();\n }\n\n /** Set the current auth session tokens and optionally seed the user profile. */\n setSession(session: AggClientSessionInput): void {\n const wasAuthenticated = this.isAuthenticated;\n this.accessTokenUserId =\n session.user?.id ??\n (this.accessToken === session.accessToken ? this.accessTokenUserId : undefined);\n this.accessToken = session.accessToken;\n\n if (\"refreshToken\" in session) {\n this.refreshTokenValue = session.refreshToken;\n }\n\n if (session.user !== undefined) {\n this.currentUser = normalizeSessionUser(session.user, this.currentUser);\n }\n\n this._authStatus = \"authenticated\";\n this.persistSession();\n this.notifyListeners();\n\n if (!wasAuthenticated) {\n this.broadcastAuth(\"login\");\n }\n }\n\n /** Clear the user access token, refresh token, and user info. Broadcasts cross-tab logout. */\n clearAccessToken(): void {\n this.accessToken = undefined;\n this.accessTokenUserId = undefined;\n this.refreshTokenValue = undefined;\n this.currentUser = undefined;\n this._authStatus = \"unauthenticated\";\n this.persistSession();\n this.notifyListeners();\n this.broadcastAuth(\"logout\");\n }\n\n private broadcastAuth(type: \"login\" | \"logout\"): void {\n try {\n this.authChannel?.postMessage({ type });\n } catch {\n // Channel may be closed or unavailable.\n }\n }\n\n /**\n * The App this client speaks for, or `undefined` for an admin-key-only\n * client. Exposed so callers can scope per-app caches by it — app config is\n * app-scoped data, and two clients sharing one cache must not share entries.\n */\n get appId(): string | undefined {\n return this._appId;\n }\n\n /** Current auth lifecycle status. */\n get authStatus(): AuthStatus {\n return this._authStatus;\n }\n\n /** Whether a user access token is currently set. */\n get isAuthenticated(): boolean {\n return !!this.accessToken;\n }\n\n /** Primary wallet address derived from the current user profile. */\n get address(): string | undefined {\n return getWalletAddressFromUserProfile(this.currentUser);\n }\n\n /** Subscribe to auth state changes. Returns an unsubscribe function. */\n onAuthStateChange(listener: AuthStateListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notifyListeners(): void {\n const authenticated = this.isAuthenticated;\n for (const listener of Array.from(this.listeners)) {\n listener(authenticated);\n }\n }\n\n /** Get the currently authenticated user, if any. */\n get user(): UserProfile | undefined {\n return this.currentUser;\n }\n\n // --- SIWE auth ---\n\n /**\n * Build an EIP-4361 SIWE message string.\n *\n * `params.address` is accepted in any casing. EIP-4361 requires the address\n * line to be EIP-55 checksummed, and wallets commonly return a lowercase one\n * — `eth_requestAccounts` does — so the checksum is applied here, the way\n * viem, ethers and `siwe` do inside their own message builders. An address\n * that is not 20 bytes of hex throws: no message we could build from it\n * would verify.\n */\n buildSiweMessage(params: SiweMessageParams): string {\n const chainId = params.chainId ?? 1;\n const issuedAt = params.issuedAt ?? new Date().toISOString();\n const address = toChecksumAddress(params.address);\n\n let message = `${params.domain} wants you to sign in with your Ethereum account:\\n${address}`;\n\n // EIP-4361 keeps the statement SLOT even when there is no statement: the\n // ABNF is `address LF LF [statement] LF LF`, so a statement-less message\n // still carries the blank line. Emitting `address LF LF URI:` produces a\n // message no conforming parser accepts — and because the API maps every\n // parse failure onto the same 401, it surfaces as \"Invalid SIWE signature\",\n // pointing the partner at their signature rather than at the message.\n message += params.statement ? `\\n\\n${params.statement}` : \"\\n\";\n\n message += `\\n\\nURI: ${params.uri}\\nVersion: 1\\nChain ID: ${chainId}\\nNonce: ${params.nonce}\\nIssued At: ${issuedAt}`;\n\n return message;\n }\n\n /** Build a SIWS message string for Solana wallet sign-in (pure formatting, no crypto). */\n buildSiwsMessage(params: SiwsMessageParams): string {\n const chainId = params.chainId ?? \"mainnet\";\n const issuedAt = params.issuedAt ?? new Date().toISOString();\n\n let message = `${params.domain} wants you to sign in with your Solana account:\\n${params.address}`;\n\n if (params.statement) {\n message += `\\n\\n${params.statement}`;\n }\n\n message += `\\n\\nURI: ${params.uri}\\nVersion: 1\\nChain ID: ${chainId}\\nNonce: ${params.nonce}\\nIssued At: ${issuedAt}`;\n\n return message;\n }\n\n /** Verify a SIWE/SIWS signature or a Privy access token with the API, store the token + user. */\n async verify(args: AggAuthVerifyBody): Promise<UserAuthResult> {\n const res = await this.request<VerifyResponse>(\n \"/auth/verify\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify(this.withAuthPayload(args)),\n }),\n );\n\n this.setSession({\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n user: res.user,\n });\n\n try {\n const user = await this.getCurrentUser();\n return this.buildUserAuthResult(res, user);\n } catch (error) {\n this.clearAccessToken();\n throw error;\n }\n }\n\n /** Backwards-compatible alias for `verify()`. */\n async verifySignIn(args: AggAuthVerifyBody): Promise<UserAuthResult> {\n return this.verify(args);\n }\n\n /** Initiate an auth flow (SIWE nonce, OAuth redirect URL, or magic link). */\n async authStart(body: AggAuthStartBody): Promise<AggAuthStartResult> {\n // `credentials: \"include\"` lets the browser accept the signin-proof cookie the\n // server sets for OAuth flows. Without it the cookie is dropped on cross-origin\n // responses and the OAuth callback would reject the state as unbound.\n return this.request(\"/auth/start\", {\n method: \"POST\",\n body: JSON.stringify(this.withAuthPayload(body)),\n credentials: \"include\",\n });\n }\n\n /** Backwards-compatible alias for `authStart()`. */\n async startAuth(body: AggAuthStartBody): Promise<AggAuthStartResult> {\n return this.authStart(body);\n }\n\n /**\n * Start an account-link flow. Requires the caller to already be signed in — sends\n * the bearer automatically. Response shape:\n * - OAuth providers → `{ type: \"redirect\", url }`; redirect the browser to `url`.\n * - Email → `{ type: \"magic_link\", success: true }`; check the destination inbox.\n * - Wallet providers (siwe/siws) → `{ type: \"wallet_challenge\", message }`; have the\n * user sign `message` VERBATIM, then submit it to `linkAccountConfirm()` as\n * `{ kind: \"wallet_signature\", message, signature }`.\n *\n * After the OAuth/email callback runs, the browser lands back on the app's `redirectUrl`\n * with a `link_confirm_token` query param. Feed that token to `linkAccountConfirm()`\n * to persist the Account row.\n */\n async linkAccount(body: AggLinkAccountBody): Promise<AggLinkAccountResult> {\n // `credentials: \"include\"` so the browser stores the same-origin link-proof\n // cookie the server sets on this response (mirrors authStart). Without it the\n // cookie is dropped on a cross-origin response and the OAuth link callback\n // rejects with `link_proof_invalid`, so the link never completes.\n return this.request(\n \"/users/me/link-account/start\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify(body),\n credentials: \"include\",\n }),\n );\n }\n\n /**\n * Finalize an account link.\n *\n * - Pass a `link_confirm_token` string (OAuth/email) to exchange it for a linked\n * `Account` row.\n * - Pass `{ kind: \"wallet_signature\", message, signature }` (wallet providers) to\n * verify the signature over the `wallet_challenge` `message` returned by\n * `linkAccount()`.\n *\n * The server matches the current bearer's `principalId` to the challenge/token's\n * `principalId` before writing — this is the final ownership check. A wallet already\n * linked to a DIFFERENT principal rejects with HTTP 409.\n */\n async linkAccountConfirm(\n input: string | AggLinkAccountWalletConfirmBody,\n ): Promise<AggLinkAccountConfirmResult> {\n // Confirm runs on the OAuth redirect-return page, where the in-memory access\n // token was wiped by the full-page reload (tokens are never persisted). Without\n // a bearer the user-tier guard 401s, and request()'s 401-refresh-retry is gated\n // on an existing token so it can't recover. Mint one from the refresh\n // cookie/token first (deduped, coalescing with any in-flight refresh). If the\n // session is genuinely gone the refresh throws and the caller surfaces it.\n if (!this.accessToken) {\n await this.refreshWithDedup();\n }\n const body = typeof input === \"string\" ? { token: input } : input;\n return this.request(\n \"/users/me/link-account/confirm\",\n this.buildAuthRequestInit({ method: \"POST\", body: JSON.stringify(body) }),\n );\n }\n\n /** Exchange a one-time auth code (from OAuth/magic-link callback) for tokens. */\n async exchangeAuthCode(code: string): Promise<UserAuthResult> {\n const res = await this.request<VerifyResponse>(\n \"/auth/token/exchange\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify({ code }),\n }),\n );\n\n this.setSession({\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n user: res.user,\n });\n\n try {\n const user = await this.getCurrentUser();\n return this.buildUserAuthResult(res, user);\n } catch (error) {\n this.clearAccessToken();\n throw error;\n }\n }\n\n /** Refresh the access token using the stored refresh token. */\n async refreshAccessToken(): Promise<string> {\n if (this.authDelivery !== COOKIE_REFRESH_DELIVERY && !this.refreshTokenValue) {\n throw new Error(\"No refresh token available\");\n }\n const res = await this.request<VerifyResponse>(\n \"/auth/token/refresh\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify(\n this.authDelivery === COOKIE_REFRESH_DELIVERY\n ? {}\n : { refreshToken: this.refreshTokenValue },\n ),\n }),\n );\n\n this.setSession({\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n user: res.user,\n });\n return res.accessToken;\n }\n\n /** Get the current user's profile. */\n async getCurrentUser(): Promise<UserProfile> {\n const user = await this.request<UserProfile>(\"/users/me\");\n this.currentUser = user;\n this.accessTokenUserId = user.id;\n this.persistSession();\n this.notifyListeners();\n return user;\n }\n\n /** Update the current user (e.g. username). Requires currentUser.id; call getCurrentUser() first if needed. */\n async updateUser(data: UpdateUserBody): Promise<UserProfile> {\n if (!this.currentUser?.id) {\n const profile = await this.getCurrentUser();\n if (!profile?.id) throw new Error(\"Not authenticated\");\n }\n const profile = await this.request<UserProfile>(\"/users/me\", {\n method: \"PATCH\",\n body: JSON.stringify(data),\n });\n this.currentUser = profile;\n this.persistSession();\n this.notifyListeners();\n return profile;\n }\n\n /** Link a partner-provided external user ID assertion to the current user. */\n async linkExternalId(params: {\n externalId: string;\n timestamp: number;\n hmac: string;\n }): Promise<UserProfile> {\n const profile = await this.request<UserProfile>(\"/users/me/external-id\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n this.currentUser = profile;\n this.persistSession();\n this.notifyListeners();\n return profile;\n }\n\n /** Create a presigned avatar upload URL for the current user. */\n async createAvatarUploadUrl(contentType: string): Promise<{\n uploadUrl: string;\n assetKey: string;\n cdnUrl: string;\n }> {\n return this.request<{ uploadUrl: string; assetKey: string; cdnUrl: string }>(\n \"/users/me/avatar\",\n {\n method: \"POST\",\n body: JSON.stringify({ contentType }),\n },\n );\n }\n\n /** Disconnect a linked auth provider from the current user. */\n async disconnectAccount(\n provider: \"wallet\" | \"solana_wallet\" | \"google\" | \"twitter\" | \"apple\" | \"email\",\n ): Promise<{ success: true }> {\n return this.request<{ success: true }>(`/users/me/accounts/${provider}`, {\n method: \"DELETE\",\n body: JSON.stringify({}),\n });\n }\n\n /** Sign out — revoke all tokens server-side and clear local session. */\n async signOut(): Promise<void> {\n if (this.accessToken) {\n try {\n await this.performSignOutRequest();\n } catch (error) {\n if (\n this.authDelivery === COOKIE_REFRESH_DELIVERY &&\n (error as { status?: number }).status === 401\n ) {\n try {\n await this.refreshAccessToken();\n await this.performSignOutRequest();\n } catch {\n // Best-effort: clear local session regardless\n }\n }\n // Ignore non-401 and non-cookie-mode failures. Local cleanup happens below even if the\n // remote revoke request fails.\n }\n }\n this.refreshTokenValue = undefined;\n this.clearAccessToken();\n }\n\n /** Get user holdings (positions) for a venue. Uses backend to resolve venue-specific identifiers. */\n async getUserHoldings(params: {\n venue: Venue;\n venueMarketId?: string;\n venueEventId?: string;\n cursor?: string;\n }): Promise<PaginatedResponse<UserHolding>> {\n const { venue, venueMarketId, venueEventId, cursor } = params;\n const query: Record<string, string> = { venue };\n if (venueMarketId != null) query.venueMarketId = venueMarketId;\n if (venueEventId != null) query.venueEventId = venueEventId;\n if (cursor != null) query.cursor = cursor;\n return this.request<PaginatedResponse<UserHolding>>(\"/trading/holdings\", {\n query,\n });\n }\n\n /** List trade-executor orders for the authenticated user. */\n async getOrders(params: OrderListQuery = {}): Promise<TradeExecutorOrderListResponse> {\n const query: Record<string, string> = {};\n if (params.userId) query.userId = params.userId;\n if (params.status) query.status = params.status;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.offset != null) query.offset = String(params.offset);\n\n return this.request<TradeExecutorOrderListResponse>(\"/orders\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * List execution orders for the authenticated user (cursor pagination).\n *\n * Pass `quoteId` to fetch every leg of a multi-venue split route in\n * one call — `useQuoteSummary(quoteId)` reduces the list into a\n * rollup (total cost, share-weighted avg price, to-win). Pass\n * `venueMarketIds` to narrow to the orders on those markets. Sent as\n * repeated params in one request; batch long lists yourself (or use\n * `useExecutionOrdersForMarkets`) to keep the URL short.\n */\n async getExecutionOrders(\n params: ExecutionOrdersQuery = {},\n ): Promise<PaginatedResponse<ExecutionOrderItem>> {\n const query: Record<string, string | string[]> = {};\n if (params.orderId) query.orderId = params.orderId;\n if (params.quoteId) query.quoteId = params.quoteId;\n if (params.externalId) query.externalId = params.externalId;\n if (params.clientOrderId) query.clientOrderId = params.clientOrderId;\n if (params.venueMarketIds?.length) query.venueMarketIds = params.venueMarketIds;\n if (params.status) query.status = params.status;\n if (params.orderType) query.orderType = params.orderType;\n if (params.mode) query.mode = params.mode;\n if (params.cursor) query.cursor = params.cursor;\n if (params.limit != null) query.limit = String(params.limit);\n\n return this.request<PaginatedResponse<ExecutionOrderItem>>(\"/execution/orders\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * Get quote-scoped execution progress, DAG step state, and order leg\n * terminal status. Also carries `pendingSignatures` — this is the route\n * `fillSelfCustody` polls while an on-chain step is in flight, so a caller\n * already polling this for progress learns about newly-parked steps here\n * too, not just from the signatures endpoint.\n */\n async getExecutionStatus(params: ExecutionStatusQuery): Promise<ExecutionStatusResponse> {\n const query: Record<string, string> = { quoteId: params.quoteId };\n if (params.mode) query.mode = params.mode;\n\n return this.request<ExecutionStatusResponse>(\"/execution/status\", { query });\n }\n\n /** Unified user activity feed (trades, deposits, withdrawals, bridges, wallet ops). */\n async getUserActivity(\n params: UserActivityQuery = {},\n ): Promise<PaginatedResponse<UserActivityItem>> {\n const query: Record<string, string> = {};\n if (params.type) query.type = params.type;\n if (params.cursor) query.cursor = params.cursor;\n if (params.limit != null) query.limit = String(params.limit);\n\n return this.request<PaginatedResponse<UserActivityItem>>(\"/users/activity\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * Per-app trader leaderboard ranked by realized P&L or volume over an\n * inclusive UTC day range. `rank` is exact within the top 100.\n */\n async getLeaderboard(params: LeaderboardQuery = {}): Promise<PaginatedResponse<LeaderboardRow>> {\n const query: Record<string, string | string[]> = {};\n for (const key of [\n \"from\",\n \"to\",\n \"metric\",\n \"cursor\",\n \"userId\",\n \"externalId\",\n \"username\",\n \"walletAddress\",\n ] as const) {\n const value = params[key];\n if (value) query[key] = value;\n }\n if (params.limit != null) query.limit = String(params.limit);\n for (const key of [\"categoryIds\", \"venueEventIds\", \"userIds\"] as const) {\n const value = params[key];\n if (value?.length) query[key] = value;\n }\n return this.request<PaginatedResponse<LeaderboardRow>>(\"/leaderboard\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * One user's (or, with no user, the whole app's) leaderboard stats per UTC\n * day (default the last 30 days, at most 366) with a running cumulative\n * realized P&L, optionally for a single category. Gross of fees;\n * unrealized P&L is not included.\n */\n async getLeaderboardSeries(params: LeaderboardSeriesQuery): Promise<LeaderboardSeries> {\n const query: Record<string, string | string[]> = {};\n for (const key of [\n \"from\",\n \"to\",\n \"userId\",\n \"externalId\",\n \"username\",\n \"walletAddress\",\n ] as const) {\n const value = params[key];\n if (value) query[key] = value;\n }\n if (params.categoryIds?.length) query.categoryIds = params.categoryIds;\n return this.request<LeaderboardSeries>(\"/leaderboard/series\", { query });\n }\n\n /** List execution positions for the authenticated user (cursor pagination). */\n async getExecutionPositions(\n params: ExecutionPositionsQuery = {},\n ): Promise<PaginatedResponse<ExecutionPositionGroup>> {\n const query: Record<string, string | string[]> = {};\n if (params.cursor) query.cursor = params.cursor;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.status) query.status = params.status;\n if (params.mode) query.mode = params.mode;\n if (params.categoryIds?.length) query.categoryIds = params.categoryIds;\n if (params.sort) query.sort = params.sort;\n\n return this.request<PaginatedResponse<ExecutionPositionGroup>>(\"/execution/positions\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * Get cash balances and per-venue position balances.\n *\n * `custody: \"self\"` returns the wallets linked to this account — plus their\n * Polymarket deposit and legacy wallets — instead of the managed wallet. Each\n * chain row then carries `address` and `custodyKind`; `positions` is\n * account-wide either way.\n *\n * Caveat on the headline number: a chain row with `custodyKind:\n * \"POLYMARKET_LEGACY\"` and `legacyKind: \"proxy\"` holds funds that can only\n * be spent on Polymarket, but it still counts towards its token's\n * `totalRaw`/`availableRaw` (a token's totals are always the sum of its\n * chain rows). If you show \"spendable anywhere\", subtract those rows.\n */\n async getManagedBalances(params: ManagedBalancesParams = {}): Promise<UnifiedBalanceResponse> {\n const query: Record<string, string> = {};\n if (params.mode) query.mode = params.mode;\n if (params.custody) query.custody = params.custody;\n return this.request<UnifiedBalanceResponse>(\"/execution/balances\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /** Read hosted custody status without creating a signing wallet or account. */\n async getHostedVenueAccount(\n venue: \"betdex\",\n params: ManagedBalancesParams = {},\n ): Promise<HostedVenueAccount> {\n return this.request<HostedVenueAccount>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}`,\n {\n query: params.mode ? { mode: params.mode } : undefined,\n },\n );\n }\n\n /** Owned exact ledger entries; not balances, fill fees or withdrawal finality. */\n async getHostedVenueActivity(\n venue: \"betdex\",\n params: HostedVenueActivityQuery = {},\n ): Promise<HostedVenueActivity> {\n return this.request<HostedVenueActivity>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/activity`,\n {\n query: {\n ...(params.mode ? { mode: params.mode } : {}),\n ...(params.page !== undefined ? { page: String(params.page) } : {}),\n },\n },\n );\n }\n\n /** Explicit hosted-account creation; no signing wallet or credential upload. */\n async provisionHostedVenueAccount(\n venue: \"betdex\",\n body: ProvisionHostedVenueAccountBody,\n ): Promise<HostedVenueAccount> {\n return this.request<HostedVenueAccount>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}`,\n {\n method: \"POST\",\n body: JSON.stringify(body),\n },\n );\n }\n\n /** Fetch the owned hosted account's verified Solana USDC deposit address. */\n async getHostedVenueDepositAddress(\n venue: \"betdex\",\n params: ManagedBalancesParams = {},\n ): Promise<HostedVenueDepositAddress> {\n return this.request<HostedVenueDepositAddress>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/deposit-address`,\n { query: params.mode ? { mode: params.mode } : undefined },\n );\n }\n\n /** Submit exactly one explicit hosted withdrawal under a caller idempotency key. */\n async withdrawHostedVenue(\n venue: \"betdex\",\n body: HostedVenueWithdrawalRequest,\n ): Promise<HostedVenueWithdrawal> {\n return this.request<HostedVenueWithdrawal>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/withdrawals`,\n { method: \"POST\", body: JSON.stringify(body) },\n );\n }\n\n /** Read only Agg's persisted withdrawal state; this never replays a native request. */\n async getHostedVenueWithdrawal(\n venue: \"betdex\",\n withdrawalId: string,\n params: ManagedBalancesParams = {},\n ): Promise<HostedVenueWithdrawal> {\n if (!withdrawalId) throw new Error(\"withdrawalId is required\");\n return this.request<HostedVenueWithdrawal>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/withdrawals/${encodeURIComponent(withdrawalId)}`,\n { query: params.mode ? { mode: params.mode } : undefined },\n );\n }\n\n /** Store or replace encrypted credentials for a venue. Secrets are never returned. */\n async upsertVenueKey(body: UpsertVenueKey): Promise<VenueKeySummary> {\n return this.request<VenueKeySummary>(\"/venue-keys\", {\n method: \"PUT\",\n body: JSON.stringify(body),\n });\n }\n\n /** List venues with stored credentials. */\n async listVenueKeys(): Promise<VenueKeySummary[]> {\n return this.request<VenueKeySummary[]>(\"/venue-keys\");\n }\n\n /** Fetch connection and verification status for stored venue credentials. */\n async getVenueKeyStatus(venue: Venue): Promise<VenueKeyStatus> {\n return this.request<VenueKeyStatus>(`/venue-keys/${encodeURIComponent(venue)}/status`);\n }\n\n /** Remove stored credentials for a venue. */\n async deleteVenueKey(venue: Venue): Promise<void> {\n await this.request(`/venue-keys/${encodeURIComponent(venue)}`, { method: \"DELETE\" });\n }\n\n /** Create a server-managed paper trading account for an app. Requires adminKey or apiKey. */\n async createPaperTradingAccount(\n params: CreatePaperTradingAccountParams,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingAccount> {\n return this.request<PaperTradingAccount>(this.paperTradingAccountsPath(options?.appId), {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** List server-managed paper trading accounts for an app. Requires adminKey or apiKey. */\n async listPaperTradingAccounts(\n params: PaperTradingAccountListParams & PaperTradingAppOptions = {},\n ): Promise<PaperTradingAccountsPage> {\n const { appId, ...listParams } = params;\n return this.request<PaperTradingAccountsPage>(this.paperTradingAccountsPath(appId), {\n query: this.paperTradingAccountListQuery(listParams),\n });\n }\n\n /** Fetch a server-managed paper trading account. Requires adminKey or apiKey. */\n async getPaperTradingAccount(\n accountId: string,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingAccount> {\n return this.request<PaperTradingAccount>(\n this.paperTradingAccountPath(accountId, options?.appId),\n );\n }\n\n /** Set a paper trading account cash balance. Requires adminKey or apiKey. */\n async setPaperTradingBalance(\n accountId: string,\n params: SetPaperTradingBalanceParams,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingBalanceResponse> {\n return this.request<PaperTradingBalanceResponse>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/balance`,\n {\n method: \"PATCH\",\n body: JSON.stringify(params),\n },\n );\n }\n\n /** Clear positions and reset cash for a paper trading account. Requires adminKey or apiKey. */\n async resetPaperTradingAccount(\n accountId: string,\n params: ResetPaperTradingAccountParams = {},\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingBalanceResponse> {\n return this.request<PaperTradingBalanceResponse>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/reset`,\n {\n method: \"POST\",\n body: JSON.stringify(params),\n },\n );\n }\n\n /** Place a direct simulated order in a paper trading account. Requires adminKey or apiKey. */\n async placePaperTradingOrder(\n accountId: string,\n params: PlacePaperTradingOrderParams,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingOrder> {\n return this.request<PaperTradingOrder>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/orders`,\n {\n method: \"POST\",\n body: JSON.stringify(params),\n },\n );\n }\n\n /** List positions for a server-managed paper trading account. Requires adminKey or apiKey. */\n async listPaperTradingPositions(\n accountId: string,\n params: PaperTradingListParams & PaperTradingAppOptions = {},\n ): Promise<PaperTradingPositionsPage> {\n const { appId, ...listParams } = params;\n return this.request<PaperTradingPositionsPage>(\n `${this.paperTradingAccountPath(accountId, appId)}/positions`,\n {\n query: this.paperTradingListQuery(listParams),\n },\n );\n }\n\n /** List orders for a server-managed paper trading account. Requires adminKey or apiKey. */\n async listPaperTradingOrders(\n accountId: string,\n params: PaperTradingListParams & PaperTradingAppOptions = {},\n ): Promise<PaperTradingOrdersPage> {\n const { appId, ...listParams } = params;\n return this.request<PaperTradingOrdersPage>(\n `${this.paperTradingAccountPath(accountId, appId)}/orders`,\n {\n query: this.paperTradingListQuery(listParams),\n },\n );\n }\n\n /** Fetch account-level paper trading equity, P&L, and marked positions. Requires adminKey or apiKey. */\n async getPaperTradingPortfolio(\n accountId: string,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingPortfolio> {\n return this.request<PaperTradingPortfolio>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/portfolio`,\n );\n }\n\n /**\n * Cancel an agg order by id. Self-custody needs Polymarket ClobAuth\n * or a fresh Hyperliquid cancel action signed by the EOA/client-held agent.\n */\n async cancelManagedOrder(\n orderId: string,\n options?: { signal?: AbortSignal; cancelSignature?: CancelOrderSignature },\n ): Promise<CancelManagedExecutionResponse> {\n return this.request<CancelManagedExecutionResponse>(\"/execution/orders/cancel\", {\n method: \"POST\",\n body: JSON.stringify({\n orderId,\n ...(options?.cancelSignature ? { cancelSignature: options.cancelSignature } : {}),\n }),\n signal: options?.signal,\n });\n }\n\n /**\n * Cancel a Polymarket or Hyperliquid limit order that one of the user's\n * linked self-custody wallets placed outside AGG. `signerAddress` must be\n * that wallet and must have produced `cancelSignature`.\n */\n async cancelVenueOrder(\n params: CancelVenueOrderParams,\n options?: { signal?: AbortSignal },\n ): Promise<CancelManagedExecutionResponse> {\n return this.request<CancelManagedExecutionResponse>(\"/execution/orders/cancel\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n // --- Venue events & venue markets (primary) ---\n\n /** List venue events with optional filters. Requires appId or admin auth. Supports cursor-based pagination. */\n async getVenueEvents(options?: {\n venues?: Venue[];\n search?: string;\n categoryIds?: string[];\n matchStatus?: MatchStatus[];\n status?: MarketStatus[];\n sortBy?: string;\n sortDir?: string;\n aggKey?: string | string[];\n recurrence?: RecurrenceFilter | RecurrenceFilter[];\n limit?: number;\n cursor?: string;\n minYesPrice?: number;\n maxYesPrice?: number;\n /** Lifetime-volume floor (USD). Hides events/markets below it. Omit or 0 = no filter. */\n minVolume?: number;\n /** ISO-8601 timestamp. Hides events with endDate <= this value. NULL-endDate events are kept. */\n endDateFrom?: string;\n signal?: AbortSignal;\n /**\n * When true, fold same-venue companion events into one tile per game\n * (`groupParentId IS NULL`). Sent as `grouped=true`; omitted when false/absent\n * (default = ungrouped). Consumers showing one tile per game need a detail\n * view that loads the folded companions via aggKey.\n */\n grouped?: boolean;\n }): Promise<PaginatedResponse<VenueEvent>> {\n const query: Record<string, string | string[]> = {};\n if (options?.venues && options.venues.length > 0) query.venues = options.venues;\n if (options?.search?.trim()) query.search = options.search.trim();\n if (options?.categoryIds && options.categoryIds.length > 0)\n query.categoryIds = options.categoryIds;\n if (options?.matchStatus && options.matchStatus.length > 0)\n query.matchStatus = options.matchStatus;\n if (options?.status && options.status.length > 0) query.status = options.status;\n if (options?.sortBy) query.sortBy = options.sortBy;\n if (options?.sortDir) query.sortDir = options.sortDir;\n if (options?.aggKey) query.aggKey = options.aggKey;\n if (options?.recurrence) query.recurrence = options.recurrence;\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.minYesPrice != null) query.minYesPrice = String(options.minYesPrice);\n if (options?.maxYesPrice != null) query.maxYesPrice = String(options.maxYesPrice);\n if (options?.minVolume != null && options.minVolume > 0)\n query.minVolume = String(options.minVolume);\n if (options?.endDateFrom) query.endDateFrom = options.endDateFrom;\n if (options?.grouped) query.grouped = \"true\";\n return this.request<PaginatedResponse<VenueEvent>>(\"/venue-events\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: options?.signal,\n });\n }\n\n /** Get a single venue event by ID. Requires appId or admin auth. */\n async getEventBootstrap(\n eventId: string,\n options?: { limit?: number; minVolume?: number; signal?: AbortSignal },\n ): Promise<EventBootstrapResponse> {\n const query: Record<string, string> = {};\n if (options?.limit) query.limit = String(options.limit);\n if (options?.minVolume != null && options.minVolume > 0)\n query.minVolume = String(options.minVolume);\n return this.request<EventBootstrapResponse>(\n `/venue-events/${encodeURIComponent(eventId)}/bootstrap`,\n {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: options?.signal,\n },\n );\n }\n\n async getVenueEventById(\n id: string,\n options?: {\n signal?: AbortSignal;\n /**\n * Scope `marketCount` and the rolled-up `volume` to the whole matched\n * cluster (default, `true`) or to this one venue event (`false`). Pair it\n * with the same value on {@link getVenueMarkets} so the count matches the\n * market list you render.\n */\n cluster?: boolean;\n /**\n * Lifetime-volume floor (USD). Scopes `marketCount` to the markets\n * {@link getVenueMarkets} returns with the same `minVolume`. Omit or 0 = no filter.\n */\n minVolume?: number;\n },\n ): Promise<VenueEvent> {\n return this.request<VenueEvent>(`/venue-events/${encodeURIComponent(id)}`, {\n // Opt into the lean response (no embedded `venueMarkets`) — markets are\n // fetched separately via GET /venue-markets. Empty `expand` (no `markets`\n // token) tells the API to omit the deprecated embedded array.\n query: {\n expand: \"\",\n ...(options?.cluster === false ? { cluster: \"false\" } : {}),\n ...(options?.minVolume != null && options.minVolume > 0\n ? { minVolume: String(options.minVolume) }\n : {}),\n },\n signal: options?.signal,\n });\n }\n\n /** Get normalized live score state for sports events. Requires appId or admin auth. */\n async getSportsLive(\n eventIds: string[],\n options?: { signal?: AbortSignal },\n ): Promise<SportsLiveResponse> {\n const normalizedEventIds = normalizeRequestedVenueMarketIds(eventIds);\n if (normalizedEventIds.length === 0) {\n return { data: [], missingEventIds: [] };\n }\n\n const responses = await Promise.all(\n chunkArray(normalizedEventIds, MAX_SPORTS_EVENT_IDS_PER_REQUEST).map((eventIdChunk) =>\n this.request<SportsLiveResponse>(\"/sports/live\", {\n query: { eventIds: eventIdChunk },\n signal: options?.signal,\n }),\n ),\n );\n\n return {\n data: responses.flatMap((response) => response.data),\n missingEventIds: [...new Set(responses.flatMap((response) => response.missingEventIds))],\n };\n }\n\n /** List deterministic recurring crypto window markets across venues. Requires appId or admin auth. */\n async listRecurringCryptoMarkets(\n options?: ListRecurringCryptoMarketsOptions & { signal?: AbortSignal },\n ): Promise<RecurringCryptoMarketsResponse> {\n const query: Record<string, string | string[]> = {};\n if (options?.assets && options.assets.length > 0) query.assets = options.assets;\n if (options?.durations && options.durations.length > 0) query.durations = options.durations;\n if (options?.interval) query.interval = options.interval;\n if (options?.window) query.window = options.window;\n if (options?.venues && options.venues.length > 0) query.venues = options.venues;\n if (options?.status && options.status.length > 0) query.status = options.status;\n if (options?.windowStartFrom) query.windowStartFrom = options.windowStartFrom;\n if (options?.windowStartTo) query.windowStartTo = options.windowStartTo;\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.includeOrderbookPrices != null) {\n query.includeOrderbookPrices = String(options.includeOrderbookPrices);\n }\n if (options?.includeReferencePrices != null) {\n query.includeReferencePrices = String(options.includeReferencePrices);\n }\n if (options?.includeDirectVenueMarkets != null) {\n query.includeDirectVenueMarkets = String(options.includeDirectVenueMarkets);\n }\n if (options?.includeOrderbookDepth != null) {\n query.includeOrderbookDepth = String(options.includeOrderbookDepth);\n }\n if (options?.orderbookDepth != null) {\n query.orderbookDepth = String(options.orderbookDepth);\n }\n if (options?.orderbookDepthAmountUsd != null) {\n query.orderbookDepthAmountUsd = String(options.orderbookDepthAmountUsd);\n }\n\n return this.request<RecurringCryptoMarketsResponse>(\"/crypto/recurring-markets\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: options?.signal,\n });\n }\n\n /** Poll fresh reference prices for recurring crypto markets. Requires appId or admin auth. */\n async getCryptoReferencePrices(\n options: GetCryptoReferencePricesOptions,\n ): Promise<CryptoReferencePricesResponse> {\n const targets: CryptoReferencePriceTarget[] = [\n ...(options.targets ?? []),\n ...(options.venueMarketIds ?? []).map((venueMarketId) => ({\n type: \"venueMarket\" as const,\n venueMarketId,\n })),\n ...(options.venueEventIds ?? []).map((venueEventId) => ({\n type: \"venueEvent\" as const,\n venueEventId,\n })),\n ...(options.externalMarkets ?? []).map((market) => ({\n type: \"externalVenueMarket\" as const,\n venue: market.venue,\n externalMarketId: market.externalMarketId,\n })),\n ...(options.markets ?? []).map((market) => ({\n type: \"market\" as const,\n venue: market.venue,\n venueEventId: market.venueEventId,\n venueMarketId: market.venueMarketId,\n externalEventId: market.externalEventId,\n externalMarketId: market.externalMarketId,\n asset: market.asset,\n quoteAsset: market.quoteAsset ?? \"USD\",\n resolution: market.resolution,\n })),\n ...(options.windowMarkets ?? []).flatMap((windowMarket) =>\n windowMarket.markets.map((market) => ({\n type: \"market\" as const,\n venue: market.venue,\n venueEventId: market.venueEventId,\n venueMarketId: market.venueMarketId,\n externalEventId: market.externalEventId,\n externalMarketId: market.externalMarketId,\n asset: windowMarket.asset,\n quoteAsset: windowMarket.quoteAsset,\n resolution: market.resolution,\n })),\n ),\n ];\n\n if (targets.length === 0) {\n throw new Error(\"getCryptoReferencePrices requires at least one target\");\n }\n\n return this.request<CryptoReferencePricesResponse>(\"/crypto/reference-prices\", {\n method: \"POST\",\n body: JSON.stringify({ targets }),\n signal: options.signal,\n });\n }\n\n /** List venue markets with optional filters. Requires appId or admin auth. Supports cursor-based pagination. */\n async getVenueMarkets(\n options?: {\n venue?: Venue;\n venueEventId?: string;\n /** Exact venue-native identifiers; requires venue, at most 20. */\n externalIdentifier?: string[];\n /**\n * Scope `venueEventId` to the whole matched cluster (default, `true`) or to\n * that one venue event (`false`). Under the default, naming any member of a\n * cluster returns every venue's markets for that real-world event with\n * matched siblings folded into their anchor. Ignored without `venueEventId`.\n */\n cluster?: boolean;\n search?: string;\n matchStatus?: MatchStatus;\n status?: MarketStatus;\n aggKey?: string[];\n sportsMarketType?: string[];\n period?: string[];\n marketCategory?: string[];\n marketGroup?: string[];\n limit?: number;\n cursor?: string;\n sortBy?: \"volume\" | \"volume24hr\" | \"createdAt\" | \"updatedAt\";\n sortDir?: \"asc\" | \"desc\";\n context?: \"list\" | \"detail\";\n /** Omit wide text independently of sort; summary marks detailsDeferred. */\n projection?: \"summary\" | \"full\";\n /** Lifetime-volume floor (USD). Omit or 0 = no filter. */\n minVolume?: number;\n },\n requestOptions?: { signal?: AbortSignal },\n ): Promise<PaginatedResponse<VenueMarket>> {\n const query: Record<string, string | string[]> = {};\n if (options?.venue) query.venue = options.venue;\n if (options?.externalIdentifier?.length) query.externalIdentifier = options.externalIdentifier;\n if (options?.venueEventId) query.venueEventId = options.venueEventId;\n // Server default is cluster scope — only send the opt-out.\n if (options?.cluster === false) query.cluster = \"false\";\n if (options?.search?.trim()) query.search = options.search.trim();\n if (options?.matchStatus) query.matchStatus = options.matchStatus;\n if (options?.status) query.status = options.status;\n if (options?.aggKey && options.aggKey.length > 0) query.aggKey = options.aggKey;\n if (options?.sportsMarketType && options.sportsMarketType.length > 0) {\n query.sportsMarketType = options.sportsMarketType;\n }\n if (options?.period && options.period.length > 0) query.period = options.period;\n if (options?.marketCategory && options.marketCategory.length > 0) {\n query.marketCategory = options.marketCategory;\n }\n if (options?.marketGroup && options.marketGroup.length > 0) {\n query.marketGroup = options.marketGroup;\n }\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.sortBy) query.sortBy = options.sortBy;\n if (options?.sortDir) query.sortDir = options.sortDir;\n if (options?.context) query.context = options.context;\n if (options?.projection) query.projection = options.projection;\n if (options?.minVolume != null && options.minVolume > 0)\n query.minVolume = String(options.minVolume);\n return this.request<PaginatedResponse<VenueMarket>>(\"/venue-markets\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: requestOptions?.signal,\n });\n }\n\n /** Get categories with cursor-based pagination. Requires appId. */\n async getCategories(options?: {\n limit?: number;\n cursor?: string;\n parentId?: string;\n }): Promise<PaginatedResponse<Category>> {\n const query: Record<string, string> = {};\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.parentId) query.parentId = options.parentId;\n return this.request<PaginatedResponse<Category>>(\"/categories\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n });\n }\n\n /** Get per-app UI config (disabled venues + category presets). Requires appId. */\n async getAppConfig(init?: RequestInit): Promise<AppClientConfigResponse> {\n return this.request<AppClientConfigResponse>(\"/app/config\", init);\n }\n\n /**\n * Get the per-venue blocked-country lists (ISO 3166-1 alpha-2). Requires appId.\n *\n * This is the raw venue policy, not per-user eligibility — to gate a fill,\n * read the `warnings` array on the quote response instead.\n */\n async getVenueGeoPolicy(init?: RequestInit): Promise<VenueGeoPolicyResponse> {\n return this.request<VenueGeoPolicyResponse>(\"/app/venue-geo-policy\", init);\n }\n\n /** Get a temporary Alchemy JWT token for RPC connections. */\n async getRpcToken(init?: RequestInit): Promise<RpcTokenResponse> {\n return this.request<RpcTokenResponse>(\"/app/rpc-tokens/alchemy\", init);\n }\n\n private buildNewsFeedQuery(options?: NewsFeedPageOptions): Record<string, string> | undefined {\n const query: Record<string, string> = {};\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.since) query.since = options.since;\n if (options?.before) query.before = options.before;\n if (options?.limit != null) query.limit = String(options.limit);\n return Object.keys(query).length > 0 ? query : undefined;\n }\n\n /** List available market news feeds and item counts. */\n async getNewsFeeds(options?: { signal?: AbortSignal }): Promise<NewsFeedListResponse> {\n return this.request<NewsFeedListResponse>(\"/news-feed\", {\n signal: options?.signal,\n });\n }\n\n /** Get the article-centric market news feed for a category. */\n async getNewsFeed(\n category: string,\n options?: NewsFeedPageOptions & { signal?: AbortSignal },\n ): Promise<NewsFeedArticleFeedResponse> {\n return this.request<NewsFeedArticleFeedResponse>(`/news-feed/${encodeURIComponent(category)}`, {\n query: this.buildNewsFeedQuery(options),\n signal: options?.signal,\n });\n }\n\n /** Get the market-centric market news feed for a category. */\n async getNewsFeedMarkets(\n category: string,\n options?: NewsFeedPageOptions & { signal?: AbortSignal },\n ): Promise<NewsFeedMarketFeedResponse> {\n return this.request<NewsFeedMarketFeedResponse>(\n `/news-feed/${encodeURIComponent(category)}/markets`,\n {\n query: this.buildNewsFeedQuery(options),\n signal: options?.signal,\n },\n );\n }\n\n /** Get news feed coverage and per-category counts. */\n async getNewsFeedStatus(options?: { signal?: AbortSignal }): Promise<NewsFeedStatusResponse> {\n return this.request<NewsFeedStatusResponse>(\"/news-feed/status\", {\n signal: options?.signal,\n });\n }\n\n /** Search recent news for specific markets and return market impact summaries. */\n async getMarketNews(\n params: NewsFeedMarketNewsParams,\n options?: { signal?: AbortSignal },\n ): Promise<NewsFeedMarketNewsResponse> {\n return this.request<NewsFeedMarketNewsResponse>(\"/news-feed/market-news\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n /**\n * Search events or markets by query string. Supports cursor-based pagination.\n *\n * Pass `deep: true` on submit (Enter / Search button) to opt in to the\n * server-side reranker. Leave it off for debounced typeahead — the wire\n * format intentionally omits the param so the server hits the cheaper\n * (and longer-TTL) light cache slot.\n */\n async search<T = VenueEvent>(\n params: SearchParams,\n options?: { signal?: AbortSignal },\n ): Promise<SearchResponse<T>> {\n const query: Record<string, string | string[]> = {\n q: params.q,\n type: params.type,\n };\n if (params.categoryIds && params.categoryIds.length > 0) query.categoryIds = params.categoryIds;\n if (params.status && params.status.length > 0) query.status = params.status;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n // Only send the flag when explicitly true — keeps the wire URL minimal\n // and lets the server's default-false path stay cache-stable across\n // partner SDK versions that pre-date this option.\n if (params.deep) query.deepSearch = \"true\";\n if (params.mode) query.mode = params.mode;\n return this.request<SearchResponse<T>>(\"/search\", {\n query,\n signal: options?.signal,\n });\n }\n\n /** Get Correlated Markets processing and embedding coverage. */\n async getCorrelatedMarketsStatus(options?: {\n signal?: AbortSignal;\n }): Promise<CorrelatedMarketsStatus> {\n return this.request<CorrelatedMarketsStatus>(\"/correlated-markets/status\", {\n signal: options?.signal,\n });\n }\n\n /** Get the generated correlated market signals for a market. */\n async getMarketCorrelatedSignals(\n venueMarketId: string,\n options?: { signal?: AbortSignal; includeResolved?: boolean },\n ): Promise<CorrelatedMarketSignalBatch> {\n const query: Record<string, string> = {};\n if (options?.includeResolved != null) query.includeResolved = String(options.includeResolved);\n return this.request<CorrelatedMarketSignalBatch>(\n `/correlated-markets/${encodeURIComponent(venueMarketId)}`,\n { query, signal: options?.signal },\n );\n }\n\n /** Search markets by Correlated Markets signal similarity. */\n async queryCorrelatedMarkets(\n params: {\n text: string;\n limit?: number;\n includeResolved?: boolean;\n direction?: \"more_likely\" | \"less_likely\";\n balanced?: boolean;\n },\n options?: { signal?: AbortSignal },\n ): Promise<{ results: CorrelatedMarketQueryResult[] }> {\n return this.request<{ results: CorrelatedMarketQueryResult[] }>(\"/correlated-markets/query\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n /** Get expansion and hedge candidates for an already-processed market. */\n async getCorrelatedMarketCascade(\n params: {\n venueMarketId: string;\n side?: \"yes\" | \"no\";\n mode?: \"expand\" | \"hedge\";\n limit?: number;\n cursor?: string;\n includeResolved?: boolean;\n },\n options?: { signal?: AbortSignal },\n ): Promise<CorrelatedMarketCascadeResponse> {\n const query: Record<string, string> = {};\n if (params.side) query.side = params.side;\n if (params.mode) query.mode = params.mode;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n if (params.includeResolved != null) query.includeResolved = String(params.includeResolved);\n return this.request<CorrelatedMarketCascadeResponse>(\n `/correlated-markets/cascade/${encodeURIComponent(params.venueMarketId)}`,\n { query, signal: options?.signal },\n );\n }\n\n /** Resolve a market by ID, venue identifier, slug, conditionId, or text, then return candidates. */\n async resolveCorrelatedMarkets(\n params: ResolveCorrelatedMarketsParams,\n options?: { signal?: AbortSignal },\n ): Promise<ResolveCorrelatedMarketsResponse> {\n return this.request<ResolveCorrelatedMarketsResponse>(\"/correlated-markets/resolve\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n // --- Chart data ---\n /** Get the canonical TradingView-style bar series for a single venue market outcome. */\n async getChartBars(\n params: {\n venueMarketOutcomeId: string;\n resolution?: ChartResolution;\n from?: number;\n to: number;\n countBack?: number;\n },\n options?: { signal?: AbortSignal; decode?: (payload: string) => Promise<ChartBarsResponse> },\n ): Promise<ChartBarsResponse> {\n const resolution = mapChartResolution(params.resolution);\n\n const query: Record<string, string | string[]> = {\n venueMarketOutcomeId: params.venueMarketOutcomeId,\n to: String(params.to),\n };\n if (resolution) query.resolution = resolution;\n if (params.from != null) query.from = String(params.from);\n if (params.countBack != null) query.countBack = String(params.countBack);\n\n if (options?.decode) {\n // Keep headers, cancellation and auth refresh here; decode after request resolves so a\n // validation error cannot be mistaken for an authentication-refresh failure.\n const text = await this.request<string>(\n \"/charts/bars\",\n { query, signal: options.signal },\n (response) => readChartHistoryText(response),\n );\n options.signal?.throwIfAborted();\n const decoded = await options.decode(text);\n options.signal?.throwIfAborted();\n return decoded;\n }\n return this.request<ChartBarsResponse>(\"/charts/bars\", {\n query,\n signal: options?.signal,\n });\n }\n\n async getChartHistoryManifest(\n params: {\n venueMarketOutcomeId: string;\n resolution?: ChartResolution;\n from?: number;\n to: number;\n countBack?: number;\n },\n options?: { signal?: AbortSignal },\n ): Promise<ChartHistoryManifest> {\n const query: Record<string, string> = {\n venueMarketOutcomeId: params.venueMarketOutcomeId,\n to: String(params.to),\n };\n const resolution = mapChartResolution(params.resolution);\n if (resolution) query.resolution = resolution;\n if (params.from != null) query.from = String(params.from);\n if (params.countBack != null) query.countBack = String(params.countBack);\n return this.request<ChartHistoryManifest>(\"/charts/history/manifest\", {\n query,\n signal: options?.signal,\n });\n }\n\n // --- Batch orderbooks ---\n /** Get live per-venue orderbooks for the explicit venueMarketIds requested. */\n async getOrderbooks(\n params: { venueMarketIds: string[]; depth?: number },\n options?: { signal?: AbortSignal },\n ): Promise<BatchOrderbooksResponse> {\n const query: Record<string, string | string[]> = {\n venueMarketIds: params.venueMarketIds,\n };\n if (params.depth != null) query.depth = String(params.depth);\n\n return this.request<BatchOrderbooksResponse>(\"/orderbooks\", {\n query,\n signal: options?.signal,\n });\n }\n\n /** Get live midpoints for the explicit venueMarketIds requested. */\n async getMidpoints(\n params: { venueMarketIds: string[]; bestPrice?: boolean; maxMidpointIdsPerRequest?: number },\n options?: { signal?: AbortSignal; maxMidpointIdsPerRequest?: number },\n ): Promise<BatchMidpointsResponse>;\n async getMidpoints(\n venueMarketIds: string[],\n options?: { signal?: AbortSignal; bestPrice?: boolean; maxMidpointIdsPerRequest?: number },\n ): Promise<BatchMidpointsResponse>;\n async getMidpoints(\n paramsOrVenueMarketIds:\n | { venueMarketIds: string[]; bestPrice?: boolean; maxMidpointIdsPerRequest?: number }\n | string[],\n options?: { signal?: AbortSignal; bestPrice?: boolean; maxMidpointIdsPerRequest?: number },\n ): Promise<BatchMidpointsResponse> {\n const requestedVenueMarketIds = Array.isArray(paramsOrVenueMarketIds)\n ? paramsOrVenueMarketIds\n : paramsOrVenueMarketIds.venueMarketIds;\n const venueMarketIds = normalizeRequestedVenueMarketIds(requestedVenueMarketIds);\n\n const bestPrice = !Array.isArray(paramsOrVenueMarketIds)\n ? paramsOrVenueMarketIds.bestPrice\n : options?.bestPrice;\n\n const maxMidpointIdsPerRequest = resolveMidpointIdsPerRequest(\n options?.maxMidpointIdsPerRequest ??\n (Array.isArray(paramsOrVenueMarketIds)\n ? undefined\n : paramsOrVenueMarketIds.maxMidpointIdsPerRequest),\n );\n\n const requestBatch = (batchVenueMarketIds: string[]): Promise<BatchMidpointsResponse> => {\n const query: Record<string, string | string[]> = { venueMarketIds: batchVenueMarketIds };\n if (bestPrice) query.bestPrice = \"true\";\n\n return this.request<BatchMidpointsResponse>(\"/midpoints\", {\n query,\n signal: options?.signal,\n });\n };\n\n if (venueMarketIds.length === 0) {\n return { data: [] };\n }\n\n if (venueMarketIds.length <= maxMidpointIdsPerRequest) {\n return requestBatch(venueMarketIds);\n }\n\n const responses = await Promise.all(\n chunkArray(venueMarketIds, maxMidpointIdsPerRequest).map((batch) => requestBatch(batch)),\n );\n return { data: responses.flatMap((response) => response.data) };\n }\n\n /** Get a single outcome-level orderbook from the engine. */\n async getOutcomeOrderbook(\n outcomeId: string,\n options?: { depth?: number; signal?: AbortSignal },\n ): Promise<OutcomeOrderbookResponse | null> {\n const query: Record<string, string> = {};\n if (options?.depth != null) query.depth = String(options.depth);\n\n try {\n return await this.request<OutcomeOrderbookResponse>(`/orderbook/outcome/${outcomeId}`, {\n query,\n signal: options?.signal,\n });\n } catch (err: any) {\n if (err?.status === 404) return null;\n throw err;\n }\n }\n\n // --- Market data / orderbook ---\n\n /**\n * Compute optimal order routing across venues via the MILP solver.\n * Returns a user-scoped quote with per-venue fills and verification timing.\n * Deprecated aliases are accepted for source compatibility during the\n * outcome-level migration window.\n */\n async getSmartRoute(\n params: SmartRouteParams,\n options?: { signal?: AbortSignal },\n ): Promise<SmartRouteResponse> {\n const venueMarketOutcomeId =\n params.venueMarketOutcomeId ?? params.venueMarketId ?? params.outcomeId;\n if (!venueMarketOutcomeId) {\n throw new Error(\"getSmartRoute requires venueMarketOutcomeId\");\n }\n\n const query: Record<string, string | string[]> = {};\n if (params.maxSpend != null) query.maxSpend = String(params.maxSpend);\n if (params.sellShares != null) query.sellShares = String(params.sellShares);\n if (params.chainBalances) query.chainBalances = JSON.stringify(params.chainBalances);\n if (params.slipCapBps != null) query.slipCapBps = String(params.slipCapBps);\n if (params.compareVenues) query.compareVenues = \"true\";\n if (params.allowedVenues?.length) query.allowedVenues = params.allowedVenues.map(String);\n if (params.tradeSide) query.side = params.tradeSide;\n if (params.mode) query.mode = params.mode;\n if (params.deepEstimate) query.deepEstimate = \"true\";\n if (params.appFeeBips != null) query.appFeeBips = String(params.appFeeBips);\n if (params.referrer) query.referrer = params.referrer;\n if (params.referrerFeeBips != null) query.referrerFeeBips = String(params.referrerFeeBips);\n if (params.appFeeBipsByVenue)\n query.appFeeBipsByVenue = JSON.stringify(params.appFeeBipsByVenue);\n if (params.referrerFeeBipsByVenue) {\n query.referrerFeeBipsByVenue = JSON.stringify(params.referrerFeeBipsByVenue);\n }\n if (params.referralPayer) query.referralPayer = params.referralPayer;\n if (params.referralPayerAddress) query.referralPayerAddress = params.referralPayerAddress;\n if (params.referralActivationSponsorAddress) {\n query.referralActivationSponsorAddress = params.referralActivationSponsorAddress;\n }\n\n const response = await this.request<SmartRouteResponse>(\n `/orderbook/${encodeURIComponent(venueMarketOutcomeId)}/route`,\n { query, signal: options?.signal },\n );\n\n return params.side ? { ...response, side: params.side } : response;\n }\n\n /** Seed subscribed outcomes with one bounded batch of compatible snapshots. */\n async getOutcomeOrderbooks(\n params: { venueMarketOutcomeIds: string[]; depth?: number },\n options?: { signal?: AbortSignal },\n ): Promise<{ data: (OutcomeOrderbookResponse | null)[] }> {\n return this.request(\"/orderbooks/outcomes\", {\n query: {\n venueMarketOutcomeIds: params.venueMarketOutcomeIds.join(\",\"),\n ...(params.depth == null ? {} : { depth: String(params.depth) }),\n },\n signal: options?.signal,\n });\n }\n\n /**\n * Create an AggWebSocket instance configured with this client's appId and current auth session.\n * Session changes update this socket until it or the client is destroyed.\n * Requires `wsUrl` to be set in the client options.\n */\n createWebSocket(\n callbacks?: AggWebSocketCallbacks,\n options?: {\n enableLogs?: boolean;\n /**\n * Checks books with no update for 5 minutes against\n * `GET /orderbooks/outcomes` and heals any that drifted. On by default;\n * pass `false` to disable or an object to tune the timings.\n */\n bookWatchdog?: false | Pick<BookWatchdogOptions, \"silenceMs\" | \"checkIntervalMs\">;\n },\n ): AggWebSocket {\n if (!this.wsUrl) {\n throw new Error(\"AggClient.createWebSocket() requires wsUrl to be set in client options\");\n }\n\n const url = new URL(this.wsUrl);\n if (this._appId) url.searchParams.set(\"appId\", this._appId);\n\n const createSocket =\n this.webSocketFactory ?? ((socketOptions) => new AggWebSocket(socketOptions));\n const watchdogHeaders: Record<string, string> = {};\n if (this._appId) watchdogHeaders[\"x-app-id\"] = this._appId;\n if (this.apiKey) watchdogHeaders[\"x-app-api-key\"] = this.apiKey;\n\n const socket = createSocket({\n url: url.toString(),\n callbacks,\n initialToken: this.accessToken,\n enableLogs: options?.enableLogs ?? false,\n bookWatchdog:\n options?.bookWatchdog === false\n ? undefined\n : { baseUrl: this.baseUrl, headers: watchdogHeaders, ...options?.bookWatchdog },\n });\n this.bindWebSocketAuth(socket, callbacks);\n return socket;\n }\n\n private bindWebSocketAuth(socket: AggWebSocket, callbacks?: AggWebSocketCallbacks): void {\n let token = this.accessToken;\n let userId = this.accessTokenUserId;\n let authenticatedUserId: string | undefined;\n let awaitingDisconnect = false;\n let connectRequested = false;\n let manuallyDisconnected = false;\n let currentCallbacks = callbacks ?? {};\n const originalSetCallbacks = socket.setCallbacks;\n const originalConnect = socket.connect;\n const originalDisconnect = socket.disconnect;\n const originalDestroy = socket.destroy;\n\n const canReceiveUserEvent = (eventUserId?: string): boolean =>\n !!this.accessToken &&\n !awaitingDisconnect &&\n authenticatedUserId !== undefined &&\n (this.accessTokenUserId === undefined || authenticatedUserId === this.accessTokenUserId) &&\n (eventUserId === undefined || eventUserId === authenticatedUserId);\n\n const wrapCallbacks = (handlers: AggWebSocketCallbacks): AggWebSocketCallbacks => ({\n ...handlers,\n onConnectionStateChange: (connected) => {\n if (!connected) {\n authenticatedUserId = undefined;\n awaitingDisconnect = false;\n }\n handlers.onConnectionStateChange?.(connected);\n },\n onAuthenticated: (message) => {\n if (\n awaitingDisconnect ||\n !this.accessToken ||\n (this.accessTokenUserId !== undefined && this.accessTokenUserId !== message.userId)\n )\n return;\n authenticatedUserId = message.userId;\n handlers.onAuthenticated?.(message);\n },\n onOrderEvent: (message) => {\n if (canReceiveUserEvent(message.userId)) handlers.onOrderEvent?.(message);\n },\n onOrderEventReceipt: (message) => {\n if (canReceiveUserEvent()) handlers.onOrderEventReceipt?.(message);\n },\n onOrderSubmitted: (message) => {\n if (canReceiveUserEvent()) handlers.onOrderSubmitted?.(message);\n },\n onBalanceUpdate: (message) => {\n if (canReceiveUserEvent()) handlers.onBalanceUpdate?.(message);\n },\n onRedeemEvent: (message) => {\n if (canReceiveUserEvent()) handlers.onRedeemEvent?.(message);\n },\n onWithdrawalLifecycle: (message) => {\n if (canReceiveUserEvent(message.userId)) handlers.onWithdrawalLifecycle?.(message);\n },\n });\n\n socket.setCallbacks = (handlers) => {\n currentCallbacks = handlers;\n originalSetCallbacks.call(socket, wrapCallbacks(handlers));\n };\n socket.setCallbacks(currentCallbacks);\n socket.connect = () => {\n connectRequested = true;\n manuallyDisconnected = false;\n originalConnect.call(socket);\n };\n socket.disconnect = () => {\n connectRequested = false;\n manuallyDisconnected = true;\n originalDisconnect.call(socket);\n };\n\n const unsubscribe = this.onAuthStateChange(() => {\n const nextToken = this.accessToken;\n const nextUserId = this.accessTokenUserId;\n if (token === nextToken && userId === nextUserId) return;\n const resetConnection =\n !nextToken || (!!token && (userId !== nextUserId || nextUserId === undefined));\n token = nextToken;\n userId = nextUserId;\n if (resetConnection) {\n const diagnostics = socket.getDiagnostics();\n const reconnect =\n connectRequested ||\n socket.connected ||\n (!manuallyDisconnected &&\n (diagnostics.orderbookOutcomeIds.length > 0 ||\n diagnostics.tradeOutcomeIds.length > 0 ||\n diagnostics.arbMarketIds.length > 0 ||\n diagnostics.arbFeedSubscribers > 0));\n // The gateway has no deauthenticate frame. Close the old user transport;\n // Worker callbacks already queued are held until its disconnect arrives.\n authenticatedUserId = undefined;\n awaitingDisconnect = true;\n originalDisconnect.call(socket);\n socket.authenticate(nextToken ?? \"\");\n if (reconnect) originalConnect.call(socket);\n } else if (nextToken) {\n // Also replaces the token used on future reconnects and Worker fallback.\n socket.authenticate(nextToken);\n }\n });\n\n const cleanup = () => {\n unsubscribe();\n this.webSocketAuthCleanups.delete(cleanup);\n socket.setCallbacks = originalSetCallbacks;\n socket.connect = originalConnect;\n socket.disconnect = originalDisconnect;\n socket.destroy = originalDestroy;\n socket.setCallbacks(currentCallbacks);\n };\n this.webSocketAuthCleanups.add(cleanup);\n socket.destroy = () => {\n cleanup();\n originalDestroy.call(socket);\n };\n }\n\n /** Execute a previously quoted managed trade. Returns pending order IDs. */\n async executeManaged(params: ExecuteManagedParams): Promise<ExecuteManagedResponse> {\n return this.request<ExecuteManagedResponse>(\"/execution/fill\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Submit signatures for a parked fill. Returns whatever is still outstanding. */\n async submitFillSignatures(\n quoteId: string,\n // Exactly `SubmitSignaturesBody`'s element type: a signed payload carries\n // `signature`, a broadcast one carries `txHash`, and the server 400s in\n // both wrong-field directions.\n signatures: Array<{ stepId: string; signature?: string; txHash?: string }>,\n ): Promise<ExecuteManagedResponse & { accepted?: number }> {\n // Same body as `POST /execution/fill`. `accepted` rides along as a\n // diagnostic extra — the contract's 200 schema doesn't declare it, so it\n // isn't guaranteed present.\n return this.request(`/execution/fill/${encodeURIComponent(quoteId)}/signatures`, {\n method: \"POST\",\n body: JSON.stringify({ signatures }),\n });\n }\n\n /**\n * Execute a quote in self-custodial mode.\n *\n * Identical to `executeManaged` when the server can sign for the user. When\n * it cannot, the DAG parks on a signature request instead — but that park\n * always happens asynchronously, in the trade-executor process, so it can\n * never show up on this `POST /execution/fill` response itself. This\n * drives the round trip from there: poll `getExecutionStatus` while an\n * on-chain step is in flight, sign whatever it hands back with the\n * configured `signer`, post the signatures back, and repeat until the\n * server reports nothing outstanding and the run reaches a terminal state.\n */\n async fillSelfCustody(params: ExecuteManagedParams): Promise<ExecuteManagedResponse> {\n // A configured signer means the partner holds the key. Sending no wallet\n // would silently route this fill to our server wallet instead, so refuse\n // here rather than produce a managed fill the caller did not ask for.\n if (this.signer && !params.signingAddress) {\n throw new Error(\n \"fillSelfCustody requires `signingAddress` — the wallet that will sign this fill.\",\n );\n }\n\n // Inverse config error: a wallet was named but no `signer` was passed to\n // createAggClient(). Checked BEFORE any fetch (final review Ruling\n // R30(b)) — posting the fill first would create real orders, stamp\n // `Order.accountId`, take admission reservations, and — because that\n // column's FK is ON DELETE RESTRICT — permanently pin an\n // un-disconnectable wallet, all for a pure partner configuration\n // mistake.\n if (params.signingAddress && !this.signer) {\n throw new Error(\n \"This fill requires client-side signatures, but no `signer` was passed to createAggClient(). \" +\n \"Provide one to trade in self-custodial mode.\",\n );\n }\n\n const first = await this.executeManaged(params);\n\n // Managed case: no signer configured and no wallet named — ordinary\n // managed custody, which never parks. Whatever the server returned is\n // the whole answer.\n if (!this.signer && !params.signingAddress) return first;\n\n // Both checks above guarantee a signer is configured on every path that\n // reaches here.\n const signer = this.signer!;\n\n // `fallbackToLatest` can resolve to a DIFFERENT quote than the one\n // requested. Resume against whatever quoteId the fill actually landed\n // on — using the caller's original id would 403/404 on every subsequent\n // call.\n const quoteId = first.quoteId;\n\n // `POST /execution/fill` can NEVER carry `pendingSignatures` — the DAG\n // park happens later, once the trade-executor process picks up the run.\n // So an empty/absent list here does not mean \"no signing needed\"; like\n // everywhere else in this loop, it means \"go poll\".\n let pending = first.pendingSignatures ?? [];\n // Guard against a server that keeps handing back the same step: without\n // this a transient backend bug becomes an infinite loop in the partner's app.\n let lastKey = \"\";\n const deadline = Date.now() + SELF_CUSTODY_FILL_TIMEOUT_MS;\n\n // How long to wait before the NEXT status read. The server tells us\n // (`pollAfterMs`); until it has, we are guessing. Because `POST\n // /execution/fill` can never park (see above), the first sleep is spent\n // before this loop has looked even once — so start at the floor. One cheap\n // extra read puts us on the server's advertised grid immediately instead of\n // burning a full hardcoded interval to learn it.\n let nextPollMs = MIN_POLL_INTERVAL_MS;\n\n // An EMPTY pendingSignatures list does NOT mean the fill is finished. A\n // first-time user signs the wallet-setup batch, and the run then spends a\n // few seconds on-chain before parking again for the order. Returning here\n // would report success while the run waits for a signature nobody is going\n // to send — a fill that silently never happens. So an empty list means\n // \"poll\", and only a TERMINAL overallState means \"stop\".\n // Optional requests this call has already declined — rejected by the\n // signer, or expired before we got to them. The server may keep listing\n // one until its TTL; it is never asked for twice and never blocks the fill.\n const declinedOptional = new Set<string>();\n // A Polymarket buy fee pre-sign is prepared independently of the order, so\n // it can be listed before the order prompt exists. Awaiting its signer then\n // would stop this loop polling and hold the order for the whole fee bound.\n // So it is not signed until this call has posted the Polymarket ORDER\n // signature itself: any other required one (auth, setup) can be posted\n // while the order prompt does not exist yet. The order request is the\n // trade-executor's `poly-sign-<orderId>` step; the request carries no other\n // field that names it. One never signed just expires server-side and the\n // fee is asked for after the fill.\n const isOptionalFee = (req: SignatureRequest) => req.optional && req.purpose === \"app_fee\";\n let orderSubmitted = false;\n\n for (;;) {\n pending = pending.filter(\n (p) => !declinedOptional.has(p.stepId) && (orderSubmitted || !isOptionalFee(p)),\n );\n\n // Checked every iteration, not just the poll arm: the no-progress guard\n // below only remembers the immediately preceding round, so a server\n // alternating between two step ids never trips it. The deadline is\n // what actually bounds that case.\n if (Date.now() > deadline) {\n throw new Error(`Fill for quote ${quoteId} did not finish within the timeout.`);\n }\n\n if (pending.length === 0) {\n await new Promise((r) => setTimeout(r, nextPollMs));\n const polled = await this.getExecutionStatus({ quoteId });\n // Follow the server's cadence (`RUNNING_POLL_AFTER_MS`, 1s today)\n // instead of our own guess — expected time-to-discovery for a parked\n // signature is half the poll interval, so this is on the critical path\n // of every self-custody fill. `Number.isFinite` covers all three\n // fall-back cases in one test: `null` on a terminal response,\n // `undefined` from an API old enough not to send the field, and a\n // non-numeric value that would otherwise reach `setTimeout` as NaN\n // (i.e. 0) and busy-loop.\n nextPollMs = Number.isFinite(polled.pollAfterMs)\n ? Math.min(\n Math.max(polled.pollAfterMs as number, MIN_POLL_INTERVAL_MS),\n MAX_POLL_INTERVAL_MS,\n )\n : SELF_CUSTODY_POLL_INTERVAL_MS;\n if (TERMINAL_EXECUTION_STATES.has(polled.overallState)) {\n if (polled.overallState !== \"filled\" && polled.overallState !== \"partially_filled\") {\n throw new Error(`Fill for quote ${quoteId} ended as ${polled.overallState}.`);\n }\n return { ...first, pendingSignatures: [] };\n }\n pending = polled.pendingSignatures ?? [];\n continue;\n }\n\n const key = pending\n .map((p) => p.stepId)\n .sort()\n .join(\",\");\n if (key === lastKey) {\n throw new Error(\n `Fill for quote ${quoteId} did not advance — still awaiting steps [${key}] after signing them.`,\n );\n }\n lastKey = key;\n\n const signatures: Array<{ stepId: string; signature?: string; txHash?: string }> = [];\n // Required first, so the wallet prompts for the order before anything\n // else. Apart from optional fee pre-signs, use one batch: the server reads an\n // optional signature (a referral code, a sponsor) right after the order\n // finalises, so a second round would arrive too late. An optional\n // request signed by a wallet OTHER than the user's (a partner's sponsor)\n // is bounded by OPTIONAL_SIGNATURE_TIMEOUT_MS and then declined; one the\n // user signs (a referral code) waits for the human, as it always has.\n // A buy fee pre-sign is usable after order submission. Submit the other\n // requests first so a slow or declined fee prompt cannot hold the order.\n const round = pending.some((req) => !isOptionalFee(req))\n ? pending.filter((req) => !isOptionalFee(req))\n : pending;\n const ordered = [...round].sort((a, b) => Number(!!a.optional) - Number(!!b.optional));\n const userSigners = new Set(\n [params.signingAddress, ...pending.filter((p) => !p.optional).map((p) => p.signerAddress)]\n .filter((a): a is string => !!a)\n .map((a) => a.toLowerCase()),\n );\n for (const req of ordered) {\n // The server's signature TTL (`DEFAULT_TTL_MS` in the request-signature\n // handler) defaults to 120s — well inside this loop's 5-minute budget,\n // which spans multiple sequential requests, each with its own TTL. A\n // request that is already expired by the time we're about to sign it\n // will be rejected by the server no matter what we post, so fail with\n // a clear message here instead of prompting the wallet and eating an\n // opaque 400 from `submitFillSignatures`.\n if (Date.now() > new Date(req.expiresAt).getTime()) {\n if (req.optional) {\n declinedOptional.add(req.stepId);\n continue;\n }\n throw new Error(\n `Signature request ${req.stepId} for quote ${quoteId} expired at ${req.expiresAt}; ` +\n \"the fill must be re-quoted.\",\n );\n }\n // A `transaction` request is broadcast, not signed, and the server\n // rejects a hash posted in `signature`. Before this branch existed the\n // push was unconditional, which made the user-broadcast funding path\n // unreachable from the SDK.\n let signed: Awaited<ReturnType<typeof signer>>;\n try {\n signed = isOptionalFee(req)\n ? await withTimeout(signer(req), OPTIONAL_FEE_SIGNATURE_TIMEOUT_MS)\n : req.optional && !userSigners.has(req.signerAddress?.toLowerCase())\n ? await withTimeout(signer(req), OPTIONAL_SIGNATURE_TIMEOUT_MS)\n : await signer(req);\n } catch (err) {\n // An optional request (e.g. a partner referral) must never cost the\n // user the trade parked beside it: skip it and post the rest.\n if (!req.optional) throw err;\n declinedOptional.add(req.stepId);\n continue;\n }\n signatures.push(\n typeof signed === \"string\"\n ? { stepId: req.stepId, signature: signed }\n : { stepId: req.stepId, txHash: signed.txHash },\n );\n }\n\n if (signatures.length === 0) {\n // Everything in this round was an optional request we declined.\n pending = [];\n continue;\n }\n const next = await this.submitFillSignatures(quoteId, signatures);\n if (signatures.some((s) => s.stepId.startsWith(PM_ORDER_SIGNATURE_STEP_PREFIX)))\n orderSubmitted = true;\n pending = next.pendingSignatures ?? [];\n }\n }\n\n /**\n * Enqueue a limit order. For self-custody, poll getExecutionStatus with the\n * returned quoteId and answer pending requests through submitFillSignatures.\n * A pending response does not mean the order has reached the venue.\n */\n async placeLimitOrder(params: PlaceLimitOrderParams): Promise<PlaceLimitOrderResponse> {\n return this.request<PlaceLimitOrderResponse>(\"/execution/limit-orders\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /**\n * Place a market order directly on a named venue — no prior quote needed.\n * Always produces exactly one order. `externalId` is required and unique\n * within your app — two different users of the same app cannot share one —\n * so retrying a timed-out call with the same value is safe.\n */\n async placeOrder(params: PlaceOrderParams): Promise<PlaceOrderResponse> {\n return this.request<PlaceOrderResponse>(\"/execution/orders\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Redeem resolved winning positions by venue market outcome ids. */\n async redeem(body: RedeemRequest): Promise<RedeemResponse> {\n return this.request<RedeemResponse>(\"/execution/redeem\", {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n }\n\n /** List the authenticated user's managed balance refill policies. */\n async getBalanceRefillPolicies(): Promise<BalanceRefillPolicy[]> {\n return this.request<BalanceRefillPolicy[]>(\"/execution/balance-refill-policies\");\n }\n\n /** Create a managed-USDC refill policy for a target chain. */\n async createBalanceRefillPolicy(\n params: CreateBalanceRefillPolicyParams,\n ): Promise<BalanceRefillPolicy> {\n return this.request<BalanceRefillPolicy>(\"/execution/balance-refill-policies\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Update thresholds or pause/resume an existing balance refill policy. */\n async updateBalanceRefillPolicy(\n policyId: string,\n params: UpdateBalanceRefillPolicyParams,\n ): Promise<BalanceRefillPolicy> {\n if (!policyId) throw new Error(\"policyId is required\");\n return this.request<BalanceRefillPolicy>(\n `/execution/balance-refill-policies/${encodeURIComponent(policyId)}`,\n { method: \"PATCH\", body: JSON.stringify(params) },\n );\n }\n\n /** Return the 25 most recent attempts for a refill policy. */\n async getBalanceRefillAttempts(policyId: string): Promise<BalanceRefillAttempt[]> {\n if (!policyId) throw new Error(\"policyId is required\");\n return this.request<BalanceRefillAttempt[]>(\n `/execution/balance-refill-policies/${encodeURIComponent(policyId)}/attempts`,\n );\n }\n\n /** Withdraw funds from managed wallets to an external address. */\n async withdrawManaged(params: WithdrawManagedParams): Promise<WithdrawManagedResponse> {\n return this.request<WithdrawManagedResponse>(\"/execution/withdraw\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /**\n * Preview a withdrawal — real fee + receive estimate without creating one.\n * Optional: `withdrawManaged` does NOT require a prior preview, so partners\n * integrating against the SDK can ignore this entirely.\n */\n async withdrawPreview(params: WithdrawPreviewParams): Promise<WithdrawPreviewResponse> {\n return this.request<WithdrawPreviewResponse>(\"/execution/withdraw/preview\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Quote maximum deliverable withdrawal amount for a token and destination chain. */\n async getWithdrawalQuote(params: WithdrawalQuoteParams): Promise<WithdrawalQuoteResponse> {\n return this.request<WithdrawalQuoteResponse>(\"/execution/withdrawable/quote\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /**\n * Read the current persisted state of a withdrawal. Used as a backfill for\n * the WS lifecycle channel: the client polls this on hook mount and on WS\n * reconnect to recover events that fired before the listener was attached\n * or while the socket was disconnected. Same response shape as\n * `withdrawManaged`.\n */\n async getWithdrawalStatus(withdrawalId: string): Promise<WithdrawManagedResponse> {\n if (!withdrawalId) {\n throw new Error(\"withdrawalId is required\");\n }\n return this.request<WithdrawManagedResponse>(\n `/execution/withdrawals/${encodeURIComponent(withdrawalId)}`,\n );\n }\n\n /** Trigger an on-chain balance sync for all tracked tokens across all chains. */\n async syncManagedBalances(): Promise<SyncBalancesResponse> {\n return this.request<SyncBalancesResponse>(\"/execution/sync-balances\", {\n method: \"POST\",\n body: JSON.stringify({}),\n });\n }\n\n /** Get managed wallet deposit addresses (EVM + Solana). Returns 202 shape while provisioning. */\n async getDepositAddresses(): Promise<DepositAddressesResponse> {\n return this.request<DepositAddressesResponse>(\"/execution/deposit-addresses\");\n }\n\n /**\n * Internal: record that a deposit tx was initiated via the in-app\n * connected-wallet flow, so the activity feed can label it correctly.\n * Best-effort — callers should not block the UX on this.\n */\n async recordDepositIntent(body: { chainId: number; txHash: string }): Promise<void> {\n await this.request<{ success: true }>(\n \"/execution/deposit-intent\",\n this.buildAuthRequestInit({ method: \"POST\", body: JSON.stringify(body) }),\n );\n }\n\n /** Get open positions grouped by matched market with per-venue breakdown. */\n async getPositions(params?: GetPositionsParams): Promise<PaginatedResponse<PositionGroup>> {\n const query: Record<string, string | string[]> = {};\n if (params?.cursor) query.cursor = params.cursor;\n if (params?.limit != null) query.limit = String(params.limit);\n if (params?.status) query.status = params.status;\n if (params?.mode) query.mode = params.mode;\n if (params?.categoryIds?.length) query.categoryIds = params.categoryIds;\n if (params?.sort) query.sort = params.sort;\n return this.request<PaginatedResponse<PositionGroup>>(\"/execution/positions\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n });\n }\n\n // --- Ramp ---\n\n /** Get crypto purchase quotes. */\n async getRampQuotes(params: RampQuoteRequest): Promise<RampQuote[]> {\n return this.request<RampQuote[]>(\"/ramp/quotes\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Create a ramp widget session for checkout. */\n async createRampSession(params: RampSessionRequest): Promise<RampWidgetSession> {\n return this.request<RampWidgetSession>(\"/ramp/session\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Authoritative shared Novig/ProphetX KYC status for the current managed wallet. */\n async getSharedKycStatus(): Promise<{ verified: boolean }> {\n return this.request<{ verified: boolean }>(\"/kyc/status\");\n }\n\n /** Start shared KYC; already-verified wallets need no redirect. Kalshi v2 is not applicable. */\n async initiateKyc(\n venue: string,\n redirectUri: string,\n ): Promise<{ status: string; kycUrl?: string }> {\n return this.request<{ status: string; kycUrl?: string }>(`/kyc/${venue}`, {\n method: \"POST\",\n body: JSON.stringify({ redirectUri }),\n });\n }\n}\n","import { computeBestSplitsByAmount as computeBestSplitsByAmountFromCommon } from \"@agg/common/types-only\";\n\nexport type { SplitsByAmountResult } from \"@agg/common/types-only\";\n\nexport const computeBestSplitsByAmount = computeBestSplitsByAmountFromCommon;\n","import type { Candle } from \"./candle-builder\";\n\n/**\n * Merge forming candles from matched venues into one aggregate.\n * Open/Close: volume-weighted average (simple average if all v=0).\n * High: max across venues. Low: min across venues. Volume: sum.\n */\nexport function mergeCandles(candles: (Candle | null | undefined)[]): Candle | null {\n const valid = candles.filter((c): c is Candle => c != null);\n if (valid.length === 0) return null;\n if (valid.length === 1) return { ...valid[0] };\n\n const totalVolume = valid.reduce((sum, c) => sum + c.v, 0);\n\n let o: number;\n let c: number;\n if (totalVolume > 0) {\n o = valid.reduce((sum, candle) => sum + candle.o * candle.v, 0) / totalVolume;\n c = valid.reduce((sum, candle) => sum + candle.c * candle.v, 0) / totalVolume;\n } else {\n o = valid.reduce((sum, candle) => sum + candle.o, 0) / valid.length;\n c = valid.reduce((sum, candle) => sum + candle.c, 0) / valid.length;\n }\n\n return {\n openTime: valid[0].openTime,\n o,\n h: Math.max(...valid.map((candle) => candle.h)),\n l: Math.min(...valid.map((candle) => candle.l)),\n c,\n v: totalVolume,\n tradeCount: valid.reduce((sum, candle) => sum + candle.tradeCount, 0),\n isFinal: valid.every((candle) => candle.isFinal),\n };\n}\n\n/**\n * Merge arrays of closed candles from multiple venues, aligned by openTime.\n * For each openTime present in ANY venue, produces one merged candle.\n */\nexport function mergeClosedCandles(candleArrays: Candle[][]): Candle[] {\n const byTime = new Map<number, Candle[]>();\n\n for (const arr of candleArrays) {\n for (const candle of arr) {\n const group = byTime.get(candle.openTime);\n if (group) {\n group.push(candle);\n } else {\n byTime.set(candle.openTime, [candle]);\n }\n }\n }\n\n const merged: Candle[] = [];\n for (const [, group] of byTime) {\n const result = mergeCandles(group);\n if (result) merged.push(result);\n }\n\n merged.sort((a, b) => a.openTime - b.openTime);\n return merged;\n}\n\n/** Simple average of available midpoints. */\nexport function aggregateMidpoint(midpoints: (number | null | undefined)[]): number | null {\n const valid = midpoints.filter((m): m is number => m != null && Number.isFinite(m));\n if (valid.length === 0) return null;\n return valid.reduce((sum, m) => sum + m, 0) / valid.length;\n}\n","import { Venue, type HostedVenueAccount } from \"@agg/common\";\nimport type { AggClient } from \"./client\";\nimport type { SmartRouteResponse, WithdrawManagedParams, WithdrawManagedResponse } from \"./types\";\n\n/** An exact transfer intent survives a page reload before its response arrives.\n * The normal withdrawal service owns dispatch, bridging and reconciliation. */\nexport interface HostedVenueFundingIntent {\n version: 1;\n accountId: string;\n environment: \"production\";\n request: WithdrawManagedParams & { requestId: string };\n balanceBeforeRaw: string;\n estimatedFeeRaw: string;\n withdrawalId?: string;\n terminal?: boolean;\n}\n\nexport interface HostedVenueFundingOptions {\n venue: \"betdex\";\n requiredRaw: string;\n /** Scope this store to the current application/user/venue. */\n journal: {\n load(): HostedVenueFundingIntent | null;\n save(intent: HostedVenueFundingIntent | null): void;\n };\n createRequestId(): string;\n /** Called around every await and before every write. Abort on sign-out/user change. */\n assertActive(): void;\n onProgress?: (phase: \"preparing\" | \"transferring\" | \"confirming\") => void;\n timeoutMs?: number;\n}\n\ntype FundingClient = Pick<\n AggClient,\n | \"getHostedVenueAccount\"\n | \"provisionHostedVenueAccount\"\n | \"getHostedVenueDepositAddress\"\n | \"withdrawPreview\"\n | \"withdrawManaged\"\n | \"getWithdrawalStatus\"\n>;\n\nconst SOLANA = 792703809;\nconst atoms = (value: string): bigint => {\n if (!/^(0|[1-9][0-9]{0,31})$/.test(value)) throw new Error(\"Invalid funding amount\");\n return BigInt(value);\n};\nconst spendable = (account: HostedVenueAccount): bigint => {\n if (\n account.status !== \"active\" ||\n !account.accountId ||\n account.environment !== \"production\" ||\n account.balanceStatus !== \"available\" ||\n !account.balance ||\n account.balance.asset !== \"USDC\" ||\n account.balance.decimals !== 6\n )\n throw new Error(\"Venue balance is temporarily unavailable. Please try again.\");\n return atoms(account.balance.availableRaw);\n};\nconst terminal = (status: WithdrawManagedResponse[\"status\"]) =>\n status === \"completed\" || status === \"partial\" || status === \"failed\";\n\n/** Prepare the cash required by an order using the existing managed transfer\n * planner. It selects same-chain cash or bridges supported wallet sources to\n * the user's verified venue address. No venue order is placed here: callers\n * obtain a fresh executable quote after native credit and keep their normal\n * slippage, admission and fill workflow.\n *\n * The currently supported hosted-account API is BETDEX; future hosted venues\n * use the same account/deposit contract and this transfer lifecycle. On-chain\n * venues retain their existing execution-DAG funding.\n */\nexport async function prepareHostedVenueFunding(\n client: FundingClient,\n options: HostedVenueFundingOptions,\n): Promise<{ availableRaw: string; feeRaw: string; withdrawalId?: string }> {\n const { venue, journal, assertActive } = options;\n const required = atoms(options.requiredRaw);\n if (required <= BigInt(0)) throw new Error(\"Invalid funding amount\");\n const deadline = Date.now() + (options.timeoutMs ?? 300_000);\n const check = () => {\n assertActive();\n if (Date.now() >= deadline)\n throw new Error(\"Funding is still confirming. Your transfer is saved; retry to resume it.\");\n };\n const read = async <T>(operation: () => Promise<T>): Promise<T> => {\n check();\n const result = await operation();\n check();\n return result;\n };\n const pause = () => read(() => new Promise<void>((resolve) => setTimeout(resolve, 1000)));\n const save = (intent: HostedVenueFundingIntent | null) => {\n check();\n journal.save(intent);\n };\n options.onProgress?.(\"preparing\");\n let account = await read(() => client.getHostedVenueAccount(venue, { mode: \"live\" }));\n if (account.environment !== \"production\")\n throw new Error(\"This venue account does not accept live wallet transfers.\");\n if (account.status === \"not_created\" && account.provisioningEnabled) {\n account = await read(() => client.provisionHostedVenueAccount(venue, { mode: \"live\" }));\n }\n while (account.status === \"provisioning\") {\n await pause();\n account = await read(() => client.getHostedVenueAccount(venue, { mode: \"live\" }));\n }\n const before = spendable(account);\n let intent = journal.load();\n if (intent?.terminal) {\n // Only a new explicit order attempt reaches here; the prior intent has a\n // persisted terminal result. Never discard an ambiguous in-flight intent.\n save(null);\n intent = null;\n }\n if (!intent && before >= required) return { availableRaw: before.toString(), feeRaw: \"0\" };\n const address = await read(() => client.getHostedVenueDepositAddress(venue, { mode: \"live\" }));\n if (\n address.accountId !== account.accountId ||\n address.environment !== account.environment ||\n address.network !== \"solana\" ||\n address.asset !== \"USDC\" ||\n !/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address.address)\n )\n throw new Error(\"Venue funding address changed. Refresh and try again.\");\n if (intent) {\n if (\n intent.version !== 1 ||\n intent.accountId !== account.accountId ||\n intent.environment !== \"production\" ||\n intent.request.destinationAddress !== address.address ||\n intent.request.destinationChainId !== SOLANA ||\n intent.request.tokenSymbol !== \"USDC\" ||\n !intent.request.requestId ||\n intent.request.max ||\n atoms(intent.request.amountRaw) <= BigInt(0) ||\n atoms(intent.balanceBeforeRaw) < BigInt(0) ||\n atoms(intent.estimatedFeeRaw) < BigInt(0)\n )\n throw new Error(\"Saved funding does not match this account. No new transfer was sent.\");\n } else {\n // The shared transfer API's actual minimum is one token. Any excess stays\n // in this user's own cash account, never becomes extra order spend.\n const deficit = required - before;\n const amountRaw = (deficit < BigInt(1_000_000) ? BigInt(1_000_000) : deficit).toString();\n const request = {\n requestId: options.createRequestId(),\n amountRaw,\n tokenSymbol: \"USDC\" as const,\n destinationAddress: address.address,\n destinationChainId: SOLANA,\n };\n const preview = await read(() => client.withdrawPreview(request));\n if (\n preview.pricingStatus !== \"quoted\" ||\n !preview.receiveAmountRaw ||\n atoms(preview.receiveAmountRaw) <= BigInt(0)\n )\n throw new Error(preview.unviableReason ?? \"No funding route is currently available.\");\n intent = {\n version: 1,\n accountId: account.accountId!,\n environment: \"production\",\n request,\n balanceBeforeRaw: before.toString(),\n estimatedFeeRaw: preview.feeRaw ?? \"0\",\n };\n // Save before mutation. Storage failure or a lost response cannot create\n // a second transfer: the same requestId is replayed at the server.\n save(intent);\n }\n options.onProgress?.(\"transferring\");\n let transfer = intent.withdrawalId\n ? await read(() => client.getWithdrawalStatus(intent!.withdrawalId!))\n : await read(() => client.withdrawManaged(intent!.request));\n const assertTransfer = () => {\n if (\n transfer.requested.amountRaw !== intent!.request.amountRaw ||\n transfer.requested.tokenSymbol !== \"USDC\" ||\n transfer.destination.chainId !== SOLANA ||\n transfer.destination.address !== address.address ||\n transfer.destination.tokenSymbol !== \"USDC\" ||\n (intent!.withdrawalId && transfer.withdrawalId !== intent!.withdrawalId)\n )\n throw new Error(\"Funding response does not match the saved transfer.\");\n };\n assertTransfer();\n intent = { ...intent, withdrawalId: transfer.withdrawalId };\n save(intent);\n while (!terminal(transfer.status)) {\n await pause();\n transfer = await read(() => client.getWithdrawalStatus(intent!.withdrawalId!));\n assertTransfer();\n }\n if (transfer.status === \"failed\") {\n save({ ...intent, terminal: true });\n throw new Error(transfer.errorMessage ?? \"Funding could not complete. No order was placed.\");\n }\n options.onProgress?.(\"confirming\");\n // A chain/bridge acknowledgement is not native credit. Re-read the owned\n // venue balance; cached values expire on the normal account query interval.\n let available = before;\n while (available <= atoms(intent.balanceBeforeRaw)) {\n await pause();\n const current = await read(() => client.getHostedVenueAccount(venue, { mode: \"live\" }));\n if (current.accountId !== account.accountId || current.environment !== account.environment)\n throw new Error(\"Venue account changed while funding. No order was placed.\");\n available = spendable(current);\n }\n const fee = atoms(transfer.expected.feeRaw ?? intent.estimatedFeeRaw);\n save(null);\n return {\n availableRaw: available.toString(),\n feeRaw: fee.toString(),\n withdrawalId: transfer.withdrawalId,\n };\n}\n\n/** Keep the normal priced order flow after preparing native cash. Requotes\n * may use only the outcomes the user selected, within the accepted price and\n * total spend. Transfer fees reduce order spend rather than increasing it. */\nexport async function prepareHostedVenueRoute(\n client: FundingClient & Pick<AggClient, \"getSmartRoute\">,\n options: Omit<HostedVenueFundingOptions, \"requiredRaw\"> & {\n quote: SmartRouteResponse;\n venueMarketOutcomeId: string;\n maxSpend: number;\n slipCapBps: number;\n },\n): Promise<SmartRouteResponse> {\n const fills = options.quote.fills;\n const native = fills.filter((fill) => fill.venue === options.venue);\n const required = native.reduce((sum, fill) => sum + fill.avgPrice * fill.venueQty, 0);\n if (\n !native.length ||\n !Number.isFinite(required) ||\n required <= 0 ||\n !Number.isFinite(options.maxSpend) ||\n options.maxSpend <= 0 ||\n !Number.isFinite(options.slipCapBps) ||\n options.slipCapBps < 0\n )\n throw new Error(\"An available order quote is required before funding.\");\n const funding = await prepareHostedVenueFunding(client, {\n ...options,\n requiredRaw: Math.ceil(required * 1e6).toString(),\n });\n options.assertActive();\n const originalBudget = BigInt(Math.floor(options.maxSpend * 1e6));\n let budget = originalBudget - atoms(funding.feeRaw);\n if (native.length === fills.length) {\n const available = atoms(funding.availableRaw);\n if (available < budget) budget = available;\n }\n if (budget <= BigInt(0))\n throw new Error(\"Funding fees exceeded the order amount. No order was placed.\");\n const venues = [...new Set(fills.map((fill) => fill.venue))];\n const allowedVenues = venues.filter((value): value is Venue =>\n Object.values(Venue).some((venue) => venue === value),\n );\n if (allowedVenues.length !== venues.length) throw new Error(\"Unknown venue in funding quote\");\n const quote = await client.getSmartRoute({\n venueMarketOutcomeId: options.venueMarketOutcomeId,\n maxSpend: Number(budget) / 1e6,\n tradeSide: \"buy\",\n compareVenues: false,\n allowedVenues,\n slipCapBps: options.slipCapBps,\n });\n options.assertActive();\n if (quote.status !== \"ok\" || !quote.quoteId || !quote.fills.length)\n throw new Error(quote.error ?? \"Funds are ready. Refresh the quote and try again.\");\n for (const fill of quote.fills) {\n const original = fills.find(\n (item) =>\n item.venue === fill.venue &&\n item.venueMarketId === fill.venueMarketId &&\n item.venueMarketOutcomeId === fill.venueMarketOutcomeId,\n );\n if (\n !original ||\n !Number.isFinite(fill.avgPrice) ||\n fill.avgPrice <= 0 ||\n fill.avgPrice > original.avgPrice * (1 + options.slipCapBps / 10000) + 1e-9\n )\n throw new Error(\"The price changed while funding. Funds are ready; review the new quote.\");\n }\n if (!Number.isFinite(quote.rawExecCost) || quote.rawExecCost * 1e6 > Number(budget) + 1)\n throw new Error(\"The new quote exceeds the order amount. No order was placed.\");\n return quote;\n}\n","import { AggClient } from \"./client\";\nimport type { AggClientOptions } from \"./types\";\n\nexport { AggWebSocket } from \"./agg-websocket\";\nexport type {\n AggWebSocketCallbacks,\n AggWebSocketOptions,\n AggWebSocketDiagnostics,\n BookWatchdogOptions,\n} from \"./agg-websocket\";\nexport { computeBestSplitsByAmount } from \"./best-split\";\nexport type { SplitsByAmountResult } from \"./best-split\";\nexport { applyOrderbookDelta, computeChecksum, snapshotToOrderbook } from \"./orderbook-utils\";\nexport type { OrderbookLevel, OrderbookState, VenueOrderbookLevel } from \"./orderbook-utils\";\nexport { RECURRENCE_CADENCES } from \"./types\";\nexport {\n OPTIONAL_SIGNATURE_TIMEOUT_MS,\n SELF_CUSTODY_FILL_TIMEOUT_MS,\n SELF_CUSTODY_POLL_INTERVAL_MS,\n TERMINAL_EXECUTION_STATES,\n} from \"./types\";\nexport type { SignatureRequest, SignatureRequestType, SignerFn } from \"./types\";\nexport {\n adjustLimitPriceRawToTick,\n LIMIT_PRICE_RAW_SCALE,\n type LimitPriceSide,\n type LimitPriceTickAdjustment,\n} from \"@agg/common\";\nexport type {\n AggAuthPrivyVerifyBody,\n AggAuthVerifyBody,\n AggAuthWalletVerifyBody,\n AggClientAuthOptions,\n AggClientOptions,\n AggAuthDeliveryMode,\n AggAuthProviderType,\n AggAuthStartBody,\n AggAuthStartResult,\n AggLinkAccountBody,\n AggLinkAccountConfirmResult,\n AggLinkAccountResult,\n AggLinkAccountWalletConfirmBody,\n AggClientSessionInput,\n AggregatedOrderbookLevel,\n AggregatedOrderbookResponse,\n AggSessionUser,\n AuthStatus,\n BatchMidpointsResponse,\n BatchOrderbooksResponse,\n BalanceRefillAttempt,\n BalanceRefillAttemptStatus,\n BalanceRefillPolicy,\n BalanceRefillPolicyStatus,\n CancelManagedExecutionResponse,\n ChartBarsResponse,\n ChartBarsMeta,\n ChartCandle,\n ChartResolution,\n ChartVenueCandles,\n CorrelatedMarketCascadeItem,\n CorrelatedMarketCascadeResponse,\n CorrelatedMarketQueryResult,\n CorrelatedMarketsStatus,\n CorrelatedMarketSide,\n CorrelatedMarketSignal,\n CorrelatedMarketSignalBatch,\n CorrelatedMarketSignalDirection,\n CreateBalanceRefillPolicyParams,\n CryptoReferencePriceError,\n CryptoReferencePriceExternalMarketInput,\n CryptoReferencePriceMarketInput,\n CryptoReferencePricesResponse,\n CryptoReferencePriceResult,\n CryptoReferencePriceSource,\n CryptoReferencePriceTarget,\n DepositAddressesPendingResponse,\n DepositAddressesReadyResponse,\n DepositAddressesResponse,\n DepositAddressesSupportedChain,\n DepositAddressesToken,\n ExecuteManagedParams,\n ExecuteManagedResponse,\n ExecutionOrderItem,\n ExecutionMode,\n ExecutionOrdersQuery,\n ExecutionDagProgress,\n ExecutionOverallState,\n ExecutionStatusOrder,\n ExecutionStatusQuery,\n ExecutionStatusResponse,\n ExecutionStatusStep,\n ExecutionDisplayStepKind,\n ExecutionDisplayGroupStatus,\n UserActivityBridge,\n UserActivityDeposit,\n UserActivityItem,\n UserActivityQuery,\n UserActivityRedeem,\n UserActivityRedeemLeg,\n UserActivityTrade,\n UserActivityType,\n UserActivityUserOp,\n UserActivityWithdrawal,\n LeaderboardMetric,\n LeaderboardQuery,\n LeaderboardRow,\n LeaderboardSeries,\n LeaderboardSeriesPoint,\n LeaderboardSeriesQuery,\n LeaderboardStats,\n ExecutionPositionGroup,\n ExecutionPositionsQuery,\n GetOrdersParams,\n GetCryptoReferencePricesOptions,\n GetPositionsParams,\n LimitOrderTimeInForce,\n ListRecurringCryptoMarketsOptions,\n NewsFeedArticleFeedItem,\n NewsFeedArticleFeedResponse,\n NewsFeedArticleWithSummary,\n NewsFeedLinkedMarket,\n NewsFeedListResponse,\n NewsFeedMarketFeedArticle,\n NewsFeedMarketFeedItem,\n NewsFeedMarketFeedResponse,\n NewsFeedMarketNewsParams,\n NewsFeedMarketNewsResponse,\n NewsFeedMarketNewsResult,\n NewsFeedPageOptions,\n NewsFeedStatusResponse,\n OrderbookQuoteFill,\n OrderbookBatchItemError,\n OrderbookBatchItemErrorCode,\n OrderbookBatchItemStatus,\n OrderbookQuoteParams,\n OrderbookQuoteResponse,\n OrderbookServiceUnavailableError,\n OrderbooksOnlyError,\n OrderListQuery,\n PaginatedResponse,\n CreatePaperTradingAccountParams,\n PaperTradingAccount,\n PaperTradingAccountsPage,\n PaperTradingAppOptions,\n PaperTradingBalanceAdjustment,\n PaperTradingBalanceResponse,\n PaperTradingLiquidityStatus,\n PaperTradingListParams,\n PaperTradingMarkSource,\n PaperTradingOrder,\n PaperTradingOrdersPage,\n PaperTradingPortfolio,\n PaperTradingPosition,\n PaperTradingPositionsPage,\n PlaceLimitOrderParams,\n CancelOrderSignature,\n CancelVenueOrderParams,\n PlaceLimitOrderResponse,\n PlacePaperTradingOrderParams,\n PositionRedeemStatus,\n PersistedAuthSnapshot,\n RedeemLegResult,\n RedeemLegStatus,\n RedeemRequest,\n RecurrenceCadence,\n RecurrenceFilter,\n RecurringCryptoDuration,\n RecurringCryptoDurationInput,\n RecurringCryptoComparisonPoint,\n RecurringCryptoComparisonPriceSource,\n RecurringCryptoMarketMetrics,\n RecurringCryptoMarketsResponse,\n RecurringCryptoOutcome,\n RecurringCryptoOrderbookDepthLevel,\n RecurringCryptoOrderbookDepthSide,\n RecurringCryptoOutcomeOrderbookDepth,\n RecurringCryptoPriceComparison,\n RecurringCryptoReferencePrice,\n RecurringCryptoResolution,\n RecurringCryptoSourceConfidence,\n RecurringCryptoVenueMarket,\n RecurringCryptoWindowComparisons,\n RecurringCryptoWindowMarket,\n RedeemResponse,\n ResetPaperTradingAccountParams,\n ResolveCorrelatedMarketsParams,\n ResolveCorrelatedMarketsResponse,\n ResolvedCorrelatedMarketsResponse,\n RequestedOrderbookMarket,\n SimpleOrderbookLevel,\n SmartRouteAllocation,\n SmartRouteBridgeStep,\n SmartRouteFeeBreakdown,\n SmartRouteFill,\n SmartRouteParams,\n SmartRouteResponse,\n SmartRouteSettlementLeg,\n SmartRouteSettlementPlan,\n SmartRouteSetupCostLine,\n SmartRouteSide,\n SmartRouteStatus,\n SportsGameStatus,\n SportsLiveParticipant,\n SportsLiveResponse,\n SportsLiveState,\n SmartRouteVenueFill,\n TradeExecutorOrder,\n TradeExecutorOrderListResponse,\n UpdateBalanceRefillPolicyParams,\n SetPaperTradingBalanceParams,\n MidpointRow,\n OutcomeMidpointRow,\n OutcomeOrderbookResponse,\n ValidateManagedParams,\n ValidateManagedResponse,\n ManagedBalancesParams,\n BalanceCustody,\n MarkSource,\n MatchedOrderbookMarket,\n VenueMarketRef,\n VenueOrderbookEntry,\n VenuePriceInfo,\n VenueSoloQuote,\n WithdrawManagedParams,\n WithdrawManagedResponse,\n WithdrawManagedSourceItem,\n WithdrawalSourceTokenSymbol,\n WithdrawalQuoteParams,\n WithdrawalQuoteResponse,\n WithdrawPreviewParams,\n WithdrawPreviewResponse,\n WithdrawTokenSymbol,\n WithdrawalLifecycleStatus,\n WithdrawalSourceStatus,\n WithdrawalLegType,\n WithdrawalLegStatus,\n WithdrawalLeg,\n WithdrawalExpected,\n RampQuoteRequest,\n RampQuote,\n RampSessionRequest,\n RampWidgetSession,\n RpcTokenResponse,\n} from \"./types\";\nexport { AggClient };\nexport { AggApiError, isAggApiError, TurnstileChallengeError } from \"./errors\";\nexport type {\n HostedVenueAccount,\n HostedVenueBalance,\n HostedVenueActivity,\n HostedVenueActivityCode,\n HostedVenueActivityQuery,\n HostedVenueDepositAddress,\n HostedVenueWithdrawal,\n HostedVenueWithdrawalRequest,\n ProvisionHostedVenueAccountBody,\n} from \"@agg/common/types-only\";\nexport type { AggApiErrorInit, AggRateLimitResponse, AggApiFieldError } from \"./errors\";\n\n// WS types — re-export all for partner usage\nexport type {\n DiagnosticCallback,\n DiagnosticEvent,\n WsArbFeedBatch,\n WsArbFeedEntry,\n WsArbMarketUpdate,\n WsAttributedLevel,\n WsAuthenticated,\n WsBalanceUpdate,\n WsCandleInterval,\n WsClientMessage,\n WsConnected,\n WsError,\n WsHeartbeat,\n WsMarketResolved,\n WsMarkSource,\n WsOrderbookDelta,\n WsOrderbookSnapshot,\n WsOrderEvent,\n WsOrderEventType,\n WsRedeemEvent,\n WsOrderSubmitted,\n WsServerMessage,\n WsSubscribed,\n WsTrade,\n WsUnsubscribed,\n WsVenueBook,\n WsVenueInfo,\n WsVenueLevel,\n WsWithdrawalLegStatus,\n WsWithdrawalLifecycleEvent,\n WsWithdrawalLifecycleLeg,\n WsWithdrawalLifecycleStatus,\n} from \"./ws-types\";\n\n// Candle computation (chart-library-agnostic)\nexport { CandleBuilder } from \"./candle-builder\";\nexport { toChecksumAddress } from \"./eip55\";\nexport type { Candle, CandleInterval } from \"./candle-builder\";\nexport { aggregateMidpoint, mergeCandles, mergeClosedCandles } from \"./market-aggregator\";\n\nexport function createAggClient(options: AggClientOptions) {\n return new AggClient(options);\n}\n\nexport * from \"@agg/common/types-only\";\nexport type {\n AppClientConfigResponse,\n AppTradingMode,\n VenueGeoPolicyEntry,\n VenueGeoPolicyResponse,\n} from \"./types\";\n\nexport type {\n MarketView,\n MarketViewBatch,\n CandleTail,\n HistoryRangeRequest,\n} from \"./market-data/engine\";\n\nexport { loadImmutableHistory } from \"./market-history\";\nexport type { LoadImmutableHistoryOptions } from \"./market-history\";\nexport type {\n EventBootstrapResponse,\n ChartHistoryManifest,\n SearchParams,\n SearchResponse,\n} from \"./types\";\n\nexport { prepareHostedVenueFunding, prepareHostedVenueRoute } from \"./hosted-venue-funding\";\nexport type { HostedVenueFundingIntent, HostedVenueFundingOptions } from \"./hosted-venue-funding\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["computeBestSplitsByAmount","computeBestSplitsByAmountFromCommon"],"sources":["../../common/src/enums/venue.ts","../../common/src/enums/image-size.ts","../../common/src/enums/account.ts","../../common/src/enums/chain.ts","../../common/src/enums/market-status.ts","../../common/src/enums/trading.ts","../../common/src/utils/format-market-display.ts","../../common/src/utils/auth.ts","../../common/src/utils/validate.ts","../../common/src/utils/trading-splits.ts","../../common/src/utils/image-url.ts","../../common/src/utils/venue-market-cluster.ts","../../common/src/utils/sort-venues.ts","../../common/src/utils/venue-url.ts","../../common/src/utils/limit-price-ticks.ts","../../common/src/utils/balance-refill.ts","../src/retry-after.ts","../src/errors.ts","../src/eip55.ts","../src/types.ts","../src/client.ts","../src/best-split.ts","../src/market-aggregator.ts","../src/hosted-venue-funding.ts","../src/index.ts"],"sourcesContent":["/** Use these constants instead of hardcoding \"kalshi\" or \"polymarket\". */\nexport enum Venue {\n kalshi = \"kalshi\",\n polymarket = \"polymarket\",\n limitless = \"limitless\",\n opinion = \"opinion\",\n predict = \"predict\",\n pred = \"pred\",\n tiprun = \"tiprun\",\n probable = \"probable\",\n myriad = \"myriad\",\n hyperliquid = \"hyperliquid\",\n novig = \"novig\",\n prophetx = \"prophetx\",\n betdex = \"betdex\",\n}\n\n/** Single source of truth for venue identifiers. */\nexport const VENUES = [\n Venue.kalshi,\n Venue.polymarket,\n Venue.limitless,\n Venue.opinion,\n Venue.predict,\n Venue.pred,\n Venue.tiprun,\n Venue.probable,\n Venue.myriad,\n Venue.hyperliquid,\n Venue.novig,\n Venue.prophetx,\n Venue.betdex,\n] as const;\n\n/** Canonical destination chain for venues with on-chain funding or settlement. */\nexport const VENUE_CHAIN_IDS: Partial<Record<Venue, number>> = {\n [Venue.kalshi]: 792703809,\n [Venue.polymarket]: 137,\n [Venue.limitless]: 8453,\n [Venue.predict]: 56,\n [Venue.pred]: 8453,\n [Venue.tiprun]: 42161,\n [Venue.myriad]: 56,\n [Venue.hyperliquid]: 1337,\n [Venue.novig]: 792703809,\n [Venue.prophetx]: 792703809,\n};\n\n/**\n * Venues that participate in new discovery, market-data, and execution flows.\n *\n * Keep retired venues in {@link Venue} and {@link VENUES}: historical orders,\n * positions, settlement, and redemption still rely on those identifiers.\n * Re-activating a venue is therefore an intentional code change here rather\n * than a runtime configuration toggle.\n */\nexport const ACTIVE_VENUES = [\n Venue.kalshi,\n Venue.polymarket,\n Venue.limitless,\n Venue.opinion,\n Venue.predict,\n Venue.pred,\n Venue.tiprun,\n Venue.probable,\n Venue.myriad,\n Venue.hyperliquid,\n Venue.novig,\n Venue.prophetx,\n Venue.betdex,\n] as const;\n\n/**\n * Venues excluded from new user-facing activity. BETDEX is active at the\n * compile-time boundary now that discovery and execution are implemented;\n * partner rollout remains controlled by app policy and runtime flags.\n */\nexport const INACTIVE_VENUES = [] as const;\n\n/**\n * Venues hidden from an app that has no explicit venue configuration of its\n * own — and the value stamped onto every new App via the `disabledVenues`\n * schema default.\n *\n * Deliberately SEPARATE from {@link INACTIVE_VENUES}. `INACTIVE_VENUES` answers \"has this venue\n * launched?\" — a compile-time fact that also drives {@link isVenueInactive},\n * the published SDK contract and the UI's tab-flash guard. This answers \"what\n * does an unconfigured caller see?\", which an App row is allowed to override\n * in both directions. PRED, Novig and ProphetX are globally launched but remain off\n * by default until a super admin opts a specific app in.\n *\n * A venue leaves this set only when it should become visible to apps that\n * never opted in — which is a data migration, not a constant edit.\n */\nexport const DEFAULT_DISABLED_VENUES = [\n Venue.pred,\n Venue.tiprun,\n Venue.novig,\n Venue.prophetx,\n Venue.betdex,\n] as const;\n\nconst ACTIVE_VENUE_SET = new Set<string>(ACTIVE_VENUES);\nconst INACTIVE_VENUE_SET = new Set<string>(INACTIVE_VENUES);\n\nfunction normalizeVenue(venue: string): string {\n return venue.trim().toLowerCase();\n}\n\n/** Whether a venue may participate in new user-facing activity. */\nexport function isVenueActive(venue: string): boolean {\n // Engine and API wire values are already canonical lowercase strings. Keep\n // that realtime path allocation-free; only normalize compatibility inputs.\n if (ACTIVE_VENUE_SET.has(venue)) return true;\n if (INACTIVE_VENUE_SET.has(venue)) return false;\n return ACTIVE_VENUE_SET.has(normalizeVenue(venue));\n}\n\n/** Whether a venue is intentionally retained only for wind-down/history flows. */\nexport function isVenueInactive(venue: string): boolean {\n if (INACTIVE_VENUE_SET.has(venue)) return true;\n if (ACTIVE_VENUE_SET.has(venue)) return false;\n return INACTIVE_VENUE_SET.has(normalizeVenue(venue));\n}\n\n/**\n * Data-plane visibility (listings/search/orderbook DISPLAY). Distinct from\n * {@link isVenueActive} (execution/routing) — this predicate never affects\n * whether a venue can trade. `dataVisibleOverride` un-hides specific venues\n * for DATA surfaces only; callers pass an env-derived list.\n */\nexport function isVenueDataVisible(\n venue: string,\n dataVisibleOverride: readonly Venue[] = [],\n): boolean {\n if (isVenueActive(venue)) return true;\n const n = normalizeVenue(venue);\n return dataVisibleOverride.some((v) => normalizeVenue(v) === n);\n}\n\n/**\n * Merge app-specific disabled venues with the compile-time retired set, then\n * remove any venue explicitly opted into data visibility via\n * `dataVisibleVenues` (see {@link isVenueDataVisible}). Results use the\n * canonical {@link VENUES} order and ignore unknown values.\n */\nexport function getEffectiveDisabledVenues(\n disabledVenues?: readonly (Venue | string)[],\n dataVisibleVenues: readonly Venue[] = [],\n): Venue[] {\n // `undefined` means NO APP CONTEXT — an admin-tier or authless discovery\n // call, or a global cron. There is no App row to consult and none to\n // backfill, so fall back to the platform default rather than showing\n // everything. The env override still applies here, which is what lets\n // staging verify a venue before any app opts in.\n if (disabledVenues === undefined) {\n const disabled = new Set<string>(DEFAULT_DISABLED_VENUES);\n for (const venue of dataVisibleVenues) disabled.delete(normalizeVenue(venue));\n return VENUES.filter((venue) => disabled.has(venue));\n }\n\n // An App row is authoritative in BOTH directions. It may reveal a venue the\n // platform hides by default (a super admin opted this app in) and it may hide\n // one the platform shows. Notably the env override is NOT applied here: it\n // used to delete from this set unconditionally, which erased an app's own\n // entry and made per-app hiding impossible wherever the override was set.\n const disabled = new Set(disabledVenues.map(normalizeVenue));\n return VENUES.filter((venue) => disabled.has(venue));\n}\n","export enum ImageSize {\n sm = 44,\n md = 48,\n lg = 60,\n // Retina (2x) variants. The processor Lambda has emitted these since\n // 2026-07-31; older assets lack them until the backfill runs, so consumers\n // must fall back to a 1x variant when one 404s.\n xl = 80,\n xxl = 96,\n xxxl = 120,\n original = 0,\n}\n\n// Keep in sync with SIZES in infra/src/handlers/image-processor.ts.\nexport const IMAGE_SIZES = [\n ImageSize.sm,\n ImageSize.md,\n ImageSize.lg,\n ImageSize.xl,\n ImageSize.xxl,\n ImageSize.xxxl,\n] as const;\n\n/** Variants sized for 2x displays. */\nexport const RETINA_IMAGE_SIZES = [ImageSize.xl, ImageSize.xxl, ImageSize.xxxl] as const;\n","export enum AccountType {\n oauth = \"oauth\",\n siwe = \"siwe\",\n siws = \"siws\",\n email = \"email\",\n}\n\nexport enum AccountProvider {\n wallet = \"wallet\",\n solana_wallet = \"solana_wallet\",\n google = \"google\",\n twitter = \"twitter\",\n apple = \"apple\",\n email = \"email\",\n}\n","export enum Chain {\n evm = \"evm\",\n svm = \"svm\",\n}\n","export enum MatchStatus {\n pending = \"pending\",\n unmatched = \"unmatched\",\n review = \"review\",\n matched = \"matched\",\n verified = \"verified\",\n rejected = \"rejected\",\n}\n\nexport enum MatchType {\n manual = \"manual\",\n llm = \"llm\",\n}\n\n/** Match statuses considered \"confirmed\" for user-facing data (orderbooks, listings, aggregation). */\nexport const CONFIRMED_MATCH_STATUSES: MatchStatus[] = [MatchStatus.matched, MatchStatus.verified];\n\nexport enum MarketStatus {\n open = \"open\",\n closed = \"closed\",\n resolved = \"resolved\",\n unopened = \"unopened\",\n paused = \"paused\",\n}\n","export enum OrderStatus {\n pending = \"pending\",\n signing = \"signing\",\n pending_bridge = \"pending_bridge\",\n submitting = \"submitting\",\n submitted = \"submitted\",\n open = \"open\",\n partially_filled_open = \"partially_filled_open\",\n cancel_pending = \"cancel_pending\",\n filled = \"filled\",\n partial_fill = \"partial_fill\",\n failed = \"failed\",\n expired = \"expired\",\n cancelled = \"cancelled\",\n}\n\nexport enum TradeSide {\n Buy = \"buy\",\n Sell = \"sell\",\n}\n\nexport enum OrderType {\n Market = \"market\",\n Limit = \"limit\",\n}\n\nexport enum TimeInForce {\n GTC = \"GTC\",\n GTD = \"GTD\",\n FOK = \"FOK\",\n FAK = \"FAK\",\n IOC = \"IOC\",\n ALO = \"ALO\",\n}\n","import { Venue } from \"../enums/venue\";\n\n/**\n * API response-boundary formatters for market display fields.\n *\n * Called by the response mappers (mapVenueMarketRow, toVenueEventDto) to\n * produce display-ready text before it reaches the client. Internal code\n * (matching, sorting, DB) uses the raw DB values.\n */\n\n/**\n * Resolve the display label for a VenueMarketOutcome.\n *\n * - **Kalshi:** Always return `label`. Kalshi's label IS the canonical\n * display text (\"Yes\"/\"No\"); `title` is a subtitle shown elsewhere.\n * - **All other venues:** Return `title` if present and non-empty,\n * otherwise `label`. Polymarket normalizes binary outcomes to\n * \"Yes\"/\"No\" labels and stores the original descriptive text in `title`\n * (e.g. label=\"Yes\", title=\"Trump Wins\").\n *\n * When `market` context is provided and the outcome's `title` duplicates\n * the market's `question` (a known Limitless group-sub-market quirk where\n * the driver name lands on every outcome's title), fall back to `label`\n * so \"Yes\"/\"No\" remain distinguishable instead of both collapsing to the\n * market subject.\n */\nexport function formatOutcomeLabel(\n venue: Venue,\n outcome: { label: string; title?: string | null },\n _market?: { question?: string | null },\n): string {\n // ON FE we check at places where label is Yes or No so we should return the label directly\n // and then on FE display we would use title instead of label directly so user sees it clearly.\n return outcome.label;\n\n // @deprecated\n // if (venue === Venue.kalshi) return outcome.label;\n // const title = outcome.title?.trim();\n // if (!title) return outcome.label;\n // const question = market?.question?.trim();\n // if (question && title === question) return outcome.label;\n // return title;\n}\n\n/**\n * Resolve the display question for a VenueMarket.\n *\n * - **Kalshi:** Return the first outcome's `title` if available. Kalshi\n * market tickers (e.g. \"INXD-26APR08-T7563.43\") are stored in\n * `question` but the human-readable text is in the outcome's `title`\n * (e.g. \"S&P 500 closes above 7,563.43\"). Falls back to `question` if\n * no outcome title exists.\n * - **All other venues:** Return `question` as-is (already human-readable).\n */\nexport function formatMarketQuestion(\n venue: Venue,\n market: {\n question: string;\n shortTitle?: string | null;\n venueMarketOutcomes?: Array<{ label: string; title?: string | null }>;\n },\n): string {\n if (market.shortTitle?.trim()) return market.shortTitle.trim();\n if (venue === Venue.kalshi) {\n const firstTitle = market.venueMarketOutcomes?.[0]?.title?.trim();\n if (firstTitle) return firstTitle;\n }\n return market.question.trim();\n}\n\n/**\n * Resolve the display title for a VenueMarketOutcome.\n *\n * Returns `null` when every outcome on the market shares the same `title`\n * (Kalshi binary markets often store the same human-readable phrase on\n * both Yes/No outcomes — repeating it on each option is redundant). The\n * frontend should fall back to `label` in that case.\n *\n * Otherwise returns the outcome's stored `title` verbatim (or `null` when\n * unset). The DB `label` is always returned untouched by this helper.\n *\n * Polymarket player-prop fallback: when a binary Yes/No outcome has no\n * stored title (Gamma sends `outcomes=[\"Yes\",\"No\"]` for these markets,\n * e.g. *\"Mikal Bridges: Rebounds O/U 2.5\"*), derive `Over`/`Under` from\n * the question's `O/U <n>` token so the FE has something meaningful to\n * show. Sports-totals (`[\"Over\",\"Under\"]`) and spread markets\n * (`[\"<TeamA>\",\"<TeamB>\"]`) already get titles from upstream and are\n * unaffected.\n */\nexport function formatOutcomeTitle(\n _venue: Venue,\n outcome: { label: string; title?: string | null },\n market: {\n question?: string | null;\n venueMarketOutcomes?: Array<{ label: string; title?: string | null }>;\n },\n): string | null {\n const outcomes = market.venueMarketOutcomes ?? [];\n if (outcomes.length >= 2) {\n const normalized = outcomes.map((o) => o.title?.trim() ?? \"\");\n const hasAnyTitle = normalized.some((t) => t.length > 0);\n // Kalshi shape: every outcome carries the same non-empty title — fall\n // back to label so Yes/No stay distinguishable. We only short-circuit\n // here when at least one title is populated; if all are empty, fall\n // through to the O/U derivation below.\n if (hasAnyTitle && normalized.every((t) => t === normalized[0])) return null;\n }\n const title = outcome.title?.trim();\n if (title) return title;\n return deriveOverUnderTitle(outcome.label, market.question);\n}\n\nconst OVER_UNDER_QUESTION = /\\bO\\/U\\s+\\d/i;\n\nfunction deriveOverUnderTitle(label: string, question: string | null | undefined): string | null {\n if (!question || !OVER_UNDER_QUESTION.test(question)) return null;\n const normalized = label.trim().toLowerCase();\n if (normalized === \"yes\") return \"Over\";\n if (normalized === \"no\") return \"Under\";\n return null;\n}\n","import type { UserProfile } from \"../types-standalone\";\nimport { AccountType } from \"../enums/account\";\n\nexport function getWalletAddressFromUserProfile(user: UserProfile | undefined): string | undefined {\n // Prefer explicit wallet oauth account if present\n const oauthWallet =\n user?.accounts?.find(\n (a) => a.type === AccountType.oauth && String(a.provider).toLowerCase() === \"wallet\",\n ) ?? null;\n if (oauthWallet?.providerAccountId) return oauthWallet.providerAccountId;\n\n // Fallback to SIWE account\n const siweAccount = user?.accounts?.find((a) => a.type === AccountType.siwe) ?? null;\n return siweAccount?.providerAccountId ?? undefined;\n}\n","/**\n * Lightweight runtime validation utilities — zero dependencies.\n * Replaces Zod's safeParse/parse for simple type-guard-based validation.\n */\n\n// ── safeParse ────────────────────────────────────────────────────────\n\nexport type SafeParseSuccess<T> = { success: true; data: T };\nexport type SafeParseFailure = { success: false; error?: { issues: Array<{ message: string }> } };\nexport type SafeParseResult<T> = SafeParseSuccess<T> | SafeParseFailure;\n\n/** Generic safeParse — drop-in replacement for zod's schema.safeParse(). */\nexport function safeParse<T>(value: unknown, guard: (v: unknown) => v is T): SafeParseResult<T> {\n if (guard(value)) return { success: true, data: value };\n return { success: false };\n}\n\n/** Throwing parse — drop-in replacement for zod's schema.parse(). */\nexport function parse<T>(\n value: unknown,\n guard: (v: unknown) => v is T,\n message = \"Validation failed\",\n): T {\n if (guard(value)) return value;\n const err = new Error(message);\n (err as any).issues = [{ message }];\n throw err;\n}\n\n// ── Guard factories ──────────────────────────────────────────────────\n\n/** Creates a type guard for a set of string values (enums, string unions). */\nexport function isEnum<T extends string>(values: ReadonlySet<string>): (v: unknown) => v is T {\n return (v: unknown): v is T => typeof v === \"string\" && values.has(v);\n}\n\n/** Creates a type guard for a set of string values from an enum or array. */\nexport function enumGuard<T extends string>(\n source: Record<string, T> | readonly T[],\n): (v: unknown) => v is T {\n const values = new Set<string>(Array.isArray(source) ? source : Object.values(source));\n return isEnum<T>(values);\n}\n\n// ── Built-in guards ──────────────────────────────────────────────────\n\n/** Finite, non-negative number. */\nexport function isFiniteNonNeg(v: unknown): v is number {\n return typeof v === \"number\" && Number.isFinite(v) && v >= 0;\n}\n\n/** Non-empty string. */\nexport function isNonEmptyString(v: unknown): v is string {\n return typeof v === \"string\" && v.length > 0;\n}\n\n/** Object with specific keys present and of the right primitive type. */\nexport function hasShape<T>(v: unknown, checks: Record<string, (val: unknown) => boolean>): v is T {\n if (typeof v !== \"object\" || v === null) return false;\n const obj = v as Record<string, unknown>;\n for (const [key, check] of Object.entries(checks)) {\n if (!(key in obj) || !check(obj[key])) return false;\n }\n return true;\n}\n\n// ── Email validation ─────────────────────────────────────────────────\n\nconst EMAIL_MSG = \"Enter a valid email address.\";\nconst EMAIL_MAX_LEN = 254; // RFC 5321\n\n/**\n * Linear-scan email check matching /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/ semantics\n * without polynomial-regex backtracking. Exported so the API's TypeBox\n * FormatRegistry can share the same implementation.\n */\nexport function isEmail(v: string): boolean {\n const n = v.length;\n if (n === 0 || n > EMAIL_MAX_LEN) return false;\n let atIdx = -1;\n for (let i = 0; i < n; i++) {\n const c = v.charCodeAt(i);\n if (c === 32 || (c >= 9 && c <= 13)) return false;\n if (c === 0x40 /* @ */) {\n if (atIdx !== -1) return false;\n atIdx = i;\n }\n }\n if (atIdx <= 0 || atIdx === n - 1) return false;\n for (let i = atIdx + 2; i < n - 1; i++) {\n if (v.charCodeAt(i) === 0x2e /* . */) return true;\n }\n return false;\n}\n\n/** Validates + trims email. Returns safeParse-compatible result with error.issues shape. */\nexport function parseEmail(raw: string): SafeParseResult<{ email: string }> {\n const email = raw.trim();\n if (!isEmail(email)) {\n return { success: false, error: { issues: [{ message: EMAIL_MSG }] } };\n }\n return { success: true, data: { email } };\n}\n\n/** Strict email parse — throws with .issues for catch-block compat. */\nexport function parseEmailStrict(raw: string): { email: string } {\n const result = parseEmail(raw);\n if (!result.success) {\n const err = new Error(EMAIL_MSG);\n (err as any).issues = result.error?.issues;\n throw err;\n }\n return result.data;\n}\n","import type { Orderbook, TradeSplit, VenueMarket, VenueMarketOutcome } from \"../types-standalone\";\nimport type { Venue } from \"../enums/venue\";\nimport { TradeSide } from \"../enums/trading\";\n\ninterface Level {\n venue: Venue;\n venueMarketOutcomeId: string;\n outcomeExternalIdentifier: string | undefined;\n price: number;\n size: number;\n negRisk: boolean;\n}\n\nexport interface SplitsByAmountResult {\n splits: TradeSplit[];\n totalSize: number;\n totalCost: number;\n}\n\nexport function computeBestSplitsByAmount(\n selections: Array<{\n market: VenueMarket;\n outcome: VenueMarketOutcome;\n orderbook: Orderbook;\n }>,\n side: TradeSide,\n maxDollarAmount: number,\n): SplitsByAmountResult {\n if (selections.length === 0 || maxDollarAmount <= 0) {\n return { splits: [], totalSize: 0, totalCost: 0 };\n }\n\n const levels: Level[] = [];\n for (const o of selections) {\n const venue = o.market.venue as Venue;\n const venueMarketOutcomeId = o.outcome.id;\n const outcomeExternalIdentifier = o.outcome.externalIdentifier ?? undefined;\n if (side === TradeSide.Buy) {\n [...o.orderbook.asks]\n .sort((a, b) => a.price - b.price)\n .forEach((l) =>\n levels.push({\n venue,\n venueMarketOutcomeId,\n outcomeExternalIdentifier,\n price: l.price,\n size: l.size,\n negRisk: o.orderbook.negRisk ?? false,\n }),\n );\n } else {\n [...o.orderbook.bids]\n .sort((a, b) => b.price - a.price)\n .forEach((l) =>\n levels.push({\n venue,\n venueMarketOutcomeId,\n outcomeExternalIdentifier,\n price: 1 - l.price,\n size: l.size,\n negRisk: o.orderbook.negRisk ?? false,\n }),\n );\n }\n }\n\n levels.sort((a, b) => a.price - b.price);\n\n let totalCost = 0;\n const fills: Level[] = [];\n for (const l of levels) {\n if (totalCost >= maxDollarAmount) break;\n const remainingBudget = maxDollarAmount - totalCost;\n const maxSizeAtLevel = Math.min(l.size, remainingBudget / l.price);\n if (maxSizeAtLevel <= 0) continue;\n const take = maxSizeAtLevel;\n fills.push({\n venue: l.venue,\n venueMarketOutcomeId: l.venueMarketOutcomeId,\n outcomeExternalIdentifier: l.outcomeExternalIdentifier,\n price: l.price,\n size: take,\n negRisk: l.negRisk,\n });\n totalCost += l.price * take;\n }\n\n if (fills.length === 0) {\n return { splits: [], totalSize: 0, totalCost: 0 };\n }\n\n const byOutcome: Record<\n string,\n {\n size: number;\n venue: Venue;\n venueMarketOutcomeId: string;\n outcomeExternalIdentifier: string | undefined;\n negRisk: boolean;\n }\n > = {};\n for (const f of fills) {\n const key = `${f.venue}:${f.venueMarketOutcomeId}`;\n const existing = byOutcome[key];\n if (!existing) {\n byOutcome[key] = {\n size: f.size,\n venue: f.venue,\n venueMarketOutcomeId: f.venueMarketOutcomeId,\n outcomeExternalIdentifier: f.outcomeExternalIdentifier,\n negRisk: f.negRisk,\n };\n } else {\n existing.size += f.size;\n }\n }\n\n const splits: TradeSplit[] = [];\n let totalSize = 0;\n for (const key in byOutcome) {\n const { size, venue, venueMarketOutcomeId, outcomeExternalIdentifier, negRisk } =\n byOutcome[key];\n totalSize += size;\n let price = 0;\n if (size > 0) {\n const outcomeFills = fills.filter(\n (f) => f.venue === venue && f.venueMarketOutcomeId === venueMarketOutcomeId,\n );\n if (side === TradeSide.Buy) {\n const rawPrice = Math.max(...outcomeFills.map((f) => f.price));\n price = Math.ceil(rawPrice * 100) / 100;\n } else {\n const rawPrice = Math.min(...outcomeFills.map((f) => 1 - f.price));\n price = Math.floor(rawPrice * 100) / 100;\n }\n }\n splits.push({\n venue,\n venueMarketOutcomeId,\n side,\n price,\n size,\n negRisk,\n outcomeExternalIdentifier,\n });\n }\n return {\n splits,\n totalSize,\n totalCost,\n };\n}\n","import { ImageSize, RETINA_IMAGE_SIZES } from \"../enums/image-size\";\n\n/**\n * Pick the smallest pre-processed variant that covers the requested pixel size.\n * Falls back to `original` when no pre-processed size is large enough.\n */\nfunction pickVariant(px: number): ImageSize {\n if (px <= ImageSize.sm) return ImageSize.sm; // 44\n if (px <= ImageSize.md) return ImageSize.md; // 48\n if (px <= ImageSize.lg) return ImageSize.lg; // 60\n return ImageSize.original;\n}\n\nconst VARIANT_RE = /\\/(original|raw|\\d+)\\.webp$/;\n\n/**\n * Rewrite a CDN image URL to use the pre-processed variant closest to `maxPx`.\n *\n * - CDN URLs ending in `/original.webp` or `/{size}.webp` are rewritten.\n * - External URLs (venue logos, non-CDN) pass through unchanged.\n * - Falsy inputs return `undefined`.\n *\n * @param url Full image URL from the API (e.g. `https://assets.agg.market/users/.../original.webp`)\n * @param maxPx Largest dimension the image will be rendered at, in CSS pixels.\n * Pass the **largest** responsive breakpoint size (e.g. 60 for `size-10 md:size-[60px]`).\n */\nexport function optimizedImageUrl(\n url: string | null | undefined,\n maxPx: number,\n): string | undefined {\n if (!url) return undefined;\n if (!VARIANT_RE.test(url)) return url;\n const variant = pickVariant(maxPx);\n const filename = variant === ImageSize.original ? \"original.webp\" : `${variant}.webp`;\n return url.replace(VARIANT_RE, `/${filename}`);\n}\n\n/**\n * Rewrite a CDN image URL to the retina variant covering `maxPx` at 2x density,\n * for use as the `2x` candidate beside {@link optimizedImageUrl}.\n *\n * Returns `undefined` for external URLs, falsy inputs, or when `maxPx * 2`\n * exceeds the largest retina variant (the 1x URL is then the only candidate).\n * Assets processed before 2026-07-31 may not have retina variants yet, so\n * callers must fall back to the 1x URL when this one fails to load.\n */\nexport function retinaImageUrl(url: string | null | undefined, maxPx: number): string | undefined {\n if (!url) return undefined;\n if (!VARIANT_RE.test(url)) return undefined;\n const variant = RETINA_IMAGE_SIZES.find((size) => size >= maxPx * 2);\n if (variant == null) return undefined;\n return url.replace(VARIANT_RE, `/${variant}.webp`);\n}\n","export type VenueMarketClusterNode<TMarket = unknown> = {\n id: string;\n venue: string;\n matchedVenueMarkets?: readonly TMarket[] | null;\n matchEntry?:\n | {\n targetVenueMarketId?: string | null;\n targetVenueMarket?: TMarket | null;\n }\n | null\n | undefined;\n venues?: readonly string[] | null;\n venueCount?: number | null;\n};\n\nconst toNonEmptyString = (value: string | null | undefined): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n\n const trimmedValue = value.trim();\n return trimmedValue ? trimmedValue : undefined;\n};\n\nconst addGraphEdge = (\n adjacencyById: Map<string, Set<string>>,\n fromMarketId: string,\n toMarketId: string,\n): void => {\n if (fromMarketId === toMarketId) return;\n\n const fromNeighbors = adjacencyById.get(fromMarketId) ?? new Set<string>();\n fromNeighbors.add(toMarketId);\n adjacencyById.set(fromMarketId, fromNeighbors);\n\n const toNeighbors = adjacencyById.get(toMarketId) ?? new Set<string>();\n toNeighbors.add(fromMarketId);\n adjacencyById.set(toMarketId, toNeighbors);\n};\n\nconst collectDirectRelationMarkets = <TMarket extends VenueMarketClusterNode<TMarket>>(\n market: TMarket,\n): TMarket[] => {\n const relationMarkets: TMarket[] = [];\n const seenRelationIds = new Set<string>();\n\n const addRelationMarket = (relationMarket: TMarket | null | undefined): void => {\n if (!relationMarket) return;\n if (seenRelationIds.has(relationMarket.id)) return;\n\n seenRelationIds.add(relationMarket.id);\n relationMarkets.push(relationMarket);\n };\n\n for (const matchedVenueMarket of market.matchedVenueMarkets ?? []) {\n addRelationMarket(matchedVenueMarket);\n }\n\n addRelationMarket(market.matchEntry?.targetVenueMarket ?? undefined);\n\n return relationMarkets;\n};\n\nconst dedupeSourceMarketsById = <TMarket extends VenueMarketClusterNode<TMarket>>(\n markets: readonly TMarket[],\n): TMarket[] => {\n const seenMarketIds = new Set<string>();\n\n return markets.filter((market) => {\n if (seenMarketIds.has(market.id)) {\n return false;\n }\n\n seenMarketIds.add(market.id);\n return true;\n });\n};\n\nconst collectUniqueRelatedMarkets = <TMarket extends VenueMarketClusterNode<TMarket>>(\n markets: readonly TMarket[],\n sourceMarketsById: Map<string, TMarket>,\n): TMarket[] => {\n const relatedMarketsById = new Map<string, TMarket>();\n\n for (const market of markets) {\n for (const relatedMarket of collectDirectRelationMarkets(market)) {\n if (sourceMarketsById.has(relatedMarket.id) || relatedMarketsById.has(relatedMarket.id)) {\n continue;\n }\n\n relatedMarketsById.set(relatedMarket.id, relatedMarket);\n }\n }\n\n return Array.from(relatedMarketsById.values());\n};\n\nexport const normalizeVenueMarketCluster = <TMarket extends VenueMarketClusterNode<TMarket>>(\n markets: readonly TMarket[],\n selectedMarketId?: string | null,\n): TMarket[] => {\n if (markets.length === 0) return [];\n\n const orderedSourceMarkets = dedupeSourceMarketsById(markets);\n const sourceMarketsById = new Map(orderedSourceMarkets.map((market) => [market.id, market]));\n const orderedRelatedMarkets = collectUniqueRelatedMarkets(\n orderedSourceMarkets,\n sourceMarketsById,\n );\n const relatedMarketsById = new Map(orderedRelatedMarkets.map((market) => [market.id, market]));\n\n const resolvedSelectedMarketId = toNonEmptyString(selectedMarketId);\n if (!resolvedSelectedMarketId) {\n return [...orderedSourceMarkets, ...orderedRelatedMarkets];\n }\n\n const adjacencyById = new Map<string, Set<string>>();\n\n for (const market of orderedSourceMarkets) {\n for (const relatedMarket of collectDirectRelationMarkets(market)) {\n addGraphEdge(adjacencyById, market.id, relatedMarket.id);\n }\n\n const targetVenueMarketId = toNonEmptyString(market.matchEntry?.targetVenueMarketId);\n if (targetVenueMarketId) {\n addGraphEdge(adjacencyById, market.id, targetVenueMarketId);\n }\n }\n\n if (\n !sourceMarketsById.has(resolvedSelectedMarketId) &&\n !relatedMarketsById.has(resolvedSelectedMarketId)\n ) {\n return [];\n }\n\n const visitedMarketIds = new Set<string>();\n const queue = [resolvedSelectedMarketId];\n\n while (queue.length > 0) {\n const currentMarketId = queue.shift();\n if (!currentMarketId || visitedMarketIds.has(currentMarketId)) {\n continue;\n }\n\n visitedMarketIds.add(currentMarketId);\n\n const neighborMarketIds = adjacencyById.get(currentMarketId);\n for (const neighborMarketId of Array.from(neighborMarketIds ?? new Set<string>())) {\n if (!visitedMarketIds.has(neighborMarketId)) {\n queue.push(neighborMarketId);\n }\n }\n }\n\n const orderedClusterMarkets: TMarket[] = [];\n const appendedMarketIds = new Set<string>();\n\n const appendMarket = (market: TMarket | undefined): void => {\n if (!market) return;\n if (!visitedMarketIds.has(market.id)) return;\n if (appendedMarketIds.has(market.id)) return;\n\n appendedMarketIds.add(market.id);\n orderedClusterMarkets.push(market);\n };\n\n appendMarket(\n sourceMarketsById.get(resolvedSelectedMarketId) ??\n relatedMarketsById.get(resolvedSelectedMarketId),\n );\n\n for (const market of orderedSourceMarkets) {\n appendMarket(market);\n }\n\n for (const market of orderedRelatedMarkets) {\n appendMarket(market);\n }\n\n return orderedClusterMarkets;\n};\n","import { Venue } from \"../enums/venue\";\n\n/**\n * Canonical venue display order — the single source of truth for every surface\n * that lists venues (event cards, orderbook columns, chart tie-breaks, and the\n * admin Settings venue list).\n *\n * Admin's drag-to-reorder is LOCAL STATE ONLY: no App column, contract field or\n * endpoint persists a per-app order, so a drag is discarded on save. Changing\n * the order is a code change here until that lands.\n */\nconst VENUE_SORT_ORDER: readonly string[] = [\n Venue.polymarket,\n Venue.hyperliquid,\n Venue.predict,\n Venue.prophetx,\n Venue.betdex,\n Venue.kalshi,\n Venue.limitless,\n Venue.myriad,\n Venue.pred,\n Venue.tiprun,\n Venue.probable,\n Venue.novig,\n Venue.opinion,\n];\n\nconst venueOrderIndex = new Map(VENUE_SORT_ORDER.map((v, i) => [v, i]));\n\nconst getVenueOrder = (venue: string): number =>\n venueOrderIndex.get(venue) ?? VENUE_SORT_ORDER.length;\n\nexport const sortVenues = <T extends string>(venues: readonly T[]): T[] =>\n [...venues].sort((a, b) => getVenueOrder(a) - getVenueOrder(b));\n","/**\n * Build an external URL to a venue's event/market page.\n *\n * Single source of truth — used by API services AND by the admin Matched\n * Events page to deep-link rows out to the venue's UI.\n *\n * Returns `null` when there isn't enough data to construct a working URL.\n * Callers should hide the link button rather than render a broken href.\n *\n * Per-venue URL conventions are kept here so any future change (e.g.\n * Kalshi moves to a new path, Polymarket rebrands) is a one-file edit.\n */\nexport interface BuildVenueUrlOpts {\n /** VenueEvent.slug — preferred input for venues that use slug-style URLs. */\n eventSlug?: string | null;\n /** VenueEvent.externalIdentifier — used by Kalshi (with series) and as a fallback. */\n eventExternalId?: string | null;\n /** VenueEvent.series.externalIdentifier — required for Kalshi's canonical URL. */\n seriesExternalId?: string | null;\n /** VenueMarket.conditionId — used as a fallback for Polymarket when slug is missing. */\n conditionId?: string | null;\n /**\n * Novig outcome id — the per-side (Yes/No) id, e.g.\n * `DiscoveredOutcome.external_identifier` / `o.id` in\n * agg-venue-novig/src/convert.rs. NOT the same id as `eventExternalId`\n * (Novig's event id, `ev.id`) or a market id (`m.id`) — Novig's deeplink\n * template takes the outcome, one level more specific than either. Not\n * currently plumbed from any caller.\n */\n outcomeExternalId?: string | null;\n /**\n * Novig-issued partner id, required by Novig's deeplink URL structure for\n * attribution tracking (https://docs.novig.com/llms-full.txt,\n * \"Deeplinking\"). Not currently plumbed from any caller — no Novig case\n * builds a URL without it, so pass it explicitly once we have one.\n */\n partnerId?: string | null;\n /**\n * Which of Novig's two documented deeplink schemes to build — Novig's docs\n * say to detect the caller's platform via User-Agent and pick accordingly.\n * Defaults to `\"web\"`. Ignored by every other venue.\n */\n platform?: \"web\" | \"native\";\n}\n\nexport function buildVenueUrl(venue: string, opts: BuildVenueUrlOpts): string | null {\n switch (venue) {\n case \"kalshi\": {\n // Kalshi canonical: /markets/<series>/<event>. Both lowercased.\n // Without the series id we can't build a URL that resolves, so we\n // return null and the FE hides the link button.\n const series = opts.seriesExternalId;\n const event = opts.eventExternalId;\n if (series && event) {\n return `https://kalshi.com/markets/${series.toLowerCase()}/${event.toLowerCase()}`;\n }\n return null;\n }\n case \"polymarket\": {\n if (opts.eventSlug) return `https://polymarket.com/event/${opts.eventSlug}`;\n if (opts.conditionId) return `https://polymarket.com/market/${opts.conditionId}`;\n return null;\n }\n case \"predict\": {\n if (opts.eventSlug) return `https://predict.fun/market/${opts.eventSlug}`;\n return null;\n }\n case \"pred\": {\n // PRED's SPA routes fixture-level canonical names through /trade/:canonicalName.\n // Discovery stores that canonical name as VenueEvent.slug, so the event\n // slug is the only safe identifier here; child market ids do not resolve\n // as standalone public pages.\n if (opts.eventSlug) return `https://www.pred.app/trade/${opts.eventSlug}`;\n return null;\n }\n case \"limitless\": {\n if (opts.eventSlug) return `https://limitless.exchange/markets/${opts.eventSlug}`;\n return null;\n }\n case \"opinion\": {\n if (opts.eventSlug) return `https://www.opinion.trade/market/${opts.eventSlug}`;\n return null;\n }\n case \"myriad\": {\n // https://myriad.markets/markets/<slug>\n if (opts.eventSlug) return `https://myriad.markets/markets/${opts.eventSlug}`;\n return null;\n }\n case \"hyperliquid\": {\n // https://app.hyperliquid.xyz/trade/<slug>\n // Hyperliquid uses slug-style market names, NOT the numeric externalId.\n if (opts.eventSlug) return `https://app.hyperliquid.xyz/trade/${opts.eventSlug}`;\n return null;\n }\n case \"probable\": {\n if (opts.eventSlug) return `https://probable.markets/event/${opts.eventSlug}`;\n return null;\n }\n case \"novig\": {\n // Documented formats (docs.novig.com/llms-full.txt, \"Deeplinking\"):\n // web: novig.com/events/<outcome_id>/<partner_id>/<wager_amount>?referralCode=YOUR_CODE\n // native: novigapp://events/<outcome_id>/<partner_id>?referralCode=YOUR_CODE\n // outcome_id and partner_id are both required — Novig's docs state\n // partner_id must \"always\" be included for attribution tracking, with\n // no documented fallback URL that omits either.\n //\n // INTENTIONALLY INERT today: no caller supplies partnerId (no Novig\n // partner/affiliate id is plumbed anywhere in this codebase yet), so\n // this always returns null — same \"insufficient data, hide the link\"\n // pattern as every other case above. Left in (not deleted) so the\n // mapping is correct and ready the moment a partnerId source exists,\n // rather than being reintroduced from scratch and re-risking a wrong\n // id mapping.\n if (opts.outcomeExternalId && opts.partnerId) {\n return opts.platform === \"native\"\n ? `novigapp://events/${opts.outcomeExternalId}/${opts.partnerId}`\n : `https://novig.com/events/${opts.outcomeExternalId}/${opts.partnerId}`;\n }\n return null;\n }\n default:\n return null;\n }\n}\n","export const LIMIT_PRICE_RAW_SCALE = BigInt(1_000_000);\n\nexport type LimitPriceSide = \"buy\" | \"sell\";\n\nexport type LimitPriceTickAdjustment = {\n adjusted: boolean;\n adjustedPriceRaw: string;\n originalPriceRaw: string;\n tickSizeRaw: string | null;\n};\n\nconst resolveTickSizeRaw = (tickSize: number): bigint => {\n const scaledTick = tickSize * Number(LIMIT_PRICE_RAW_SCALE);\n const roundedTick = Math.round(scaledTick);\n\n if (\n !Number.isFinite(scaledTick) ||\n roundedTick <= 0 ||\n Math.abs(scaledTick - roundedTick) > 1e-6\n ) {\n throw new RangeError(`Unsupported limit-order tick size: ${tickSize}`);\n }\n\n return BigInt(roundedTick);\n};\n\n/**\n * Aligns a six-decimal limit price to a venue tick in the user's favor.\n * All rounding is performed with integers after the venue tick is scaled.\n */\nexport const adjustLimitPriceRawToTick = ({\n limitPriceRaw,\n side,\n tickSize,\n}: {\n limitPriceRaw: string;\n side: LimitPriceSide;\n tickSize?: number | null;\n}): LimitPriceTickAdjustment => {\n const originalPrice = BigInt(limitPriceRaw);\n const originalPriceRaw = originalPrice.toString();\n if (tickSize == null) {\n return {\n adjusted: false,\n adjustedPriceRaw: originalPriceRaw,\n originalPriceRaw,\n tickSizeRaw: null,\n };\n }\n\n const tickSizeRaw = resolveTickSizeRaw(tickSize);\n const remainder = originalPrice % tickSizeRaw;\n if (remainder === BigInt(0)) {\n return {\n adjusted: false,\n adjustedPriceRaw: originalPriceRaw,\n originalPriceRaw,\n tickSizeRaw: tickSizeRaw.toString(),\n };\n }\n\n const adjustedPrice =\n side === \"buy\" ? originalPrice - remainder : originalPrice + (tickSizeRaw - remainder);\n\n return {\n adjusted: true,\n adjustedPriceRaw: adjustedPrice.toString(),\n originalPriceRaw,\n tickSizeRaw: tickSizeRaw.toString(),\n };\n};\n","export const DEFAULT_BALANCE_REFILL_DAILY_CAP_RAW = \"1002000000\";\nexport const DEFAULT_BALANCE_REFILL_MAX_FEE_RAW = \"2000000\";\n\nexport const getBalanceRefillMaximumRaw = (dailyCapRaw: string, maxFeeRaw: string): string => {\n const dailyCap = BigInt(dailyCapRaw);\n const maximumFee = BigInt(maxFeeRaw);\n if (dailyCap <= maximumFee) return \"0\";\n\n return (dailyCap - maximumFee).toString();\n};\n\nexport const isBalanceRefillWithinDailyCap = (\n minimumRaw: string,\n refillAmountRaw: string,\n dailyCapRaw: string,\n maxFeeRaw: string,\n): boolean => {\n const maximum = BigInt(getBalanceRefillMaximumRaw(dailyCapRaw, maxFeeRaw));\n return BigInt(minimumRaw) <= maximum && BigInt(refillAmountRaw) <= maximum;\n};\n","/** Convert explicit retry hints to milliseconds without treating arbitrary strings as dates. */\nexport function parseRetryAfterSeconds(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) return undefined;\n const milliseconds = value * 1000;\n return Number.isSafeInteger(milliseconds) ? milliseconds : undefined;\n}\n\nexport function parseRetryAfterHeader(\n value: string | null | undefined,\n now = Date.now(),\n): number | undefined {\n if (!value) return undefined;\n const text = value.trim();\n if (/^\\d+$/.test(text)) return parseRetryAfterSeconds(Number(text));\n // HTTP-date uses GMT; accepting Date.parse's additional formats would turn malformed\n // numeric or locale-specific hints into unrelated dates. Verify calendar/weekday too.\n if (\n !/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \\d{2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d{4} \\d{2}:\\d{2}:\\d{2} GMT$/.test(\n text,\n )\n )\n return undefined;\n const timestamp = Date.parse(text);\n if (!Number.isFinite(timestamp) || new Date(timestamp).toUTCString() !== text) return undefined;\n const milliseconds = timestamp - now;\n return Number.isSafeInteger(milliseconds) && milliseconds >= 0 ? milliseconds : undefined;\n}\n","/**\n * Thrown when the server returns `challenge_required` during auth start.\n * The client should render a Cloudflare Turnstile widget using `siteKey`,\n * then retry the auth flow with the resulting `turnstileToken`.\n */\nexport class TurnstileChallengeError extends Error {\n readonly siteKey: string;\n\n constructor(siteKey: string) {\n super(\"Bot protection challenge required. Render Turnstile widget and retry.\");\n this.name = \"TurnstileChallengeError\";\n this.siteKey = siteKey;\n }\n}\n\n/** Public 429 body. Optional fields preserve compatibility with message-only rate limiters. */\nexport interface AggRateLimitResponse {\n message: string;\n statusCode?: 429;\n code?: \"rate_limited\" | \"venue_rate_limited\";\n /** Present when the upstream account, rather than Agg admission, is throttled. */\n venue?: \"prophetx\";\n /** Retry delay in seconds; the SDK exposes parsed error hints as retryAfterMs. */\n retryAfter?: number;\n}\n\n/** Field-level validation detail returned by the API on 400 responses. */\nexport interface AggApiFieldError {\n field: string;\n message: string;\n}\n\nexport interface AggApiErrorInit {\n code?: string;\n retryable?: boolean;\n /** Server-requested delay before a retry, in milliseconds. Does not enable automatic SDK retries. */\n retryAfterMs?: number;\n errors?: AggApiFieldError[];\n}\n\n/**\n * Thrown for every non-2xx response from the AGG API.\n *\n * Branch on `status` and `code` rather than matching `message` text —\n * messages are human-facing and may be reworded without a major bump.\n *\n * ```ts\n * try {\n * await client.getPositions();\n * } catch (err) {\n * if (isAggApiError(err) && err.status === 401) {\n * // session lapsed — prompt reconnect\n * }\n * }\n * ```\n */\nexport class AggApiError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly retryable?: boolean;\n readonly retryAfterMs?: number;\n readonly errors?: AggApiFieldError[];\n\n constructor(message: string, status: number, init: AggApiErrorInit = {}) {\n super(message);\n this.name = \"AggApiError\";\n this.status = status;\n if (init.code !== undefined) this.code = init.code;\n if (init.retryable !== undefined) this.retryable = init.retryable;\n if (init.retryAfterMs !== undefined) this.retryAfterMs = init.retryAfterMs;\n if (init.errors !== undefined) this.errors = init.errors;\n // Required for `instanceof` to survive the ES5 downlevel target.\n Object.setPrototypeOf(this, AggApiError.prototype);\n }\n}\n\n/** Type guard for {@link AggApiError}, safe across bundle boundaries. */\nexport function isAggApiError(value: unknown): value is AggApiError {\n return value instanceof AggApiError;\n}\n","/**\n * EIP-55 address checksumming, self-contained.\n *\n * EIP-4361 (SIWE) requires the address line of the message to be EIP-55\n * checksummed, and wallets routinely hand back a lowercase address —\n * `eth_requestAccounts` does. Every SIWE client library (viem, ethers, `siwe`)\n * checksums inside `buildMessage`; this package has no runtime dependencies,\n * so it carries the one primitive that needs: Keccak-256.\n *\n * The permutation below is a port of `keccakP` from @noble/hashes (MIT,\n * Copyright (c) 2022 Paul Miller — https://github.com/paulmillr/noble-hashes),\n * reduced to the single Keccak-256 instance EIP-55 needs. Lanes are held as\n * `[low32, high32]` pairs in a Uint32Array; bytes are absorbed and squeezed\n * little-endian explicitly, so nothing here depends on platform endianness.\n * `eip55.test.ts` pins it to the classic Keccak vectors and the EIP-55 examples.\n */\n\n// The 24 round constants, split into 32-bit halves.\nconst IOTA_LO = [\n 0x00000001, 0x00008082, 0x0000808a, 0x80008000, 0x0000808b, 0x80000001, 0x80008081, 0x00008009,\n 0x0000008a, 0x00000088, 0x80008009, 0x8000000a, 0x8000808b, 0x0000008b, 0x00008089, 0x00008003,\n 0x00008002, 0x00000080, 0x0000800a, 0x8000000a, 0x80008081, 0x00008080, 0x80000001, 0x80008008,\n];\nconst IOTA_HI = [\n 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000,\n 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000,\n 0x80000000, 0x80000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000, 0x00000000, 0x80000000,\n];\n\n// Rho rotation offsets and Pi lane permutation, in the order the round applies\n// them. None of the offsets is 0 or 32, which matters: a JS shift by 32 is a\n// no-op, so the rotate helpers below never have to special-case it.\nconst PI: number[] = [];\nconst ROTL: number[] = [];\nfor (let round = 0, x = 1, y = 0; round < 24; round++) {\n [x, y] = [y, (2 * x + 3 * y) % 5];\n PI.push(2 * (5 * y + x));\n ROTL.push((((round + 1) * (round + 2)) / 2) % 64);\n}\n\n// 64-bit rotate-left on a (lo, hi) pair, one half at a time.\nconst rotlLo = (lo: number, hi: number, s: number) =>\n s > 32 ? (hi << (s - 32)) | (lo >>> (64 - s)) : (lo << s) | (hi >>> (32 - s));\nconst rotlHi = (lo: number, hi: number, s: number) =>\n s > 32 ? (lo << (s - 32)) | (hi >>> (64 - s)) : (hi << s) | (lo >>> (32 - s));\n\n/** Keccak-f[1600] on a 25-lane state stored as 50 little-endian u32 halves. */\nfunction keccakP(s: Uint32Array): void {\n const B = new Uint32Array(10);\n for (let round = 0; round < 24; round++) {\n // Theta\n for (let x = 0; x < 10; x++) B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];\n for (let x = 0; x < 10; x += 2) {\n const idx1 = (x + 8) % 10;\n const idx0 = (x + 2) % 10;\n const B0 = B[idx0];\n const B1 = B[idx0 + 1];\n const Tlo = rotlLo(B0, B1, 1) ^ B[idx1];\n const Thi = rotlHi(B0, B1, 1) ^ B[idx1 + 1];\n for (let y = 0; y < 50; y += 10) {\n s[x + y] ^= Tlo;\n s[x + y + 1] ^= Thi;\n }\n }\n // Rho + Pi\n let curLo = s[2];\n let curHi = s[3];\n for (let t = 0; t < 24; t++) {\n const shift = ROTL[t];\n const Tlo = rotlLo(curLo, curHi, shift);\n const Thi = rotlHi(curLo, curHi, shift);\n const pi = PI[t];\n curLo = s[pi];\n curHi = s[pi + 1];\n s[pi] = Tlo;\n s[pi + 1] = Thi;\n }\n // Chi\n for (let y = 0; y < 50; y += 10) {\n for (let x = 0; x < 10; x++) B[x] = s[y + x];\n for (let x = 0; x < 10; x++) s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];\n }\n // Iota\n s[0] ^= IOTA_LO[round];\n s[1] ^= IOTA_HI[round];\n }\n}\n\n/** Rate of Keccak-256 in bytes: 1600 − 2·256 bits. */\nconst RATE = 136;\n\n/** Keccak-256 (the Ethereum flavour: `0x01` padding, not NIST SHA3's `0x06`). */\nexport function keccak256(data: Uint8Array): Uint8Array {\n const s = new Uint32Array(50);\n let pos = 0;\n for (let i = 0; i < data.length; i++) {\n s[pos >> 2] ^= data[i] << ((pos & 3) * 8);\n if (++pos === RATE) {\n keccakP(s);\n pos = 0;\n }\n }\n // pad10*1: first bit after the message, last bit of the block. When the\n // message ends one byte short of the rate the two land on the same byte.\n s[pos >> 2] ^= 0x01 << ((pos & 3) * 8);\n s[(RATE - 1) >> 2] ^= 0x80 << (((RATE - 1) & 3) * 8);\n keccakP(s);\n\n const out = new Uint8Array(32);\n for (let i = 0; i < 32; i++) out[i] = (s[i >> 2] >>> ((i & 3) * 8)) & 0xff;\n return out;\n}\n\n/**\n * EIP-55 checksum an EVM address.\n *\n * Accepts any casing — lowercase, uppercase, or an already-checksummed\n * address — and returns the canonical mixed-case form. A mixed-case input\n * with a WRONG checksum is corrected, not rejected: this is a message\n * builder, and the wallet's signature is what authenticates the address\n * downstream. Throws only when the input is not a 20-byte hex address at all.\n */\nexport function toChecksumAddress(address: string): string {\n if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {\n throw new Error(`\"${address}\" is not a 20-byte hex address`);\n }\n const lower = address.slice(2).toLowerCase();\n // The hash is over the ASCII of the lowercase hex, not the address bytes.\n const hash = keccak256(Uint8Array.from(lower, (c) => c.charCodeAt(0)));\n\n let out = \"0x\";\n for (let i = 0; i < 40; i++) {\n const nibble = i % 2 === 0 ? hash[i >> 1] >> 4 : hash[i >> 1] & 0x0f;\n out += nibble >= 8 ? lower[i].toUpperCase() : lower[i];\n }\n return out;\n}\n","import type {\n AuthUser,\n VenueEvent,\n VenueMarket,\n GetOrdersQuery,\n GetPositionsQuery,\n Orderbook,\n OrderListItem,\n MarketStatus,\n PositionGroup,\n UnifiedBalanceResponse,\n UserProfile,\n Venue,\n} from \"@agg/common/types-only\";\n\n/** App-level paper/live mode. An app is one or the other, never both. */\nexport type AppTradingMode = \"live\" | \"paper\";\n\nexport interface AppClientConfigResponse {\n prophetxExecutionMode?: \"clearinghouse\" | \"direct\";\n novigExecutionMode?: \"clearinghouse\" | \"direct\";\n disabledVenues: Venue[];\n disabledCategoryPresets: string[];\n earlyAccessEnabled: boolean;\n authOptions: AppClientAuthOption[];\n /**\n * Server-owned execution mode. Prefer this over any locally-configured\n * `trading.executionMode` — the API enforces it regardless of what the\n * client sends, and end users cannot change it.\n */\n tradingMode: AppTradingMode;\n /**\n * One-time simulated balance granted on first paper use, in dollars.\n * Interpolate this into paper copy rather than hardcoding a figure.\n */\n paperStartingBalance: number;\n}\n\nexport interface VenueGeoPolicyEntry {\n venue: Venue;\n /** ISO 3166-1 alpha-2, upper-case. Empty means no country restriction. */\n blockedCountries: string[];\n /**\n * ISO 3166-1 alpha-2, upper-case. When present, this venue is ALLOWLIST\n * mode: ONLY these countries are permitted (`blockedCountries` is always\n * `[]` alongside this and must be ignored). Absent/undefined ⇒ ordinary\n * denylist mode, use `blockedCountries` as before. Only Novig uses this\n * today — a client that reads only `blockedCountries` sees an allowlisted\n * venue as unrestricted, which is exactly the misread this field closes.\n */\n allowedCountries?: string[];\n}\n\nexport interface VenueGeoPolicyResponse {\n venues: VenueGeoPolicyEntry[];\n}\n\nexport interface RpcTokenResponse {\n token: string;\n expiresAt: number;\n}\n\nexport type AggAuthProviderType = \"siwe\" | \"siws\" | \"google\" | \"twitter\" | \"apple\" | \"email\";\nexport interface AppClientAuthOption {\n provider: AggAuthProviderType;\n type: \"oauth\" | \"email\" | \"wallet\";\n enabled: boolean;\n callbackUrl?: string;\n statement?: string;\n}\nexport type AggAuthDeliveryMode = \"body\" | \"cookie-refresh\";\n\nexport interface AggClientAuthOptions {\n getEarlyAccessCode?: () => string | null;\n}\n\nexport type AggAuthStartBody =\n | {\n provider: Exclude<AggAuthProviderType, \"email\">;\n redirectUrl?: string;\n /** Cloudflare Turnstile token — required when a prior authStart returned `challenge_required`. */\n turnstileToken?: string;\n earlyAccessCode?: string;\n }\n | {\n provider: \"email\";\n email: string;\n redirectUrl?: string;\n /** Cloudflare Turnstile token — required when a prior authStart returned `challenge_required`. */\n turnstileToken?: string;\n earlyAccessCode?: string;\n };\n\n/** SIWE / SIWS sign-in. `kind` is optional so callers that predate the discriminator still compile. */\nexport interface AggAuthWalletVerifyBody {\n kind?: \"wallet\";\n message: string;\n signature: string;\n earlyAccessCode?: string;\n}\n\n/** Privy sign-in. Requires the app's wallet provider to be Privy; the token must come from that Privy app. */\nexport interface AggAuthPrivyVerifyBody {\n kind: \"privy\";\n privyToken: string;\n earlyAccessCode?: string;\n}\n\n/** Body for `POST /auth/verify` — mirrors the API's union on `kind`. */\nexport type AggAuthVerifyBody = AggAuthWalletVerifyBody | AggAuthPrivyVerifyBody;\n\nexport type AggAuthStartResult =\n | { type: \"nonce\"; nonce: string; statement?: string }\n | { type: \"redirect\"; url: string }\n | { type: \"magic_link\"; success: true }\n | { type: \"challenge_required\"; siteKey: string };\n\n/**\n * Body for `POST /users/me/link-account/start` — authenticated account linking.\n *\n * `redirectUrl` is required for OAuth/email providers: the callback / magic-link\n * verify hands the partner a `link_confirm_token` by redirecting to `redirectUrl`,\n * and the partner app completes the flow by calling `/confirm` from that page.\n *\n * Wallet providers (`siwe`/`siws`) instead return a `wallet_challenge` with a\n * `message` the user signs VERBATIM; the signature is then confirmed with\n * `{ kind: \"wallet_signature\", message, signature }`.\n */\nexport type AggLinkAccountBody =\n | { provider: \"google\" | \"twitter\" | \"apple\"; redirectUrl: string }\n | { provider: \"email\"; email: string; redirectUrl: string }\n | { provider: \"siwe\" | \"siws\"; address: string };\n\nexport type AggLinkAccountResult =\n | { type: \"redirect\"; url: string }\n | { type: \"magic_link\"; success: true }\n | { type: \"wallet_challenge\"; message: string };\n\n/**\n * Wallet branch of `POST /users/me/link-account/confirm`. Requires `kind` so it\n * can never be confused with the `token` branch. `message` MUST be the exact\n * `message` returned by `/start`'s `wallet_challenge` — the server compares it\n * byte-for-byte, so do not reconstruct or edit it client-side.\n */\nexport type AggLinkAccountWalletConfirmBody = {\n kind: \"wallet_signature\";\n message: string;\n signature: string;\n};\n\n/**\n * Success result of /users/me/link-account/confirm.\n * - `linked` — new Account row written.\n * - `already_linked_same` — identity was already attached to the caller's Principal\n * (idempotent; safe to retry).\n *\n * Collisions with a different Principal surface as HTTP 409 and are thrown by the\n * SDK's request layer — catch them at the call site, don't expect them here.\n */\nexport type AggLinkAccountConfirmResult = {\n status: \"linked\" | \"already_linked_same\";\n provider: string;\n};\n\nexport type AggSessionUser = AuthUser | UserProfile;\n\nexport interface AggClientSessionInput {\n accessToken: string;\n refreshToken?: string;\n user?: AggSessionUser;\n}\n\n/** Non-sensitive auth snapshot persisted to localStorage for UI bootstrapping.\n * Tokens are NEVER included — they exist only in process memory. */\nexport interface PersistedAuthSnapshot {\n user: {\n id: string;\n username: string | null;\n avatarUrl: string | null;\n walletAddress?: string | null;\n } | null;\n authHint: { wasAuthenticated: boolean };\n}\n\n/** Auth lifecycle status for UI state machines. */\nexport type AuthStatus = \"unknown\" | \"authenticated\" | \"unauthenticated\";\n\n// ── Self-custodial fills ──\n\nexport type SignatureRequestType =\n | \"eip712\"\n | \"personal_sign\"\n /** EVM transaction — bridge legs and approvals. secp256k1. */\n | \"transaction\"\n /** Solana transaction — bridge legs on SVM. ed25519, NOT secp256k1. */\n | \"solana_transaction\"\n | \"hl_l1_action\"\n /**\n * EIP-7702 authorization over `{ contractAddress, chainId, nonce }`.\n *\n * A signature over a RAW digest — `keccak(0x05 ‖ rlp([chainId, delegate,\n * nonce]))` — not EIP-191 and not EIP-712. Many wallets do not expose this,\n * and that is expected: reject it and the server falls back to asking the\n * user to broadcast a plain approve instead.\n */\n | \"eip7702_authorization\"\n /**\n * A Gnosis Safe transaction relayed through Polymarket — a legacy Polymarket\n * wallet funding a fill. The payload is the SafeTx as EIP-712 typed data,\n * but the wallet must `personal_sign` the RAW 32 bytes of\n * `hashTypedData(payload)` (`signMessage({ message: { raw: hash } })`):\n * Polymarket's relayer only accepts that shape. `payload.safeTxHash` carries\n * the digest for convenience; the server recomputes it from the typed data.\n */\n | \"safe_tx\";\n\n/** One payload the client must sign before a fill can proceed. */\nexport interface SignatureRequest {\n /** Echo this back with the signature. */\n stepId: string;\n /** Payload shape. Discriminates how to sign — not which venue. */\n type: SignatureRequestType;\n venue: string;\n /** The address that must produce this signature. Sign with this key, not another. */\n signerAddress: string;\n /** Absent for non-EVM payloads (e.g. Hyperliquid L1 actions). */\n chainId?: number;\n /** Sign verbatim. */\n payload: unknown;\n expiresAt: string;\n /** Why this signature is being asked for, when the server knows (e.g. `\"fee\"`, `\"funding_and_fee\"`). Display only. */\n purpose?: string;\n /**\n * The fill proceeds without this one (e.g. `purpose: \"hl_referral\"`, a\n * partner referral parked beside a Hyperliquid order). `fillSelfCustody`\n * skips it if your signer throws or it has expired, instead of failing the\n * fill.\n */\n optional?: boolean;\n}\n\n/**\n * Supplied by the partner. Receives a payload, returns a signature. The SDK\n * never sees the key.\n *\n * Return a 0x-prefixed hex string for anything the wallet SIGNS:\n *\n * - `eip712` — `signTypedData` over `payload`.\n * - `personal_sign` — EIP-191 over `payload`: a UTF-8 string or `{ raw: \"0x…\" }\n * bytes (Polymarket proxy batches). Pass it directly as viem `message`.\n * - `safe_tx` — `personal_sign` over the RAW 32 bytes of\n * `hashTypedData(payload)` (viem: `signMessage({ message: { raw: hash } })`,\n * MetaMask: `personal_sign` with the hex hash). The wallet shows a hash, not\n * a structured prompt — that is what Polymarket's own relayer requires.\n * - `hl_l1_action` — Hyperliquid L1 action, EIP-712 in phantom-agent form.\n * - `eip7702_authorization` — an EIP-7702 authorization over\n * `{ contractAddress, chainId, nonce }`. This is a signature over a RAW\n * digest, not EIP-191 and not EIP-712, and many wallets do not expose it.\n * **Throwing here does not help**: there is no reject verb, so a thrown\n * signer is indistinguishable from a slow user — the request simply expires\n * and the fill dies. If your wallet cannot produce this signature, declare\n * `approveMode: \"user_broadcast\"` on the fill instead and the approve is\n * requested as a `transaction` the user sends themselves. Handling this\n * request is what makes funding gasless.\n *\n * Return `{ txHash }` for anything the wallet BROADCASTS:\n *\n * - `transaction` — send it, then return the hash **immediately, without\n * awaiting the receipt**. The server watches for the mined receipt itself\n * and will not resume until it matches the request byte-for-byte.\n */\nexport type SignerFn = (req: SignatureRequest) => Promise<string | { txHash: string }>;\n\n/**\n * How long `fillSelfCustody` will keep waiting before giving up.\n *\n * Covers a first-time user: sign the wallet-setup batch, wait for it on-chain,\n * then sign the order. Generous because the wait is a relayer transaction\n * confirming, not a human deciding.\n */\nexport const SELF_CUSTODY_FILL_TIMEOUT_MS = 5 * 60_000;\n\n/** Gap between re-reads while an on-chain step is in flight. */\nexport const SELF_CUSTODY_POLL_INTERVAL_MS = 2_000;\n\n/**\n * How long `fillSelfCustody` waits on the `signer` for ONE optional request\n * signed by a wallet other than the user's — e.g. a partner's activation\n * sponsor. Such a request can delay the batch's submission by at most this long,\n * after which it is declined and the required signatures go out without it.\n * Required requests, and optional ones the user's own wallet signs (the fill's\n * `signingAddress` or any required request's `signerAddress`, e.g. a referral\n * code), are never bounded by this.\n */\nexport const OPTIONAL_SIGNATURE_TIMEOUT_MS = 15_000;\n\n/**\n * How long `fillSelfCustody` waits on an optional Polymarket buy fee pre-sign\n * (`purpose: \"app_fee\"`). It never holds the order (that round is already\n * posted), so it can wait for a slow wallet: just under the server's 60s grace,\n * after which the request is expired and a post-fill signature asked instead.\n */\nexport const OPTIONAL_FEE_SIGNATURE_TIMEOUT_MS = 55_000;\n\n/**\n * States a run never leaves. Everything else means \"still working\".\n *\n * Typed against `ExecutionOverallState` so a typo'd or renamed literal (e.g.\n * `cancelled` drifting to `canceled`) is a compile error instead of a state\n * that silently stops being treated as terminal. Mirrors\n * `ExecutionOverallStateTB` in the contract; keep the two in step.\n */\nexport const TERMINAL_EXECUTION_STATES: ReadonlySet<ExecutionOverallState> =\n new Set<ExecutionOverallState>([\"filled\", \"partially_filled\", \"failed\", \"cancelled\", \"expired\"]);\nexport type SportsGameStatus =\n | \"scheduled\"\n | \"live\"\n | \"paused\"\n | \"finished\"\n | \"cancelled\"\n | \"postponed\"\n | \"unknown\";\n\nexport interface SportsLiveParticipant {\n position: \"first\" | \"second\";\n name: string;\n shortName: string | null;\n imageUrl: string | null;\n score: string | null;\n}\n\nexport interface SportsLiveState {\n eventId: string;\n sport: string;\n status: SportsGameStatus;\n participants: [SportsLiveParticipant, SportsLiveParticipant];\n period: string | null;\n clock: string | null;\n updatedAt: string | null;\n}\n\nexport interface SportsLiveResponse {\n data: SportsLiveState[];\n missingEventIds: string[];\n}\n\n// SDK-specific types (not in common).\nexport interface AggClientOptions {\n /** Browser adapters can inject a Worker transport; other runtimes keep the native client. */\n webSocketFactory?: (\n options: import(\"./agg-websocket\").AggWebSocketOptions,\n ) => import(\"./agg-websocket\").AggWebSocket;\n baseUrl: string;\n /** Public App ID — sent as x-app-id header. For client-side partner usage. */\n appId?: string;\n /** Secret admin key — sent as x-admin-key header. Server-side only. */\n adminKey?: string;\n /**\n * Partner API key for server-side use. Sent as `x-app-api-key`. NEVER embed\n * in browser bundles, source maps, or logs. Keys start with `agg_<appId>_`.\n */\n apiKey?: string;\n /** WebSocket URL for real-time feeds. Must be set explicitly to use createWebSocket(). */\n wsUrl?: string;\n /** Opt in after immutable history publication/CDN rollout. Defaults false. */\n preferImmutableHistory?: boolean;\n /**\n * @deprecated Kalshi live discovery and trading are retired. This ignored\n * compatibility option remains to avoid breaking existing SDK consumers.\n */\n kalshiDemo?: boolean;\n /** Optional auth request hooks used to enrich auth payloads. */\n auth?: AggClientAuthOptions;\n /** Move refresh delivery to an HttpOnly cookie on auth endpoints. Defaults to \"body\". */\n authDelivery?: AggAuthDeliveryMode;\n /** Persist a non-sensitive auth hint to localStorage for UI bootstrapping.\n * Tokens are NEVER persisted — they exist only in process memory.\n * When authDelivery is \"body\", refresh tokens are lost on page reload.\n * When authDelivery is \"cookie-refresh\", refresh tokens survive via HttpOnly cookies\n * and the SDK attempts a silent refresh on cold start. Defaults to true. */\n persistSession?: boolean;\n /**\n * Supplies signatures for self-custodial fills. Required whenever\n * `fillSelfCustody()` is called with `signingAddress` — the SDK never\n * holds a key itself, so without this option a fill that needs a\n * client-side signature cannot proceed. The signature requests never\n * come back on `POST /execution/fill` itself: `fillSelfCustody()` polls\n * `GET /execution/status` for them (`pendingSignatures`), signs each one\n * with this function, and posts the result to\n * `POST /execution/fill/:quoteId/signatures`.\n */\n signer?: SignerFn;\n}\n\nexport interface SiweMessageParams {\n domain: string;\n address: string;\n uri: string;\n nonce: string;\n chainId?: number;\n statement?: string;\n issuedAt?: string;\n}\n\nexport interface SiwsMessageParams {\n domain: string;\n /** Base58-encoded Solana public key. */\n address: string;\n uri: string;\n nonce: string;\n /** Solana chain ID: \"mainnet\", \"devnet\", \"testnet\", or \"localnet\". Defaults to \"mainnet\". */\n chainId?: string;\n statement?: string;\n issuedAt?: string;\n}\n\n/** OHLCV bar point for chart rendering. */\nexport interface ChartCandle {\n /** Venue average; distinct from OHLC close. */\n mean?: number;\n /** Open time in Unix milliseconds. */\n t: number;\n /** Open price (0-1). */\n o: number;\n /** High price (0-1). */\n h: number;\n /** Low price (0-1). */\n l: number;\n /** Close price (0-1). */\n c: number;\n /** Volume (null if unavailable). */\n v: number | null;\n}\n\n/** @deprecated Historical chart bars are canonical per outcome. Use ChartBarsResponse instead. */\nexport interface ChartVenueCandles {\n venue: string;\n candles: ChartCandle[];\n}\n\nexport type ChartResolution = \"1m\" | \"5m\" | \"1h\" | \"1d\";\n\n/**\n * Freshness signal embedded in every chart response. Compare\n * `staleSeconds` against the resolution to decide whether to show a\n * \"delayed\" badge on the chart.\n */\nexport interface ChartBarsMeta {\n state?: \"ready\" | \"warming\" | \"unsupported\" | \"failed\" | \"empty\";\n complete?: boolean;\n retryAfterMs?: number;\n /** Agg fetch/publication time. Does not measure upstream delivery latency. */\n fetchedAtMs?: number;\n /** Server-side wall clock when the response was assembled, in milliseconds. */\n serverTime: number;\n /** `open_time` of the most-recent bar in `data`, in milliseconds. Null if `data` is empty. */\n lastBarOpenTime: number | null;\n /** `serverTime - lastBarOpenTime` in seconds. Null if `data` is empty. */\n staleSeconds: number | null;\n}\n\n/** Response from GET /charts/bars. */\nexport interface ChartBarsResponse {\n /** VenueMarketOutcome.id requested by the caller. */\n venueMarketOutcomeId: string;\n /** Venue of the canonical historical series. */\n venue: string;\n /** Resolution returned by the backend. */\n resolution: ChartResolution;\n /** Bars sorted in ascending open time. */\n data: ChartCandle[];\n /** Freshness signal — see {@link ChartBarsMeta}. */\n meta: ChartBarsMeta;\n}\n\nexport interface ChartHistoryManifest {\n version: 1;\n revision: string | null;\n venueMarketOutcomeId: string;\n venue: string;\n resolution: ChartResolution;\n semantics: \"venue-ohlcv-v1\" | \"polymarket-price-samples-v1\" | \"kalshi-ohlcv-quote-fallback-v2\";\n from: number;\n to: number;\n finalizedThrough: number;\n chunks: Array<{\n key: string;\n url: string;\n sha256: string;\n from: number;\n to: number;\n points: number;\n }>;\n meta: ChartBarsMeta;\n}\n\n/** @deprecated Use ChartBarsResponse. */\nexport type ChartCandlestickResponse = ChartBarsResponse;\n\n/** Matched market reference returned by batch/aggregate endpoints. */\nexport interface VenueMarketRef {\n venue: string;\n venueMarketId: string;\n}\n\nexport type OrderbookBatchItemStatus =\n | \"ok\"\n | \"market_not_found\"\n | \"market_resolved\"\n | \"market_closed\"\n | \"market_paused\"\n | \"market_unopened\"\n | \"book_not_loaded\";\n\nexport type OrderbookBatchItemErrorCode =\n | \"market_not_found\"\n | \"market_resolved\"\n | \"market_closed\"\n | \"market_paused\"\n | \"market_unopened\"\n | \"book_not_loaded\";\n\nexport interface OrderbookBatchItemError {\n code: OrderbookBatchItemErrorCode;\n message: string;\n retryable: boolean;\n}\n\nexport interface OrderbooksOnlyError {\n code: \"use_orderbooks_endpoint\";\n message: string;\n retryable: boolean;\n}\n\nexport interface OrderbookServiceUnavailableError {\n code: \"orderbook_service_unavailable\";\n message: string;\n retryable: boolean;\n}\n\nexport interface RequestedOrderbookMarket {\n venueMarketId: string;\n venue: string;\n marketStatus: \"open\" | \"closed\" | \"resolved\" | \"unopened\" | \"paused\";\n tickSize: number | null;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this market, raw 6-dec shares.\n * Absent means no known minimum. */\n minSizeRaw?: string;\n endDate: string | null;\n resolutionDate: string | null;\n}\n\nexport interface MatchedOrderbookMarket extends VenueMarketRef {\n marketStatus: \"open\" | \"closed\" | \"resolved\" | \"unopened\" | \"paused\";\n tickSize: number | null;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this market, raw 6-dec shares.\n * Absent means no known minimum. */\n minSizeRaw?: string;\n hasOrderbook: boolean;\n /**\n * Hyperliquid HIP-4 deployer namespace this member belongs to (e.g. \"ap\").\n * `null` for every other venue and for Hyperliquid members without one.\n * Names which deployer this cluster member is — distinct from whether its\n * book was published (see `hasOrderbook`).\n */\n deployerVenue?: string | null;\n}\n\n/**\n * Provenance of a published `midpoint`. Mirrors the engine's `MarkSource`.\n *\n * - `local` — true two-sided midpoint from the venue's own book\n * - `local_merged` — midpoint from the cross-venue merged book\n * - `local_one_sided` — only one side present; mark is the live side, NOT a midpoint\n * - `sibling` — derived from the complementary outcome (e.g. NO from YES)\n * - `local_boundary` — clamped to the [tick, 1-tick] boundary\n * - `none` — no mark available\n */\nexport type MarkSource =\n | \"local\"\n | \"local_merged\"\n | \"local_one_sided\"\n | \"sibling\"\n | \"local_boundary\"\n | \"none\";\n\nexport const RECURRENCE_CADENCES = [\n \"PT5M\",\n \"PT10M\",\n \"PT15M\",\n \"PT30M\",\n \"PT1H\",\n \"PT4H\",\n \"P1D\",\n \"P1W\",\n \"P1M\",\n \"P1Y\",\n] as const;\nexport type RecurrenceCadence = (typeof RECURRENCE_CADENCES)[number];\nexport type RecurrenceFilter = RecurrenceCadence | \"null\";\n\nexport type RecurringCryptoDuration = \"PT5M\" | \"PT15M\" | \"PT30M\" | \"PT1H\" | \"PT4H\" | \"P1D\";\nexport type RecurringCryptoDurationInput =\n | RecurringCryptoDuration\n | \"5m\"\n | \"15m\"\n | \"30m\"\n | \"1h\"\n | \"4h\"\n | \"1d\";\nexport type RecurringCryptoSourceConfidence = \"verified\" | \"inferred\" | \"missing\";\n\nexport interface ListRecurringCryptoMarketsOptions {\n assets?: string[];\n durations?: RecurringCryptoDurationInput[];\n interval?: RecurringCryptoDurationInput;\n window?: \"current\";\n venues?: Venue[];\n status?: MarketStatus[];\n windowStartFrom?: string;\n windowStartTo?: string;\n cursor?: string;\n limit?: number;\n includeOrderbookPrices?: boolean;\n includeReferencePrices?: boolean;\n includeDirectVenueMarkets?: boolean;\n includeOrderbookDepth?: boolean;\n orderbookDepth?: number;\n orderbookDepthAmountUsd?: number;\n}\n\nexport interface RecurringCryptoOrderbookDepthLevel {\n price: number;\n size: number;\n notionalUsd: number;\n cumulativeSize: number;\n cumulativeNotionalUsd: number;\n fillSize: number | null;\n fillNotionalUsd: number | null;\n}\n\nexport interface RecurringCryptoOrderbookDepthSide {\n levels: RecurringCryptoOrderbookDepthLevel[];\n totalSize: number;\n totalNotionalUsd: number;\n requestedNotionalUsd: number | null;\n filledSize: number | null;\n filledNotionalUsd: number | null;\n unfilledNotionalUsd: number | null;\n avgPrice: number | null;\n worstPrice: number | null;\n fillsComplete: boolean | null;\n}\n\nexport interface RecurringCryptoOutcomeOrderbookDepth {\n currency: \"USD\";\n amountUsd: number | null;\n buy: RecurringCryptoOrderbookDepthSide;\n sell: RecurringCryptoOrderbookDepthSide;\n}\n\nexport interface RecurringCryptoOutcome {\n /**\n * Canonical Agg outcome id. Null for direct live venue rows because those\n * rows are discovery data and cannot be passed to smart order routing.\n */\n venueMarketOutcomeId: string | null;\n /** Venue-native outcome id or synthetic external id for direct live rows. */\n externalOutcomeId: string | null;\n /** False for this endpoint; live crypto markets are not smart-route inputs. */\n routeable: boolean;\n /** False for this endpoint; split-order routing is not supported here. */\n splitOrdersAllowed: boolean;\n label: string;\n title: string | null;\n midpoint: number | null;\n bestBid: number | null;\n bestAsk: number | null;\n markSource: MarkSource | string | null;\n lastKnownPrice: number | null;\n orderbookDepth: RecurringCryptoOutcomeOrderbookDepth | null;\n}\n\nexport interface RecurringCryptoMarketMetrics {\n volume: number | null;\n volume24h: number | null;\n openInterest: number | null;\n liquidity: number | null;\n spread: number | null;\n}\n\nexport interface RecurringCryptoResolution {\n sourceName: string | null;\n sourceUrl: string | null;\n sourceDomain: string | null;\n rawCriteria: unknown;\n confidence: RecurringCryptoSourceConfidence;\n}\n\nexport interface RecurringCryptoReferencePrice {\n asset: string;\n quoteAsset: \"USD\";\n raw: string | null;\n decimals: number | null;\n normalized: number | null;\n timestamp: string | null;\n provider: string | null;\n providerMarketId: string | null;\n confidence: RecurringCryptoSourceConfidence;\n fetchedAt?: string | null;\n ageMs?: number | null;\n refreshing?: boolean;\n stale?: boolean;\n}\n\nexport type CryptoReferencePriceTarget =\n | { type: \"venueMarket\"; venueMarketId: string }\n | { type: \"venueEvent\"; venueEventId: string }\n | { type: \"externalVenueMarket\"; venue: Venue; externalMarketId: string }\n | {\n type: \"market\";\n venue: Venue;\n venueEventId?: string;\n venueMarketId: string;\n externalEventId?: string | null;\n externalMarketId?: string;\n asset: string;\n quoteAsset?: \"USD\";\n resolution: RecurringCryptoResolution;\n };\n\nexport interface CryptoReferencePriceExternalMarketInput {\n venue: Venue;\n externalMarketId: string;\n}\n\nexport interface CryptoReferencePriceMarketInput extends RecurringCryptoVenueMarket {\n asset: string;\n quoteAsset?: \"USD\";\n}\n\nexport interface GetCryptoReferencePricesOptions {\n targets?: CryptoReferencePriceTarget[];\n venueMarketIds?: string[];\n venueEventIds?: string[];\n externalMarkets?: CryptoReferencePriceExternalMarketInput[];\n markets?: CryptoReferencePriceMarketInput[];\n windowMarkets?: RecurringCryptoWindowMarket[];\n signal?: AbortSignal;\n}\n\nexport interface CryptoReferencePriceError {\n code:\n | \"not_found\"\n | \"not_recurring_crypto\"\n | \"reference_feed_missing\"\n | \"price_unavailable\"\n | \"stale_price\";\n message: string;\n}\n\nexport interface CryptoReferencePriceSource {\n provider: string | null;\n providerMarketId: string | null;\n confidence: RecurringCryptoSourceConfidence;\n}\n\nexport interface CryptoReferencePriceResult {\n target: CryptoReferencePriceTarget;\n venue: Venue | null;\n venueEventId: string | null;\n venueMarketId: string | null;\n externalEventId: string | null;\n externalMarketId: string | null;\n asset: string | null;\n quoteAsset: \"USD\" | null;\n raw: string | null;\n decimals: number | null;\n normalized: number | null;\n providerTimestamp: string | null;\n fetchedAt: string | null;\n ageMs: number | null;\n refreshing: boolean;\n stale: boolean;\n source: CryptoReferencePriceSource;\n error: CryptoReferencePriceError | null;\n}\n\nexport interface CryptoReferencePricesResponse {\n data: CryptoReferencePriceResult[];\n softRefreshMs: number;\n hardMaxAgeMs: number;\n}\n\nexport type RecurringCryptoComparisonPriceSource = \"referencePrice\" | \"midpoint\" | \"lastKnownPrice\";\n\nexport interface RecurringCryptoComparisonPoint {\n venue: Venue;\n venueMarketId: string;\n value: number;\n label: string | null;\n source: RecurringCryptoComparisonPriceSource;\n provider: string | null;\n providerMarketId: string | null;\n timestamp: string | null;\n confidence: RecurringCryptoSourceConfidence | null;\n}\n\nexport interface RecurringCryptoPriceComparison {\n count: number;\n min: RecurringCryptoComparisonPoint | null;\n max: RecurringCryptoComparisonPoint | null;\n spread: number | null;\n spreadBps: number | null;\n byVenue: RecurringCryptoComparisonPoint[];\n}\n\nexport interface RecurringCryptoWindowComparisons {\n referencePrice: RecurringCryptoPriceComparison;\n outcomePrices: {\n up: RecurringCryptoPriceComparison;\n down: RecurringCryptoPriceComparison;\n };\n}\n\nexport interface RecurringCryptoVenueMarket {\n venue: Venue;\n venueEventId: string;\n venueMarketId: string;\n externalEventId: string | null;\n externalMarketId: string;\n question: string;\n status: MarketStatus;\n priceSource: \"snag\" | \"direct\";\n /** False for this endpoint; live crypto markets are not smart-route inputs. */\n routeable: boolean;\n /** False for this endpoint; split-order routing is not supported here. */\n splitOrdersAllowed: boolean;\n outcomes: RecurringCryptoOutcome[];\n metrics: RecurringCryptoMarketMetrics;\n resolution: RecurringCryptoResolution;\n referencePrice: RecurringCryptoReferencePrice;\n}\n\nexport interface RecurringCryptoWindowMarket {\n id: string;\n asset: string;\n quoteAsset: \"USD\";\n duration: RecurringCryptoDuration;\n windowStart: string;\n windowEnd: string;\n status: MarketStatus;\n markets: RecurringCryptoVenueMarket[];\n comparisons: RecurringCryptoWindowComparisons;\n}\n\nexport interface RecurringCryptoMarketsResponse {\n data: RecurringCryptoWindowMarket[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n/** Per-venue orderbook entry with native tick spacing. */\nexport interface VenueOrderbookEntry {\n venueMarketId: string;\n tickSize: number | null;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this market, raw 6-dec shares.\n * Absent means no known minimum. */\n minSizeRaw?: string;\n orderbook: Orderbook;\n /**\n * Sticky tick of this venue's book inferred at runtime by the engine. May\n * differ from the seed `tickSize` when the live grid is finer than the DB\n * metadata. Optional — only populated when the engine has emitted runtime\n * metadata for this entry.\n */\n tick?: number | null;\n /** Provenance of this venue book's published midpoint. See {@link MarkSource}. */\n markSource?: MarkSource;\n /**\n * Hyperliquid HIP-4 deployer namespace whose book this entry publishes\n * (e.g. \"ap\"). `null` for every other venue. When a cluster has more than\n * one Hyperliquid deployer member, only one member's book is published per\n * request — this names which one, so a caller never pairs this entry's depth\n * with a different member's `venueMarketId`.\n */\n deployerVenue?: string | null;\n}\n\n/** Response from GET /orderbooks (batch). */\nexport interface BatchOrderbooksResponse {\n data: Array<{\n venueMarketId: string;\n status: OrderbookBatchItemStatus;\n error: OrderbookBatchItemError | null;\n requestedMarket: RequestedOrderbookMarket | null;\n venueOrderbooks: Record<string, VenueOrderbookEntry>;\n matchedMarkets: MatchedOrderbookMarket[];\n }>;\n meta: {\n requestedCount: number;\n okCount: number;\n errorCount: number;\n };\n}\n\n/** A single market midpoint row returned by GET /midpoints. */\nexport interface MidpointRow {\n venueMarketId: string;\n venue: string;\n midpoint: number | null;\n spread: number | null;\n timestamp: number | null;\n arbReturn?: number | null;\n /** Provenance of `midpoint`. */\n markSource?: MarkSource;\n /**\n * When `markSource === \"sibling\"`, the matched venueMarketId whose book\n * supplied the headline mark. Allows the FE to label \"sourced from venue X\"\n * without re-running the matching logic.\n */\n siblingVenueMarketId?: string;\n /** Top-of-book buy-side price. Only present when `bestPrice=true`. */\n bestBid?: number | null;\n /** Top-of-book sell-side price. Only present when `bestPrice=true`. */\n bestAsk?: number | null;\n}\n\n/** Per-outcome midpoint from a live orderbook. */\nexport interface OutcomeMidpointRow {\n venueMarketOutcomeId: string;\n label: string;\n midpoint: number | null;\n /** Provenance of `midpoint`. */\n markSource?: MarkSource;\n /** Top-of-book buy-side price. Only present when `bestPrice=true`. */\n bestBid?: number | null;\n /** Top-of-book sell-side price. Only present when `bestPrice=true`. */\n bestAsk?: number | null;\n}\n\n/** Response from GET /midpoints (batch). */\nexport interface BatchMidpointsResponse {\n data: Array<\n MidpointRow & {\n outcomes: OutcomeMidpointRow[];\n matched: MidpointRow[];\n /**\n * Live, quality-gated cross-venue arbitrage return for this market's\n * cluster as a decimal fraction (`0.0085` = 0.85%), computed fresh by\n * the engine on this request. Prefer it over the `arbReturn` embedded\n * in venue-event listings, which a background sync can leave stale.\n * Only present when the request set `bestPrice=true`.\n */\n arbReturn?: number | null;\n /**\n * DB status of the requested market. Present whenever the id resolves\n * to a known market. Resolved markets never serve a price (see `error`).\n */\n marketStatus?: MarketStatus;\n /**\n * Structured refusal, mirroring GET /orderbooks per-item errors:\n * `market_resolved` for settled markets (prices are nulled instead of\n * serving a stale mark), `market_not_found` for unknown ids.\n */\n error?: {\n code: \"market_resolved\" | \"market_not_found\";\n message: string;\n retryable: boolean;\n };\n }\n >;\n}\n\n/** Response from GET /orderbook/outcome/:id (single outcome). */\nexport interface OutcomeOrderbookResponse {\n /** CRC of returned depth-limited levels; full engine checksum remains unchanged. */\n snapshotChecksum?: number;\n venueMarketOutcomeId: string;\n venueMarketId: string;\n venue: string;\n orderbook: {\n bids: Array<{ price: number; size: number }>;\n asks: Array<{ price: number; size: number }>;\n };\n midpoint: number | null;\n spread: number | null;\n seq: number;\n checksum: number;\n timestamp: number;\n /** Sticky tick of this outcome's book, inferred at runtime. `null` until inferred. */\n tick: number | null;\n /** Provenance of `midpoint`. See {@link MarkSource}. */\n markSource: MarkSource;\n}\n\n/** Standard paginated list response from the API. */\nexport interface PaginatedResponse<T> {\n data: T[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface OrderListQuery {\n userId?: string;\n status?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface TradeExecutorOrder {\n id: string;\n userId: string;\n venue: string;\n status: string;\n marketId: string;\n tokenId: string;\n side: string;\n amountRaw: string;\n quoteId: string | null;\n externalId: string | null;\n clientOrderId: string | null;\n dagRunId: string | null;\n filledAmountRaw: string | null;\n executionPrice: string | null;\n txHash: string | null;\n errorMessage: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface TradeExecutorOrderListResponse {\n orders: TradeExecutorOrder[];\n total: number;\n}\n\n// ── Aggregated orderbook (GET /orderbook/:venueMarketId) ──\n\n/** A single level in the aggregated orderbook with per-venue attribution. */\nexport interface AggregatedOrderbookLevel {\n price: number;\n size: number;\n venues: Record<string, number>;\n}\n\n/** A simple orderbook level without venue attribution. */\nexport interface SimpleOrderbookLevel {\n price: number;\n size: number;\n}\n\n/** Per-venue best-bid/ask info. */\nexport interface VenuePriceInfo {\n bestBid: number | null;\n bestAsk: number | null;\n}\n\n/** Response from GET /orderbook/:venueMarketId — canonical aggregated orderbook. */\nexport interface AggregatedOrderbookResponse {\n venueMarketId: string;\n orderbook: {\n bids: AggregatedOrderbookLevel[];\n asks: AggregatedOrderbookLevel[];\n };\n venueOrderbooks: Record<string, { bids: SimpleOrderbookLevel[]; asks: SimpleOrderbookLevel[] }>;\n venues: Record<string, VenuePriceInfo>;\n midpoint: number | null;\n spread: number | null;\n timestamp: number;\n /** Sequence number (present in live responses). */\n seq?: number;\n /** CRC32 checksum (present in live responses). */\n checksum?: number | null;\n /** Markets matched across venues for this canonical market. */\n matchedMarkets?: Array<{ venue: string; venueMarketId: string }>;\n}\n\n// ── Managed Execution ──\n\nexport interface ExecuteManagedParams {\n quoteId: string;\n /**\n * Optional idempotency key: your own id for this trade, unique within your\n * app. Saved on every order the quote splits into, so\n * `getExecutionOrders({ externalId })` returns all legs and each\n * `trades.filled` webhook carries it. Reusing it on a different quote is\n * rejected with 409.\n */\n externalId?: string;\n /** Trading mode. Defaults to live. */\n mode?: ExecutionMode;\n /**\n * Optional intent fallback. When the supplied `quoteId` has expired in the\n * cache (e.g. user clicked Buy after a tab was inactive), the server\n * resolves the latest quote for this intent and refreshes/executes against\n * that instead of returning 400 `quote_not_found`. Same intent = same buttons\n * the user pressed in the UI; a different `maxSpend`, mode, or venue scope is\n * a different intent and won't match.\n */\n fallbackToLatest?: {\n outcomeId: string;\n side: \"buy\" | \"sell\";\n maxSpend?: number;\n sellShares?: number;\n allowedVenues?: Venue[];\n };\n /**\n * Self-custody: the wallet that will sign this fill. Must be a wallet\n * already linked to this account. Omit for managed custody (the default).\n */\n signingAddress?: string;\n /**\n * Self-custody only: which approve shape a cross-chain fill uses when the\n * bridge needs an ERC20 approve. Omit (the default) for \"sponsored\" — the\n * approve costs the wallet no gas, but the wallet must sign a one-time\n * EIP-7702 authorization over a RAW DIGEST, which many wallets cannot\n * produce. Send \"user_broadcast\" when yours cannot: the user sends the\n * approve from their own wallet and pays its gas. Only your client can know\n * which applies — it is a property of the wallet software, not of the\n * address or the chain.\n *\n * Worth surfacing in your UI: \"user_broadcast\" never establishes the\n * delegation, so an approve is needed on EVERY bridge. \"sponsored\" costs one\n * signature once per chain.\n *\n * Neither mode makes bridging free — the approve is only one of the costs.\n * Relay's fee comes out of the amount delivered on every bridge, and one-time\n * costs apply per route. Quote with `deepEstimate` and read\n * `feeBreakdown.bridgeFees` and `feeBreakdown.setupCosts` rather than\n * inferring cost from the approve mode.\n */\n approveMode?: \"sponsored\" | \"user_broadcast\";\n}\n\nexport interface ExecuteManagedResponse {\n alreadyAccepted?: boolean;\n quoteId: string;\n orderIds: string[];\n status: \"pending\";\n redeemId?: string;\n message?: string;\n /**\n * What this fill is waiting to be signed, if anything. On the immediate\n * `POST /execution/fill` response this is always absent or empty — even\n * for a self-custody fill, the DAG parks asynchronously, after this\n * response has already been sent. Real entries only ever come back from\n * polling `GET /execution/status` or from the next\n * `POST /execution/fill/:quoteId/signatures` response (this same shape,\n * reused). Drive the whole round trip through `fillSelfCustody()` rather\n * than reading this field on the fill response by hand.\n */\n pendingSignatures?: SignatureRequest[];\n}\n\nexport type LimitOrderTimeInForce = \"GTC\" | \"GTD\" | \"FOK\" | \"FAK\" | \"IOC\" | \"ALO\";\n\nexport type CancelOrderSignature =\n | { signature: string; timestamp: number }\n | {\n venue: \"hyperliquid\";\n action: { type: \"cancel\"; cancels: Array<{ a: number; o: number }> };\n nonce: number;\n signature: { r: string; s: string; v: 27 | 28 };\n };\n\nexport interface CancelVenueOrderParams {\n venue: \"polymarket\" | \"hyperliquid\";\n venueOrderId: string;\n signerAddress: string;\n cancelSignature: CancelOrderSignature;\n}\n\nexport interface PlaceLimitOrderParams {\n /** BETDEX uses hosted cash: GTC/IOC only, no signer, post-only or expiry.\n * Native odds are rounded conservatively and stake is rounded down. GTC\n * unmatched liquidity is cancelled at the in-play transition. SELL closes\n * the same For outcome and requires collateral as well as owned inventory.\n */\n venue: Venue;\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n limitPriceRaw: string;\n sizeRaw: string;\n timeInForce: LimitOrderTimeInForce;\n postOnly?: boolean;\n expiresAt?: string;\n clientOrderId?: string;\n /** Linked account EOA. Polymarket supports GTC/GTD buys; Hyperliquid supports GTC/ALO buys and sells. Agent keys stay on the client. Omit for managed custody. */\n signingAddress?: string;\n /** Same bridge approval mode as market fills; defaults to sponsored. */\n approveMode?: ExecuteManagedParams[\"approveMode\"];\n /** Self-custody buys only: other wallets linked to this account whose balances may bridge in to fund the order. Requires signingAddress. */\n fundingAddresses?: string[];\n}\n\nexport interface PlaceLimitOrderResponse {\n orderId: string;\n /** Poll getExecutionStatus and answer submitFillSignatures using this ID. */\n quoteId?: string;\n status:\n | \"pending\"\n | \"submitting\"\n | \"submitted\"\n | \"cancel_pending\"\n | \"partial_fill\"\n | \"open\"\n | \"partially_filled_open\"\n | \"filled\"\n | \"cancelled\"\n | \"expired\"\n | \"failed\";\n venue: Venue;\n venueOrderId?: string | null;\n reservedCostRaw?: string | null;\n limitPriceRaw: string;\n limitSizeRaw: string;\n filledSizeRaw: string;\n remainingSizeRaw: string;\n}\n\nexport interface PlaceOrderParams {\n venue: Venue;\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n /** Buy only. Maximum all-in USD spend, inclusive of app fee. */\n maxSpend?: number;\n /** Sell only. Number of contracts to sell. */\n sellShares?: number;\n /**\n * Your trade id. Required, unique within your app — two different users of\n * the same app cannot share one. A repeat returns 409 instead of trading twice.\n */\n externalId: string;\n /** Slippage cap in bps. Defaults to 500 (5%). Set explicitly on sells. */\n slipCapBps?: number;\n /** Restrict funding to these chain IDs. Omit to allow every funded chain. */\n allowedSourceChainIds?: number[];\n /** USD budgets capped by refreshed wallet balances; omitted chains cannot fund. */\n chainBalances?: Record<string, number>;\n /** Per-trade app fee in bips (0..10000), replacing the app's configured rate. Needs an app API key. Buy only. */\n appFeeBips?: number;\n /** Per-venue app fee in bips (each 0..10000), e.g. `{ polymarket: 20, hyperliquid: 10 }`. Wins over `appFeeBips` on the venues it names; `appFeeBips` still covers the rest. Needs an app API key. Buy only. */\n appFeeBipsByVenue?: Record<string, number>;\n /** Referral: EVM address that receives the referral fee. Needs an app API key. */\n referrer?: string;\n /** Referral fee in bips of routed notional (1..10000). Snag-free. */\n referrerFeeBips?: number;\n /** Per-venue referral fee in bips (each 0..10000; 0 = none on that venue). Wins over `referrerFeeBips` on the venues it names. Needs `referrer` and an app API key. Not for `skipQuote`. */\n referrerFeeBipsByVenue?: Record<string, number>;\n /** Who funds the referral: \"user\" (default) reserves it from maxSpend; \"app\" pays from `referralPayerAddress` after the fill. */\n referralPayer?: \"user\" | \"app\";\n /** Required with `referralPayer: \"app\"`: the wallet that signs the parked payout transaction. */\n referralPayerAddress?: string;\n /**\n * User-paid referral only: a wallet that pays Hyperliquid's one-time 1 USDC\n * activation fee for a referrer with no HyperCore account (self-custody\n * Hyperliquid buys). Before the fill a pending signature with this\n * `signerAddress` and `purpose: \"hl_activation_sponsor\"` is passed to your\n * `signer`; it is `optional`, so declining it — or not answering within\n * `OPTIONAL_SIGNATURE_TIMEOUT_MS` — never costs the trade.\n */\n referralActivationSponsorAddress?: string;\n /**\n * Skip the smart-route solver and send one order straight to `venue` (predict,\n * hyperliquid, novig and prophetx only; others return 400). Requires a `read_write` `x-app-api-key`. No\n * bridging: funds must already sit on the venue's own chain, and `allowedSourceChainIds` /\n * `chainBalances` are ignored alongside it. You own price and minimum\n * checks — an order the venue refuses fails after acceptance and uses up its `externalId`.\n */\n skipQuote?: boolean;\n /**\n * With `skipQuote`, skip the balance check and fund hold on a buy: nothing checks the\n * balance and an underfunded order fails at the venue. Sells still check the position.\n * Without `skipQuote`, skip only the quote-time balance refresh: the route uses the last\n * stored balances, and the fund hold and balance check still run. Faster, but a stale\n * balance can fail the order after it was accepted. Requires a `read_write` `x-app-api-key`.\n */\n skipBalance?: boolean;\n /**\n * With `skipQuote`, the price to trade at (e.g. `0.52`). Optional: if omitted, the best\n * available price at submission is used (best ask to buy, bid to sell). Ignored on\n * prophetx, which prices the order itself within `slipCapBps`.\n */\n price?: number;\n}\n\nexport interface PlaceOrderResponse {\n orderId: string;\n externalId: string;\n venue: Venue;\n status: \"pending\";\n quoteId: string;\n /** `null` if the order row doesn't carry a quoted price. Not zero. */\n quotedPriceRaw: string | null;\n /** `null` under the same conditions as `quotedPriceRaw`. Not zero. */\n quotedCostRaw: string | null;\n /** `null` under the same conditions as `quotedPriceRaw`. Not zero. */\n quotedSharesRaw: string | null;\n}\n\nexport interface ValidateManagedParams {\n venueMarketOutcomeIds: string[];\n side: \"buy\" | \"sell\";\n amount: number;\n}\n\nexport interface ValidateManagedResponse {\n canExecute: boolean;\n availableBalanceRaw: string;\n requiredBalanceRaw: string;\n bridgeSourceChainId?: number;\n bridgeAmountRaw?: string;\n}\n\nexport type BalanceRefillPolicyStatus = \"enabled\" | \"paused\";\nexport type BalanceRefillAttemptStatus = \"reserved\" | \"executing\" | \"completed\" | \"failed\";\n\nexport interface BalanceRefillAttempt {\n id: string;\n policyId: string;\n status: BalanceRefillAttemptStatus;\n /** Target-chain balance when the threshold was crossed, in 6-decimal USD units. */\n triggerBalanceRaw: string;\n /** Minimum amount the refill must deliver, in 6-decimal USD units. */\n requestedDeliveryRaw: string;\n /** Reserved source amount, in 6-decimal USD units. */\n sourceAmountRaw: string;\n completedAmountRaw: string | null;\n sourceChainId: number;\n targetChainId: number;\n feeRaw: string | null;\n errorMessage: string | null;\n startedAt: string | null;\n completedAt: string | null;\n createdAt: string;\n}\n\nexport interface BalanceRefillPolicy {\n id: string;\n targetChainId: number;\n targetTokenAddress: string;\n targetTokenSymbol: \"USDC\";\n /** Balance floor, in 6-decimal USD units. */\n minimumRaw: string;\n /** Minimum delivered amount per refill, in 6-decimal USD units. */\n refillAmountRaw: string;\n dailyCapRaw: string;\n maxFeeRaw: string;\n status: BalanceRefillPolicyStatus;\n cooldownSeconds: number;\n lastObservedRaw: string | null;\n lastEvaluatedAt: string | null;\n nextEligibleAt: string | null;\n consentedAt: string;\n createdAt: string;\n updatedAt: string;\n latestAttempt: BalanceRefillAttempt | null;\n}\n\nexport interface CreateBalanceRefillPolicyParams {\n targetChainId: number;\n targetTokenSymbol?: \"USDC\";\n minimumRaw: string;\n refillAmountRaw: string;\n /** Optional daily refill limit. Defaults to $1,002 in 6-decimal USD units. */\n dailyCapRaw?: string;\n /** Optional per-refill fee limit. Defaults to $2 in 6-decimal USD units. */\n maxFeeRaw?: string;\n}\n\nexport interface UpdateBalanceRefillPolicyParams {\n minimumRaw?: string;\n refillAmountRaw?: string;\n dailyCapRaw?: string;\n maxFeeRaw?: string;\n status?: BalanceRefillPolicyStatus;\n}\n\nexport type WithdrawTokenSymbol = \"USDC\" | \"USDC.e\" | \"USDT\";\nexport type WithdrawalSourceTokenSymbol = WithdrawTokenSymbol | \"pUSD\" | \"USD1\";\n\nexport interface WithdrawManagedParams {\n /** Idempotency key for exact-amount transfers. Retry the same request, never a new key, after a lost response. Not combined with max. */\n requestId?: string;\n /** Positive integer string in the token's native decimals (e.g. \"100000\" = 0.1 USDC). */\n amountRaw: string;\n tokenSymbol: WithdrawTokenSymbol;\n /** Recipient address. EVM destinations use 0x-prefixed 20-byte hex; Solana uses base58. */\n destinationAddress: string;\n /** Chain ID where the recipient should receive funds. Required as of v2026.04. */\n destinationChainId: number;\n /**\n * When `true`, the server caps the withdrawal to the maximum deliverable amount\n * instead of rejecting an over-balance request. Use only when the user explicitly\n * clicked Max — manual over-typed amounts must still surface the unviable state.\n */\n max?: boolean;\n}\n\nexport type WithdrawalLifecycleStatus =\n | \"pending\"\n | \"bridging\"\n | \"transferring\"\n | \"completed\"\n | \"partial\"\n | \"failed\";\n\nexport type WithdrawalSourceStatus = \"pending\" | \"submitted\" | \"confirmed\" | \"failed\";\n\nexport type WithdrawalLegType = \"transfer\" | \"bridge\";\nexport type WithdrawalLegStatus = \"planned\" | \"submitted\" | \"confirmed\" | \"failed\";\n\nexport interface WithdrawalLeg {\n type: WithdrawalLegType;\n status: WithdrawalLegStatus;\n sourceChainId: number;\n destChainId: number;\n amountRaw: string;\n txHash: string | null;\n bridgeOperationId: string | null;\n /** Human-readable failure reason when `status === \"failed\"`. Null when succeeded or in-flight. */\n errorMessage?: string | null;\n}\n\nexport interface WithdrawManagedSourceItem {\n sourceId: string;\n chainId: number;\n tokenSymbol: WithdrawalSourceTokenSymbol;\n /** On-chain token address on `chainId`. */\n tokenAddress: string;\n /**\n * On-chain decimals for `(chainId, tokenAddress)`. Required to interpret\n * `amountRaw`: BNB USDC is 18-dec, EVM USDC is 6-dec.\n */\n decimals: number;\n amountRaw: string;\n /** Smart-wallet or native-account custody; absent for ordinary EOA sources. */\n custodyKind?: \"DEPOSIT_WALLET\" | \"VENUE_ACCOUNT\";\n /** Venue that owns the source (for example, `pred` or `tiprun`). */\n venue?: string;\n sourceVenueAccountId?: string;\n /** Lossless native account ID, not an EVM address. */\n sourceExternalAccountId?: string;\n status: WithdrawalSourceStatus;\n txHash: string | null;\n bridgeOperationId: string | null;\n /**\n * Present only while a venue-account source is submitted but not confirmed:\n * what it is waiting on (`awaiting_venue_approval` = the venue has not\n * approved the withdrawal yet).\n */\n pendingReason?:\n | \"awaiting_venue_submission\"\n | \"awaiting_venue_approval\"\n | \"awaiting_chain\"\n | \"awaiting_venue_balance\"\n | \"rechecking\";\n}\n\n/**\n * `pricingStatus === \"quoted\"` means the response includes a fresh preflight\n * quote; other states may carry null `expected.*` fields. Do NOT treat null\n * fields as missing.\n */\nexport interface WithdrawalExpected {\n outputRaw: string | null;\n feeRaw: string | null;\n etaSeconds: number | null;\n}\n\n/** Body for POST /execution/withdraw/preview — identical to a withdraw request. */\nexport type WithdrawPreviewParams = WithdrawManagedParams;\n\nexport interface WithdrawalQuoteParams {\n tokenSymbol: WithdrawTokenSymbol;\n destinationChainId: number;\n}\n\nexport interface WithdrawalQuoteResponse {\n tokenSymbol: WithdrawTokenSymbol;\n destinationChainId: number;\n maxDeliverableRaw: string;\n rawBalanceRaw: string;\n decimals: number;\n}\n\n/** Response from POST /execution/withdraw/preview. All amounts are raw strings in destination-token native decimals. */\nexport interface WithdrawPreviewResponse {\n receiveAmountRaw: string | null;\n feeRaw: string | null;\n relayFeeRaw: string | null;\n networkFeeRaw: string | null;\n pricingStatus: \"quoted\" | \"unviable\";\n quoteExpiresAt: string | null;\n unviableReason: string | null;\n maxDeliverableRaw: string | null;\n}\n\nexport interface WithdrawManagedResponse {\n withdrawalId: string;\n status: WithdrawalLifecycleStatus;\n requested: { tokenSymbol: WithdrawTokenSymbol; amountRaw: string };\n /**\n * Terminal settled amount in destination-token native decimals.\n * Null until at least one source confirms.\n */\n completedAmountRaw: string | null;\n destination: { chainId: number; address: string; tokenSymbol: WithdrawTokenSymbol };\n legs: WithdrawalLeg[];\n expected: WithdrawalExpected;\n pricingStatus: \"unquoted\" | \"quoting\" | \"quoted\" | \"unviable\";\n /**\n * Persisted terminal-state error reason. Always `null` until the\n * withdrawal reaches `failed` / `partial`. The submit response always\n * returns `null`; populated values arrive via the GET status endpoint or\n * via a terminal `withdrawal_lifecycle` WS event.\n */\n errorMessage: string | null;\n sources: WithdrawManagedSourceItem[];\n}\n\nexport interface DepositAddressesToken {\n symbol: string;\n address: string;\n decimals: number;\n}\n\nexport interface DepositAddressesSupportedChain {\n chainId: number;\n name: string;\n tokens: DepositAddressesToken[];\n}\n\nexport interface DepositAddressesReadyResponse {\n ready: true;\n evmAddress: string;\n svmAddress: string;\n supportedChains: DepositAddressesSupportedChain[];\n}\n\nexport interface DepositAddressesPendingResponse {\n ready: false;\n}\n\nexport type DepositAddressesResponse =\n | DepositAddressesReadyResponse\n | DepositAddressesPendingResponse;\n\nexport interface GetPositionsParams {\n cursor?: string;\n limit?: number;\n status?: \"active\" | \"closed\";\n mode?: ExecutionMode;\n categoryIds?: string[];\n sort?: \"realizedPnl\";\n}\n\nexport interface GetOrdersParams {\n status?: string;\n cursor?: string;\n limit?: number;\n}\n\n// ── Orderbook Quote (GET /orderbook/:marketId/quote) ──\n\nexport interface OrderbookQuoteParams {\n marketId: string;\n side: \"buy\" | \"sell\";\n size: number;\n}\n\nexport interface OrderbookQuoteFill {\n venue: string;\n size: number;\n avgPrice: number;\n cost: number;\n}\n\nexport interface OrderbookQuoteResponse {\n marketId: string;\n side: \"buy\" | \"sell\";\n requestedSize: number;\n filledSize: number;\n avgPrice: number | null;\n totalCost: number;\n slippage: number | null;\n fills: OrderbookQuoteFill[];\n}\nexport type ExecutionOrdersQuery = GetOrdersQuery & { mode?: ExecutionMode };\nexport type ExecutionOrderItem = OrderListItem;\nexport type ExecutionStatusQuery = { quoteId: string; mode?: ExecutionMode };\nexport type ExecutionOverallState =\n | \"created\"\n | \"routing\"\n | \"quoting\"\n | \"placing\"\n | \"confirming\"\n | \"filled\"\n | \"partially_filled\"\n | \"failed\"\n | \"cancelled\"\n | \"expired\";\nexport interface ExecutionDagProgress {\n dagRunId: string;\n totalSteps: number;\n currentSequence: number;\n currentStepType: string | null;\n completedSequences: number[];\n stepTypes: Record<number, string>;\n status: \"running\" | \"completed\" | \"failed\";\n errorReason: string | null;\n}\nexport type ExecutionDisplayStepKind = \"submit\" | \"setup\" | \"bridge\" | \"fill\" | \"internal\";\nexport type ExecutionDisplayGroupStatus =\n | \"pending\"\n | \"in_progress\"\n | \"completed\"\n | \"failed\"\n | \"skipped\";\n\nexport interface ExecutionStatusStep {\n sequence: number;\n stepType: string;\n status: \"pending\" | \"in_progress\" | \"completed\" | \"failed\" | \"skipped\";\n attempt: number;\n startedAt: string | null;\n completedAt: string | null;\n errorReason: string | null;\n\n /** Venue legs this step funds or executes; join to `orders[].orderId`. */\n orderIds: string[];\n /** Display class. `internal` steps are not meant to be rendered. */\n kind: ExecutionDisplayStepKind;\n /** Steps sharing a groupId render as ONE row. */\n groupId: string;\n /** Rolled-up status for the group; identical on every member. */\n groupStatus: ExecutionDisplayGroupStatus;\n /** Row copy, phrased for the current `groupStatus`. */\n label: string;\n /** Set on `kind: \"bridge\"` only. */\n bridge?: {\n amount: string;\n tokenSymbol: string;\n fromChain: string;\n toChain: string;\n };\n}\nexport interface ExecutionStatusOrder {\n orderId: string;\n venue: string;\n status: string;\n event: \"filled\" | \"partial_fill\" | \"failed\" | null;\n filledAmountRaw?: string;\n remainingAmountRaw?: string;\n quotedSharesRaw?: string;\n actualSharesRaw?: string;\n quotedToWinRaw?: string;\n actualToWinRaw?: string;\n quotedPriceRaw?: string;\n executionPriceRaw?: string;\n partialFillReason?: string;\n errorReason?: string;\n venueOrderId?: string;\n txHash?: string;\n updatedAt: string;\n}\nexport interface ExecutionStatusResponse {\n executionId: string | null;\n quoteId: string;\n orderIds: string[];\n overallState: ExecutionOverallState;\n terminal: boolean;\n errorReason: string | null;\n pollAfterMs: number | null;\n dagProgress: ExecutionDagProgress | null;\n steps: ExecutionStatusStep[];\n orders: ExecutionStatusOrder[];\n /**\n * What this run is waiting to be signed, mirroring the fill response's\n * field of the same name. This is the polling route `fillSelfCustody` reads\n * while an on-chain step is in flight — a caller polling this route for\n * progress learns about newly-parked steps here too, not just from the\n * signatures endpoint.\n */\n pendingSignatures?: SignatureRequest[];\n}\nexport type ExecutionPositionsQuery = GetPositionsQuery & { mode?: ExecutionMode };\nexport type ExecutionPositionGroup = PositionGroup;\n/** Whose cash to return: the managed server wallet (default) or the account's linked wallets. */\nexport type BalanceCustody = \"managed\" | \"self\";\nexport type ManagedBalancesParams = { mode?: ExecutionMode; custody?: BalanceCustody };\nexport type ManagedBalancesResponse = UnifiedBalanceResponse;\n\n// ── Paper trading account administration (/apps/:appId/paper-trading) ──\n\nexport interface PaperTradingAppOptions {\n /** App ID for the paper account namespace. Defaults to AggClient appId. */\n appId?: string;\n}\n\nexport interface PaperTradingListParams {\n limit?: number;\n cursor?: string;\n}\n\nexport interface PaperTradingAccountListParams extends PaperTradingListParams {\n externalId?: string;\n}\n\nexport interface CreatePaperTradingAccountParams {\n name?: string;\n externalId?: string;\n initialBalanceRaw?: string;\n initialBalance?: number;\n}\n\nexport interface SetPaperTradingBalanceParams {\n balanceRaw?: string;\n balance?: number;\n reason?: string;\n}\n\nexport interface ResetPaperTradingAccountParams {\n balanceRaw?: string;\n balance?: number;\n reason?: string;\n}\n\nexport interface PlacePaperTradingOrderParams {\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n spendRaw?: string;\n spend?: number;\n shares?: number;\n slippageBps?: number;\n clientOrderId?: string;\n}\n\nexport type PaperTradingMarkSource = \"orderbook_midpoint\" | \"orderbook_best_bid\" | \"catalog_price\";\n\nexport type PaperTradingLiquidityStatus = \"full\" | \"partial\" | \"none\";\n\nexport interface PaperTradingAccount {\n id: string;\n appId: string;\n name: string | null;\n externalId: string | null;\n currency: string;\n startingBalanceRaw: string;\n startingBalance: number;\n cashBalanceRaw: string;\n cashBalance: number;\n realizedPnlRaw: string;\n realizedPnl: number;\n kycStatus: \"verified\";\n kycVerified: true;\n status: \"active\" | \"archived\";\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface PaperTradingPosition {\n id: string;\n accountId: string;\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n marketQuestion: string;\n outcomeLabel: string;\n size: number;\n avgEntryPrice: number;\n markPrice: number;\n markSource: PaperTradingMarkSource;\n markTimestamp: number | null;\n bestBidPrice: number | null;\n bestAskPrice: number | null;\n midpoint: number | null;\n spread: number | null;\n marketValueRaw: string;\n marketValue: number;\n unrealizedPnlRaw: string;\n unrealizedPnl: number;\n liquidationPrice: number | null;\n liquidationValueRaw: string;\n liquidationValue: number;\n liquidationPnlRaw: string;\n liquidationPnl: number;\n liquidityShares: number;\n liquidityStatus: PaperTradingLiquidityStatus;\n realizedPnlRaw: string;\n realizedPnl: number;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface PaperTradingOrder {\n id: string;\n accountId: string;\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n marketQuestion: string;\n outcomeLabel: string;\n side: \"buy\" | \"sell\";\n status: \"filled\" | \"rejected\";\n clientOrderId: string | null;\n requestedSpendRaw: string | null;\n requestedSpend: number | null;\n requestedShares: number | null;\n filledShares: number;\n avgPrice: number | null;\n slippageBps: number | null;\n notionalRaw: string;\n notional: number;\n cashDeltaRaw: string;\n cashDelta: number;\n realizedPnlRaw: string;\n realizedPnl: number;\n rejectionReason: string | null;\n createdAt: string;\n}\n\nexport interface PaperTradingBalanceAdjustment {\n id: string;\n accountId: string;\n type: \"set_balance\" | \"reset\";\n amountRaw: string;\n amount: number;\n previousCashBalanceRaw: string;\n previousCashBalance: number;\n newCashBalanceRaw: string;\n newCashBalance: number;\n reason: string | null;\n createdAt: string;\n}\n\nexport interface PaperTradingPortfolio {\n account: PaperTradingAccount;\n cashBalanceRaw: string;\n cashBalance: number;\n marketValueRaw: string;\n marketValue: number;\n equityRaw: string;\n equity: number;\n realizedPnlRaw: string;\n realizedPnl: number;\n unrealizedPnlRaw: string;\n unrealizedPnl: number;\n liquidationValueRaw: string;\n liquidationValue: number;\n liquidationEquityRaw: string;\n liquidationEquity: number;\n liquidationPnlRaw: string;\n liquidationPnl: number;\n positions: PaperTradingPosition[];\n}\n\nexport interface PaperTradingAccountsPage {\n data: PaperTradingAccount[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface PaperTradingPositionsPage {\n data: PaperTradingPosition[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface PaperTradingOrdersPage {\n data: PaperTradingOrder[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface PaperTradingBalanceResponse {\n account: PaperTradingAccount;\n adjustment: PaperTradingBalanceAdjustment;\n}\n\n// ── Unified user activity feed (/users/activity) ──\n\nexport type UserActivityType = \"trade\" | \"withdrawal\" | \"bridge\" | \"deposit\" | \"user_op\" | \"redeem\";\n\ninterface UserActivityBase {\n id: string;\n createdAt: string;\n updatedAt: string;\n status: string;\n}\n\ninterface UserActivityVenueMarket {\n id: string;\n venueEventId: string;\n question: string | null;\n image: string | null;\n}\n\ninterface UserActivityVenueMarketOutcome {\n id: string;\n label: string;\n title: string | null;\n price: number;\n}\n\nexport interface UserActivityTrade extends UserActivityBase {\n type: \"trade\";\n venue: string;\n side: string;\n amountRaw: string;\n filledAmountRaw: string | null;\n executionPrice: string | null;\n venueMarket: UserActivityVenueMarket | null;\n venueMarketOutcome: UserActivityVenueMarketOutcome | null;\n txHash: string | null;\n errorMessage: string | null;\n /** @deprecated Use venueMarket.question. */\n marketQuestion?: string | null;\n /** @deprecated Use venueMarketOutcome.label/title. */\n outcomeLabel?: string | null;\n}\n\nexport interface UserActivityWithdrawal extends UserActivityBase {\n type: \"withdrawal\";\n tokenSymbol: string;\n amountRaw: string;\n destinationAddress: string;\n destinationChainId: string;\n completedAmountRaw: string | null;\n chainId?: string | null;\n txHash?: string | null;\n errorMessage: string | null;\n}\n\nexport interface UserActivityBridge extends UserActivityBase {\n type: \"bridge\";\n tokenSymbol: string;\n amountRaw: string;\n sourceChainId: string;\n destChainId: string;\n sourceTxHash: string | null;\n destTxHash: string | null;\n}\n\nexport interface UserActivityDeposit extends UserActivityBase {\n type: \"deposit\";\n tokenSymbol: string;\n amountRaw: string;\n chainId: string;\n fromAddress: string;\n txHash: string;\n source: \"connected_wallet\" | \"external_wallet\";\n}\n\nexport interface UserActivityUserOp extends UserActivityBase {\n type: \"user_op\";\n callsId: string;\n chainId: string;\n walletAddress: string;\n txHash: string | null;\n confirmedAt: string | null;\n}\n\nexport interface UserActivityRedeemLeg {\n id: string;\n venueMarketOutcomeId: string;\n venue: string;\n status: string;\n chainId: string;\n payoutTokenSymbol: string;\n payoutAmountRaw: string | null;\n txHash: string | null;\n errorMessage: string | null;\n venueMarket: UserActivityVenueMarket | null;\n venueMarketOutcome: Omit<UserActivityVenueMarketOutcome, \"price\"> | null;\n}\n\nexport interface UserActivityRedeem extends UserActivityBase {\n type: \"redeem\";\n totalPayoutRaw: string | null;\n legs: UserActivityRedeemLeg[];\n}\n\nexport type UserActivityItem =\n | UserActivityTrade\n | UserActivityWithdrawal\n | UserActivityBridge\n | UserActivityDeposit\n | UserActivityUserOp\n | UserActivityRedeem;\n\nexport interface UserActivityQuery {\n type?: UserActivityType;\n cursor?: string;\n limit?: number;\n}\n\n// ── Leaderboard ──────────────────────────────────────────────────────────────\n\n/** Column a leaderboard is ranked by. */\nexport type LeaderboardMetric = \"realizedPnl\" | \"volume\";\n\nexport interface LeaderboardQuery {\n /** Inclusive UTC day `YYYY-MM-DD`. Omit both `from` and `to` for all time. */\n from?: string;\n to?: string;\n metric?: LeaderboardMetric;\n /** 1..100, default 50. */\n limit?: number;\n cursor?: string;\n /** Look up one user (at most one of these four). */\n userId?: string;\n externalId?: string;\n /** Only when the app's `leaderboardIdentity` is `profile`. */\n username?: string;\n /** Not when the app's `leaderboardIdentity` is `anonymous`. */\n walletAddress?: string;\n /** One `Category.id` (a league is a category); includes sub-categories. At most 1. */\n categoryIds?: string[];\n /** Up to 5 event ids, each merged across venues. All time only; not with `categoryIds`. */\n venueEventIds?: string[];\n /**\n * Up to 100 AGG user ids; unpaginated. Not with the single-user lookups or `cursor`.\n * Returns rows only for users that have stats: a requested user with no activity is\n * simply absent (the single-user lookups return a zero row instead).\n */\n userIds?: string[];\n}\n\nexport interface LeaderboardRow {\n /** Exact within the top 100, `null` beyond. */\n rank: number | null;\n userId: string;\n /** Null unless the app's `leaderboardIdentity` is `profile`. */\n username: string | null;\n /** Null unless the app's `leaderboardIdentity` is `profile`. */\n avatarUrl: string | null;\n /** Null under `anonymous`; primary wallet under `wallet` or `profile`. */\n walletAddress: string | null;\n /** Filled orders in the range. */\n orders: number;\n /** USD notional of every filled order in the range, buys and sells. */\n volume: number;\n /** USD notional of filled buy orders only — what the trader put in. */\n spent: number;\n /** Gross realized P&L in USD (sells + settlements, before fees). */\n realizedPnl: number;\n /** Settled position legs whose settlement booked a profit. */\n wins: number;\n /** Settled position legs whose settlement booked a loss. A zero settlement (void, refund) is neither. */\n losses: number;\n /** wins / (wins + losses), 0 to 1; `null` before any settlement. */\n winRate: number | null;\n}\n\n/** At most one of `userId`, `externalId`, `username`, `walletAddress`; none = the whole app. */\nexport interface LeaderboardSeriesQuery {\n /** Inclusive UTC calendar day, `YYYY-MM-DD`. Default: 29 days before `to`. */\n from?: string;\n /** Inclusive UTC calendar day, `YYYY-MM-DD`. Default and maximum: today. */\n to?: string;\n userId?: string;\n externalId?: string;\n /** Only when the app's `leaderboardIdentity` is `profile`. */\n username?: string;\n /** Not when the app's `leaderboardIdentity` is `anonymous`. */\n walletAddress?: string;\n /** One `Category.id`. At most 1. */\n categoryIds?: string[];\n}\n\nexport interface LeaderboardStats {\n orders: number;\n volume: number;\n spent: number;\n realizedPnl: number;\n wins: number;\n losses: number;\n winRate: number | null;\n}\n\nexport interface LeaderboardSeriesPoint extends LeaderboardStats {\n /** UTC calendar day, `YYYY-MM-DD`. */\n day: string;\n /** Running total of `realizedPnl` from `from` through this day. */\n cumulativeRealizedPnl: number;\n /** Win rate over `from` through this day; `null` until a position settles. */\n cumulativeWinRate: number | null;\n}\n\nexport interface LeaderboardSeries {\n /** `null` for an app-wide series (no user given). */\n userId: string | null;\n from: string;\n to: string;\n /** Sums over `[from, to]`. */\n totals: LeaderboardStats;\n /** One point per day in `[from, to]`, oldest first; days without activity are 0. */\n points: LeaderboardSeriesPoint[];\n}\n\n// ── Ramp ──\n\nexport interface RampQuoteRequest {\n sourceAmount: string;\n sourceCurrencyCode: string;\n destinationCurrencyCode: string;\n paymentMethodType?: string;\n}\n\nexport interface RampQuote {\n serviceProvider: string;\n transactionType: string;\n sourceAmount: number;\n sourceCurrencyCode: string;\n destinationAmount: number;\n destinationCurrencyCode: string;\n exchangeRate: number;\n totalFee: number;\n networkFee: number;\n transactionFee: number;\n partnerFee: number;\n fiatAmountWithoutFees: number;\n paymentMethodType: string;\n countryCode: string;\n rampScore: number;\n lowKyc: boolean;\n}\n\nexport interface RampSessionRequest {\n sourceAmount: string;\n sourceCurrencyCode: string;\n destinationCurrencyCode: string;\n serviceProvider: string;\n walletAddress: string;\n redirectUrl?: string;\n}\n\nexport interface RampWidgetSession {\n id: string;\n token: string;\n widgetUrl: string;\n serviceProviderWidgetUrl: string;\n}\n// ── Smart order routing (GET /orderbook/:venueMarketOutcomeId/route) ──\n\nexport type SmartRouteStatus =\n | \"ok\"\n | \"infeasible\"\n | \"checker_rejected\"\n | \"solver_error\"\n | \"invalid_input\"\n | \"no_orderbooks\"\n | \"min_order_size_violated\"\n | \"insufficient_input_amount\"\n | \"engine_unavailable\"\n | \"insufficient_position\"\n | \"insufficient_depth\"\n | \"no_bids_above_min_price\"\n | \"insufficient_balance\";\n\n/** A single fill at a price level within a venue. */\nexport interface SmartRouteFill {\n price: number;\n size: number;\n fill: number;\n}\n\n/** Per-venue routing result with fills and chain info. */\nexport interface SmartRouteVenueFill {\n /** Age of the observed orderbook; absent for native venue quotes. */\n bookAgeMs?: number;\n /** Default (r3) or explicitly enabled relaxed (r4) freshness budget. */\n freshnessRow?: \"r3\" | \"r4\";\n /** CH executable price and normalized input, in micro-USDC. */\n limitPriceMicroUsdc?: string;\n inAmount?: string;\n outAmount?: string;\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n chain: string;\n avgPrice: number;\n yesPrice: number;\n noPrice: number;\n fills: SmartRouteFill[];\n executionBackend?: \"clearinghouse\" | \"direct\";\n venueAccountId?: string;\n venueQty: number;\n /**\n * Builder fee for this fill in USD — the slice paid to a builder code\n * rather than to the venue. Excluded from `venueFee`. Optional so an\n * older engine build that does not emit it still validates.\n */\n builderFee?: number;\n /**\n * What the venue takes from this leg's payout if the outcome wins (USD):\n * Hyperliquid HIP-4's close fee on the $1 settlement, 0 elsewhere. Not a\n * cost at fill; already netted out of `estimatedPayout`.\n */\n settlementFee?: number;\n /** Inclusive fee/reserve funding budget. For fee display, use the route's\n * feeBreakdown.venueFees and executionReserve instead. */\n venueFee?: number;\n}\n\nexport interface SmartRouteAllocation {\n sourceChainId: string;\n venue: string;\n amount: number;\n sourceTokenAddress?: string;\n custodyKind?: \"EOA\" | \"DEPOSIT_WALLET\" | \"POLYMARKET_LEGACY\" | \"VENUE_ACCOUNT\";\n custodyAddress?: string;\n /** Native venue cash identifies an account, not an EVM custody address. */\n sourceVenueAccountId?: string;\n /** Lossless decimal native account ID; never convert this to a JS number. */\n sourceExternalAccountId?: string;\n /** On-chain funding wallet, when present; absent for native venue cash. */\n sourceAddress?: string;\n exactToken?: boolean;\n}\n\nexport interface SmartRouteBridgeStep {\n sourceChainId: string;\n destChainId: string;\n /** Source-side amount sent into the bridge, in USD: the allocations this lane funds plus `cost`. */\n amount: number;\n /**\n * Delivery margin, in USD, sent on top of the allocations so the destination\n * still receives them in full after the bridge takes its fee. A planning\n * reserve, not the expected fee: excluded from `feeBreakdown.bridgeFees` and\n * `totalCost`, and whatever the bridge does not charge arrives at the\n * destination as the user's balance. Read `feeBreakdown.bridgeFees` for the\n * expected bridge fee.\n */\n cost: number;\n sourceTokenAddress?: string;\n destTokenAddress?: string;\n}\n\nexport interface VenueSoloQuote {\n quoteFailure?: { venue: string; code: string; retryAt?: string };\n /**\n * Minted by the API per successful + executable solo; send this to\n * /execution/fill to execute single-venue. `null` when the solo is not\n * executable (status !== \"ok\", filledQty === 0, or venue not in\n * SUPPORTED_FILL_VENUES). FE filters on truthiness.\n */\n quoteId: string | null;\n /** Why this venue cannot execute when quoteId is null (or execution is geo-gated). */\n unavailableReason?: string;\n venue: string;\n /**\n * The outcome this solo is bound to. `venue` alone is NOT unique — one venue\n * can list the same matched outcome more than once (e.g. two Hyperliquid\n * deployers listing the same game), producing two solo cards with the same\n * `venue`. Key on this alongside `venue` when identifying a card.\n */\n venueMarketOutcomeId?: string;\n avgPrice: number | null;\n filledQty: number;\n rawExecCost: number;\n estimatedPayout: number;\n estimatedProfit: number;\n returnPct: number;\n /**\n * `feeBreakdown.totalCost` plus this solo's own user-paid app fee and\n * referral — same composition as the primary route's `totalCostIncFees`.\n * `estimatedProfit`/`returnPct` stay router values, unaffected. Absent\n * when the router sent no `feeBreakdown` for this solo.\n */\n totalCostIncFees?: number;\n status: string;\n /** Per-price-level fills, identical shape to primary fills. Empty for non-ok statuses. */\n fills: SmartRouteVenueFill[];\n allocations?: SmartRouteAllocation[];\n bridgeSteps?: SmartRouteBridgeStep[];\n /**\n * One-time setup costs for this solo's chosen venue + market. Populated\n * only when the originating quote opted in via `deepEstimate=true`; absent\n * on cheap quotes and on non-executable / failed solos. Same shape as the\n * multi-route `feeBreakdown.setupCosts`. The solo's `estimatedProfit` and\n * `returnPct` are recomputed against `cost basis + setupCostsTotal` so\n * per-venue comparisons are setup-inclusive.\n */\n setupCosts?: SmartRouteSetupCostLine[];\n /** Sum of this solo's `setupCosts` entries where `alreadyPaid=false`. */\n setupCostsTotal?: number;\n /**\n * Cost breakdown for executing THIS venue alone. Present when\n * `status === \"ok\"`; absent otherwise.\n *\n * Read this — not the top-level `feeBreakdown` — when rendering fees for a\n * single venue. A solo's bridge lanes and venue fee are its own, so a venue\n * needing no bridge reports `bridgeFees: 0` here even when the multi-route\n * plan bridged.\n */\n feeBreakdown?: SmartRouteFeeBreakdown;\n}\n\n/** @deprecated Smart-route side overrides are kept only for source compatibility. */\nexport type SmartRouteSide = \"yes\" | \"no\";\n\n/** Trade direction for order routing. \"buy\" (default) reads asks, \"sell\" reads bids. */\nexport type TradeSide = \"buy\" | \"sell\";\n\n/** Trading mode for normal execution endpoints. Defaults to live. */\nexport type ExecutionMode = \"live\" | \"paper\";\n\n/** Request params for GET /orderbook/:venueMarketOutcomeId/route. */\nexport interface SmartRouteParams {\n venueMarketOutcomeId?: string;\n /** @deprecated Use venueMarketOutcomeId. */\n venueMarketId?: string;\n /** @deprecated Use venueMarketOutcomeId. */\n outcomeId?: string;\n /** @deprecated Side is ignored for routing and echoed back only for legacy consumers. */\n side?: SmartRouteSide;\n /** Trade direction: \"buy\" (default) or \"sell\". */\n tradeSide?: TradeSide;\n /** Trading mode. Defaults to live. */\n mode?: ExecutionMode;\n maxSpend?: number;\n /** Sell only: target number of contracts to sell. Required for sell unless maxSpend is given. */\n sellShares?: number;\n chainBalances?: Record<string, number>;\n slipCapBps?: number;\n compareVenues?: boolean;\n /** Restrict this quote to one or more executable venues. */\n allowedVenues?: Venue[];\n /**\n * Opt in to the deep cost-estimate surface. When `true`, the response\n * `feeBreakdown` includes `setupCosts` (one-time chain approvals + Kalshi\n * SPL token-account rents) with per-item `alreadyPaid` flags from the\n * user's prior trade history. Buy-only; ignored for sells.\n *\n * Deep quotes also pre-deduct the unpaid setup total from `maxSpend`\n * before routing, so `totalCostIncFees` (and the recomputed\n * `estimatedProfit` / `returnPct`) stay within the partner's stated\n * budget.\n */\n deepEstimate?: boolean;\n /** Per-trade app fee in bips (0..10000), replacing the app's configured rate. Needs an app API key. Buy only. */\n appFeeBips?: number;\n /** Per-venue app fee in bips (each 0..10000), e.g. `{ polymarket: 20, hyperliquid: 10 }`. Wins over `appFeeBips` on the venues it names; `appFeeBips` still covers the rest. Needs an app API key. Buy only. */\n appFeeBipsByVenue?: Record<string, number>;\n /** Referral: EVM address that receives the referral fee. Needs an app API key. */\n referrer?: string;\n /** Referral fee in bips of routed notional (1..10000). Snag-free. */\n referrerFeeBips?: number;\n /** Per-venue referral fee in bips (each 0..10000; 0 = none on that venue). Wins over `referrerFeeBips` on the venues it names. Needs `referrer` and an app API key. Not for `skipQuote`. */\n referrerFeeBipsByVenue?: Record<string, number>;\n /** Who funds the referral: \"user\" (default) reserves it from maxSpend; \"app\" pays from `referralPayerAddress` after the fill. */\n referralPayer?: \"user\" | \"app\";\n /** Required with `referralPayer: \"app\"`: the wallet that signs the parked payout transaction. */\n referralPayerAddress?: string;\n /**\n * User-paid referral only: a wallet that pays Hyperliquid's one-time 1 USDC\n * activation fee for a referrer with no HyperCore account (self-custody\n * Hyperliquid buys). Before the fill a pending signature with this\n * `signerAddress` and `purpose: \"hl_activation_sponsor\"` is passed to your\n * `signer`; it is `optional`, so declining it — or not answering within\n * `OPTIONAL_SIGNATURE_TIMEOUT_MS` — never costs the trade.\n */\n referralActivationSponsorAddress?: string;\n}\n\n/** One-time setup line item — populated only on deep-estimate quotes. */\nexport interface SmartRouteSetupCostLine {\n /** \"chainApproval\" = ERC-20 + venue-contract approvals on the venue's\n * chain (Polymarket / Polygon, Limitless / Base, predict.fun / BNB).\n * \"venueMarketAta\" = Kalshi-on-Solana per-market token-account rent.\n * \"hyperliquidActivation\" = Hyperliquid's one-time 1 USDC fee to activate\n * the user's address on its first deposit; `alreadyPaid` once the address\n * exists on Hyperliquid. Deducted from the bridged amount, not a step. */\n kind: \"chainApproval\" | \"venueMarketAta\" | \"hyperliquidActivation\";\n venue: string;\n /** Set when `kind === \"chainApproval\"`. */\n chainId?: number;\n /** Set when `kind === \"venueMarketAta\"`. */\n venueMarketId?: string;\n /** Per-item cost in USD. Sourced from documented chain-paymaster floors\n * (Polygon/Base/Arbitrum ≈ $0.05, BNB $0.20, Solana ATA ≈ $0.30). */\n costUsd: number;\n /** True if the user has already paid this on a prior fill — render as a\n * strike-through \"first-time fee\" chip rather than charging again. */\n alreadyPaid: boolean;\n}\n\n/** Cost breakdown for a route quote. */\nexport interface SmartRouteFeeBreakdown {\n rawExecCost: number;\n venueFees: number;\n /**\n * Builder fee in USD — the slice paid to a builder code rather than to the\n * venue. Partners with their own builder code see their own rate here;\n * everyone else sees the platform default. Excluded from `venueFees`,\n * included in `totalCost`.\n */\n builderFee?: number;\n /** Additional CH funding reserve for slippage or possible venue charges.\n * Excluded from venueFees and totalCost; included in funding allocations.\n * Only the unused portion is released after execution. */\n executionReserve?: number;\n bridgeFees: number;\n executionGas: number;\n totalCost: number;\n /** Populated only when the request specified `deepEstimate=true`. */\n setupCosts?: SmartRouteSetupCostLine[];\n /** Sum of `setupCosts` entries where `alreadyPaid === false`. */\n setupCostsTotal?: number;\n /**\n * Partner-level execution fee in USD. The worst-case fee the user will\n * pay against the routed buy notional at quote time. Buy-side only —\n * sell quotes don't carry this field.\n *\n * Actual collection happens after the trade fills, against realized\n * notional (which may be less on partial fills). Partner UIs should\n * render this as \"you'll pay up to $X in app fees\".\n *\n * Both `appFee` and `appFeeBips` are present iff `appFee > 0`.\n */\n appFee?: number;\n /** The rate that produced `appFee` — the partner's configured bips, or the request's `appFeeBips`. When the venues this route fills have different rates, the highest of them; see `appFeeBipsByVenue`. */\n appFeeBips?: number;\n /** App fee rate per venue this route fills, in bips. Present only when those rates differ. */\n appFeeBipsByVenue?: Record<string, number>;\n /** Category key the bips resolved against (e.g. \"sports\", \"all\" for the fallback, \"override\" for a per-request `appFeeBips`). */\n appFeeCategory?: string;\n /** The `executionGas` line when it is actually collected with the app fee. Present iff > 0; already inside `totalCost`. */\n gasReimbursement?: number;\n /** Referral fee the USER pays, in USD. Present iff > 0 and `referralPayer` is \"user\"; already inside `totalCostIncFees`. An app-paid referral never appears here. */\n referralFee?: number;\n /** Referral fee rate per venue this route fills, in bips. Present with `referralFee`, only when those rates differ. */\n referralFeeBipsByVenue?: Record<string, number>;\n}\n\n/** Response from GET /orderbook/:venueMarketOutcomeId/route. */\nexport interface SmartRouteSettlementLeg {\n action: \"redeem\";\n venue: string;\n venueMarketId: string;\n venueMarketOutcomeId: string;\n positionId: string;\n size: string;\n redeemPath: \"evm\" | \"svm\";\n}\n\nexport interface SmartRouteSettlementPlan {\n redeemId: string;\n status: \"redeem_only\" | \"partial_redeem\";\n message: string;\n totalRedeemableShares: number;\n totalRedeemShares: number;\n totalSellShares: number;\n redeemLegs: SmartRouteSettlementLeg[];\n}\n\n/** Slippage metrics for the route. Mirrors `SmartRouteResponseTB.slippage`. */\nexport interface SmartRouteSlippage {\n /** Volume-weighted average price. */\n vwap: number;\n /** Reference midpoint used by the optimizer. */\n refMidpoint: number;\n /** Route slippage = max(0, VWAP - refMidpoint). */\n slippage: number;\n /** Slippage in basis points relative to ref midpoint. */\n slippageBps: number;\n}\n\nexport interface SmartRouteResponse {\n /** Accepted worst execution price for protected route legs. */\n legBounds?: Array<{\n venue: string;\n venueMarketOutcomeId: string;\n side: \"buy\" | \"sell\";\n worstPrice: number;\n effectiveSlippageBps: number;\n }>;\n\n quoteRefreshNotBefore?: string;\n quoteFailure?: { venue: string; code: string; retryAt?: string };\n quoteId: string;\n venueMarketOutcomeId: string;\n venueMarketId: string;\n estimatedCostRaw: string;\n expiresAt: string;\n /**\n * Timestamp at which the quote begins to drift — frontends should refetch\n * a fresh `getSmartRoute` at this point even though the cached quoteId\n * remains executable until `expiresAt`. Always earlier than `expiresAt`.\n */\n refreshAt: string;\n status: SmartRouteStatus;\n fills: SmartRouteVenueFill[];\n totalFilled: number;\n rawExecCost: number;\n solveTimeMs: number;\n verifyTimeMs: number;\n matchedMarkets: Array<{ venue: string; venueMarketId: string }>;\n error?: string;\n message?: string;\n settlementPlan?: SmartRouteSettlementPlan;\n warnings?: Array<{ venue: string; venueMarketOutcomeId: string; reason: string }>;\n venueSoloQuotes?: VenueSoloQuote[];\n allocations?: SmartRouteAllocation[];\n bridgeSteps?: SmartRouteBridgeStep[];\n /**\n * Route slippage metrics. Present on the wire (`SmartRouteResponseTB`) but\n * missing from this mirror until now — `@agg-build/hooks` already reads\n * `slippage.slippageBps` to flag thin liquidity.\n */\n slippage?: SmartRouteSlippage;\n /** Limit-order size step on this venue, raw 6-dec shares (\"10000\" = 0.01).\n * Only on a single-venue quote; absent means a 1-unit step. */\n sizeStepRaw?: string;\n /** Smallest limit-order size on this venue/market, raw 6-dec shares.\n * Only on a single-venue quote; absent means no known minimum. */\n minSizeRaw?: string;\n /** Estimated payout if the outcome wins (= totalFilled shares × $1, less\n * settlement fees — see `fills[].settlementFee`). */\n estimatedPayout?: number;\n /** Total cost including all fees (rawExecCost + venueFees + bridgeFees +\n * executionGas). For deep-estimate quotes, `setupCostsTotal` is folded\n * into this number and `estimatedProfit` / `returnPct` are recomputed\n * against it. */\n totalCostIncFees?: number;\n /** Sell only: gross proceeds minus venue, builder, app, and user-paid\n * referral fees, in USD — what the sell returns. */\n estimatedNetProceeds?: number;\n /** Estimated profit if the outcome wins (= estimatedPayout − totalCostIncFees). */\n estimatedProfit?: number;\n /** Return on investment percentage (= estimatedProfit / totalCostIncFees × 100). */\n returnPct?: number;\n /** Per-route fee breakdown. Always present when the engine produced a\n * feasible plan; omitted on solo / failed quotes. The `setupCosts` and\n * `setupCostsTotal` fields are populated only when the request set\n * `deepEstimate=true`. */\n feeBreakdown?: SmartRouteFeeBreakdown;\n /**\n * Quote-time snapshot of the partner fee configuration that produced\n * `feeBreakdown.appFee`, frozen so config drift between quote and execute\n * cannot change what the user is charged.\n *\n * This is NOT the display number — that is `feeBreakdown.appFee`, in USD.\n * This is the audit record: `quotedAppFeeRaw` is the worst-case charge in\n * 6-decimal USD atoms, and is what a partner reconciles against their\n * `AppFeeCharge` rows. `null` when the app has no fee configured.\n */\n appFee?: {\n /** The route rate: the highest among the venues this route fills. */\n bips: number;\n categoryKey: string;\n quotedAppFeeRaw: string;\n /** Rate per venue this route fills. Present only when those rates differ. */\n bipsByVenue?: Record<string, number>;\n } | null;\n /** Referral snapshot; null/absent when no referrer was accepted. */\n referral?: {\n referrer: string;\n /** The highest rate among the venues this route fills. */\n feeBips: number;\n /** Rate per venue this route fills. Present only when those rates differ. */\n feeBipsByVenue?: Record<string, number>;\n payer: \"user\" | \"app\";\n payerAddress?: string;\n /** Wallet sponsoring the referrer's HyperCore activation, when sent. */\n activationSponsorAddress?: string;\n quotedFeeUsd: number;\n } | null;\n /**\n * Sell quotes only: the user's sellable shares when the quote was built, on\n * the venues the request allows. Returned on `ok` sell quotes too; on\n * `insufficient_position` it says how much can be sold. A snapshot, not a\n * reservation: the fill re-checks the live venue balance.\n */\n positionAvailability?: {\n totalSellableShares: number;\n venueMarketOutcomes: Array<{\n id: string;\n venue: string;\n venueMarketId: string;\n availableShares: number;\n }>;\n };\n /** @deprecated Echoed only when the deprecated request-side override is provided. */\n side?: SmartRouteSide;\n}\n\nexport interface CancelManagedExecutionResponse {\n quoteId: string | null;\n orderIds: string[];\n status: \"cancelled\" | \"cancel_pending\";\n}\n\nexport type PositionRedeemStatus = \"eligible\" | \"pending\" | \"redeemed\" | \"ineligible\";\n\nexport type RedeemLegStatus = \"submitted\" | \"confirmed\" | \"ineligible\" | \"rejected\";\n\nexport interface RedeemLegResult {\n venueMarketOutcomeId: string;\n status: RedeemLegStatus;\n callsId: string | null;\n pendingUserOpId: string | null;\n txHash: string | null;\n reason: string | null;\n}\n\nexport interface RedeemRequest {\n venueMarketOutcomeIds: string[];\n /**\n * Trading mode. Defaults to live, matching the other execution methods.\n * Honoured on a live app; ignored on a paper app, which has no real-money\n * path and always settles on paper.\n */\n mode?: ExecutionMode;\n}\n\nexport interface RedeemResponse {\n redeemId: string;\n results: RedeemLegResult[];\n}\n\n// ── Search ──\n\nexport type SearchType = \"events\" | \"markets\";\n\nexport interface SearchParams {\n mode?: \"instant\" | \"full\";\n q: string;\n type: SearchType;\n categoryIds?: string[];\n /**\n * Filter results by status (e.g. `[\"open\"]` for tradeable-only). Without\n * it the server returns all statuses; recurring series (\"BTC Up or Down -\n * 5 Min\") can then fill a page with resolved history, which a UI that\n * hides non-open rows renders as an empty result.\n */\n status?: MarketStatus[];\n limit?: number;\n cursor?: string;\n /**\n * Opt in to the server-side reranker for higher-quality top results.\n *\n * Send `deep: true` for the final search-results page (submit / Enter) and\n * leave it off for debounced typeahead. Adds ~100–150 ms on a cold rerank\n * cache and ~3 ms on a warm one — typeahead can't afford the cold cost,\n * and the result orderings differ enough that the server gives the two\n * modes separate cache slots.\n *\n * Defaults to `false`.\n */\n deep?: boolean;\n}\n\nexport type SearchResponse<T> = {\n meta?: { complete?: boolean; degradedSignals?: string[] };\n type: SearchType;\n data: T[];\n nextCursor: string | null;\n hasMore: boolean;\n};\n\n// ── News Feed ──\n\nexport interface NewsFeedPageOptions {\n cursor?: string;\n since?: string;\n before?: string;\n limit?: number;\n}\n\nexport interface NewsFeedMarketNewsParams {\n venueMarketIds?: string[];\n venueEventIds?: string[];\n customQuery?: string;\n tbs?: string;\n limit?: number;\n}\n\nexport interface NewsFeedArticleWithSummary {\n title: string;\n url: string;\n snippet: string;\n source: string;\n imageUrl: string | null;\n publishedAt: string | null;\n summary: string;\n relevanceScore: number;\n}\n\nexport interface NewsFeedMarketNewsResult {\n venueMarketId: string;\n venueEventId: string;\n question: string;\n eventTitle: string;\n category: string;\n searchQuery: string;\n timeRange: string;\n timeRangeLabel: string;\n articles: NewsFeedArticleWithSummary[];\n}\n\nexport interface NewsFeedMarketNewsResponse {\n results: NewsFeedMarketNewsResult[];\n}\n\nexport interface NewsFeedLinkedMarket {\n venueMarketId: string;\n question: string;\n venue: string;\n yesPrice: number;\n eventTitle: string;\n eventId: string;\n summary: string;\n relevanceScore: number;\n}\n\nexport interface NewsFeedArticleFeedItem {\n article: {\n id: string;\n title: string;\n url: string;\n snippet: string;\n source: string;\n imageUrl: string | null;\n publishedAt: string | null;\n };\n markets: NewsFeedLinkedMarket[];\n category: string;\n id: string;\n seq: number;\n timestamp: string;\n}\n\nexport interface NewsFeedMarketFeedArticle {\n title: string;\n url: string;\n source: string;\n imageUrl: string | null;\n publishedAt: string | null;\n summary: string;\n relevanceScore: number;\n seq: number;\n addedAt: string;\n}\n\nexport interface NewsFeedMarketFeedItem {\n venueMarketId: string;\n question: string;\n venue: string;\n yesPrice: number;\n eventTitle: string;\n eventId: string;\n category: string;\n articleCount: number;\n articles: NewsFeedMarketFeedArticle[];\n}\n\nexport interface NewsFeedArticleFeedResponse {\n data: NewsFeedArticleFeedItem[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface NewsFeedMarketFeedResponse {\n data: NewsFeedMarketFeedItem[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface NewsFeedListResponse {\n feeds: Array<{\n id: string;\n name: string;\n itemCount: number;\n }>;\n}\n\nexport interface NewsFeedStatusResponse {\n articles: { total: number; today: number };\n feedItems: { total: number; today: number };\n perCategory: Array<{\n category: string;\n todayCount: number;\n dailyLimit: number;\n }>;\n config: {\n cronEnabled: boolean;\n itemsPerDay: number;\n batchSize: number;\n categories: string[];\n };\n}\n\n// ── Correlated Markets ──\n\nexport type CorrelatedMarketSide = \"yes\" | \"no\";\nexport type CorrelatedMarketSignalDirection = \"more_likely\" | \"less_likely\";\n\nexport interface CorrelatedMarketSignal {\n id: string;\n text: string;\n side: CorrelatedMarketSide;\n direction: CorrelatedMarketSignalDirection;\n domain: string;\n}\n\nexport interface CorrelatedMarketSignalBatch {\n id: string;\n venueMarketId: string;\n sourceModel: string;\n promptVersion: number;\n createdAt: string;\n signals: CorrelatedMarketSignal[];\n}\n\nexport interface CorrelatedMarketsStatus {\n markets: {\n total: number;\n processed: number;\n coverage: number;\n };\n signals: {\n total: number;\n withEmbeddings: number;\n missingEmbeddings: number;\n };\n eventTitleEmbeddings: {\n total: number;\n events: number;\n coverage: number;\n };\n config: {\n batchSize: number;\n jobsEnabled: boolean;\n backfillInterval: string;\n reembedInterval: string;\n eventEmbeddingInterval: string;\n };\n}\n\nexport interface CorrelatedMarketQueryResult {\n venueMarketId: string;\n marketQuestion: string;\n marketStatus: MarketStatus;\n marketStartDate: string;\n marketEndDate: string | null;\n eventTitle: string;\n eventStatus: MarketStatus;\n eventStartDate: string;\n eventEndDate: string | null;\n score: number;\n matchedSignal: CorrelatedMarketSignal;\n matchSource: \"signal\" | \"title_fallback\";\n venue: string;\n}\n\nexport interface CorrelatedMarketCascadeItem {\n venueEventId: string;\n eventTitle: string;\n eventStatus: MarketStatus;\n eventStartDate: string;\n eventEndDate: string | null;\n score: number;\n action: string;\n reason: string;\n reasonDomain: string;\n}\n\nexport interface CorrelatedMarketCascadeResponse {\n data: CorrelatedMarketCascadeItem[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\nexport interface ResolveCorrelatedMarketsParams {\n venue?: string;\n externalId?: string;\n slug?: string;\n conditionId?: string;\n q?: string;\n side?: CorrelatedMarketSide;\n mode?: \"expand\" | \"hedge\";\n limit?: number;\n cursor?: string;\n includeResolved?: boolean;\n}\n\nexport type ResolveCorrelatedMarketsResponse =\n | ({\n market: { id: string; question: string };\n } & CorrelatedMarketCascadeResponse)\n | {\n market: { id: string; question: string };\n status: \"processing\";\n message: string;\n };\n\nexport interface ResolvedCorrelatedMarketsResponse extends CorrelatedMarketCascadeResponse {\n market: { id: string; question: string };\n}\n\n/** Display-first event navigation payload; market pages remain cursor paginated. */\nexport interface EventBootstrapResponse {\n detailsDeferred: true;\n event: VenueEvent;\n markets: PaginatedResponse<VenueMarket>;\n selectedOutcomeIds: string[];\n references: { historyManifestPath: \"/charts/history/manifest\"; liveChannel: \"orderbook\" };\n freshness: { assembledAt: number; marketStatus: \"open\" | null };\n}\n","import type {\n AuthUser,\n Category,\n PositionGroup,\n SyncBalancesResponse,\n UnifiedBalanceResponse,\n UpsertVenueKey,\n UpdateUserBody,\n UserHolding,\n UserProfile,\n VenueEvent,\n VenueMarket,\n VenueKeyStatus,\n VenueKeySummary,\n HostedVenueAccount,\n HostedVenueActivity,\n HostedVenueActivityQuery,\n HostedVenueDepositAddress,\n HostedVenueWithdrawal,\n HostedVenueWithdrawalRequest,\n ProvisionHostedVenueAccountBody,\n VerifyResponse,\n} from \"@agg/common/types-only\";\nimport {\n AccountProvider,\n AccountType,\n getWalletAddressFromUserProfile,\n MarketStatus,\n MatchStatus,\n Venue,\n} from \"@agg/common/types-only\";\nimport { parseRetryAfterHeader, parseRetryAfterSeconds } from \"./retry-after\";\nimport { readChartHistoryText } from \"./market-data/history-decoder\";\nimport { AggApiError } from \"./errors\";\nimport { toChecksumAddress } from \"./eip55\";\nimport {\n SELF_CUSTODY_FILL_TIMEOUT_MS,\n OPTIONAL_SIGNATURE_TIMEOUT_MS,\n OPTIONAL_FEE_SIGNATURE_TIMEOUT_MS,\n SELF_CUSTODY_POLL_INTERVAL_MS,\n TERMINAL_EXECUTION_STATES,\n} from \"./types\";\nimport {\n AggWebSocket,\n type AggWebSocketCallbacks,\n type BookWatchdogOptions,\n} from \"./agg-websocket\";\nimport type {\n SignatureRequest,\n AggAuthDeliveryMode,\n AggAuthVerifyBody,\n AggAuthStartBody,\n AggAuthStartResult,\n AggClientAuthOptions,\n AggLinkAccountBody,\n AggLinkAccountConfirmResult,\n AggLinkAccountResult,\n AggLinkAccountWalletConfirmBody,\n AggClientOptions,\n AggClientSessionInput,\n AppClientConfigResponse,\n RpcTokenResponse,\n VenueGeoPolicyResponse,\n AuthStatus,\n BatchMidpointsResponse,\n BatchOrderbooksResponse,\n BalanceRefillAttempt,\n BalanceRefillPolicy,\n CancelManagedExecutionResponse,\n CancelVenueOrderParams,\n ChartBarsResponse,\n ChartHistoryManifest,\n EventBootstrapResponse,\n ChartResolution,\n CorrelatedMarketCascadeResponse,\n CorrelatedMarketQueryResult,\n CorrelatedMarketsStatus,\n CorrelatedMarketSignalBatch,\n CreateBalanceRefillPolicyParams,\n CryptoReferencePricesResponse,\n CryptoReferencePriceTarget,\n DepositAddressesResponse,\n ExecuteManagedParams,\n ExecuteManagedResponse,\n ExecutionOrderItem,\n ExecutionOrdersQuery,\n ExecutionStatusQuery,\n ExecutionStatusResponse,\n UserActivityItem,\n UserActivityQuery,\n LeaderboardQuery,\n LeaderboardRow,\n LeaderboardSeries,\n LeaderboardSeriesQuery,\n ExecutionPositionGroup,\n ExecutionPositionsQuery,\n GetPositionsParams,\n GetCryptoReferencePricesOptions,\n ManagedBalancesParams,\n ListRecurringCryptoMarketsOptions,\n NewsFeedArticleFeedResponse,\n NewsFeedListResponse,\n NewsFeedMarketFeedResponse,\n NewsFeedMarketNewsParams,\n NewsFeedMarketNewsResponse,\n NewsFeedPageOptions,\n NewsFeedStatusResponse,\n OrderListQuery,\n OutcomeOrderbookResponse,\n PaginatedResponse,\n PaperTradingAccount,\n PaperTradingAccountListParams,\n PaperTradingAccountsPage,\n PaperTradingAppOptions,\n PaperTradingBalanceResponse,\n PaperTradingListParams,\n PaperTradingOrdersPage,\n PaperTradingOrder,\n PaperTradingPortfolio,\n PaperTradingPositionsPage,\n PlaceLimitOrderParams,\n CancelOrderSignature,\n PlaceLimitOrderResponse,\n PlaceOrderParams,\n PlaceOrderResponse,\n PlacePaperTradingOrderParams,\n PersistedAuthSnapshot,\n CreatePaperTradingAccountParams,\n RedeemRequest,\n RedeemResponse,\n ResetPaperTradingAccountParams,\n ResolveCorrelatedMarketsParams,\n ResolveCorrelatedMarketsResponse,\n SetPaperTradingBalanceParams,\n RampQuote,\n RampQuoteRequest,\n RampSessionRequest,\n RampWidgetSession,\n RecurringCryptoMarketsResponse,\n RecurrenceFilter,\n SearchParams,\n SearchResponse,\n SignerFn,\n SiweMessageParams,\n SiwsMessageParams,\n SmartRouteParams,\n SmartRouteResponse,\n SportsLiveResponse,\n TradeExecutorOrderListResponse,\n UpdateBalanceRefillPolicyParams,\n WithdrawManagedParams,\n WithdrawManagedResponse,\n WithdrawalQuoteParams,\n WithdrawalQuoteResponse,\n WithdrawPreviewParams,\n WithdrawPreviewResponse,\n} from \"./types\";\n\ntype AuthStateListener = (authenticated: boolean) => void;\ntype UserAuthResult = { accessToken: string; refreshToken?: string; user: UserProfile };\nconst COOKIE_REFRESH_DELIVERY = \"cookie-refresh\";\nconst DEFAULT_MIDPOINT_IDS_PER_REQUEST = 75;\nconst MAX_MIDPOINT_IDS_PER_REQUEST = 75;\nconst MAX_SPORTS_EVENT_IDS_PER_REQUEST = 25;\n\n/**\n * Bounds on the `pollAfterMs` the server hands back on a non-terminal\n * `/execution/status` response. It is server-supplied and drives a loop, so it\n * is clamped rather than trusted.\n *\n * Floor 250ms: a 0 — from a server bug, or a future backoff scheme that means\n * \"immediately\" — would turn this into a busy-loop hammering `/execution/status`\n * for the whole 5-minute budget.\n *\n * Ceiling 30s: the loop is bounded by `SELF_CUSTODY_FILL_TIMEOUT_MS` (5 min).\n * A longer sleep would leave a parked signature undiscovered for most of that\n * budget; 30s still buys at least ten looks before the deadline.\n */\nconst MIN_POLL_INTERVAL_MS = 250;\nconst MAX_POLL_INTERVAL_MS = 30_000;\n/** Step id prefix of a Polymarket order signature request (`poly-sign-<orderId>`). */\nconst PM_ORDER_SIGNATURE_STEP_PREFIX = \"poly-sign-\";\n\nconst isUserProfile = (user: AuthUser | UserProfile): user is UserProfile => {\n return \"accounts\" in user && \"wallets\" in user && \"avatarUrl\" in user;\n};\n\nconst createPersistedHintUserProfile = (input: {\n id: string;\n username: string | null;\n avatarUrl: string | null;\n walletAddress?: string | null;\n}): UserProfile => {\n const normalizedWalletAddress =\n typeof input.walletAddress === \"string\" && input.walletAddress.trim().length > 0\n ? input.walletAddress\n : null;\n\n return {\n id: input.id,\n username: input.username,\n avatarUrl: input.avatarUrl,\n externalId: null,\n isLocationBlocked: false,\n accounts: normalizedWalletAddress\n ? [\n {\n type: AccountType.siwe,\n provider: AccountProvider.wallet,\n providerAccountId: normalizedWalletAddress,\n },\n ]\n : [],\n wallets: [],\n venueAccounts: [],\n };\n};\n\nconst normalizeSessionUser = (\n user: AuthUser | UserProfile | undefined,\n currentUser: UserProfile | undefined,\n): UserProfile | undefined => {\n if (!user) return undefined;\n if (isUserProfile(user)) return user;\n if (currentUser?.id === user.id) return currentUser;\n\n return createPersistedHintUserProfile({\n id: user.id,\n username: null,\n avatarUrl: null,\n walletAddress: null,\n });\n};\n\nconst resolveMidpointIdsPerRequest = (value: number | undefined): number => {\n if (value == null || !Number.isFinite(value)) return DEFAULT_MIDPOINT_IDS_PER_REQUEST;\n return Math.min(MAX_MIDPOINT_IDS_PER_REQUEST, Math.max(1, Math.floor(value)));\n};\n\nconst chunkArray = <T>(items: T[], size: number): T[][] => {\n const chunks: T[][] = [];\n for (let index = 0; index < items.length; index += size) {\n chunks.push(items.slice(index, index + size));\n }\n return chunks;\n};\n\nconst normalizeRequestedVenueMarketIds = (venueMarketIds: string[]): string[] => {\n const normalizedIds: string[] = [];\n const seenIds = new Set<string>();\n\n for (const venueMarketId of venueMarketIds) {\n const normalizedVenueMarketId = venueMarketId.trim();\n if (!normalizedVenueMarketId || seenIds.has(normalizedVenueMarketId)) continue;\n\n seenIds.add(normalizedVenueMarketId);\n normalizedIds.push(normalizedVenueMarketId);\n }\n\n return normalizedIds;\n};\n\nconst mapChartResolution = (resolution?: ChartResolution): \"1\" | \"5\" | \"60\" | \"1D\" | undefined => {\n switch (resolution) {\n case undefined:\n return undefined;\n case \"1m\":\n return \"1\";\n case \"5m\":\n return \"5\";\n case \"1h\":\n return \"60\";\n case \"1d\":\n return \"1D\";\n }\n};\n\n/** Paths that handle their own auth flow and should never trigger automatic 401 retry. */\nconst AUTH_PATHS = new Set([\n \"/auth/start\",\n \"/auth/verify\",\n \"/auth/token/refresh\",\n \"/auth/token/exchange\",\n \"/auth/sign-out\",\n]);\n\n/** Rejects after `ms`; a late settlement of `p` is ignored. */\nfunction withTimeout<T>(p: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);\n p.then(\n (v) => {\n clearTimeout(timer);\n resolve(v);\n },\n (e) => {\n clearTimeout(timer);\n reject(e);\n },\n );\n });\n}\n\nexport class AggClient {\n private _appId?: string;\n private adminKey?: string;\n private apiKey?: string;\n private baseUrl: string;\n private accessToken?: string;\n /** Identity verified for the current token, when supplied with the session/profile. */\n private accessTokenUserId?: string;\n private refreshTokenValue?: string;\n private currentUser?: UserProfile;\n private listeners: Set<AuthStateListener> = new Set();\n private readonly webSocketAuthCleanups = new Set<() => void>();\n private storageKey: string;\n private shouldPersistSession: boolean;\n private authDelivery: AggAuthDeliveryMode;\n private wsUrl?: string;\n readonly preferImmutableHistory: boolean;\n private readonly webSocketFactory?: AggClientOptions[\"webSocketFactory\"];\n private _authStatus: AuthStatus = \"unauthenticated\";\n private authChannel: BroadcastChannel | null = null;\n private authOptions?: AggClientAuthOptions;\n /** In-flight refresh promise — serializes concurrent 401 retries so only one refresh runs. */\n private pendingRefresh: Promise<string> | null = null;\n /** Partner-supplied signature callback for self-custodial fills. The SDK never sees a key. */\n private readonly signer?: SignerFn;\n\n constructor(options: AggClientOptions) {\n if (!options.appId && !options.adminKey) {\n throw new Error(\"AggClient requires at least one of appId or adminKey\");\n }\n this._appId = options.appId;\n this.adminKey = options.adminKey;\n this.apiKey = options.apiKey;\n this.signer = options.signer;\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.wsUrl = options.wsUrl;\n this.preferImmutableHistory = options.preferImmutableHistory ?? false;\n this.webSocketFactory = options.webSocketFactory;\n this.authOptions = options.auth;\n this.storageKey = `agg_auth_${this._appId ?? \"default\"}`;\n this.authDelivery = options.authDelivery ?? \"body\";\n this.shouldPersistSession = options.persistSession !== false;\n this.restoreSession();\n this.initAuthChannel();\n }\n\n private resolvePaperTradingAppId(appId?: string): string {\n const resolvedAppId = appId ?? this._appId;\n if (!resolvedAppId) {\n throw new Error(\n \"Paper trading account methods require appId in client options or method options\",\n );\n }\n return encodeURIComponent(resolvedAppId);\n }\n\n private paperTradingAccountsPath(appId?: string): string {\n return `/apps/${this.resolvePaperTradingAppId(appId)}/paper-trading/accounts`;\n }\n\n private paperTradingAccountPath(accountId: string, appId?: string): string {\n return `${this.paperTradingAccountsPath(appId)}/${encodeURIComponent(accountId)}`;\n }\n\n private paperTradingListQuery(\n params: PaperTradingListParams = {},\n ): Record<string, string> | undefined {\n const query: Record<string, string> = {};\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n return Object.keys(query).length ? query : undefined;\n }\n\n private paperTradingAccountListQuery(\n params: PaperTradingAccountListParams = {},\n ): Record<string, string> | undefined {\n const query = this.paperTradingListQuery(params) ?? {};\n if (params.externalId) query.externalId = params.externalId;\n return Object.keys(query).length ? query : undefined;\n }\n\n private withAuthPayload<T extends { earlyAccessCode?: string }>(payload: T): T {\n if (typeof payload.earlyAccessCode === \"string\" && payload.earlyAccessCode.trim().length > 0) {\n return payload;\n }\n\n const earlyAccessCode = this.authOptions?.getEarlyAccessCode?.()?.trim();\n if (!earlyAccessCode) {\n return payload;\n }\n\n return {\n ...payload,\n earlyAccessCode,\n };\n }\n\n // --- Session persistence (tokens are NEVER persisted — only a sanitized UI hint) ---\n\n private restoreSession(): void {\n if (!this.shouldPersistSession || typeof globalThis.localStorage === \"undefined\") return;\n try {\n const raw = localStorage.getItem(this.storageKey);\n if (!raw) return;\n const data = JSON.parse(raw) as Record<string, unknown>;\n\n // Discard any legacy format that contained tokens.\n if (\"accessToken\" in data) {\n localStorage.removeItem(this.storageKey);\n return;\n }\n\n // Current format: PersistedAuthSnapshot.\n const snapshot = data as unknown as PersistedAuthSnapshot;\n if (snapshot.authHint?.wasAuthenticated && snapshot.user?.id) {\n this.currentUser = createPersistedHintUserProfile({\n id: snapshot.user.id,\n username: snapshot.user.username,\n avatarUrl: snapshot.user.avatarUrl,\n walletAddress: snapshot.user.walletAddress ?? null,\n });\n this._authStatus = \"unknown\";\n }\n } catch {\n localStorage.removeItem(this.storageKey);\n }\n }\n\n private persistSession(): void {\n if (!this.shouldPersistSession || typeof globalThis.localStorage === \"undefined\") return;\n if (this.accessToken && this.currentUser) {\n const snapshot: PersistedAuthSnapshot = {\n user: {\n id: this.currentUser.id,\n username: this.currentUser.username,\n avatarUrl: this.currentUser.avatarUrl,\n walletAddress: getWalletAddressFromUserProfile(this.currentUser) ?? null,\n },\n authHint: { wasAuthenticated: true },\n };\n localStorage.setItem(this.storageKey, JSON.stringify(snapshot));\n } else {\n localStorage.removeItem(this.storageKey);\n }\n }\n\n // --- Cross-tab auth sync via BroadcastChannel ---\n\n private initAuthChannel(): void {\n if (typeof globalThis.BroadcastChannel === \"undefined\") return;\n try {\n this.authChannel = new BroadcastChannel(`agg_auth_${this._appId ?? \"default\"}`);\n this.authChannel.onmessage = (event: MessageEvent) => {\n const { type } = event.data ?? {};\n if (type === \"logout\") {\n this.accessToken = undefined;\n this.accessTokenUserId = undefined;\n this.refreshTokenValue = undefined;\n this.currentUser = undefined;\n this._authStatus = \"unauthenticated\";\n this.persistSession();\n this.notifyListeners();\n } else if (type === \"login\") {\n // Another tab signed in — attempt silent refresh so this tab picks up\n // the session. Works in cookie-refresh mode (cookie is shared across tabs).\n // In body mode this will fail gracefully (no refresh token available).\n this.refreshAccessToken()\n .then(() => this.getCurrentUser())\n .catch(() => {\n // Silent failure — user can manually refresh or sign in.\n });\n }\n };\n } catch {\n this.authChannel = null;\n }\n }\n\n /** Release resources (BroadcastChannel, etc.). Safe to call multiple times. */\n destroy(): void {\n this.authChannel?.close();\n this.authChannel = null;\n for (const cleanup of this.webSocketAuthCleanups) cleanup();\n }\n\n // --- Core HTTP helper ---\n\n /**\n * Generic HTTP method with automatic header injection and 401 retry.\n * Attaches `x-app-id`, `Authorization: Bearer`, and `x-admin-key` headers as appropriate.\n * On 401, attempts a single token refresh and retries the request.\n * @param path - API path (e.g. `/venue-events`)\n * @param init - Fetch init options, plus optional `query` object for URL search params\n */\n public async request<T>(\n path: string,\n init?: RequestInit & { query?: Record<string, string | string[]> },\n decode?: (response: Response) => Promise<T>,\n ): Promise<T> {\n const response = await this.rawFetch(path, init);\n\n // On 401 for non-auth endpoints, attempt a single token refresh + retry.\n if (response.status === 401 && this.accessToken && !AUTH_PATHS.has(path)) {\n try {\n await this.refreshWithDedup();\n // Retry the original request with the new token.\n const retryResponse = await this.rawFetch(path, init);\n if (!retryResponse.ok) {\n return this.throwResponseError(retryResponse);\n }\n if (retryResponse.status === 204) return undefined as T;\n return decode ? decode(retryResponse) : (retryResponse.json() as Promise<T>);\n } catch {\n // Refresh failed — sign out and throw the original 401.\n this.clearAccessToken();\n return this.throwResponseError(response);\n }\n }\n\n if (!response.ok) {\n return this.throwResponseError(response);\n }\n\n if (response.status === 204) return undefined as T;\n return decode ? decode(response) : (response.json() as Promise<T>);\n }\n\n private async rawFetch(\n path: string,\n init?: RequestInit & { query?: Record<string, string | string[]> },\n ): Promise<Response> {\n const headers: Record<string, string> =\n init?.body != null ? { \"Content-Type\": \"application/json\" } : {};\n\n if (this._appId) {\n headers[\"x-app-id\"] = this._appId;\n }\n if (this.adminKey) {\n headers[\"x-admin-key\"] = this.adminKey;\n }\n if (this.apiKey) {\n headers[\"x-app-api-key\"] = this.apiKey;\n }\n if (this.accessToken) {\n headers[\"authorization\"] = `Bearer ${this.accessToken}`;\n }\n\n const url = new URL(`${this.baseUrl}${path}`);\n if (init?.query) {\n for (const [key, value] of Object.entries(init.query)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n v !== undefined && url.searchParams.append(key, v?.toString());\n }\n } else {\n value !== undefined && url.searchParams.set(key, value?.toString());\n }\n }\n }\n\n return fetch(url, {\n ...init,\n headers: {\n ...headers,\n ...init?.headers,\n },\n });\n }\n\n private async throwResponseError(response: Response): Promise<never> {\n let message =\n response.status === 404\n ? \"Market not found\"\n : `AGG API error: ${response.status} ${response.statusText}`;\n let code: string | undefined;\n let retryable: boolean | undefined;\n let retryAfterMs = parseRetryAfterHeader(response.headers?.get(\"Retry-After\"));\n let errors: { field: string; message: string }[] | undefined;\n\n try {\n const body = (await response.json()) as {\n message?: string;\n code?: string;\n retryable?: boolean;\n retryAfter?: unknown;\n errors?: { field?: unknown; message?: unknown }[];\n };\n retryAfterMs ??= parseRetryAfterSeconds(body?.retryAfter);\n if (typeof body.message === \"string\" && body.message.length > 0) {\n message = body.message;\n }\n if (typeof body.code === \"string\" && body.code.length > 0) {\n code = body.code;\n }\n if (typeof body.retryable === \"boolean\") {\n retryable = body.retryable;\n }\n if (Array.isArray(body.errors)) {\n const parsed = body.errors\n .map((e) => ({\n field: typeof e?.field === \"string\" ? e.field : \"\",\n message: typeof e?.message === \"string\" ? e.message : \"\",\n }))\n .filter((e) => e.message.length > 0);\n if (parsed.length > 0) errors = parsed;\n }\n } catch {\n // Best-effort parse only — fall back to the status text message above.\n }\n\n throw new AggApiError(message, response.status, { code, retryable, retryAfterMs, errors });\n }\n\n /**\n * Deduplicates concurrent refresh attempts — if multiple requests hit 401 at the same time,\n * only one refresh call is made and the rest wait for it.\n */\n private refreshWithDedup(): Promise<string> {\n if (!this.pendingRefresh) {\n this.pendingRefresh = this.refreshAccessToken().finally(() => {\n this.pendingRefresh = null;\n });\n }\n return this.pendingRefresh;\n }\n\n private buildAuthRequestInit(\n init: RequestInit,\n options?: { includeDeliveryHeader?: boolean },\n ): RequestInit {\n if (this.authDelivery !== COOKIE_REFRESH_DELIVERY) {\n return init;\n }\n\n const headers = {\n ...(init.headers as Record<string, string> | undefined),\n };\n\n if (options?.includeDeliveryHeader !== false) {\n headers[\"x-auth-delivery\"] = COOKIE_REFRESH_DELIVERY;\n }\n\n return {\n ...init,\n credentials: \"include\",\n headers,\n };\n }\n\n private buildUserAuthResult(response: VerifyResponse, user: UserProfile): UserAuthResult {\n return response.refreshToken === undefined\n ? { accessToken: response.accessToken, user }\n : {\n accessToken: response.accessToken,\n refreshToken: response.refreshToken,\n user,\n };\n }\n\n private async performSignOutRequest(): Promise<void> {\n await this.request(\n \"/auth/sign-out\",\n this.buildAuthRequestInit({ method: \"POST\", body: \"{}\" }, { includeDeliveryHeader: false }),\n );\n }\n\n // --- Auth & session state ---\n /** Set the user access token (for future user-tier auth). */\n setAccessToken(token: string): void {\n if (this.accessToken !== token) this.accessTokenUserId = undefined;\n this.accessToken = token;\n this._authStatus = \"authenticated\";\n this.persistSession();\n this.notifyListeners();\n }\n\n /** Set the current auth session tokens and optionally seed the user profile. */\n setSession(session: AggClientSessionInput): void {\n const wasAuthenticated = this.isAuthenticated;\n this.accessTokenUserId =\n session.user?.id ??\n (this.accessToken === session.accessToken ? this.accessTokenUserId : undefined);\n this.accessToken = session.accessToken;\n\n if (\"refreshToken\" in session) {\n this.refreshTokenValue = session.refreshToken;\n }\n\n if (session.user !== undefined) {\n this.currentUser = normalizeSessionUser(session.user, this.currentUser);\n }\n\n this._authStatus = \"authenticated\";\n this.persistSession();\n this.notifyListeners();\n\n if (!wasAuthenticated) {\n this.broadcastAuth(\"login\");\n }\n }\n\n /** Clear the user access token, refresh token, and user info. Broadcasts cross-tab logout. */\n clearAccessToken(): void {\n this.accessToken = undefined;\n this.accessTokenUserId = undefined;\n this.refreshTokenValue = undefined;\n this.currentUser = undefined;\n this._authStatus = \"unauthenticated\";\n this.persistSession();\n this.notifyListeners();\n this.broadcastAuth(\"logout\");\n }\n\n private broadcastAuth(type: \"login\" | \"logout\"): void {\n try {\n this.authChannel?.postMessage({ type });\n } catch {\n // Channel may be closed or unavailable.\n }\n }\n\n /**\n * The App this client speaks for, or `undefined` for an admin-key-only\n * client. Exposed so callers can scope per-app caches by it — app config is\n * app-scoped data, and two clients sharing one cache must not share entries.\n */\n get appId(): string | undefined {\n return this._appId;\n }\n\n /** Current auth lifecycle status. */\n get authStatus(): AuthStatus {\n return this._authStatus;\n }\n\n /** Whether a user access token is currently set. */\n get isAuthenticated(): boolean {\n return !!this.accessToken;\n }\n\n /** Primary wallet address derived from the current user profile. */\n get address(): string | undefined {\n return getWalletAddressFromUserProfile(this.currentUser);\n }\n\n /** Subscribe to auth state changes. Returns an unsubscribe function. */\n onAuthStateChange(listener: AuthStateListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notifyListeners(): void {\n const authenticated = this.isAuthenticated;\n for (const listener of Array.from(this.listeners)) {\n listener(authenticated);\n }\n }\n\n /** Get the currently authenticated user, if any. */\n get user(): UserProfile | undefined {\n return this.currentUser;\n }\n\n // --- SIWE auth ---\n\n /**\n * Build an EIP-4361 SIWE message string.\n *\n * `params.address` is accepted in any casing. EIP-4361 requires the address\n * line to be EIP-55 checksummed, and wallets commonly return a lowercase one\n * — `eth_requestAccounts` does — so the checksum is applied here, the way\n * viem, ethers and `siwe` do inside their own message builders. An address\n * that is not 20 bytes of hex throws: no message we could build from it\n * would verify.\n */\n buildSiweMessage(params: SiweMessageParams): string {\n const chainId = params.chainId ?? 1;\n const issuedAt = params.issuedAt ?? new Date().toISOString();\n const address = toChecksumAddress(params.address);\n\n let message = `${params.domain} wants you to sign in with your Ethereum account:\\n${address}`;\n\n // EIP-4361 keeps the statement SLOT even when there is no statement: the\n // ABNF is `address LF LF [statement] LF LF`, so a statement-less message\n // still carries the blank line. Emitting `address LF LF URI:` produces a\n // message no conforming parser accepts — and because the API maps every\n // parse failure onto the same 401, it surfaces as \"Invalid SIWE signature\",\n // pointing the partner at their signature rather than at the message.\n message += params.statement ? `\\n\\n${params.statement}` : \"\\n\";\n\n message += `\\n\\nURI: ${params.uri}\\nVersion: 1\\nChain ID: ${chainId}\\nNonce: ${params.nonce}\\nIssued At: ${issuedAt}`;\n\n return message;\n }\n\n /** Build a SIWS message string for Solana wallet sign-in (pure formatting, no crypto). */\n buildSiwsMessage(params: SiwsMessageParams): string {\n const chainId = params.chainId ?? \"mainnet\";\n const issuedAt = params.issuedAt ?? new Date().toISOString();\n\n let message = `${params.domain} wants you to sign in with your Solana account:\\n${params.address}`;\n\n if (params.statement) {\n message += `\\n\\n${params.statement}`;\n }\n\n message += `\\n\\nURI: ${params.uri}\\nVersion: 1\\nChain ID: ${chainId}\\nNonce: ${params.nonce}\\nIssued At: ${issuedAt}`;\n\n return message;\n }\n\n /** Verify a SIWE/SIWS signature or a Privy access token with the API, store the token + user. */\n async verify(args: AggAuthVerifyBody): Promise<UserAuthResult> {\n const res = await this.request<VerifyResponse>(\n \"/auth/verify\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify(this.withAuthPayload(args)),\n }),\n );\n\n this.setSession({\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n user: res.user,\n });\n\n try {\n const user = await this.getCurrentUser();\n return this.buildUserAuthResult(res, user);\n } catch (error) {\n this.clearAccessToken();\n throw error;\n }\n }\n\n /** Backwards-compatible alias for `verify()`. */\n async verifySignIn(args: AggAuthVerifyBody): Promise<UserAuthResult> {\n return this.verify(args);\n }\n\n /** Initiate an auth flow (SIWE nonce, OAuth redirect URL, or magic link). */\n async authStart(body: AggAuthStartBody): Promise<AggAuthStartResult> {\n // `credentials: \"include\"` lets the browser accept the signin-proof cookie the\n // server sets for OAuth flows. Without it the cookie is dropped on cross-origin\n // responses and the OAuth callback would reject the state as unbound.\n return this.request(\"/auth/start\", {\n method: \"POST\",\n body: JSON.stringify(this.withAuthPayload(body)),\n credentials: \"include\",\n });\n }\n\n /** Backwards-compatible alias for `authStart()`. */\n async startAuth(body: AggAuthStartBody): Promise<AggAuthStartResult> {\n return this.authStart(body);\n }\n\n /**\n * Start an account-link flow. Requires the caller to already be signed in — sends\n * the bearer automatically. Response shape:\n * - OAuth providers → `{ type: \"redirect\", url }`; redirect the browser to `url`.\n * - Email → `{ type: \"magic_link\", success: true }`; check the destination inbox.\n * - Wallet providers (siwe/siws) → `{ type: \"wallet_challenge\", message }`; have the\n * user sign `message` VERBATIM, then submit it to `linkAccountConfirm()` as\n * `{ kind: \"wallet_signature\", message, signature }`.\n *\n * After the OAuth/email callback runs, the browser lands back on the app's `redirectUrl`\n * with a `link_confirm_token` query param. Feed that token to `linkAccountConfirm()`\n * to persist the Account row.\n */\n async linkAccount(body: AggLinkAccountBody): Promise<AggLinkAccountResult> {\n // `credentials: \"include\"` so the browser stores the same-origin link-proof\n // cookie the server sets on this response (mirrors authStart). Without it the\n // cookie is dropped on a cross-origin response and the OAuth link callback\n // rejects with `link_proof_invalid`, so the link never completes.\n return this.request(\n \"/users/me/link-account/start\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify(body),\n credentials: \"include\",\n }),\n );\n }\n\n /**\n * Finalize an account link.\n *\n * - Pass a `link_confirm_token` string (OAuth/email) to exchange it for a linked\n * `Account` row.\n * - Pass `{ kind: \"wallet_signature\", message, signature }` (wallet providers) to\n * verify the signature over the `wallet_challenge` `message` returned by\n * `linkAccount()`.\n *\n * The server matches the current bearer's `principalId` to the challenge/token's\n * `principalId` before writing — this is the final ownership check. A wallet already\n * linked to a DIFFERENT principal rejects with HTTP 409.\n */\n async linkAccountConfirm(\n input: string | AggLinkAccountWalletConfirmBody,\n ): Promise<AggLinkAccountConfirmResult> {\n // Confirm runs on the OAuth redirect-return page, where the in-memory access\n // token was wiped by the full-page reload (tokens are never persisted). Without\n // a bearer the user-tier guard 401s, and request()'s 401-refresh-retry is gated\n // on an existing token so it can't recover. Mint one from the refresh\n // cookie/token first (deduped, coalescing with any in-flight refresh). If the\n // session is genuinely gone the refresh throws and the caller surfaces it.\n if (!this.accessToken) {\n await this.refreshWithDedup();\n }\n const body = typeof input === \"string\" ? { token: input } : input;\n return this.request(\n \"/users/me/link-account/confirm\",\n this.buildAuthRequestInit({ method: \"POST\", body: JSON.stringify(body) }),\n );\n }\n\n /** Exchange a one-time auth code (from OAuth/magic-link callback) for tokens. */\n async exchangeAuthCode(code: string): Promise<UserAuthResult> {\n const res = await this.request<VerifyResponse>(\n \"/auth/token/exchange\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify({ code }),\n }),\n );\n\n this.setSession({\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n user: res.user,\n });\n\n try {\n const user = await this.getCurrentUser();\n return this.buildUserAuthResult(res, user);\n } catch (error) {\n this.clearAccessToken();\n throw error;\n }\n }\n\n /** Refresh the access token using the stored refresh token. */\n async refreshAccessToken(): Promise<string> {\n if (this.authDelivery !== COOKIE_REFRESH_DELIVERY && !this.refreshTokenValue) {\n throw new Error(\"No refresh token available\");\n }\n const res = await this.request<VerifyResponse>(\n \"/auth/token/refresh\",\n this.buildAuthRequestInit({\n method: \"POST\",\n body: JSON.stringify(\n this.authDelivery === COOKIE_REFRESH_DELIVERY\n ? {}\n : { refreshToken: this.refreshTokenValue },\n ),\n }),\n );\n\n this.setSession({\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n user: res.user,\n });\n return res.accessToken;\n }\n\n /** Get the current user's profile. */\n async getCurrentUser(): Promise<UserProfile> {\n const user = await this.request<UserProfile>(\"/users/me\");\n this.currentUser = user;\n this.accessTokenUserId = user.id;\n this.persistSession();\n this.notifyListeners();\n return user;\n }\n\n /** Update the current user (e.g. username). Requires currentUser.id; call getCurrentUser() first if needed. */\n async updateUser(data: UpdateUserBody): Promise<UserProfile> {\n if (!this.currentUser?.id) {\n const profile = await this.getCurrentUser();\n if (!profile?.id) throw new Error(\"Not authenticated\");\n }\n const profile = await this.request<UserProfile>(\"/users/me\", {\n method: \"PATCH\",\n body: JSON.stringify(data),\n });\n this.currentUser = profile;\n this.persistSession();\n this.notifyListeners();\n return profile;\n }\n\n /** Link a partner-provided external user ID assertion to the current user. */\n async linkExternalId(params: {\n externalId: string;\n timestamp: number;\n hmac: string;\n }): Promise<UserProfile> {\n const profile = await this.request<UserProfile>(\"/users/me/external-id\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n this.currentUser = profile;\n this.persistSession();\n this.notifyListeners();\n return profile;\n }\n\n /** Create a presigned avatar upload URL for the current user. */\n async createAvatarUploadUrl(contentType: string): Promise<{\n uploadUrl: string;\n assetKey: string;\n cdnUrl: string;\n }> {\n return this.request<{ uploadUrl: string; assetKey: string; cdnUrl: string }>(\n \"/users/me/avatar\",\n {\n method: \"POST\",\n body: JSON.stringify({ contentType }),\n },\n );\n }\n\n /** Disconnect a linked auth provider from the current user. */\n async disconnectAccount(\n provider: \"wallet\" | \"solana_wallet\" | \"google\" | \"twitter\" | \"apple\" | \"email\",\n ): Promise<{ success: true }> {\n return this.request<{ success: true }>(`/users/me/accounts/${provider}`, {\n method: \"DELETE\",\n body: JSON.stringify({}),\n });\n }\n\n /** Sign out — revoke all tokens server-side and clear local session. */\n async signOut(): Promise<void> {\n if (this.accessToken) {\n try {\n await this.performSignOutRequest();\n } catch (error) {\n if (\n this.authDelivery === COOKIE_REFRESH_DELIVERY &&\n (error as { status?: number }).status === 401\n ) {\n try {\n await this.refreshAccessToken();\n await this.performSignOutRequest();\n } catch {\n // Best-effort: clear local session regardless\n }\n }\n // Ignore non-401 and non-cookie-mode failures. Local cleanup happens below even if the\n // remote revoke request fails.\n }\n }\n this.refreshTokenValue = undefined;\n this.clearAccessToken();\n }\n\n /** Get user holdings (positions) for a venue. Uses backend to resolve venue-specific identifiers. */\n async getUserHoldings(params: {\n venue: Venue;\n venueMarketId?: string;\n venueEventId?: string;\n cursor?: string;\n }): Promise<PaginatedResponse<UserHolding>> {\n const { venue, venueMarketId, venueEventId, cursor } = params;\n const query: Record<string, string> = { venue };\n if (venueMarketId != null) query.venueMarketId = venueMarketId;\n if (venueEventId != null) query.venueEventId = venueEventId;\n if (cursor != null) query.cursor = cursor;\n return this.request<PaginatedResponse<UserHolding>>(\"/trading/holdings\", {\n query,\n });\n }\n\n /** List trade-executor orders for the authenticated user. */\n async getOrders(params: OrderListQuery = {}): Promise<TradeExecutorOrderListResponse> {\n const query: Record<string, string> = {};\n if (params.userId) query.userId = params.userId;\n if (params.status) query.status = params.status;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.offset != null) query.offset = String(params.offset);\n\n return this.request<TradeExecutorOrderListResponse>(\"/orders\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * List execution orders for the authenticated user (cursor pagination).\n *\n * Pass `quoteId` to fetch every leg of a multi-venue split route in\n * one call — `useQuoteSummary(quoteId)` reduces the list into a\n * rollup (total cost, share-weighted avg price, to-win). Pass\n * `venueMarketIds` to narrow to the orders on those markets. Sent as\n * repeated params in one request; batch long lists yourself (or use\n * `useExecutionOrdersForMarkets`) to keep the URL short.\n */\n async getExecutionOrders(\n params: ExecutionOrdersQuery = {},\n options?: { signal?: AbortSignal },\n ): Promise<PaginatedResponse<ExecutionOrderItem>> {\n const query: Record<string, string | string[]> = {};\n if (params.orderId) query.orderId = params.orderId;\n if (params.quoteId) query.quoteId = params.quoteId;\n if (params.externalId) query.externalId = params.externalId;\n if (params.clientOrderId) query.clientOrderId = params.clientOrderId;\n if (params.venueMarketIds?.length) query.venueMarketIds = params.venueMarketIds;\n if (params.status) query.status = params.status;\n if (params.orderType) query.orderType = params.orderType;\n if (params.mode) query.mode = params.mode;\n if (params.cursor) query.cursor = params.cursor;\n if (params.limit != null) query.limit = String(params.limit);\n\n return this.request<PaginatedResponse<ExecutionOrderItem>>(\"/execution/orders\", {\n query: Object.keys(query).length ? query : undefined,\n signal: options?.signal,\n });\n }\n\n /**\n * Get quote-scoped execution progress, DAG step state, and order leg\n * terminal status. Also carries `pendingSignatures` — this is the route\n * `fillSelfCustody` polls while an on-chain step is in flight, so a caller\n * already polling this for progress learns about newly-parked steps here\n * too, not just from the signatures endpoint.\n */\n async getExecutionStatus(params: ExecutionStatusQuery): Promise<ExecutionStatusResponse> {\n const query: Record<string, string> = { quoteId: params.quoteId };\n if (params.mode) query.mode = params.mode;\n\n return this.request<ExecutionStatusResponse>(\"/execution/status\", { query });\n }\n\n /** Unified user activity feed (trades, deposits, withdrawals, bridges, wallet ops). */\n async getUserActivity(\n params: UserActivityQuery = {},\n options?: { signal?: AbortSignal },\n ): Promise<PaginatedResponse<UserActivityItem>> {\n const query: Record<string, string> = {};\n if (params.type) query.type = params.type;\n if (params.cursor) query.cursor = params.cursor;\n if (params.limit != null) query.limit = String(params.limit);\n\n return this.request<PaginatedResponse<UserActivityItem>>(\"/users/activity\", {\n query: Object.keys(query).length ? query : undefined,\n signal: options?.signal,\n });\n }\n\n /**\n * Per-app trader leaderboard ranked by realized P&L or volume over an\n * inclusive UTC day range. `rank` is exact within the top 100.\n */\n async getLeaderboard(params: LeaderboardQuery = {}): Promise<PaginatedResponse<LeaderboardRow>> {\n const query: Record<string, string | string[]> = {};\n for (const key of [\n \"from\",\n \"to\",\n \"metric\",\n \"cursor\",\n \"userId\",\n \"externalId\",\n \"username\",\n \"walletAddress\",\n ] as const) {\n const value = params[key];\n if (value) query[key] = value;\n }\n if (params.limit != null) query.limit = String(params.limit);\n for (const key of [\"categoryIds\", \"venueEventIds\", \"userIds\"] as const) {\n const value = params[key];\n if (value?.length) query[key] = value;\n }\n return this.request<PaginatedResponse<LeaderboardRow>>(\"/leaderboard\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * One user's (or, with no user, the whole app's) leaderboard stats per UTC\n * day (default the last 30 days, at most 366) with a running cumulative\n * realized P&L, optionally for a single category. Gross of fees;\n * unrealized P&L is not included.\n */\n async getLeaderboardSeries(params: LeaderboardSeriesQuery): Promise<LeaderboardSeries> {\n const query: Record<string, string | string[]> = {};\n for (const key of [\n \"from\",\n \"to\",\n \"userId\",\n \"externalId\",\n \"username\",\n \"walletAddress\",\n ] as const) {\n const value = params[key];\n if (value) query[key] = value;\n }\n if (params.categoryIds?.length) query.categoryIds = params.categoryIds;\n return this.request<LeaderboardSeries>(\"/leaderboard/series\", { query });\n }\n\n /** List execution positions for the authenticated user (cursor pagination). */\n async getExecutionPositions(\n params: ExecutionPositionsQuery = {},\n ): Promise<PaginatedResponse<ExecutionPositionGroup>> {\n const query: Record<string, string | string[]> = {};\n if (params.cursor) query.cursor = params.cursor;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.status) query.status = params.status;\n if (params.mode) query.mode = params.mode;\n if (params.categoryIds?.length) query.categoryIds = params.categoryIds;\n if (params.sort) query.sort = params.sort;\n\n return this.request<PaginatedResponse<ExecutionPositionGroup>>(\"/execution/positions\", {\n query: Object.keys(query).length ? query : undefined,\n });\n }\n\n /**\n * Get cash balances and per-venue position balances.\n *\n * `custody: \"self\"` returns the wallets linked to this account — plus their\n * Polymarket deposit and legacy wallets — instead of the managed wallet. Each\n * chain row then carries `address` and `custodyKind`; `positions` is\n * account-wide either way.\n *\n * Caveat on the headline number: a chain row with `custodyKind:\n * \"POLYMARKET_LEGACY\"` and `legacyKind: \"proxy\"` holds funds that can only\n * be spent on Polymarket, but it still counts towards its token's\n * `totalRaw`/`availableRaw` (a token's totals are always the sum of its\n * chain rows). If you show \"spendable anywhere\", subtract those rows.\n */\n async getManagedBalances(\n params: ManagedBalancesParams = {},\n options?: { signal?: AbortSignal },\n ): Promise<UnifiedBalanceResponse> {\n const query: Record<string, string> = {};\n if (params.mode) query.mode = params.mode;\n if (params.custody) query.custody = params.custody;\n return this.request<UnifiedBalanceResponse>(\"/execution/balances\", {\n query: Object.keys(query).length ? query : undefined,\n signal: options?.signal,\n });\n }\n\n /** Read hosted custody status without creating a signing wallet or account. */\n async getHostedVenueAccount(\n venue: \"betdex\",\n params: ManagedBalancesParams = {},\n ): Promise<HostedVenueAccount> {\n return this.request<HostedVenueAccount>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}`,\n {\n query: params.mode ? { mode: params.mode } : undefined,\n },\n );\n }\n\n /** Owned exact ledger entries; not balances, fill fees or withdrawal finality. */\n async getHostedVenueActivity(\n venue: \"betdex\",\n params: HostedVenueActivityQuery = {},\n ): Promise<HostedVenueActivity> {\n return this.request<HostedVenueActivity>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/activity`,\n {\n query: {\n ...(params.mode ? { mode: params.mode } : {}),\n ...(params.page !== undefined ? { page: String(params.page) } : {}),\n },\n },\n );\n }\n\n /** Explicit hosted-account creation; no signing wallet or credential upload. */\n async provisionHostedVenueAccount(\n venue: \"betdex\",\n body: ProvisionHostedVenueAccountBody,\n ): Promise<HostedVenueAccount> {\n return this.request<HostedVenueAccount>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}`,\n {\n method: \"POST\",\n body: JSON.stringify(body),\n },\n );\n }\n\n /** Fetch the owned hosted account's verified Solana USDC deposit address. */\n async getHostedVenueDepositAddress(\n venue: \"betdex\",\n params: ManagedBalancesParams = {},\n ): Promise<HostedVenueDepositAddress> {\n return this.request<HostedVenueDepositAddress>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/deposit-address`,\n { query: params.mode ? { mode: params.mode } : undefined },\n );\n }\n\n /** Submit exactly one explicit hosted withdrawal under a caller idempotency key. */\n async withdrawHostedVenue(\n venue: \"betdex\",\n body: HostedVenueWithdrawalRequest,\n ): Promise<HostedVenueWithdrawal> {\n return this.request<HostedVenueWithdrawal>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/withdrawals`,\n { method: \"POST\", body: JSON.stringify(body) },\n );\n }\n\n /** Read only Agg's persisted withdrawal state; this never replays a native request. */\n async getHostedVenueWithdrawal(\n venue: \"betdex\",\n withdrawalId: string,\n params: ManagedBalancesParams = {},\n ): Promise<HostedVenueWithdrawal> {\n if (!withdrawalId) throw new Error(\"withdrawalId is required\");\n return this.request<HostedVenueWithdrawal>(\n `/users/me/venue-accounts/${encodeURIComponent(venue)}/withdrawals/${encodeURIComponent(withdrawalId)}`,\n { query: params.mode ? { mode: params.mode } : undefined },\n );\n }\n\n /** Store or replace encrypted credentials for a venue. Secrets are never returned. */\n async upsertVenueKey(body: UpsertVenueKey): Promise<VenueKeySummary> {\n return this.request<VenueKeySummary>(\"/venue-keys\", {\n method: \"PUT\",\n body: JSON.stringify(body),\n });\n }\n\n /** List venues with stored credentials. */\n async listVenueKeys(): Promise<VenueKeySummary[]> {\n return this.request<VenueKeySummary[]>(\"/venue-keys\");\n }\n\n /** Fetch connection and verification status for stored venue credentials. */\n async getVenueKeyStatus(venue: Venue): Promise<VenueKeyStatus> {\n return this.request<VenueKeyStatus>(`/venue-keys/${encodeURIComponent(venue)}/status`);\n }\n\n /** Remove stored credentials for a venue. */\n async deleteVenueKey(venue: Venue): Promise<void> {\n await this.request(`/venue-keys/${encodeURIComponent(venue)}`, { method: \"DELETE\" });\n }\n\n /** Create a server-managed paper trading account for an app. Requires adminKey or apiKey. */\n async createPaperTradingAccount(\n params: CreatePaperTradingAccountParams,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingAccount> {\n return this.request<PaperTradingAccount>(this.paperTradingAccountsPath(options?.appId), {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** List server-managed paper trading accounts for an app. Requires adminKey or apiKey. */\n async listPaperTradingAccounts(\n params: PaperTradingAccountListParams & PaperTradingAppOptions = {},\n ): Promise<PaperTradingAccountsPage> {\n const { appId, ...listParams } = params;\n return this.request<PaperTradingAccountsPage>(this.paperTradingAccountsPath(appId), {\n query: this.paperTradingAccountListQuery(listParams),\n });\n }\n\n /** Fetch a server-managed paper trading account. Requires adminKey or apiKey. */\n async getPaperTradingAccount(\n accountId: string,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingAccount> {\n return this.request<PaperTradingAccount>(\n this.paperTradingAccountPath(accountId, options?.appId),\n );\n }\n\n /** Set a paper trading account cash balance. Requires adminKey or apiKey. */\n async setPaperTradingBalance(\n accountId: string,\n params: SetPaperTradingBalanceParams,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingBalanceResponse> {\n return this.request<PaperTradingBalanceResponse>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/balance`,\n {\n method: \"PATCH\",\n body: JSON.stringify(params),\n },\n );\n }\n\n /** Clear positions and reset cash for a paper trading account. Requires adminKey or apiKey. */\n async resetPaperTradingAccount(\n accountId: string,\n params: ResetPaperTradingAccountParams = {},\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingBalanceResponse> {\n return this.request<PaperTradingBalanceResponse>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/reset`,\n {\n method: \"POST\",\n body: JSON.stringify(params),\n },\n );\n }\n\n /** Place a direct simulated order in a paper trading account. Requires adminKey or apiKey. */\n async placePaperTradingOrder(\n accountId: string,\n params: PlacePaperTradingOrderParams,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingOrder> {\n return this.request<PaperTradingOrder>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/orders`,\n {\n method: \"POST\",\n body: JSON.stringify(params),\n },\n );\n }\n\n /** List positions for a server-managed paper trading account. Requires adminKey or apiKey. */\n async listPaperTradingPositions(\n accountId: string,\n params: PaperTradingListParams & PaperTradingAppOptions = {},\n ): Promise<PaperTradingPositionsPage> {\n const { appId, ...listParams } = params;\n return this.request<PaperTradingPositionsPage>(\n `${this.paperTradingAccountPath(accountId, appId)}/positions`,\n {\n query: this.paperTradingListQuery(listParams),\n },\n );\n }\n\n /** List orders for a server-managed paper trading account. Requires adminKey or apiKey. */\n async listPaperTradingOrders(\n accountId: string,\n params: PaperTradingListParams & PaperTradingAppOptions = {},\n ): Promise<PaperTradingOrdersPage> {\n const { appId, ...listParams } = params;\n return this.request<PaperTradingOrdersPage>(\n `${this.paperTradingAccountPath(accountId, appId)}/orders`,\n {\n query: this.paperTradingListQuery(listParams),\n },\n );\n }\n\n /** Fetch account-level paper trading equity, P&L, and marked positions. Requires adminKey or apiKey. */\n async getPaperTradingPortfolio(\n accountId: string,\n options?: PaperTradingAppOptions,\n ): Promise<PaperTradingPortfolio> {\n return this.request<PaperTradingPortfolio>(\n `${this.paperTradingAccountPath(accountId, options?.appId)}/portfolio`,\n );\n }\n\n /**\n * Cancel an agg order by id. Self-custody needs Polymarket ClobAuth\n * or a fresh Hyperliquid cancel action signed by the EOA/client-held agent.\n */\n async cancelManagedOrder(\n orderId: string,\n options?: { signal?: AbortSignal; cancelSignature?: CancelOrderSignature },\n ): Promise<CancelManagedExecutionResponse> {\n return this.request<CancelManagedExecutionResponse>(\"/execution/orders/cancel\", {\n method: \"POST\",\n body: JSON.stringify({\n orderId,\n ...(options?.cancelSignature ? { cancelSignature: options.cancelSignature } : {}),\n }),\n signal: options?.signal,\n });\n }\n\n /**\n * Cancel a Polymarket or Hyperliquid limit order that one of the user's\n * linked self-custody wallets placed outside AGG. `signerAddress` must be\n * that wallet and must have produced `cancelSignature`.\n */\n async cancelVenueOrder(\n params: CancelVenueOrderParams,\n options?: { signal?: AbortSignal },\n ): Promise<CancelManagedExecutionResponse> {\n return this.request<CancelManagedExecutionResponse>(\"/execution/orders/cancel\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n // --- Venue events & venue markets (primary) ---\n\n /** List venue events with optional filters. Requires appId or admin auth. Supports cursor-based pagination. */\n async getVenueEvents(options?: {\n venues?: Venue[];\n search?: string;\n categoryIds?: string[];\n matchStatus?: MatchStatus[];\n status?: MarketStatus[];\n sortBy?: string;\n sortDir?: string;\n aggKey?: string | string[];\n recurrence?: RecurrenceFilter | RecurrenceFilter[];\n limit?: number;\n cursor?: string;\n minYesPrice?: number;\n maxYesPrice?: number;\n /** Lifetime-volume floor (USD). Hides events/markets below it. Omit or 0 = no filter. */\n minVolume?: number;\n /** ISO-8601 timestamp. Hides events with endDate <= this value. NULL-endDate events are kept. */\n endDateFrom?: string;\n signal?: AbortSignal;\n /**\n * When true, fold same-venue companion events into one tile per game\n * (`groupParentId IS NULL`). Sent as `grouped=true`; omitted when false/absent\n * (default = ungrouped). Consumers showing one tile per game need a detail\n * view that loads the folded companions via aggKey.\n */\n grouped?: boolean;\n }): Promise<PaginatedResponse<VenueEvent>> {\n const query: Record<string, string | string[]> = {};\n if (options?.venues && options.venues.length > 0) query.venues = options.venues;\n if (options?.search?.trim()) query.search = options.search.trim();\n if (options?.categoryIds && options.categoryIds.length > 0)\n query.categoryIds = options.categoryIds;\n if (options?.matchStatus && options.matchStatus.length > 0)\n query.matchStatus = options.matchStatus;\n if (options?.status && options.status.length > 0) query.status = options.status;\n if (options?.sortBy) query.sortBy = options.sortBy;\n if (options?.sortDir) query.sortDir = options.sortDir;\n if (options?.aggKey) query.aggKey = options.aggKey;\n if (options?.recurrence) query.recurrence = options.recurrence;\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.minYesPrice != null) query.minYesPrice = String(options.minYesPrice);\n if (options?.maxYesPrice != null) query.maxYesPrice = String(options.maxYesPrice);\n if (options?.minVolume != null && options.minVolume > 0)\n query.minVolume = String(options.minVolume);\n if (options?.endDateFrom) query.endDateFrom = options.endDateFrom;\n if (options?.grouped) query.grouped = \"true\";\n return this.request<PaginatedResponse<VenueEvent>>(\"/venue-events\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: options?.signal,\n });\n }\n\n /** Get a single venue event by ID. Requires appId or admin auth. */\n async getEventBootstrap(\n eventId: string,\n options?: { limit?: number; minVolume?: number; signal?: AbortSignal },\n ): Promise<EventBootstrapResponse> {\n const query: Record<string, string> = {};\n if (options?.limit) query.limit = String(options.limit);\n if (options?.minVolume != null && options.minVolume > 0)\n query.minVolume = String(options.minVolume);\n return this.request<EventBootstrapResponse>(\n `/venue-events/${encodeURIComponent(eventId)}/bootstrap`,\n {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: options?.signal,\n },\n );\n }\n\n async getVenueEventById(\n id: string,\n options?: {\n signal?: AbortSignal;\n /**\n * Scope `marketCount` and the rolled-up `volume` to the whole matched\n * cluster (default, `true`) or to this one venue event (`false`). Pair it\n * with the same value on {@link getVenueMarkets} so the count matches the\n * market list you render.\n */\n cluster?: boolean;\n /**\n * Lifetime-volume floor (USD). Scopes `marketCount` to the markets\n * {@link getVenueMarkets} returns with the same `minVolume`. Omit or 0 = no filter.\n */\n minVolume?: number;\n },\n ): Promise<VenueEvent> {\n return this.request<VenueEvent>(`/venue-events/${encodeURIComponent(id)}`, {\n // Opt into the lean response (no embedded `venueMarkets`) — markets are\n // fetched separately via GET /venue-markets. Empty `expand` (no `markets`\n // token) tells the API to omit the deprecated embedded array.\n query: {\n expand: \"\",\n ...(options?.cluster === false ? { cluster: \"false\" } : {}),\n ...(options?.minVolume != null && options.minVolume > 0\n ? { minVolume: String(options.minVolume) }\n : {}),\n },\n signal: options?.signal,\n });\n }\n\n /** Get normalized live score state for sports events. Requires appId or admin auth. */\n async getSportsLive(\n eventIds: string[],\n options?: { signal?: AbortSignal },\n ): Promise<SportsLiveResponse> {\n const normalizedEventIds = normalizeRequestedVenueMarketIds(eventIds);\n if (normalizedEventIds.length === 0) {\n return { data: [], missingEventIds: [] };\n }\n\n const responses = await Promise.all(\n chunkArray(normalizedEventIds, MAX_SPORTS_EVENT_IDS_PER_REQUEST).map((eventIdChunk) =>\n this.request<SportsLiveResponse>(\"/sports/live\", {\n query: { eventIds: eventIdChunk },\n signal: options?.signal,\n }),\n ),\n );\n\n return {\n data: responses.flatMap((response) => response.data),\n missingEventIds: [...new Set(responses.flatMap((response) => response.missingEventIds))],\n };\n }\n\n /** List deterministic recurring crypto window markets across venues. Requires appId or admin auth. */\n async listRecurringCryptoMarkets(\n options?: ListRecurringCryptoMarketsOptions & { signal?: AbortSignal },\n ): Promise<RecurringCryptoMarketsResponse> {\n const query: Record<string, string | string[]> = {};\n if (options?.assets && options.assets.length > 0) query.assets = options.assets;\n if (options?.durations && options.durations.length > 0) query.durations = options.durations;\n if (options?.interval) query.interval = options.interval;\n if (options?.window) query.window = options.window;\n if (options?.venues && options.venues.length > 0) query.venues = options.venues;\n if (options?.status && options.status.length > 0) query.status = options.status;\n if (options?.windowStartFrom) query.windowStartFrom = options.windowStartFrom;\n if (options?.windowStartTo) query.windowStartTo = options.windowStartTo;\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.includeOrderbookPrices != null) {\n query.includeOrderbookPrices = String(options.includeOrderbookPrices);\n }\n if (options?.includeReferencePrices != null) {\n query.includeReferencePrices = String(options.includeReferencePrices);\n }\n if (options?.includeDirectVenueMarkets != null) {\n query.includeDirectVenueMarkets = String(options.includeDirectVenueMarkets);\n }\n if (options?.includeOrderbookDepth != null) {\n query.includeOrderbookDepth = String(options.includeOrderbookDepth);\n }\n if (options?.orderbookDepth != null) {\n query.orderbookDepth = String(options.orderbookDepth);\n }\n if (options?.orderbookDepthAmountUsd != null) {\n query.orderbookDepthAmountUsd = String(options.orderbookDepthAmountUsd);\n }\n\n return this.request<RecurringCryptoMarketsResponse>(\"/crypto/recurring-markets\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: options?.signal,\n });\n }\n\n /** Poll fresh reference prices for recurring crypto markets. Requires appId or admin auth. */\n async getCryptoReferencePrices(\n options: GetCryptoReferencePricesOptions,\n ): Promise<CryptoReferencePricesResponse> {\n const targets: CryptoReferencePriceTarget[] = [\n ...(options.targets ?? []),\n ...(options.venueMarketIds ?? []).map((venueMarketId) => ({\n type: \"venueMarket\" as const,\n venueMarketId,\n })),\n ...(options.venueEventIds ?? []).map((venueEventId) => ({\n type: \"venueEvent\" as const,\n venueEventId,\n })),\n ...(options.externalMarkets ?? []).map((market) => ({\n type: \"externalVenueMarket\" as const,\n venue: market.venue,\n externalMarketId: market.externalMarketId,\n })),\n ...(options.markets ?? []).map((market) => ({\n type: \"market\" as const,\n venue: market.venue,\n venueEventId: market.venueEventId,\n venueMarketId: market.venueMarketId,\n externalEventId: market.externalEventId,\n externalMarketId: market.externalMarketId,\n asset: market.asset,\n quoteAsset: market.quoteAsset ?? \"USD\",\n resolution: market.resolution,\n })),\n ...(options.windowMarkets ?? []).flatMap((windowMarket) =>\n windowMarket.markets.map((market) => ({\n type: \"market\" as const,\n venue: market.venue,\n venueEventId: market.venueEventId,\n venueMarketId: market.venueMarketId,\n externalEventId: market.externalEventId,\n externalMarketId: market.externalMarketId,\n asset: windowMarket.asset,\n quoteAsset: windowMarket.quoteAsset,\n resolution: market.resolution,\n })),\n ),\n ];\n\n if (targets.length === 0) {\n throw new Error(\"getCryptoReferencePrices requires at least one target\");\n }\n\n return this.request<CryptoReferencePricesResponse>(\"/crypto/reference-prices\", {\n method: \"POST\",\n body: JSON.stringify({ targets }),\n signal: options.signal,\n });\n }\n\n /** List venue markets with optional filters. Requires appId or admin auth. Supports cursor-based pagination. */\n async getVenueMarkets(\n options?: {\n venue?: Venue;\n venueEventId?: string;\n /** Exact venue-native identifiers; requires venue, at most 20. */\n externalIdentifier?: string[];\n /**\n * Scope `venueEventId` to the whole matched cluster (default, `true`) or to\n * that one venue event (`false`). Under the default, naming any member of a\n * cluster returns every venue's markets for that real-world event with\n * matched siblings folded into their anchor. Ignored without `venueEventId`.\n */\n cluster?: boolean;\n search?: string;\n matchStatus?: MatchStatus;\n status?: MarketStatus;\n aggKey?: string[];\n sportsMarketType?: string[];\n period?: string[];\n marketCategory?: string[];\n marketGroup?: string[];\n limit?: number;\n cursor?: string;\n sortBy?: \"volume\" | \"volume24hr\" | \"createdAt\" | \"updatedAt\";\n sortDir?: \"asc\" | \"desc\";\n context?: \"list\" | \"detail\";\n /** Omit wide text independently of sort; summary marks detailsDeferred. */\n projection?: \"summary\" | \"full\";\n /** Lifetime-volume floor (USD). Omit or 0 = no filter. */\n minVolume?: number;\n },\n requestOptions?: { signal?: AbortSignal },\n ): Promise<PaginatedResponse<VenueMarket>> {\n const query: Record<string, string | string[]> = {};\n if (options?.venue) query.venue = options.venue;\n if (options?.externalIdentifier?.length) query.externalIdentifier = options.externalIdentifier;\n if (options?.venueEventId) query.venueEventId = options.venueEventId;\n // Server default is cluster scope — only send the opt-out.\n if (options?.cluster === false) query.cluster = \"false\";\n if (options?.search?.trim()) query.search = options.search.trim();\n if (options?.matchStatus) query.matchStatus = options.matchStatus;\n if (options?.status) query.status = options.status;\n if (options?.aggKey && options.aggKey.length > 0) query.aggKey = options.aggKey;\n if (options?.sportsMarketType && options.sportsMarketType.length > 0) {\n query.sportsMarketType = options.sportsMarketType;\n }\n if (options?.period && options.period.length > 0) query.period = options.period;\n if (options?.marketCategory && options.marketCategory.length > 0) {\n query.marketCategory = options.marketCategory;\n }\n if (options?.marketGroup && options.marketGroup.length > 0) {\n query.marketGroup = options.marketGroup;\n }\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.sortBy) query.sortBy = options.sortBy;\n if (options?.sortDir) query.sortDir = options.sortDir;\n if (options?.context) query.context = options.context;\n if (options?.projection) query.projection = options.projection;\n if (options?.minVolume != null && options.minVolume > 0)\n query.minVolume = String(options.minVolume);\n return this.request<PaginatedResponse<VenueMarket>>(\"/venue-markets\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: requestOptions?.signal,\n });\n }\n\n /** Get categories with cursor-based pagination. Requires appId. */\n async getCategories(options?: {\n limit?: number;\n cursor?: string;\n parentId?: string;\n }): Promise<PaginatedResponse<Category>> {\n const query: Record<string, string> = {};\n if (options?.limit != null) query.limit = String(options.limit);\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.parentId) query.parentId = options.parentId;\n return this.request<PaginatedResponse<Category>>(\"/categories\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n });\n }\n\n /** Get per-app UI config (disabled venues + category presets). Requires appId. */\n async getAppConfig(init?: RequestInit): Promise<AppClientConfigResponse> {\n return this.request<AppClientConfigResponse>(\"/app/config\", init);\n }\n\n /**\n * Get the per-venue blocked-country lists (ISO 3166-1 alpha-2). Requires appId.\n *\n * This is the raw venue policy, not per-user eligibility — to gate a fill,\n * read the `warnings` array on the quote response instead.\n */\n async getVenueGeoPolicy(init?: RequestInit): Promise<VenueGeoPolicyResponse> {\n return this.request<VenueGeoPolicyResponse>(\"/app/venue-geo-policy\", init);\n }\n\n /** Get a temporary Alchemy JWT token for RPC connections. */\n async getRpcToken(init?: RequestInit): Promise<RpcTokenResponse> {\n return this.request<RpcTokenResponse>(\"/app/rpc-tokens/alchemy\", init);\n }\n\n private buildNewsFeedQuery(options?: NewsFeedPageOptions): Record<string, string> | undefined {\n const query: Record<string, string> = {};\n if (options?.cursor) query.cursor = options.cursor;\n if (options?.since) query.since = options.since;\n if (options?.before) query.before = options.before;\n if (options?.limit != null) query.limit = String(options.limit);\n return Object.keys(query).length > 0 ? query : undefined;\n }\n\n /** List available market news feeds and item counts. */\n async getNewsFeeds(options?: { signal?: AbortSignal }): Promise<NewsFeedListResponse> {\n return this.request<NewsFeedListResponse>(\"/news-feed\", {\n signal: options?.signal,\n });\n }\n\n /** Get the article-centric market news feed for a category. */\n async getNewsFeed(\n category: string,\n options?: NewsFeedPageOptions & { signal?: AbortSignal },\n ): Promise<NewsFeedArticleFeedResponse> {\n return this.request<NewsFeedArticleFeedResponse>(`/news-feed/${encodeURIComponent(category)}`, {\n query: this.buildNewsFeedQuery(options),\n signal: options?.signal,\n });\n }\n\n /** Get the market-centric market news feed for a category. */\n async getNewsFeedMarkets(\n category: string,\n options?: NewsFeedPageOptions & { signal?: AbortSignal },\n ): Promise<NewsFeedMarketFeedResponse> {\n return this.request<NewsFeedMarketFeedResponse>(\n `/news-feed/${encodeURIComponent(category)}/markets`,\n {\n query: this.buildNewsFeedQuery(options),\n signal: options?.signal,\n },\n );\n }\n\n /** Get news feed coverage and per-category counts. */\n async getNewsFeedStatus(options?: { signal?: AbortSignal }): Promise<NewsFeedStatusResponse> {\n return this.request<NewsFeedStatusResponse>(\"/news-feed/status\", {\n signal: options?.signal,\n });\n }\n\n /** Search recent news for specific markets and return market impact summaries. */\n async getMarketNews(\n params: NewsFeedMarketNewsParams,\n options?: { signal?: AbortSignal },\n ): Promise<NewsFeedMarketNewsResponse> {\n return this.request<NewsFeedMarketNewsResponse>(\"/news-feed/market-news\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n /**\n * Search events or markets by query string. Supports cursor-based pagination.\n *\n * Pass `deep: true` on submit (Enter / Search button) to opt in to the\n * server-side reranker. Leave it off for debounced typeahead — the wire\n * format intentionally omits the param so the server hits the cheaper\n * (and longer-TTL) light cache slot.\n */\n async search<T = VenueEvent>(\n params: SearchParams,\n options?: { signal?: AbortSignal },\n ): Promise<SearchResponse<T>> {\n const query: Record<string, string | string[]> = {\n q: params.q,\n type: params.type,\n };\n if (params.categoryIds && params.categoryIds.length > 0) query.categoryIds = params.categoryIds;\n if (params.status && params.status.length > 0) query.status = params.status;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n // Only send the flag when explicitly true — keeps the wire URL minimal\n // and lets the server's default-false path stay cache-stable across\n // partner SDK versions that pre-date this option.\n if (params.deep) query.deepSearch = \"true\";\n if (params.mode) query.mode = params.mode;\n return this.request<SearchResponse<T>>(\"/search\", {\n query,\n signal: options?.signal,\n });\n }\n\n /** Get Correlated Markets processing and embedding coverage. */\n async getCorrelatedMarketsStatus(options?: {\n signal?: AbortSignal;\n }): Promise<CorrelatedMarketsStatus> {\n return this.request<CorrelatedMarketsStatus>(\"/correlated-markets/status\", {\n signal: options?.signal,\n });\n }\n\n /** Get the generated correlated market signals for a market. */\n async getMarketCorrelatedSignals(\n venueMarketId: string,\n options?: { signal?: AbortSignal; includeResolved?: boolean },\n ): Promise<CorrelatedMarketSignalBatch> {\n const query: Record<string, string> = {};\n if (options?.includeResolved != null) query.includeResolved = String(options.includeResolved);\n return this.request<CorrelatedMarketSignalBatch>(\n `/correlated-markets/${encodeURIComponent(venueMarketId)}`,\n { query, signal: options?.signal },\n );\n }\n\n /** Search markets by Correlated Markets signal similarity. */\n async queryCorrelatedMarkets(\n params: {\n text: string;\n limit?: number;\n includeResolved?: boolean;\n direction?: \"more_likely\" | \"less_likely\";\n balanced?: boolean;\n },\n options?: { signal?: AbortSignal },\n ): Promise<{ results: CorrelatedMarketQueryResult[] }> {\n return this.request<{ results: CorrelatedMarketQueryResult[] }>(\"/correlated-markets/query\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n /** Get expansion and hedge candidates for an already-processed market. */\n async getCorrelatedMarketCascade(\n params: {\n venueMarketId: string;\n side?: \"yes\" | \"no\";\n mode?: \"expand\" | \"hedge\";\n limit?: number;\n cursor?: string;\n includeResolved?: boolean;\n },\n options?: { signal?: AbortSignal },\n ): Promise<CorrelatedMarketCascadeResponse> {\n const query: Record<string, string> = {};\n if (params.side) query.side = params.side;\n if (params.mode) query.mode = params.mode;\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n if (params.includeResolved != null) query.includeResolved = String(params.includeResolved);\n return this.request<CorrelatedMarketCascadeResponse>(\n `/correlated-markets/cascade/${encodeURIComponent(params.venueMarketId)}`,\n { query, signal: options?.signal },\n );\n }\n\n /** Resolve a market by ID, venue identifier, slug, conditionId, or text, then return candidates. */\n async resolveCorrelatedMarkets(\n params: ResolveCorrelatedMarketsParams,\n options?: { signal?: AbortSignal },\n ): Promise<ResolveCorrelatedMarketsResponse> {\n return this.request<ResolveCorrelatedMarketsResponse>(\"/correlated-markets/resolve\", {\n method: \"POST\",\n body: JSON.stringify(params),\n signal: options?.signal,\n });\n }\n\n // --- Chart data ---\n /** Get the canonical TradingView-style bar series for a single venue market outcome. */\n async getChartBars(\n params: {\n venueMarketOutcomeId: string;\n resolution?: ChartResolution;\n from?: number;\n to: number;\n countBack?: number;\n },\n options?: { signal?: AbortSignal; decode?: (payload: string) => Promise<ChartBarsResponse> },\n ): Promise<ChartBarsResponse> {\n const resolution = mapChartResolution(params.resolution);\n\n const query: Record<string, string | string[]> = {\n venueMarketOutcomeId: params.venueMarketOutcomeId,\n to: String(params.to),\n };\n if (resolution) query.resolution = resolution;\n if (params.from != null) query.from = String(params.from);\n if (params.countBack != null) query.countBack = String(params.countBack);\n\n if (options?.decode) {\n // Keep headers, cancellation and auth refresh here; decode after request resolves so a\n // validation error cannot be mistaken for an authentication-refresh failure.\n const text = await this.request<string>(\n \"/charts/bars\",\n { query, signal: options.signal },\n (response) => readChartHistoryText(response),\n );\n options.signal?.throwIfAborted();\n const decoded = await options.decode(text);\n options.signal?.throwIfAborted();\n return decoded;\n }\n return this.request<ChartBarsResponse>(\"/charts/bars\", {\n query,\n signal: options?.signal,\n });\n }\n\n async getChartHistoryManifest(\n params: {\n venueMarketOutcomeId: string;\n resolution?: ChartResolution;\n from?: number;\n to: number;\n countBack?: number;\n },\n options?: { signal?: AbortSignal },\n ): Promise<ChartHistoryManifest> {\n const query: Record<string, string> = {\n venueMarketOutcomeId: params.venueMarketOutcomeId,\n to: String(params.to),\n };\n const resolution = mapChartResolution(params.resolution);\n if (resolution) query.resolution = resolution;\n if (params.from != null) query.from = String(params.from);\n if (params.countBack != null) query.countBack = String(params.countBack);\n return this.request<ChartHistoryManifest>(\"/charts/history/manifest\", {\n query,\n signal: options?.signal,\n });\n }\n\n // --- Batch orderbooks ---\n /** Get live per-venue orderbooks for the explicit venueMarketIds requested. */\n async getOrderbooks(\n params: { venueMarketIds: string[]; depth?: number },\n options?: { signal?: AbortSignal },\n ): Promise<BatchOrderbooksResponse> {\n const query: Record<string, string | string[]> = {\n venueMarketIds: params.venueMarketIds,\n };\n if (params.depth != null) query.depth = String(params.depth);\n\n return this.request<BatchOrderbooksResponse>(\"/orderbooks\", {\n query,\n signal: options?.signal,\n });\n }\n\n /** Get live midpoints for the explicit venueMarketIds requested. */\n async getMidpoints(\n params: { venueMarketIds: string[]; bestPrice?: boolean; maxMidpointIdsPerRequest?: number },\n options?: { signal?: AbortSignal; maxMidpointIdsPerRequest?: number },\n ): Promise<BatchMidpointsResponse>;\n async getMidpoints(\n venueMarketIds: string[],\n options?: { signal?: AbortSignal; bestPrice?: boolean; maxMidpointIdsPerRequest?: number },\n ): Promise<BatchMidpointsResponse>;\n async getMidpoints(\n paramsOrVenueMarketIds:\n | { venueMarketIds: string[]; bestPrice?: boolean; maxMidpointIdsPerRequest?: number }\n | string[],\n options?: { signal?: AbortSignal; bestPrice?: boolean; maxMidpointIdsPerRequest?: number },\n ): Promise<BatchMidpointsResponse> {\n const requestedVenueMarketIds = Array.isArray(paramsOrVenueMarketIds)\n ? paramsOrVenueMarketIds\n : paramsOrVenueMarketIds.venueMarketIds;\n const venueMarketIds = normalizeRequestedVenueMarketIds(requestedVenueMarketIds);\n\n const bestPrice = !Array.isArray(paramsOrVenueMarketIds)\n ? paramsOrVenueMarketIds.bestPrice\n : options?.bestPrice;\n\n const maxMidpointIdsPerRequest = resolveMidpointIdsPerRequest(\n options?.maxMidpointIdsPerRequest ??\n (Array.isArray(paramsOrVenueMarketIds)\n ? undefined\n : paramsOrVenueMarketIds.maxMidpointIdsPerRequest),\n );\n\n const requestBatch = (batchVenueMarketIds: string[]): Promise<BatchMidpointsResponse> => {\n const query: Record<string, string | string[]> = { venueMarketIds: batchVenueMarketIds };\n if (bestPrice) query.bestPrice = \"true\";\n\n return this.request<BatchMidpointsResponse>(\"/midpoints\", {\n query,\n signal: options?.signal,\n });\n };\n\n if (venueMarketIds.length === 0) {\n return { data: [] };\n }\n\n if (venueMarketIds.length <= maxMidpointIdsPerRequest) {\n return requestBatch(venueMarketIds);\n }\n\n const responses = await Promise.all(\n chunkArray(venueMarketIds, maxMidpointIdsPerRequest).map((batch) => requestBatch(batch)),\n );\n return { data: responses.flatMap((response) => response.data) };\n }\n\n /** Get a single outcome-level orderbook from the engine. */\n async getOutcomeOrderbook(\n outcomeId: string,\n options?: { depth?: number; signal?: AbortSignal },\n ): Promise<OutcomeOrderbookResponse | null> {\n const query: Record<string, string> = {};\n if (options?.depth != null) query.depth = String(options.depth);\n\n try {\n return await this.request<OutcomeOrderbookResponse>(`/orderbook/outcome/${outcomeId}`, {\n query,\n signal: options?.signal,\n });\n } catch (err: any) {\n if (err?.status === 404) return null;\n throw err;\n }\n }\n\n // --- Market data / orderbook ---\n\n /**\n * Compute optimal order routing across venues via the MILP solver.\n * Returns a user-scoped quote with per-venue fills and verification timing.\n * Deprecated aliases are accepted for source compatibility during the\n * outcome-level migration window.\n */\n async getSmartRoute(\n params: SmartRouteParams,\n options?: { signal?: AbortSignal },\n ): Promise<SmartRouteResponse> {\n const venueMarketOutcomeId =\n params.venueMarketOutcomeId ?? params.venueMarketId ?? params.outcomeId;\n if (!venueMarketOutcomeId) {\n throw new Error(\"getSmartRoute requires venueMarketOutcomeId\");\n }\n\n const query: Record<string, string | string[]> = {};\n if (params.maxSpend != null) query.maxSpend = String(params.maxSpend);\n if (params.sellShares != null) query.sellShares = String(params.sellShares);\n if (params.chainBalances) query.chainBalances = JSON.stringify(params.chainBalances);\n if (params.slipCapBps != null) query.slipCapBps = String(params.slipCapBps);\n if (params.compareVenues) query.compareVenues = \"true\";\n if (params.allowedVenues?.length) query.allowedVenues = params.allowedVenues.map(String);\n if (params.tradeSide) query.side = params.tradeSide;\n if (params.mode) query.mode = params.mode;\n if (params.deepEstimate) query.deepEstimate = \"true\";\n if (params.appFeeBips != null) query.appFeeBips = String(params.appFeeBips);\n if (params.referrer) query.referrer = params.referrer;\n if (params.referrerFeeBips != null) query.referrerFeeBips = String(params.referrerFeeBips);\n if (params.appFeeBipsByVenue)\n query.appFeeBipsByVenue = JSON.stringify(params.appFeeBipsByVenue);\n if (params.referrerFeeBipsByVenue) {\n query.referrerFeeBipsByVenue = JSON.stringify(params.referrerFeeBipsByVenue);\n }\n if (params.referralPayer) query.referralPayer = params.referralPayer;\n if (params.referralPayerAddress) query.referralPayerAddress = params.referralPayerAddress;\n if (params.referralActivationSponsorAddress) {\n query.referralActivationSponsorAddress = params.referralActivationSponsorAddress;\n }\n\n const response = await this.request<SmartRouteResponse>(\n `/orderbook/${encodeURIComponent(venueMarketOutcomeId)}/route`,\n { query, signal: options?.signal },\n );\n\n return params.side ? { ...response, side: params.side } : response;\n }\n\n /** Seed subscribed outcomes with one bounded batch of compatible snapshots. */\n async getOutcomeOrderbooks(\n params: { venueMarketOutcomeIds: string[]; depth?: number },\n options?: { signal?: AbortSignal },\n ): Promise<{ data: (OutcomeOrderbookResponse | null)[] }> {\n return this.request(\"/orderbooks/outcomes\", {\n query: {\n venueMarketOutcomeIds: params.venueMarketOutcomeIds.join(\",\"),\n ...(params.depth == null ? {} : { depth: String(params.depth) }),\n },\n signal: options?.signal,\n });\n }\n\n /**\n * Create an AggWebSocket instance configured with this client's appId and current auth session.\n * Session changes update this socket until it or the client is destroyed.\n * Requires `wsUrl` to be set in the client options.\n */\n createWebSocket(\n callbacks?: AggWebSocketCallbacks,\n options?: {\n enableLogs?: boolean;\n /**\n * Checks books with no update for 5 minutes against\n * `GET /orderbooks/outcomes` and heals any that drifted. On by default;\n * pass `false` to disable or an object to tune the timings.\n */\n bookWatchdog?: false | Pick<BookWatchdogOptions, \"silenceMs\" | \"checkIntervalMs\">;\n },\n ): AggWebSocket {\n if (!this.wsUrl) {\n throw new Error(\"AggClient.createWebSocket() requires wsUrl to be set in client options\");\n }\n\n const url = new URL(this.wsUrl);\n if (this._appId) url.searchParams.set(\"appId\", this._appId);\n\n const createSocket =\n this.webSocketFactory ?? ((socketOptions) => new AggWebSocket(socketOptions));\n const watchdogHeaders: Record<string, string> = {};\n if (this._appId) watchdogHeaders[\"x-app-id\"] = this._appId;\n if (this.apiKey) watchdogHeaders[\"x-app-api-key\"] = this.apiKey;\n\n const socket = createSocket({\n url: url.toString(),\n callbacks,\n initialToken: this.accessToken,\n enableLogs: options?.enableLogs ?? false,\n bookWatchdog:\n options?.bookWatchdog === false\n ? undefined\n : { baseUrl: this.baseUrl, headers: watchdogHeaders, ...options?.bookWatchdog },\n });\n this.bindWebSocketAuth(socket, callbacks);\n return socket;\n }\n\n private bindWebSocketAuth(socket: AggWebSocket, callbacks?: AggWebSocketCallbacks): void {\n let token = this.accessToken;\n let userId = this.accessTokenUserId;\n let authenticatedUserId: string | undefined;\n let awaitingDisconnect = false;\n let connectRequested = false;\n let manuallyDisconnected = false;\n let currentCallbacks = callbacks ?? {};\n const originalSetCallbacks = socket.setCallbacks;\n const originalConnect = socket.connect;\n const originalDisconnect = socket.disconnect;\n const originalDestroy = socket.destroy;\n\n const canReceiveUserEvent = (eventUserId?: string): boolean =>\n !!this.accessToken &&\n !awaitingDisconnect &&\n authenticatedUserId !== undefined &&\n (this.accessTokenUserId === undefined || authenticatedUserId === this.accessTokenUserId) &&\n (eventUserId === undefined || eventUserId === authenticatedUserId);\n\n const wrapCallbacks = (handlers: AggWebSocketCallbacks): AggWebSocketCallbacks => ({\n ...handlers,\n onConnectionStateChange: (connected) => {\n if (!connected) {\n authenticatedUserId = undefined;\n awaitingDisconnect = false;\n }\n handlers.onConnectionStateChange?.(connected);\n },\n onAuthenticated: (message) => {\n if (\n awaitingDisconnect ||\n !this.accessToken ||\n (this.accessTokenUserId !== undefined && this.accessTokenUserId !== message.userId)\n )\n return;\n authenticatedUserId = message.userId;\n handlers.onAuthenticated?.(message);\n },\n onOrderEvent: (message) => {\n if (canReceiveUserEvent(message.userId)) handlers.onOrderEvent?.(message);\n },\n onOrderEventReceipt: (message) => {\n if (canReceiveUserEvent()) handlers.onOrderEventReceipt?.(message);\n },\n onOrderSubmitted: (message) => {\n if (canReceiveUserEvent()) handlers.onOrderSubmitted?.(message);\n },\n onBalanceUpdate: (message) => {\n if (canReceiveUserEvent()) handlers.onBalanceUpdate?.(message);\n },\n onRedeemEvent: (message) => {\n if (canReceiveUserEvent()) handlers.onRedeemEvent?.(message);\n },\n onWithdrawalLifecycle: (message) => {\n if (canReceiveUserEvent(message.userId)) handlers.onWithdrawalLifecycle?.(message);\n },\n });\n\n socket.setCallbacks = (handlers) => {\n currentCallbacks = handlers;\n originalSetCallbacks.call(socket, wrapCallbacks(handlers));\n };\n socket.setCallbacks(currentCallbacks);\n socket.connect = () => {\n connectRequested = true;\n manuallyDisconnected = false;\n originalConnect.call(socket);\n };\n socket.disconnect = () => {\n connectRequested = false;\n manuallyDisconnected = true;\n originalDisconnect.call(socket);\n };\n\n const unsubscribe = this.onAuthStateChange(() => {\n const nextToken = this.accessToken;\n const nextUserId = this.accessTokenUserId;\n if (token === nextToken && userId === nextUserId) return;\n const resetConnection =\n !nextToken || (!!token && (userId !== nextUserId || nextUserId === undefined));\n token = nextToken;\n userId = nextUserId;\n if (resetConnection) {\n const diagnostics = socket.getDiagnostics();\n const reconnect =\n connectRequested ||\n socket.connected ||\n (!manuallyDisconnected &&\n (diagnostics.orderbookOutcomeIds.length > 0 ||\n diagnostics.tradeOutcomeIds.length > 0 ||\n diagnostics.arbMarketIds.length > 0 ||\n diagnostics.arbFeedSubscribers > 0));\n // The gateway has no deauthenticate frame. Close the old user transport;\n // Worker callbacks already queued are held until its disconnect arrives.\n authenticatedUserId = undefined;\n awaitingDisconnect = true;\n originalDisconnect.call(socket);\n socket.authenticate(nextToken ?? \"\");\n if (reconnect) originalConnect.call(socket);\n } else if (nextToken) {\n // Also replaces the token used on future reconnects and Worker fallback.\n socket.authenticate(nextToken);\n }\n });\n\n const cleanup = () => {\n unsubscribe();\n this.webSocketAuthCleanups.delete(cleanup);\n socket.setCallbacks = originalSetCallbacks;\n socket.connect = originalConnect;\n socket.disconnect = originalDisconnect;\n socket.destroy = originalDestroy;\n socket.setCallbacks(currentCallbacks);\n };\n this.webSocketAuthCleanups.add(cleanup);\n socket.destroy = () => {\n cleanup();\n originalDestroy.call(socket);\n };\n }\n\n /** Execute a previously quoted managed trade. Returns pending order IDs. */\n async executeManaged(params: ExecuteManagedParams): Promise<ExecuteManagedResponse> {\n return this.request<ExecuteManagedResponse>(\"/execution/fill\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Submit signatures for a parked fill. Returns whatever is still outstanding. */\n async submitFillSignatures(\n quoteId: string,\n // Exactly `SubmitSignaturesBody`'s element type: a signed payload carries\n // `signature`, a broadcast one carries `txHash`, and the server 400s in\n // both wrong-field directions.\n signatures: Array<{ stepId: string; signature?: string; txHash?: string }>,\n ): Promise<ExecuteManagedResponse & { accepted?: number }> {\n // Same body as `POST /execution/fill`. `accepted` rides along as a\n // diagnostic extra — the contract's 200 schema doesn't declare it, so it\n // isn't guaranteed present.\n return this.request(`/execution/fill/${encodeURIComponent(quoteId)}/signatures`, {\n method: \"POST\",\n body: JSON.stringify({ signatures }),\n });\n }\n\n /**\n * Execute a quote in self-custodial mode.\n *\n * Identical to `executeManaged` when the server can sign for the user. When\n * it cannot, the DAG parks on a signature request instead — but that park\n * always happens asynchronously, in the trade-executor process, so it can\n * never show up on this `POST /execution/fill` response itself. This\n * drives the round trip from there: poll `getExecutionStatus` while an\n * on-chain step is in flight, sign whatever it hands back with the\n * configured `signer`, post the signatures back, and repeat until the\n * server reports nothing outstanding and the run reaches a terminal state.\n */\n async fillSelfCustody(params: ExecuteManagedParams): Promise<ExecuteManagedResponse> {\n // A configured signer means the partner holds the key. Sending no wallet\n // would silently route this fill to our server wallet instead, so refuse\n // here rather than produce a managed fill the caller did not ask for.\n if (this.signer && !params.signingAddress) {\n throw new Error(\n \"fillSelfCustody requires `signingAddress` — the wallet that will sign this fill.\",\n );\n }\n\n // Inverse config error: a wallet was named but no `signer` was passed to\n // createAggClient(). Checked BEFORE any fetch (final review Ruling\n // R30(b)) — posting the fill first would create real orders, stamp\n // `Order.accountId`, take admission reservations, and — because that\n // column's FK is ON DELETE RESTRICT — permanently pin an\n // un-disconnectable wallet, all for a pure partner configuration\n // mistake.\n if (params.signingAddress && !this.signer) {\n throw new Error(\n \"This fill requires client-side signatures, but no `signer` was passed to createAggClient(). \" +\n \"Provide one to trade in self-custodial mode.\",\n );\n }\n\n const first = await this.executeManaged(params);\n\n // Managed case: no signer configured and no wallet named — ordinary\n // managed custody, which never parks. Whatever the server returned is\n // the whole answer.\n if (!this.signer && !params.signingAddress) return first;\n\n // Both checks above guarantee a signer is configured on every path that\n // reaches here.\n const signer = this.signer!;\n\n // `fallbackToLatest` can resolve to a DIFFERENT quote than the one\n // requested. Resume against whatever quoteId the fill actually landed\n // on — using the caller's original id would 403/404 on every subsequent\n // call.\n const quoteId = first.quoteId;\n\n // `POST /execution/fill` can NEVER carry `pendingSignatures` — the DAG\n // park happens later, once the trade-executor process picks up the run.\n // So an empty/absent list here does not mean \"no signing needed\"; like\n // everywhere else in this loop, it means \"go poll\".\n let pending = first.pendingSignatures ?? [];\n // Guard against a server that keeps handing back the same step: without\n // this a transient backend bug becomes an infinite loop in the partner's app.\n let lastKey = \"\";\n const deadline = Date.now() + SELF_CUSTODY_FILL_TIMEOUT_MS;\n\n // How long to wait before the NEXT status read. The server tells us\n // (`pollAfterMs`); until it has, we are guessing. Because `POST\n // /execution/fill` can never park (see above), the first sleep is spent\n // before this loop has looked even once — so start at the floor. One cheap\n // extra read puts us on the server's advertised grid immediately instead of\n // burning a full hardcoded interval to learn it.\n let nextPollMs = MIN_POLL_INTERVAL_MS;\n\n // An EMPTY pendingSignatures list does NOT mean the fill is finished. A\n // first-time user signs the wallet-setup batch, and the run then spends a\n // few seconds on-chain before parking again for the order. Returning here\n // would report success while the run waits for a signature nobody is going\n // to send — a fill that silently never happens. So an empty list means\n // \"poll\", and only a TERMINAL overallState means \"stop\".\n // Optional requests this call has already declined — rejected by the\n // signer, or expired before we got to them. The server may keep listing\n // one until its TTL; it is never asked for twice and never blocks the fill.\n const declinedOptional = new Set<string>();\n // A Polymarket buy fee pre-sign is prepared independently of the order, so\n // it can be listed before the order prompt exists. Awaiting its signer then\n // would stop this loop polling and hold the order for the whole fee bound.\n // So it is not signed until this call has posted the Polymarket ORDER\n // signature itself: any other required one (auth, setup) can be posted\n // while the order prompt does not exist yet. The order request is the\n // trade-executor's `poly-sign-<orderId>` step; the request carries no other\n // field that names it. One never signed just expires server-side and the\n // fee is asked for after the fill.\n const isOptionalFee = (req: SignatureRequest) => req.optional && req.purpose === \"app_fee\";\n let orderSubmitted = false;\n\n for (;;) {\n pending = pending.filter(\n (p) => !declinedOptional.has(p.stepId) && (orderSubmitted || !isOptionalFee(p)),\n );\n\n // Checked every iteration, not just the poll arm: the no-progress guard\n // below only remembers the immediately preceding round, so a server\n // alternating between two step ids never trips it. The deadline is\n // what actually bounds that case.\n if (Date.now() > deadline) {\n throw new Error(`Fill for quote ${quoteId} did not finish within the timeout.`);\n }\n\n if (pending.length === 0) {\n await new Promise((r) => setTimeout(r, nextPollMs));\n const polled = await this.getExecutionStatus({ quoteId });\n // Follow the server's cadence (`RUNNING_POLL_AFTER_MS`, 1s today)\n // instead of our own guess — expected time-to-discovery for a parked\n // signature is half the poll interval, so this is on the critical path\n // of every self-custody fill. `Number.isFinite` covers all three\n // fall-back cases in one test: `null` on a terminal response,\n // `undefined` from an API old enough not to send the field, and a\n // non-numeric value that would otherwise reach `setTimeout` as NaN\n // (i.e. 0) and busy-loop.\n nextPollMs = Number.isFinite(polled.pollAfterMs)\n ? Math.min(\n Math.max(polled.pollAfterMs as number, MIN_POLL_INTERVAL_MS),\n MAX_POLL_INTERVAL_MS,\n )\n : SELF_CUSTODY_POLL_INTERVAL_MS;\n if (TERMINAL_EXECUTION_STATES.has(polled.overallState)) {\n if (polled.overallState !== \"filled\" && polled.overallState !== \"partially_filled\") {\n throw new Error(`Fill for quote ${quoteId} ended as ${polled.overallState}.`);\n }\n return { ...first, pendingSignatures: [] };\n }\n pending = polled.pendingSignatures ?? [];\n continue;\n }\n\n const key = pending\n .map((p) => p.stepId)\n .sort()\n .join(\",\");\n if (key === lastKey) {\n throw new Error(\n `Fill for quote ${quoteId} did not advance — still awaiting steps [${key}] after signing them.`,\n );\n }\n lastKey = key;\n\n const signatures: Array<{ stepId: string; signature?: string; txHash?: string }> = [];\n // Required first, so the wallet prompts for the order before anything\n // else. Apart from optional fee pre-signs, use one batch: the server reads an\n // optional signature (a referral code, a sponsor) right after the order\n // finalises, so a second round would arrive too late. An optional\n // request signed by a wallet OTHER than the user's (a partner's sponsor)\n // is bounded by OPTIONAL_SIGNATURE_TIMEOUT_MS and then declined; one the\n // user signs (a referral code) waits for the human, as it always has.\n // A buy fee pre-sign is usable after order submission. Submit the other\n // requests first so a slow or declined fee prompt cannot hold the order.\n const round = pending.some((req) => !isOptionalFee(req))\n ? pending.filter((req) => !isOptionalFee(req))\n : pending;\n const ordered = [...round].sort((a, b) => Number(!!a.optional) - Number(!!b.optional));\n const userSigners = new Set(\n [params.signingAddress, ...pending.filter((p) => !p.optional).map((p) => p.signerAddress)]\n .filter((a): a is string => !!a)\n .map((a) => a.toLowerCase()),\n );\n for (const req of ordered) {\n // The server's signature TTL (`DEFAULT_TTL_MS` in the request-signature\n // handler) defaults to 120s — well inside this loop's 5-minute budget,\n // which spans multiple sequential requests, each with its own TTL. A\n // request that is already expired by the time we're about to sign it\n // will be rejected by the server no matter what we post, so fail with\n // a clear message here instead of prompting the wallet and eating an\n // opaque 400 from `submitFillSignatures`.\n if (Date.now() > new Date(req.expiresAt).getTime()) {\n if (req.optional) {\n declinedOptional.add(req.stepId);\n continue;\n }\n throw new Error(\n `Signature request ${req.stepId} for quote ${quoteId} expired at ${req.expiresAt}; ` +\n \"the fill must be re-quoted.\",\n );\n }\n // A `transaction` request is broadcast, not signed, and the server\n // rejects a hash posted in `signature`. Before this branch existed the\n // push was unconditional, which made the user-broadcast funding path\n // unreachable from the SDK.\n let signed: Awaited<ReturnType<typeof signer>>;\n try {\n signed = isOptionalFee(req)\n ? await withTimeout(signer(req), OPTIONAL_FEE_SIGNATURE_TIMEOUT_MS)\n : req.optional && !userSigners.has(req.signerAddress?.toLowerCase())\n ? await withTimeout(signer(req), OPTIONAL_SIGNATURE_TIMEOUT_MS)\n : await signer(req);\n } catch (err) {\n // An optional request (e.g. a partner referral) must never cost the\n // user the trade parked beside it: skip it and post the rest.\n if (!req.optional) throw err;\n declinedOptional.add(req.stepId);\n continue;\n }\n signatures.push(\n typeof signed === \"string\"\n ? { stepId: req.stepId, signature: signed }\n : { stepId: req.stepId, txHash: signed.txHash },\n );\n }\n\n if (signatures.length === 0) {\n // Everything in this round was an optional request we declined.\n pending = [];\n continue;\n }\n const next = await this.submitFillSignatures(quoteId, signatures);\n if (signatures.some((s) => s.stepId.startsWith(PM_ORDER_SIGNATURE_STEP_PREFIX)))\n orderSubmitted = true;\n pending = next.pendingSignatures ?? [];\n }\n }\n\n /**\n * Enqueue a limit order. For self-custody, poll getExecutionStatus with the\n * returned quoteId and answer pending requests through submitFillSignatures.\n * A pending response does not mean the order has reached the venue.\n */\n async placeLimitOrder(params: PlaceLimitOrderParams): Promise<PlaceLimitOrderResponse> {\n return this.request<PlaceLimitOrderResponse>(\"/execution/limit-orders\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /**\n * Place a market order directly on a named venue — no prior quote needed.\n * Always produces exactly one order. `externalId` is required and unique\n * within your app — two different users of the same app cannot share one —\n * so retrying a timed-out call with the same value is safe.\n */\n async placeOrder(params: PlaceOrderParams): Promise<PlaceOrderResponse> {\n return this.request<PlaceOrderResponse>(\"/execution/orders\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Redeem resolved winning positions by venue market outcome ids. */\n async redeem(body: RedeemRequest): Promise<RedeemResponse> {\n return this.request<RedeemResponse>(\"/execution/redeem\", {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n }\n\n /** List the authenticated user's managed balance refill policies. */\n async getBalanceRefillPolicies(): Promise<BalanceRefillPolicy[]> {\n return this.request<BalanceRefillPolicy[]>(\"/execution/balance-refill-policies\");\n }\n\n /** Create a managed-USDC refill policy for a target chain. */\n async createBalanceRefillPolicy(\n params: CreateBalanceRefillPolicyParams,\n ): Promise<BalanceRefillPolicy> {\n return this.request<BalanceRefillPolicy>(\"/execution/balance-refill-policies\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Update thresholds or pause/resume an existing balance refill policy. */\n async updateBalanceRefillPolicy(\n policyId: string,\n params: UpdateBalanceRefillPolicyParams,\n ): Promise<BalanceRefillPolicy> {\n if (!policyId) throw new Error(\"policyId is required\");\n return this.request<BalanceRefillPolicy>(\n `/execution/balance-refill-policies/${encodeURIComponent(policyId)}`,\n { method: \"PATCH\", body: JSON.stringify(params) },\n );\n }\n\n /** Return the 25 most recent attempts for a refill policy. */\n async getBalanceRefillAttempts(policyId: string): Promise<BalanceRefillAttempt[]> {\n if (!policyId) throw new Error(\"policyId is required\");\n return this.request<BalanceRefillAttempt[]>(\n `/execution/balance-refill-policies/${encodeURIComponent(policyId)}/attempts`,\n );\n }\n\n /** Withdraw funds from managed wallets to an external address. */\n async withdrawManaged(params: WithdrawManagedParams): Promise<WithdrawManagedResponse> {\n return this.request<WithdrawManagedResponse>(\"/execution/withdraw\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /**\n * Preview a withdrawal — real fee + receive estimate without creating one.\n * Optional: `withdrawManaged` does NOT require a prior preview, so partners\n * integrating against the SDK can ignore this entirely.\n */\n async withdrawPreview(params: WithdrawPreviewParams): Promise<WithdrawPreviewResponse> {\n return this.request<WithdrawPreviewResponse>(\"/execution/withdraw/preview\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Quote maximum deliverable withdrawal amount for a token and destination chain. */\n async getWithdrawalQuote(params: WithdrawalQuoteParams): Promise<WithdrawalQuoteResponse> {\n return this.request<WithdrawalQuoteResponse>(\"/execution/withdrawable/quote\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /**\n * Read the current persisted state of a withdrawal. Used as a backfill for\n * the WS lifecycle channel: the client polls this on hook mount and on WS\n * reconnect to recover events that fired before the listener was attached\n * or while the socket was disconnected. Same response shape as\n * `withdrawManaged`.\n */\n async getWithdrawalStatus(withdrawalId: string): Promise<WithdrawManagedResponse> {\n if (!withdrawalId) {\n throw new Error(\"withdrawalId is required\");\n }\n return this.request<WithdrawManagedResponse>(\n `/execution/withdrawals/${encodeURIComponent(withdrawalId)}`,\n );\n }\n\n /** Trigger an on-chain balance sync for all tracked tokens across all chains. */\n async syncManagedBalances(): Promise<SyncBalancesResponse> {\n return this.request<SyncBalancesResponse>(\"/execution/sync-balances\", {\n method: \"POST\",\n body: JSON.stringify({}),\n });\n }\n\n /** Get managed wallet deposit addresses (EVM + Solana). Returns 202 shape while provisioning. */\n async getDepositAddresses(options?: { signal?: AbortSignal }): Promise<DepositAddressesResponse> {\n return this.request<DepositAddressesResponse>(\"/execution/deposit-addresses\", {\n signal: options?.signal,\n });\n }\n\n /**\n * Internal: record that a deposit tx was initiated via the in-app\n * connected-wallet flow, so the activity feed can label it correctly.\n * Best-effort — callers should not block the UX on this.\n */\n async recordDepositIntent(body: { chainId: number; txHash: string }): Promise<void> {\n await this.request<{ success: true }>(\n \"/execution/deposit-intent\",\n this.buildAuthRequestInit({ method: \"POST\", body: JSON.stringify(body) }),\n );\n }\n\n /** Get open positions grouped by matched market with per-venue breakdown. */\n async getPositions(\n params?: GetPositionsParams,\n options?: { signal?: AbortSignal },\n ): Promise<PaginatedResponse<PositionGroup>> {\n const query: Record<string, string | string[]> = {};\n if (params?.cursor) query.cursor = params.cursor;\n if (params?.limit != null) query.limit = String(params.limit);\n if (params?.status) query.status = params.status;\n if (params?.mode) query.mode = params.mode;\n if (params?.categoryIds?.length) query.categoryIds = params.categoryIds;\n if (params?.sort) query.sort = params.sort;\n return this.request<PaginatedResponse<PositionGroup>>(\"/execution/positions\", {\n query: Object.keys(query).length > 0 ? query : undefined,\n signal: options?.signal,\n });\n }\n\n // --- Ramp ---\n\n /** Get crypto purchase quotes. */\n async getRampQuotes(params: RampQuoteRequest): Promise<RampQuote[]> {\n return this.request<RampQuote[]>(\"/ramp/quotes\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Create a ramp widget session for checkout. */\n async createRampSession(params: RampSessionRequest): Promise<RampWidgetSession> {\n return this.request<RampWidgetSession>(\"/ramp/session\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n /** Authoritative shared Novig/ProphetX KYC status for the current managed wallet. */\n async getSharedKycStatus(): Promise<{ verified: boolean }> {\n return this.request<{ verified: boolean }>(\"/kyc/status\");\n }\n\n /** Start shared KYC; already-verified wallets need no redirect. Kalshi v2 is not applicable. */\n async initiateKyc(\n venue: string,\n redirectUri: string,\n ): Promise<{ status: string; kycUrl?: string }> {\n return this.request<{ status: string; kycUrl?: string }>(`/kyc/${venue}`, {\n method: \"POST\",\n body: JSON.stringify({ redirectUri }),\n });\n }\n}\n","import { computeBestSplitsByAmount as computeBestSplitsByAmountFromCommon } from \"@agg/common/types-only\";\n\nexport type { SplitsByAmountResult } from \"@agg/common/types-only\";\n\nexport const computeBestSplitsByAmount = computeBestSplitsByAmountFromCommon;\n","import type { Candle } from \"./candle-builder\";\n\n/**\n * Merge forming candles from matched venues into one aggregate.\n * Open/Close: volume-weighted average (simple average if all v=0).\n * High: max across venues. Low: min across venues. Volume: sum.\n */\nexport function mergeCandles(candles: (Candle | null | undefined)[]): Candle | null {\n const valid = candles.filter((c): c is Candle => c != null);\n if (valid.length === 0) return null;\n if (valid.length === 1) return { ...valid[0] };\n\n const totalVolume = valid.reduce((sum, c) => sum + c.v, 0);\n\n let o: number;\n let c: number;\n if (totalVolume > 0) {\n o = valid.reduce((sum, candle) => sum + candle.o * candle.v, 0) / totalVolume;\n c = valid.reduce((sum, candle) => sum + candle.c * candle.v, 0) / totalVolume;\n } else {\n o = valid.reduce((sum, candle) => sum + candle.o, 0) / valid.length;\n c = valid.reduce((sum, candle) => sum + candle.c, 0) / valid.length;\n }\n\n return {\n openTime: valid[0].openTime,\n o,\n h: Math.max(...valid.map((candle) => candle.h)),\n l: Math.min(...valid.map((candle) => candle.l)),\n c,\n v: totalVolume,\n tradeCount: valid.reduce((sum, candle) => sum + candle.tradeCount, 0),\n isFinal: valid.every((candle) => candle.isFinal),\n };\n}\n\n/**\n * Merge arrays of closed candles from multiple venues, aligned by openTime.\n * For each openTime present in ANY venue, produces one merged candle.\n */\nexport function mergeClosedCandles(candleArrays: Candle[][]): Candle[] {\n const byTime = new Map<number, Candle[]>();\n\n for (const arr of candleArrays) {\n for (const candle of arr) {\n const group = byTime.get(candle.openTime);\n if (group) {\n group.push(candle);\n } else {\n byTime.set(candle.openTime, [candle]);\n }\n }\n }\n\n const merged: Candle[] = [];\n for (const [, group] of byTime) {\n const result = mergeCandles(group);\n if (result) merged.push(result);\n }\n\n merged.sort((a, b) => a.openTime - b.openTime);\n return merged;\n}\n\n/** Simple average of available midpoints. */\nexport function aggregateMidpoint(midpoints: (number | null | undefined)[]): number | null {\n const valid = midpoints.filter((m): m is number => m != null && Number.isFinite(m));\n if (valid.length === 0) return null;\n return valid.reduce((sum, m) => sum + m, 0) / valid.length;\n}\n","import { Venue, type HostedVenueAccount } from \"@agg/common\";\nimport type { AggClient } from \"./client\";\nimport type { SmartRouteResponse, WithdrawManagedParams, WithdrawManagedResponse } from \"./types\";\n\n/** An exact transfer intent survives a page reload before its response arrives.\n * The normal withdrawal service owns dispatch, bridging and reconciliation. */\nexport interface HostedVenueFundingIntent {\n version: 1;\n accountId: string;\n environment: \"production\";\n request: WithdrawManagedParams & { requestId: string };\n balanceBeforeRaw: string;\n estimatedFeeRaw: string;\n withdrawalId?: string;\n terminal?: boolean;\n}\n\nexport interface HostedVenueFundingOptions {\n venue: \"betdex\";\n requiredRaw: string;\n /** Scope this store to the current application/user/venue. */\n journal: {\n load(): HostedVenueFundingIntent | null;\n save(intent: HostedVenueFundingIntent | null): void;\n };\n createRequestId(): string;\n /** Called around every await and before every write. Abort on sign-out/user change. */\n assertActive(): void;\n onProgress?: (phase: \"preparing\" | \"transferring\" | \"confirming\") => void;\n timeoutMs?: number;\n}\n\ntype FundingClient = Pick<\n AggClient,\n | \"getHostedVenueAccount\"\n | \"provisionHostedVenueAccount\"\n | \"getHostedVenueDepositAddress\"\n | \"withdrawPreview\"\n | \"withdrawManaged\"\n | \"getWithdrawalStatus\"\n>;\n\nconst SOLANA = 792703809;\nconst atoms = (value: string): bigint => {\n if (!/^(0|[1-9][0-9]{0,31})$/.test(value)) throw new Error(\"Invalid funding amount\");\n return BigInt(value);\n};\nconst spendable = (account: HostedVenueAccount): bigint => {\n if (\n account.status !== \"active\" ||\n !account.accountId ||\n account.environment !== \"production\" ||\n account.balanceStatus !== \"available\" ||\n !account.balance ||\n account.balance.asset !== \"USDC\" ||\n account.balance.decimals !== 6\n )\n throw new Error(\"Venue balance is temporarily unavailable. Please try again.\");\n return atoms(account.balance.availableRaw);\n};\nconst terminal = (status: WithdrawManagedResponse[\"status\"]) =>\n status === \"completed\" || status === \"partial\" || status === \"failed\";\n\n/** Prepare the cash required by an order using the existing managed transfer\n * planner. It selects same-chain cash or bridges supported wallet sources to\n * the user's verified venue address. No venue order is placed here: callers\n * obtain a fresh executable quote after native credit and keep their normal\n * slippage, admission and fill workflow.\n *\n * The currently supported hosted-account API is BETDEX; future hosted venues\n * use the same account/deposit contract and this transfer lifecycle. On-chain\n * venues retain their existing execution-DAG funding.\n */\nexport async function prepareHostedVenueFunding(\n client: FundingClient,\n options: HostedVenueFundingOptions,\n): Promise<{ availableRaw: string; feeRaw: string; withdrawalId?: string }> {\n const { venue, journal, assertActive } = options;\n const required = atoms(options.requiredRaw);\n if (required <= BigInt(0)) throw new Error(\"Invalid funding amount\");\n const deadline = Date.now() + (options.timeoutMs ?? 300_000);\n const check = () => {\n assertActive();\n if (Date.now() >= deadline)\n throw new Error(\"Funding is still confirming. Your transfer is saved; retry to resume it.\");\n };\n const read = async <T>(operation: () => Promise<T>): Promise<T> => {\n check();\n const result = await operation();\n check();\n return result;\n };\n const pause = () => read(() => new Promise<void>((resolve) => setTimeout(resolve, 1000)));\n const save = (intent: HostedVenueFundingIntent | null) => {\n check();\n journal.save(intent);\n };\n options.onProgress?.(\"preparing\");\n let account = await read(() => client.getHostedVenueAccount(venue, { mode: \"live\" }));\n if (account.environment !== \"production\")\n throw new Error(\"This venue account does not accept live wallet transfers.\");\n if (account.status === \"not_created\" && account.provisioningEnabled) {\n account = await read(() => client.provisionHostedVenueAccount(venue, { mode: \"live\" }));\n }\n while (account.status === \"provisioning\") {\n await pause();\n account = await read(() => client.getHostedVenueAccount(venue, { mode: \"live\" }));\n }\n const before = spendable(account);\n let intent = journal.load();\n if (intent?.terminal) {\n // Only a new explicit order attempt reaches here; the prior intent has a\n // persisted terminal result. Never discard an ambiguous in-flight intent.\n save(null);\n intent = null;\n }\n if (!intent && before >= required) return { availableRaw: before.toString(), feeRaw: \"0\" };\n const address = await read(() => client.getHostedVenueDepositAddress(venue, { mode: \"live\" }));\n if (\n address.accountId !== account.accountId ||\n address.environment !== account.environment ||\n address.network !== \"solana\" ||\n address.asset !== \"USDC\" ||\n !/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address.address)\n )\n throw new Error(\"Venue funding address changed. Refresh and try again.\");\n if (intent) {\n if (\n intent.version !== 1 ||\n intent.accountId !== account.accountId ||\n intent.environment !== \"production\" ||\n intent.request.destinationAddress !== address.address ||\n intent.request.destinationChainId !== SOLANA ||\n intent.request.tokenSymbol !== \"USDC\" ||\n !intent.request.requestId ||\n intent.request.max ||\n atoms(intent.request.amountRaw) <= BigInt(0) ||\n atoms(intent.balanceBeforeRaw) < BigInt(0) ||\n atoms(intent.estimatedFeeRaw) < BigInt(0)\n )\n throw new Error(\"Saved funding does not match this account. No new transfer was sent.\");\n } else {\n // The shared transfer API's actual minimum is one token. Any excess stays\n // in this user's own cash account, never becomes extra order spend.\n const deficit = required - before;\n const amountRaw = (deficit < BigInt(1_000_000) ? BigInt(1_000_000) : deficit).toString();\n const request = {\n requestId: options.createRequestId(),\n amountRaw,\n tokenSymbol: \"USDC\" as const,\n destinationAddress: address.address,\n destinationChainId: SOLANA,\n };\n const preview = await read(() => client.withdrawPreview(request));\n if (\n preview.pricingStatus !== \"quoted\" ||\n !preview.receiveAmountRaw ||\n atoms(preview.receiveAmountRaw) <= BigInt(0)\n )\n throw new Error(preview.unviableReason ?? \"No funding route is currently available.\");\n intent = {\n version: 1,\n accountId: account.accountId!,\n environment: \"production\",\n request,\n balanceBeforeRaw: before.toString(),\n estimatedFeeRaw: preview.feeRaw ?? \"0\",\n };\n // Save before mutation. Storage failure or a lost response cannot create\n // a second transfer: the same requestId is replayed at the server.\n save(intent);\n }\n options.onProgress?.(\"transferring\");\n let transfer = intent.withdrawalId\n ? await read(() => client.getWithdrawalStatus(intent!.withdrawalId!))\n : await read(() => client.withdrawManaged(intent!.request));\n const assertTransfer = () => {\n if (\n transfer.requested.amountRaw !== intent!.request.amountRaw ||\n transfer.requested.tokenSymbol !== \"USDC\" ||\n transfer.destination.chainId !== SOLANA ||\n transfer.destination.address !== address.address ||\n transfer.destination.tokenSymbol !== \"USDC\" ||\n (intent!.withdrawalId && transfer.withdrawalId !== intent!.withdrawalId)\n )\n throw new Error(\"Funding response does not match the saved transfer.\");\n };\n assertTransfer();\n intent = { ...intent, withdrawalId: transfer.withdrawalId };\n save(intent);\n while (!terminal(transfer.status)) {\n await pause();\n transfer = await read(() => client.getWithdrawalStatus(intent!.withdrawalId!));\n assertTransfer();\n }\n if (transfer.status === \"failed\") {\n save({ ...intent, terminal: true });\n throw new Error(transfer.errorMessage ?? \"Funding could not complete. No order was placed.\");\n }\n options.onProgress?.(\"confirming\");\n // A chain/bridge acknowledgement is not native credit. Re-read the owned\n // venue balance; cached values expire on the normal account query interval.\n let available = before;\n while (available <= atoms(intent.balanceBeforeRaw)) {\n await pause();\n const current = await read(() => client.getHostedVenueAccount(venue, { mode: \"live\" }));\n if (current.accountId !== account.accountId || current.environment !== account.environment)\n throw new Error(\"Venue account changed while funding. No order was placed.\");\n available = spendable(current);\n }\n const fee = atoms(transfer.expected.feeRaw ?? intent.estimatedFeeRaw);\n save(null);\n return {\n availableRaw: available.toString(),\n feeRaw: fee.toString(),\n withdrawalId: transfer.withdrawalId,\n };\n}\n\n/** Keep the normal priced order flow after preparing native cash. Requotes\n * may use only the outcomes the user selected, within the accepted price and\n * total spend. Transfer fees reduce order spend rather than increasing it. */\nexport async function prepareHostedVenueRoute(\n client: FundingClient & Pick<AggClient, \"getSmartRoute\">,\n options: Omit<HostedVenueFundingOptions, \"requiredRaw\"> & {\n quote: SmartRouteResponse;\n venueMarketOutcomeId: string;\n maxSpend: number;\n slipCapBps: number;\n },\n): Promise<SmartRouteResponse> {\n const fills = options.quote.fills;\n const native = fills.filter((fill) => fill.venue === options.venue);\n const required = native.reduce((sum, fill) => sum + fill.avgPrice * fill.venueQty, 0);\n if (\n !native.length ||\n !Number.isFinite(required) ||\n required <= 0 ||\n !Number.isFinite(options.maxSpend) ||\n options.maxSpend <= 0 ||\n !Number.isFinite(options.slipCapBps) ||\n options.slipCapBps < 0\n )\n throw new Error(\"An available order quote is required before funding.\");\n const funding = await prepareHostedVenueFunding(client, {\n ...options,\n requiredRaw: Math.ceil(required * 1e6).toString(),\n });\n options.assertActive();\n const originalBudget = BigInt(Math.floor(options.maxSpend * 1e6));\n let budget = originalBudget - atoms(funding.feeRaw);\n if (native.length === fills.length) {\n const available = atoms(funding.availableRaw);\n if (available < budget) budget = available;\n }\n if (budget <= BigInt(0))\n throw new Error(\"Funding fees exceeded the order amount. No order was placed.\");\n const venues = [...new Set(fills.map((fill) => fill.venue))];\n const allowedVenues = venues.filter((value): value is Venue =>\n Object.values(Venue).some((venue) => venue === value),\n );\n if (allowedVenues.length !== venues.length) throw new Error(\"Unknown venue in funding quote\");\n const quote = await client.getSmartRoute({\n venueMarketOutcomeId: options.venueMarketOutcomeId,\n maxSpend: Number(budget) / 1e6,\n tradeSide: \"buy\",\n compareVenues: false,\n allowedVenues,\n slipCapBps: options.slipCapBps,\n });\n options.assertActive();\n if (quote.status !== \"ok\" || !quote.quoteId || !quote.fills.length)\n throw new Error(quote.error ?? \"Funds are ready. Refresh the quote and try again.\");\n for (const fill of quote.fills) {\n const original = fills.find(\n (item) =>\n item.venue === fill.venue &&\n item.venueMarketId === fill.venueMarketId &&\n item.venueMarketOutcomeId === fill.venueMarketOutcomeId,\n );\n if (\n !original ||\n !Number.isFinite(fill.avgPrice) ||\n fill.avgPrice <= 0 ||\n fill.avgPrice > original.avgPrice * (1 + options.slipCapBps / 10000) + 1e-9\n )\n throw new Error(\"The price changed while funding. Funds are ready; review the new quote.\");\n }\n if (!Number.isFinite(quote.rawExecCost) || quote.rawExecCost * 1e6 > Number(budget) + 1)\n throw new Error(\"The new quote exceeds the order amount. No order was placed.\");\n return quote;\n}\n","import { AggClient } from \"./client\";\nimport type { AggClientOptions } from \"./types\";\n\nexport { AggWebSocket } from \"./agg-websocket\";\nexport type {\n AggWebSocketCallbacks,\n AggWebSocketOptions,\n AggWebSocketDiagnostics,\n BookWatchdogOptions,\n} from \"./agg-websocket\";\nexport { computeBestSplitsByAmount } from \"./best-split\";\nexport type { SplitsByAmountResult } from \"./best-split\";\nexport { applyOrderbookDelta, computeChecksum, snapshotToOrderbook } from \"./orderbook-utils\";\nexport type { OrderbookLevel, OrderbookState, VenueOrderbookLevel } from \"./orderbook-utils\";\nexport { RECURRENCE_CADENCES } from \"./types\";\nexport {\n OPTIONAL_SIGNATURE_TIMEOUT_MS,\n SELF_CUSTODY_FILL_TIMEOUT_MS,\n SELF_CUSTODY_POLL_INTERVAL_MS,\n TERMINAL_EXECUTION_STATES,\n} from \"./types\";\nexport type { SignatureRequest, SignatureRequestType, SignerFn } from \"./types\";\nexport {\n adjustLimitPriceRawToTick,\n LIMIT_PRICE_RAW_SCALE,\n type LimitPriceSide,\n type LimitPriceTickAdjustment,\n} from \"@agg/common\";\nexport type {\n AggAuthPrivyVerifyBody,\n AggAuthVerifyBody,\n AggAuthWalletVerifyBody,\n AggClientAuthOptions,\n AggClientOptions,\n AggAuthDeliveryMode,\n AggAuthProviderType,\n AggAuthStartBody,\n AggAuthStartResult,\n AggLinkAccountBody,\n AggLinkAccountConfirmResult,\n AggLinkAccountResult,\n AggLinkAccountWalletConfirmBody,\n AggClientSessionInput,\n AggregatedOrderbookLevel,\n AggregatedOrderbookResponse,\n AggSessionUser,\n AuthStatus,\n BatchMidpointsResponse,\n BatchOrderbooksResponse,\n BalanceRefillAttempt,\n BalanceRefillAttemptStatus,\n BalanceRefillPolicy,\n BalanceRefillPolicyStatus,\n CancelManagedExecutionResponse,\n ChartBarsResponse,\n ChartBarsMeta,\n ChartCandle,\n ChartResolution,\n ChartVenueCandles,\n CorrelatedMarketCascadeItem,\n CorrelatedMarketCascadeResponse,\n CorrelatedMarketQueryResult,\n CorrelatedMarketsStatus,\n CorrelatedMarketSide,\n CorrelatedMarketSignal,\n CorrelatedMarketSignalBatch,\n CorrelatedMarketSignalDirection,\n CreateBalanceRefillPolicyParams,\n CryptoReferencePriceError,\n CryptoReferencePriceExternalMarketInput,\n CryptoReferencePriceMarketInput,\n CryptoReferencePricesResponse,\n CryptoReferencePriceResult,\n CryptoReferencePriceSource,\n CryptoReferencePriceTarget,\n DepositAddressesPendingResponse,\n DepositAddressesReadyResponse,\n DepositAddressesResponse,\n DepositAddressesSupportedChain,\n DepositAddressesToken,\n ExecuteManagedParams,\n ExecuteManagedResponse,\n ExecutionOrderItem,\n ExecutionMode,\n ExecutionOrdersQuery,\n ExecutionDagProgress,\n ExecutionOverallState,\n ExecutionStatusOrder,\n ExecutionStatusQuery,\n ExecutionStatusResponse,\n ExecutionStatusStep,\n ExecutionDisplayStepKind,\n ExecutionDisplayGroupStatus,\n UserActivityBridge,\n UserActivityDeposit,\n UserActivityItem,\n UserActivityQuery,\n UserActivityRedeem,\n UserActivityRedeemLeg,\n UserActivityTrade,\n UserActivityType,\n UserActivityUserOp,\n UserActivityWithdrawal,\n LeaderboardMetric,\n LeaderboardQuery,\n LeaderboardRow,\n LeaderboardSeries,\n LeaderboardSeriesPoint,\n LeaderboardSeriesQuery,\n LeaderboardStats,\n ExecutionPositionGroup,\n ExecutionPositionsQuery,\n GetOrdersParams,\n GetCryptoReferencePricesOptions,\n GetPositionsParams,\n LimitOrderTimeInForce,\n ListRecurringCryptoMarketsOptions,\n NewsFeedArticleFeedItem,\n NewsFeedArticleFeedResponse,\n NewsFeedArticleWithSummary,\n NewsFeedLinkedMarket,\n NewsFeedListResponse,\n NewsFeedMarketFeedArticle,\n NewsFeedMarketFeedItem,\n NewsFeedMarketFeedResponse,\n NewsFeedMarketNewsParams,\n NewsFeedMarketNewsResponse,\n NewsFeedMarketNewsResult,\n NewsFeedPageOptions,\n NewsFeedStatusResponse,\n OrderbookQuoteFill,\n OrderbookBatchItemError,\n OrderbookBatchItemErrorCode,\n OrderbookBatchItemStatus,\n OrderbookQuoteParams,\n OrderbookQuoteResponse,\n OrderbookServiceUnavailableError,\n OrderbooksOnlyError,\n OrderListQuery,\n PaginatedResponse,\n CreatePaperTradingAccountParams,\n PaperTradingAccount,\n PaperTradingAccountsPage,\n PaperTradingAppOptions,\n PaperTradingBalanceAdjustment,\n PaperTradingBalanceResponse,\n PaperTradingLiquidityStatus,\n PaperTradingListParams,\n PaperTradingMarkSource,\n PaperTradingOrder,\n PaperTradingOrdersPage,\n PaperTradingPortfolio,\n PaperTradingPosition,\n PaperTradingPositionsPage,\n PlaceLimitOrderParams,\n CancelOrderSignature,\n CancelVenueOrderParams,\n PlaceLimitOrderResponse,\n PlacePaperTradingOrderParams,\n PositionRedeemStatus,\n PersistedAuthSnapshot,\n RedeemLegResult,\n RedeemLegStatus,\n RedeemRequest,\n RecurrenceCadence,\n RecurrenceFilter,\n RecurringCryptoDuration,\n RecurringCryptoDurationInput,\n RecurringCryptoComparisonPoint,\n RecurringCryptoComparisonPriceSource,\n RecurringCryptoMarketMetrics,\n RecurringCryptoMarketsResponse,\n RecurringCryptoOutcome,\n RecurringCryptoOrderbookDepthLevel,\n RecurringCryptoOrderbookDepthSide,\n RecurringCryptoOutcomeOrderbookDepth,\n RecurringCryptoPriceComparison,\n RecurringCryptoReferencePrice,\n RecurringCryptoResolution,\n RecurringCryptoSourceConfidence,\n RecurringCryptoVenueMarket,\n RecurringCryptoWindowComparisons,\n RecurringCryptoWindowMarket,\n RedeemResponse,\n ResetPaperTradingAccountParams,\n ResolveCorrelatedMarketsParams,\n ResolveCorrelatedMarketsResponse,\n ResolvedCorrelatedMarketsResponse,\n RequestedOrderbookMarket,\n SimpleOrderbookLevel,\n SmartRouteAllocation,\n SmartRouteBridgeStep,\n SmartRouteFeeBreakdown,\n SmartRouteFill,\n SmartRouteParams,\n SmartRouteResponse,\n SmartRouteSettlementLeg,\n SmartRouteSettlementPlan,\n SmartRouteSetupCostLine,\n SmartRouteSide,\n SmartRouteStatus,\n SportsGameStatus,\n SportsLiveParticipant,\n SportsLiveResponse,\n SportsLiveState,\n SmartRouteVenueFill,\n TradeExecutorOrder,\n TradeExecutorOrderListResponse,\n UpdateBalanceRefillPolicyParams,\n SetPaperTradingBalanceParams,\n MidpointRow,\n OutcomeMidpointRow,\n OutcomeOrderbookResponse,\n ValidateManagedParams,\n ValidateManagedResponse,\n ManagedBalancesParams,\n BalanceCustody,\n MarkSource,\n MatchedOrderbookMarket,\n VenueMarketRef,\n VenueOrderbookEntry,\n VenuePriceInfo,\n VenueSoloQuote,\n WithdrawManagedParams,\n WithdrawManagedResponse,\n WithdrawManagedSourceItem,\n WithdrawalSourceTokenSymbol,\n WithdrawalQuoteParams,\n WithdrawalQuoteResponse,\n WithdrawPreviewParams,\n WithdrawPreviewResponse,\n WithdrawTokenSymbol,\n WithdrawalLifecycleStatus,\n WithdrawalSourceStatus,\n WithdrawalLegType,\n WithdrawalLegStatus,\n WithdrawalLeg,\n WithdrawalExpected,\n RampQuoteRequest,\n RampQuote,\n RampSessionRequest,\n RampWidgetSession,\n RpcTokenResponse,\n} from \"./types\";\nexport { AggClient };\nexport { AggApiError, isAggApiError, TurnstileChallengeError } from \"./errors\";\nexport type {\n HostedVenueAccount,\n HostedVenueBalance,\n HostedVenueActivity,\n HostedVenueActivityCode,\n HostedVenueActivityQuery,\n HostedVenueDepositAddress,\n HostedVenueWithdrawal,\n HostedVenueWithdrawalRequest,\n ProvisionHostedVenueAccountBody,\n} from \"@agg/common/types-only\";\nexport type { AggApiErrorInit, AggRateLimitResponse, AggApiFieldError } from \"./errors\";\n\n// WS types — re-export all for partner usage\nexport type {\n DiagnosticCallback,\n DiagnosticEvent,\n WsArbFeedBatch,\n WsArbFeedEntry,\n WsArbMarketUpdate,\n WsAttributedLevel,\n WsAuthenticated,\n WsBalanceUpdate,\n WsCandleInterval,\n WsClientMessage,\n WsConnected,\n WsError,\n WsHeartbeat,\n WsMarketResolved,\n WsMarkSource,\n WsOrderbookDelta,\n WsOrderbookSnapshot,\n WsOrderEvent,\n WsOrderEventType,\n WsRedeemEvent,\n WsOrderSubmitted,\n WsServerMessage,\n WsSubscribed,\n WsTrade,\n WsUnsubscribed,\n WsVenueBook,\n WsVenueInfo,\n WsVenueLevel,\n WsWithdrawalLegStatus,\n WsWithdrawalLifecycleEvent,\n WsWithdrawalLifecycleLeg,\n WsWithdrawalLifecycleStatus,\n} from \"./ws-types\";\n\n// Candle computation (chart-library-agnostic)\nexport { CandleBuilder } from \"./candle-builder\";\nexport { toChecksumAddress } from \"./eip55\";\nexport type { Candle, CandleInterval } from \"./candle-builder\";\nexport { aggregateMidpoint, mergeCandles, mergeClosedCandles } from \"./market-aggregator\";\n\nexport function createAggClient(options: AggClientOptions) {\n return new AggClient(options);\n}\n\nexport * from \"@agg/common/types-only\";\nexport type {\n AppClientConfigResponse,\n AppTradingMode,\n VenueGeoPolicyEntry,\n VenueGeoPolicyResponse,\n} from \"./types\";\n\nexport type {\n MarketView,\n MarketViewBatch,\n CandleTail,\n HistoryRangeRequest,\n} from \"./market-data/engine\";\n\nexport { loadImmutableHistory } from \"./market-history\";\nexport type { LoadImmutableHistoryOptions } from \"./market-history\";\nexport type {\n EventBootstrapResponse,\n ChartHistoryManifest,\n SearchParams,\n SearchResponse,\n} from \"./types\";\n\nexport { prepareHostedVenueFunding, prepareHostedVenueRoute } from \"./hosted-venue-funding\";\nexport type { HostedVenueFundingIntent, HostedVenueFundingOptions } from \"./hosted-venue-funding\";\n"],"mappings":"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"}
|