// Code generated by protoc-gen-ts-server. DO NOT EDIT.
// source: worldmonitor/market/v1/service.proto

export interface ListMarketQuotesRequest {
  symbols: string[];
}

export interface ListMarketQuotesResponse {
  quotes: MarketQuote[];
  finnhubSkipped: boolean;
  skipReason: string;
  rateLimited: boolean;
}

export interface MarketQuote {
  symbol: string;
  name: string;
  display: string;
  price: number;
  change: number;
  sparkline: number[];
}

export interface ListCryptoQuotesRequest {
  ids: string[];
}

export interface ListCryptoQuotesResponse {
  quotes: CryptoQuote[];
}

export interface CryptoQuote {
  name: string;
  symbol: string;
  price: number;
  change: number;
  sparkline: number[];
  change7d: number;
}

export interface ListCommodityQuotesRequest {
  symbols: string[];
}

export interface ListCommodityQuotesResponse {
  quotes: CommodityQuote[];
}

export interface CommodityQuote {
  symbol: string;
  name: string;
  display: string;
  price: number;
  change: number;
  sparkline: number[];
}

export interface GetSectorSummaryRequest {
  period: string;
}

export interface GetSectorSummaryResponse {
  sectors: SectorPerformance[];
}

export interface SectorPerformance {
  symbol: string;
  name: string;
  change: number;
}

export interface ListStablecoinMarketsRequest {
  coins: string[];
}

export interface ListStablecoinMarketsResponse {
  timestamp: string;
  summary?: StablecoinSummary;
  stablecoins: Stablecoin[];
}

export interface StablecoinSummary {
  totalMarketCap: number;
  totalVolume24h: number;
  coinCount: number;
  depeggedCount: number;
  healthStatus: string;
}

export interface Stablecoin {
  id: string;
  symbol: string;
  name: string;
  price: number;
  deviation: number;
  pegStatus: string;
  marketCap: number;
  volume24h: number;
  change24h: number;
  change7d: number;
  image: string;
}

export interface ListEtfFlowsRequest {
}

export interface ListEtfFlowsResponse {
  timestamp: string;
  summary?: EtfFlowsSummary;
  etfs: EtfFlow[];
  rateLimited: boolean;
}

export interface EtfFlowsSummary {
  etfCount: number;
  totalVolume: number;
  totalEstFlow: number;
  netDirection: string;
  inflowCount: number;
  outflowCount: number;
}

export interface EtfFlow {
  ticker: string;
  issuer: string;
  price: number;
  priceChange: number;
  volume: number;
  avgVolume: number;
  volumeRatio: number;
  direction: string;
  estFlow: number;
}

export interface GetCountryStockIndexRequest {
  countryCode: string;
}

export interface GetCountryStockIndexResponse {
  available: boolean;
  code: string;
  symbol: string;
  indexName: string;
  price: number;
  weekChangePercent: number;
  currency: string;
  fetchedAt: string;
}

export interface ListGulfQuotesRequest {
}

export interface ListGulfQuotesResponse {
  quotes: GulfQuote[];
  rateLimited: boolean;
}

export interface GulfQuote {
  symbol: string;
  name: string;
  flag: string;
  country: string;
  type: string;
  price: number;
  change: number;
  sparkline: number[];
}

export interface AnalyzeStockRequest {
  symbol: string;
  name: string;
  includeNews: boolean;
}

export interface AnalyzeStockResponse {
  available: boolean;
  symbol: string;
  name: string;
  display: string;
  currency: string;
  currentPrice: number;
  changePercent: number;
  signalScore: number;
  signal: string;
  trendStatus: string;
  volumeStatus: string;
  macdStatus: string;
  rsiStatus: string;
  summary: string;
  action: string;
  confidence: string;
  technicalSummary: string;
  newsSummary: string;
  whyNow: string;
  bullishFactors: string[];
  riskFactors: string[];
  supportLevels: number[];
  resistanceLevels: number[];
  headlines: StockAnalysisHeadline[];
  ma5: number;
  ma10: number;
  ma20: number;
  ma60: number;
  biasMa5: number;
  biasMa10: number;
  biasMa20: number;
  volumeRatio5d: number;
  rsi12: number;
  macdDif: number;
  macdDea: number;
  macdBar: number;
  provider: string;
  model: string;
  fallback: boolean;
  newsSearched: boolean;
  generatedAt: string;
  analysisId: string;
  analysisAt: number;
  stopLoss: number;
  takeProfit: number;
  engineVersion: string;
  analystConsensus?: AnalystConsensus;
  priceTarget?: PriceTarget;
  recentUpgrades: UpgradeDowngrade[];
  dividendYield: number;
  trailingAnnualDividendRate: number;
  exDividendDate: number;
  payoutRatio?: number;
  dividendFrequency: string;
  dividendCagr: number;
}

