Skip to content

Magic numbers: Hardcoded service/subgraph URLs and embedded credentials without env fallbacks #508

@realfishsam

Description

@realfishsam

Category

Hardcoded Third-Party Service URLs and Embedded Project Identifiers

Locations

Goldsky subgraph — embedded project ID, no env override:

  • core/src/subscriber/external/goldsky.tsconst POLYMARKET_TRADES_ENDPOINT = 'https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/prod/gn'
    The Goldsky project ID (project_cl6mb8i9h0003e201j6li0diw) is embedded directly in the URL string. Migrating to a new Goldsky project, promoting a staging subgraph to production, or pointing to a forked subgraph requires a code change.

Router client — always targets production:

  • core/src/router/client.tsconst DEFAULT_BASE_URL = 'https://api.pmxt.dev'
    No process.env.PMXT_API_URL check. Any consumer of PmxtApiClient in tests or a staging environment hits the live production API.

Opinion exchange — three URL constants, zero env support:

  • core/src/exchanges/opinion/config.ts:1export const DEFAULT_OPINION_API_URL = "https://openapi.opinion.trade/openapi" (no env var)
  • core/src/exchanges/opinion/config.ts:2export const OPINION_WS_URL = "wss://ws.opinion.trade" (no env var)
    Both constants are used directly with no process.env.OPINION_API_URL || ... pattern.

Hardcoded GraphQL result limits within query strings:

  • core/src/subscriber/external/goldsky.tsfirst: 5 in BUILD_POLYMARKET_TRADES_AS_MAKER_QUERY
  • core/src/subscriber/external/goldsky.tsfirst: 20 in BUILD_POLYMARKET_TRADES_AS_TAKER_QUERY
    These literal integers are embedded inside template-literal GraphQL query strings, making them invisible to grep for numeric literals and impossible to adjust without editing query text.

Inconsistencies

  • Polymarket uses process.env.POLYMARKET_CLOB_URL || 'https://clob.polymarket.com' and four other env-guarded URL constants; Kalshi uses an {env} server variable in its OpenAPI spec. Opinion uses neither pattern.
  • The router client PmxtApiClient is the one internal-service URL in the codebase with no env variable override, while every exchange already supports env-level URL overrides.
  • The Goldsky maker query allows only first: 5 results per poll while the taker query allows first: 20 — a 4× asymmetry. GoldSkySubscriber.pollMs defaults to 3 000 ms. A Polymarket market maker executing more than 5 fills inside a 3-second poll window will silently drop the excess fills from balance/trade activity calculations.

Risk

  • Goldsky project ID: Goldsky subgraph migrations (version upgrades, chain re-indexing, project consolidation) require a code change and deploy rather than a config change.
  • Router default URL: Integration tests and staging deployments inadvertently call api.pmxt.dev production unless every caller manually overrides baseUrl — easy to miss and hard to detect.
  • Opinion no env: Opinion cannot be pointed at a staging/sandbox environment without a code change.
  • GraphQL first limits: Silent data loss for high-frequency Polymarket market makers — no warning is emitted when the first: 5 cap is reached.

Suggested Fix

// core/src/subscriber/external/goldsky.ts
const GOLDSKY_POLYMARKET_PROJECT_URL = process.env.POLYMARKET_GOLDSKY_URL ||
    'https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/prod/gn';

const GOLDSKY_MAKER_TRADES_LIMIT = 5;   // lower than taker: market makers trade less frequently per poll
const GOLDSKY_TAKER_TRADES_LIMIT = 20;

// core/src/router/client.ts
const DEFAULT_BASE_URL = process.env.PMXT_API_URL || 'https://api.pmxt.dev';

// core/src/exchanges/opinion/config.ts
export const DEFAULT_OPINION_API_URL = process.env.OPINION_API_URL || "https://openapi.opinion.trade/openapi";
export const OPINION_WS_URL = process.env.OPINION_WS_URL || "wss://ws.opinion.trade";

Found by automated magic numbers audit

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions