Skip to content

fix: rebuild L2 headers per page and surface API errors in pagination - #100

Open
erik-polymarket wants to merge 1 commit into
mainfrom
fix/pagination-stale-l2-headers
Open

fix: rebuild L2 headers per page and surface API errors in pagination#100
erik-polymarket wants to merge 1 commit into
mainfrom
fix/pagination-stale-l2-headers

Conversation

@erik-polymarket

@erik-polymarket erik-polymarket commented Aug 5, 2026

Copy link
Copy Markdown

Summary

Fixes two related bugs in the cursor-pagination loops reported in #99.

1. Stale L2 auth headers. getTrades, getOpenOrders, getPreMigrationOrders, getEarningsForUserForDay, and getUserEarningsAndMarketsConfig built the L2 auth headers once before the loop and reused them for every page. The HMAC timestamp is part of the header, so a long pagination run could send stale authentication on later pages. Header creation now happens inside each loop iteration, so every page request gets a fresh timestamp/signature.

2. Masked API errors. On an API error the HTTP helper returns { error, status }. The loops then did next_cursor = response.next_cursor / results = [...results, ...response.data], spreading a missing data field and throwing a misleading TypeError: undefined is not iterable — hiding the real error. A new private extractPage() helper detects error-shaped or malformed pages and throws an ApiError carrying the actual API message and status.

Note: when throwOnError is enabled, this.get already throws before the loop sees the error. When it is disabled, an array-returning pagination method cannot hand back an { error, status } object, so surfacing an ApiError is the correct way to expose the failure instead of crashing with a bogus TypeError.

Testing

New tests/client/pagination.test.ts covers both fixes with delayed page responses:

  • headers are regenerated per page (distinct POLY_TIMESTAMP / POLY_SIGNATURE across pages)
  • a mid-pagination { error, status } surfaces as an ApiError with the real message/status (not is not iterable)
  • non-string errors are stringified; a page missing its data array throws a descriptive ApiError

pnpm test → 303 passed (21 files) · pnpm lint clean · pnpm build clean.

Closes #99


Note

Medium Risk
Touches L2-authenticated fetch paths used for trades, orders, and rewards; behavior changes on long paginated runs and when the API returns errors mid-loop, but the fixes align with intended auth and error semantics.

Overview
Fixes cursor-pagination for L2-authenticated list endpoints (getTrades, getOpenOrders, getPreMigrationOrders, getEarningsForUserForDay, getUserEarningsAndMarketsConfig).

Stale L2 auth: L2 headers are built inside each loop iteration so every page gets a fresh HMAC timestamp/signature instead of reusing headers from before the loop.

Pagination errors: A new private extractPage() validates each page before appending. Error-shaped { error, status } responses and pages missing a data array throw ApiError with the real message/status instead of failing with undefined is not iterable when throwOnError is off.

Adds tests/client/pagination.test.ts for per-page header regeneration and mid-pagination error handling.

Reviewed by Cursor Bugbot for commit cc28852. Bugbot is set up for automated code reviews on this repo. Configure here.

Cursor pagination loops (getTrades, getOpenOrders, getPreMigrationOrders,
getEarningsForUserForDay, getUserEarningsAndMarketsConfig) built L2 auth
headers once before the loop and reused them for every page. Since the
HMAC timestamp is part of the header, long pagination runs could send
stale auth on later pages. Move header creation inside each loop so a
fresh timestamp/signature is generated per page.

Also, on an API error the HTTP helper returns { error, status }; the loops
spread response.data and threw a misleading 'undefined is not iterable',
hiding the real error. Add extractPage() to detect error-shaped or
malformed pages and throw an ApiError carrying the actual message/status.

Closes #99
@erik-polymarket
erik-polymarket requested a review from a team as a code owner August 5, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pagination reuses stale L2 headers and masks API errors

1 participant