export interface StockAnalysisHeadline {
  title: string;
  source: string;
  link: string;
  publishedAt: number;
}

export interface AnalystConsensus {
  strongBuy: number;
  buy: number;
  hold: number;
  sell: number;
  strongSell: number;
  total: number;
  period: string;
}

export interface PriceTarget {
  high?: number;
  low?: number;
  mean?: number;
  median?: number;
  current?: number;
  numberOfAnalysts: number;
}

export interface UpgradeDowngrade {
  firm: string;
  toGrade: string;
  fromGrade: string;
  action: string;
  epochGradeDate: number;
}

export interface GetStockAnalysisHistoryRequest {
  symbols: string[];
  limitPerSymbol: number;
  includeNews: boolean;
}

export interface GetStockAnalysisHistoryResponse {
  items: StockAnalysisHistoryItem[];
}

export interface StockAnalysisHistoryItem {
  symbol: string;
  snapshots: AnalyzeStockResponse[];
}

export interface BacktestStockRequest {
  symbol: string;
  name: string;
  evalWindowDays: number;
}

export interface BacktestStockResponse {
  available: boolean;
  symbol: string;
  name: string;
  display: string;
  currency: string;
  evalWindowDays: number;
  evaluationsRun: number;
  actionableEvaluations: number;
  winRate: number;
  directionAccuracy: number;
  avgSimulatedReturnPct: number;
  cumulativeSimulatedReturnPct: number;
  latestSignal: string;
  latestSignalScore: number;
  summary: string;
  generatedAt: string;
  evaluations: BacktestStockEvaluation[];
  engineVersion: string;
}

export interface BacktestStockEvaluation {
  analysisAt: number;
  signal: string;
  signalScore: number;
  entryPrice: number;
  exitPrice: number;
  simulatedReturnPct: number;
  directionCorrect: boolean;
  outcome: string;
  stopLoss: number;
  takeProfit: number;
  analysisId: string;
}

export interface ListStoredStockBacktestsRequest {
  symbols: string[];
  evalWindowDays: number;
}

export interface ListStoredStockBacktestsResponse {
  items: BacktestStockResponse[];
}

export interface ListCryptoSectorsRequest {
}

export interface ListCryptoSectorsResponse {
  sectors: CryptoSector[];
}

export interface CryptoSector {
  id: string;
  name: string;
  change: number;
}

export interface ListDefiTokensRequest {
}

export interface ListDefiTokensResponse {
  tokens: CryptoQuote[];
}

export interface ListAiTokensRequest {
}

export interface ListAiTokensResponse {
  tokens: CryptoQuote[];
}

export interface ListOtherTokensRequest {
}

export interface ListOtherTokensResponse {
  tokens: CryptoQuote[];
}

export interface GetFearGreedIndexRequest {
}

export interface GetFearGreedIndexResponse {
  compositeScore: number;
  compositeLabel: string;
  previousScore: number;
  seededAt: string;
  sentiment?: FearGreedCategory;
  volatility?: FearGreedCategory;
  positioning?: FearGreedCategory;
  trend?: FearGreedCategory;
  breadth?: FearGreedCategory;
  momentum?: FearGreedCategory;
  liquidity?: FearGreedCategory;
  credit?: FearGreedCategory;
  macro?: FearGreedCategory;
  crossAsset?: FearGreedCategory;
  vix: number;
  hySpread: number;
  yield10y: number;
  putCallRatio: number;
  pctAbove200d: number;
  cnnFearGreed: number;
  cnnLabel: string;
  aaiiBull: number;
  aaiiBear: number;
  fedRate: string;
  unavailable: boolean;
  fsiValue: number;
  fsiLabel: string;
  hygPrice: number;
  tltPrice: number;
  sectorPerformance: FearGreedSectorPerformance[];
}

