Skip to content

bindings: ClobTradeSchema match_time and last_update use EpochMilliseconds but /data/trades REST API sends epoch-seconds strings #76

@Nexory

Description

@Nexory

Current code

packages/bindings/src/clob/account.ts:128-132

    last_update: EpochMillisecondsToIsoDateTimeStringSchema,
    maker_address: z.string(),
    maker_orders: z.array(MakerOrderSchema),
    market: z.string(),
    match_time: EpochMillisecondsToIsoDateTimeStringSchema,

EpochMillisecondsToIsoDateTimeStringSchema is an alias for DateLikeToIsoDateTimeStringSchema, which converts a numeric string via transform(Number) and passes the result to new Date(value) — treating it as milliseconds.

Reproduction

The CLOB REST endpoint /data/trades returns these fields as epoch-seconds strings, e.g. "1710000000". Parsing that value through the current schema:

EpochMillisecondsToIsoDateTimeStringSchema.parse("1710000000")
// → "1970-01-20T19:00:00.000Z"   ❌  (54-year error)
// expected: "2024-03-09T16:00:00.000Z"

The correct schema — EpochSecondsStringToIsoDateTimeStringSchema (which multiplies by 1000 before constructing the Date) — is already used for the identical fields in the WebSocket subscription schema at packages/bindings/src/subscriptions/clob.ts:473-475:

    match_time: EpochSecondsStringToIsoDateTimeStringSchema,
    ...
    last_update: EpochSecondsStringToIsoDateTimeStringSchema,

Impact

ClobTradesPageSchema is consumed by packages/client/src/actions/account.ts:303 against the live /data/trades endpoint. Every caller of listAccountTrades() receives a wrong matchedAt and updatedAt on every trade — off by ~54 years. Any downstream logic that sorts trades by time, displays timestamps, or computes age/TTL will silently produce garbage.

Suggested fix

Replace both occurrences in ClobTradeSchema with EpochSecondsStringToIsoDateTimeStringSchema (already imported/used in subscriptions/clob.ts), or apply the same heuristic guard introduced elsewhere:

    last_update: EpochSecondsStringToIsoDateTimeStringSchema,
    ...
    match_time: EpochSecondsStringToIsoDateTimeStringSchema,

Alternatively, mirroring the guard from BuilderTradeMatchTimeSchema:

z.string().regex(/^\d+$/).transform((v) =>
  toIsoDateTimeString(new Date((Number(v) < 1_000_000_000_000 ? Number(v) * 1000 : Number(v))).toISOString())
)

Either approach fixes the 54-year offset without breaking the schema contract.

Related

  • PR fix(bindings): parse builder matchTime seconds #49 (commit 74c2cf7) fixed the identical root cause in BuilderTradeSchema.matchTime but did not update ClobTradeSchema.
  • The WebSocket path (subscriptions/clob.ts:473-475) already uses the correct seconds schema for these same fields — making the REST and WS schemas asymmetric for match_time and last_update.

Metadata

Metadata

Assignees

No one assigned

    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