export interface FearGreedCategory {
  score: number;
  weight: number;
  contribution: number;
  degraded: boolean;
  inputsJson: string;
}

export interface FearGreedSectorPerformance {
  symbol: string;
  name: string;
  change1d: number;
}

export interface ListEarningsCalendarRequest {
  fromDate: string;
  toDate: string;
}

export interface ListEarningsCalendarResponse {
  earnings: EarningsEntry[];
  fromDate: string;
  toDate: string;
  total: number;
  unavailable: boolean;
}

export interface EarningsEntry {
  symbol: string;
  company: string;
  date: string;
  hour: string;
  epsEstimate: number;
  revenueEstimate: number;
  epsActual: number;
  revenueActual: number;
  hasActuals: boolean;
  surpriseDirection: string;
}

export interface GetCotPositioningRequest {
}

export interface GetCotPositioningResponse {
  instruments: CotInstrument[];
  reportDate: string;
  unavailable: boolean;
}

export interface CotInstrument {
  name: string;
  code: string;
  reportDate: string;
  assetManagerLong: string;
  assetManagerShort: string;
  leveragedFundsLong: string;
  leveragedFundsShort: string;
  dealerLong: string;
  dealerShort: string;
  netPct: number;
}

export interface GetInsiderTransactionsRequest {
  symbol: string;
}

export interface GetInsiderTransactionsResponse {
  unavailable: boolean;
  symbol: string;
  totalBuys: number;
  totalSells: number;
  netValue: number;
  transactions: InsiderTransaction[];
  fetchedAt: string;
}

export interface InsiderTransaction {
  name: string;
  shares: number;
  value: number;
  transactionCode: string;
  transactionDate: string;
}

export interface GetMarketBreadthHistoryRequest {
}

export interface GetMarketBreadthHistoryResponse {
  currentPctAbove20d?: number;
  currentPctAbove50d?: number;
  currentPctAbove200d?: number;
  updatedAt: string;
  history: BreadthSnapshot[];
  unavailable: boolean;
}

export interface BreadthSnapshot {
  date: string;
  pctAbove20d?: number;
  pctAbove50d?: number;
  pctAbove200d?: number;
}

export interface GetGoldIntelligenceRequest {
}

export interface GetGoldIntelligenceResponse {
  goldPrice: number;
  goldChangePct: number;
  goldSparkline: number[];
  silverPrice: number;
  platinumPrice: number;
  palladiumPrice: number;
  goldSilverRatio?: number;
  goldPlatinumPremiumPct?: number;
  crossCurrencyPrices: GoldCrossCurrencyPrice[];
  cot?: GoldCotPositioning;
  updatedAt: string;
  unavailable: boolean;
  session?: GoldSessionRange;
  returns?: GoldReturns;
  range52w?: GoldRange52w;
  drivers: GoldDriver[];
  etfFlows?: GoldEtfFlows;
  cbReserves?: GoldCbReserves;
}

export interface GoldCrossCurrencyPrice {
  currency: string;
  flag: string;
  price: number;
}

export interface GoldCotPositioning {
  reportDate: string;
  nextReleaseDate: string;
  openInterest: string;
  managedMoney?: GoldCotCategory;
  producerSwap?: GoldCotCategory;
}

export interface GoldCotCategory {
  longPositions: string;
  shortPositions: string;
  netPct: number;
  oiSharePct: number;
  wowNetDelta: string;
}

export interface GoldSessionRange {
  dayHigh: number;
  dayLow: number;
  prevClose: number;
}

export interface GoldReturns {
  w1: number;
  m1: number;
  ytd: number;
  y1: number;
}

export interface GoldRange52w {
  hi: number;
  lo: number;
  positionPct: number;
}

export interface GoldDriver {
  symbol: string;
  label: string;
  value: number;
  changePct: number;
  correlation30d: number;
}

export interface GoldEtfFlows {
  asOfDate: string;
  tonnes: number;
  aumUsd: number;
  nav: number;
  changeW1Tonnes: number;
  changeM1Tonnes: number;
  changeY1Tonnes: number;
  changeW1Pct: number;
  changeM1Pct: number;
  changeY1Pct: number;
  sparkline90d: number[];
}

export interface GoldCbReserves {
  asOfMonth: string;
  totalTonnes: number;
  topHolders: GoldCbHolder[];
  topBuyers12m: GoldCbMover[];
  topSellers12m: GoldCbMover[];
}

export interface GoldCbHolder {
  iso3: string;
  name: string;
  tonnes: number;
  pctOfReserves: number;
}

export interface GoldCbMover {
  iso3: string;
  name: string;
  deltaTonnes12m: number;
}

export interface GetHyperliquidFlowRequest {
}

export interface GetHyperliquidFlowResponse {
  ts: string;
  fetchedAt: string;
  warmup: boolean;
  assetCount: number;
  assets: HyperliquidAssetFlow[];
  unavailable: boolean;
}

export interface HyperliquidAssetFlow {
  symbol: string;
  display: string;
  assetClass: string;
  group: string;
  funding: string;
  openInterest: string;
  markPx: string;
  oraclePx: string;
  dayNotional: string;
  fundingScore: number;
  volumeScore: number;
  oiScore: number;
  basisScore: number;
  composite: number;
  sparkFunding: number[];
  sparkOi: number[];
  sparkScore: number[];
  warmup: boolean;
  stale: boolean;
  staleSince: string;
  missingPolls: number;
  alerts: string[];
}

export interface FieldViolation {
  field: string;
  description: string;
}

export class ValidationError extends Error {
  violations: FieldViolation[];

  constructor(violations: FieldViolation[]) {
    super("Validation failed");
    this.name = "ValidationError";
    this.violations = violations;
  }
}

export class ApiError extends Error {
  statusCode: number;
  body: string;

  constructor(statusCode: number, message: string, body: string) {
    super(message);
    this.name = "ApiError";
    this.statusCode = statusCode;
    this.body = body;
  }
}

export interface ServerContext {
  request: Request;
  pathParams: Record<string, string>;
  headers: Record<string, string>;
}

export interface ServerOptions {
  onError?: (error: unknown, req: Request) => Response | Promise<Response>;
  validateRequest?: (methodName: string, body: unknown) => FieldViolation[] | undefined;
}

export interface RouteDescriptor {
  method: string;
  path: string;
  handler: (req: Request) => Promise<Response>;
}

export interface MarketServiceHandler {
  listMarketQuotes(ctx: ServerContext, req: ListMarketQuotesRequest): Promise<ListMarketQuotesResponse>;
  listCryptoQuotes(ctx: ServerContext, req: ListCryptoQuotesRequest): Promise<ListCryptoQuotesResponse>;
  listCommodityQuotes(ctx: ServerContext, req: ListCommodityQuotesRequest): Promise<ListCommodityQuotesResponse>;
  getSectorSummary(ctx: ServerContext, req: GetSectorSummaryRequest): Promise<GetSectorSummaryResponse>;
  listStablecoinMarkets(ctx: ServerContext, req: ListStablecoinMarketsRequest): Promise<ListStablecoinMarketsResponse>;
  listEtfFlows(ctx: ServerContext, req: ListEtfFlowsRequest): Promise<ListEtfFlowsResponse>;
  getCountryStockIndex(ctx: ServerContext, req: GetCountryStockIndexRequest): Promise<GetCountryStockIndexResponse>;
  listGulfQuotes(ctx: ServerContext, req: ListGulfQuotesRequest): Promise<ListGulfQuotesResponse>;
  analyzeStock(ctx: ServerContext, req: AnalyzeStockRequest): Promise<AnalyzeStockResponse>;
  getStockAnalysisHistory(ctx: ServerContext, req: GetStockAnalysisHistoryRequest): Promise<GetStockAnalysisHistoryResponse>;
  backtestStock(ctx: ServerContext, req: BacktestStockRequest): Promise<BacktestStockResponse>;
  listStoredStockBacktests(ctx: ServerContext, req: ListStoredStockBacktestsRequest): Promise<ListStoredStockBacktestsResponse>;
  listCryptoSectors(ctx: ServerContext, req: ListCryptoSectorsRequest): Promise<ListCryptoSectorsResponse>;
  listDefiTokens(ctx: ServerContext, req: ListDefiTokensRequest): Promise<ListDefiTokensResponse>;
  listAiTokens(ctx: ServerContext, req: ListAiTokensRequest): Promise<ListAiTokensResponse>;
  listOtherTokens(ctx: ServerContext, req: ListOtherTokensRequest): Promise<ListOtherTokensResponse>;
  getFearGreedIndex(ctx: ServerContext, req: GetFearGreedIndexRequest): Promise<GetFearGreedIndexResponse>;
  listEarningsCalendar(ctx: ServerContext, req: ListEarningsCalendarRequest): Promise<ListEarningsCalendarResponse>;
  getCotPositioning(ctx: ServerContext, req: GetCotPositioningRequest): Promise<GetCotPositioningResponse>;
  getInsiderTransactions(ctx: ServerContext, req: GetInsiderTransactionsRequest): Promise<GetInsiderTransactionsResponse>;
  getMarketBreadthHistory(ctx: ServerContext, req: GetMarketBreadthHistoryRequest): Promise<GetMarketBreadthHistoryResponse>;
  getGoldIntelligence(ctx: ServerContext, req: GetGoldIntelligenceRequest): Promise<GetGoldIntelligenceResponse>;
  getHyperliquidFlow(ctx: ServerContext, req: GetHyperliquidFlowRequest): Promise<GetHyperliquidFlowResponse>;
}

export function createMarketServiceRoutes(
  handler: MarketServiceHandler,
  options?: ServerOptions,
): RouteDescriptor[] {
  return [
    {
      method: "GET",
      path: "/api/market/v1/list-market-quotes",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: ListMarketQuotesRequest = {
            symbols: params.getAll("symbols"),
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("listMarketQuotes", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listMarketQuotes(ctx, body);
          return new Response(JSON.stringify(result as ListMarketQuotesResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-crypto-quotes",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: ListCryptoQuotesRequest = {
            ids: params.getAll("ids"),
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("listCryptoQuotes", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listCryptoQuotes(ctx, body);
          return new Response(JSON.stringify(result as ListCryptoQuotesResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-commodity-quotes",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: ListCommodityQuotesRequest = {
            symbols: params.getAll("symbols"),
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("listCommodityQuotes", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listCommodityQuotes(ctx, body);
          return new Response(JSON.stringify(result as ListCommodityQuotesResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-sector-summary",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: GetSectorSummaryRequest = {
            period: params.get("period") ?? "",
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("getSectorSummary", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getSectorSummary(ctx, body);
          return new Response(JSON.stringify(result as GetSectorSummaryResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-stablecoin-markets",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: ListStablecoinMarketsRequest = {
            coins: params.getAll("coins"),
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("listStablecoinMarkets", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listStablecoinMarkets(ctx, body);
          return new Response(JSON.stringify(result as ListStablecoinMarketsResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-etf-flows",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as ListEtfFlowsRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listEtfFlows(ctx, body);
          return new Response(JSON.stringify(result as ListEtfFlowsResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-country-stock-index",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: GetCountryStockIndexRequest = {
            countryCode: params.get("country_code") ?? "",
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("getCountryStockIndex", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getCountryStockIndex(ctx, body);
          return new Response(JSON.stringify(result as GetCountryStockIndexResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-gulf-quotes",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as ListGulfQuotesRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listGulfQuotes(ctx, body);
          return new Response(JSON.stringify(result as ListGulfQuotesResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/analyze-stock",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: AnalyzeStockRequest = {
            symbol: params.get("symbol") ?? "",
            name: params.get("name") ?? "",
            includeNews: params.get("include_news") === "true",
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("analyzeStock", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.analyzeStock(ctx, body);
          return new Response(JSON.stringify(result as AnalyzeStockResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-stock-analysis-history",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: GetStockAnalysisHistoryRequest = {
            symbols: params.getAll("symbols"),
            limitPerSymbol: Number(params.get("limit_per_symbol") ?? "0"),
            includeNews: params.get("include_news") === "true",
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("getStockAnalysisHistory", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getStockAnalysisHistory(ctx, body);
          return new Response(JSON.stringify(result as GetStockAnalysisHistoryResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/backtest-stock",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: BacktestStockRequest = {
            symbol: params.get("symbol") ?? "",
            name: params.get("name") ?? "",
            evalWindowDays: Number(params.get("eval_window_days") ?? "0"),
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("backtestStock", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.backtestStock(ctx, body);
          return new Response(JSON.stringify(result as BacktestStockResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-stored-stock-backtests",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: ListStoredStockBacktestsRequest = {
            symbols: params.getAll("symbols"),
            evalWindowDays: Number(params.get("eval_window_days") ?? "0"),
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("listStoredStockBacktests", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listStoredStockBacktests(ctx, body);
          return new Response(JSON.stringify(result as ListStoredStockBacktestsResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-crypto-sectors",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as ListCryptoSectorsRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listCryptoSectors(ctx, body);
          return new Response(JSON.stringify(result as ListCryptoSectorsResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-defi-tokens",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as ListDefiTokensRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listDefiTokens(ctx, body);
          return new Response(JSON.stringify(result as ListDefiTokensResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-ai-tokens",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as ListAiTokensRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listAiTokens(ctx, body);
          return new Response(JSON.stringify(result as ListAiTokensResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-other-tokens",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as ListOtherTokensRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listOtherTokens(ctx, body);
          return new Response(JSON.stringify(result as ListOtherTokensResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-fear-greed-index",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as GetFearGreedIndexRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getFearGreedIndex(ctx, body);
          return new Response(JSON.stringify(result as GetFearGreedIndexResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/list-earnings-calendar",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: ListEarningsCalendarRequest = {
            fromDate: params.get("fromDate") ?? "",
            toDate: params.get("toDate") ?? "",
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("listEarningsCalendar", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.listEarningsCalendar(ctx, body);
          return new Response(JSON.stringify(result as ListEarningsCalendarResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-cot-positioning",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as GetCotPositioningRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getCotPositioning(ctx, body);
          return new Response(JSON.stringify(result as GetCotPositioningResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-insider-transactions",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const url = new URL(req.url, "http://localhost");
          const params = url.searchParams;
          const body: GetInsiderTransactionsRequest = {
            symbol: params.get("symbol") ?? "",
          };
          if (options?.validateRequest) {
            const bodyViolations = options.validateRequest("getInsiderTransactions", body);
            if (bodyViolations) {
              throw new ValidationError(bodyViolations);
            }
          }

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getInsiderTransactions(ctx, body);
          return new Response(JSON.stringify(result as GetInsiderTransactionsResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-market-breadth-history",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as GetMarketBreadthHistoryRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getMarketBreadthHistory(ctx, body);
          return new Response(JSON.stringify(result as GetMarketBreadthHistoryResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-gold-intelligence",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as GetGoldIntelligenceRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getGoldIntelligence(ctx, body);
          return new Response(JSON.stringify(result as GetGoldIntelligenceResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
    {
      method: "GET",
      path: "/api/market/v1/get-hyperliquid-flow",
      handler: async (req: Request): Promise<Response> => {
        try {
          const pathParams: Record<string, string> = {};
          const body = {} as GetHyperliquidFlowRequest;

          const ctx: ServerContext = {
            request: req,
            pathParams,
            headers: Object.fromEntries(req.headers.entries()),
          };

          const result = await handler.getHyperliquidFlow(ctx, body);
          return new Response(JSON.stringify(result as GetHyperliquidFlowResponse), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          });
        } catch (err: unknown) {
          if (err instanceof ValidationError) {
            return new Response(JSON.stringify({ violations: err.violations }), {
              status: 400,
              headers: { "Content-Type": "application/json" },
            });
          }
          if (options?.onError) {
            return options.onError(err, req);
          }
          const message = err instanceof Error ? err.message : String(err);
          return new Response(JSON.stringify({ message }), {
            status: 500,
            headers: { "Content-Type": "application/json" },
          });
        }
      },
    },
  ];
}

