feat(perps): expose server time - #292
Conversation
brunson-bot
left a comment
There was a problem hiding this comment.
Reviewed the whole diff plus surrounding context. Behavior is right and the change is small and additive — the endpoint call, error union, @experimental tagging on all five new surfaces, and the minor/minor changeset all check out, and EpochMillisecondsSchema's .int() runs before toEpochMilliseconds, so the non-integer case fails as a Zod issue rather than escaping safeParse as a raw TypeError.
Three things, none blocking. The naming one is the only one I'd want settled before merge, since it's a public surface.
[issue]getServerTimeis the onlyget*in the repo and the only Perps method without aPerpsqualifier[issue]the happy-path unit test replaces a live response for behavior the live integration test already covers[issue]a read-only clock with no way to reach the SDK's own signing timestamps — what workflow does it unblock?
|
Naming and scope are acceptance decisions recorded on DEV-466: the ticket explicitly requires |
|
Round 2 ( Both MSW cases are gone; the happy path stays with the live Worth noting the malformed-response case didn't need to go with it: Still open from round 1, both non-blocking:
|
|
Verified both on DEV-466 — closing my two open findings, nothing further from me.
CI: everything green except |
| * | ||
| * @experimental This API may change in a breaking way in any release, including patch releases. | ||
| */ | ||
| export async function getServerTime( |
There was a problem hiding this comment.
What developer workflow is this standalone read intended to solve? DEV-466 starts by asking where server time is needed and whether the SDK should abstract clock synchronization, but this PR leaves signed requests on Date.now() and gives callers no way to feed the returned value into signing. If server time is needed for correctness, I would expect the SDK to own the offset and synchronization rather than require callers to fetch it. If there is an independent use case for exposing the raw read, can we document it? As a smaller naming point, getServerTime is generic on the flat client and does not follow the existing fetchPerps* convention.
There was a problem hiding this comment.
Trial period: automated Brunson reviews on this repo are being evaluated. Suggestions are a work in progress and not necessarily accurate or vetted by the team yet — please verify before acting on them.
Checked both claims against head 1a2fe01 — they hold, and the second one has a concrete victim in-tree.
- No seam into signing. Every signed Perps op takes
tsfrom the local clock with no override:createPerpsCredentials(packages/client/src/actions/perps.ts:1422-1423),revokePerpsCredentials(:1265),withdrawFromPerps(:1369), andPerpsSession.#createSignedCommand(packages/client/src/websockets/perps/session.ts:983-984).PerpsOpSignatureRequestis module-private, so there is no public path for the returned value to reach a signature. - Skew already bites in one place.
packages/client/src/actions/perps.ts:1496compares the server-issuedproxyKey.expiresAtagainst localDate.now(), and:1422derives the requestedexpiryfromDate.now() + expiresIn. That is a real cross-clock comparison today, andgetServerTime()as shipped does not fix it — nothing applies the offset. If the answer to DEV-466 is "the SDK owns synchronization", that call site is the one to fix first. - Naming.
getServerTimeis the onlyget*-prefixed method across every decorator inpackages/client/src/decorators/; everything else isfetch*/list*, and every other public Perps read carries the domain word (fetchPerpsBook,fetchPerpsFees, …). AGENTS.md defines onlylist*andfetch*.fetchPerpsServerTimeconforms on both axes.
My read: the raw endpoint read is a reasonable primitive, but as merged it is a probe nobody in the SDK consumes, and the TSDoc's "does not change how the SDK timestamps or signs" is documenting the gap rather than closing it. Either land the offset alongside it or state the standalone use case in the TSDoc.
|
For the standalone clock probe, a small usage note could prevent consumers from estimating skew incorrectly. The useful offset is based on the request midpoint, not the response time:
Callers should discard/highlight samples with large RTT, keep the lowest-RTT recent sample, and report both offset and uncertainty. Computing I agree with the existing discussion that signing should eventually consume an SDK-owned offset rather than exposing timestamp overrides on every command. Until that follow-up lands, documenting the midpoint pattern gives this read-only primitive a concrete and correct observability use case: warn that the local clock is outside tolerance before starting a delegated Perps session, without implying that the current SDK corrects signatures. |
DEV-466: Exposes the Perps server clock.
Tests: lint, typecheck, build, unit PASS; public live PASS.
Note
Low Risk
Additive, read-only public API following existing Perps info patterns; no auth, signing, or request-timestamp behavior changes.
Overview
Adds a public Perps clock so callers can read the exchange server time in epoch milliseconds via
GET /v1/info/time.Bindings introduce
GetServerTimeResponseSchema(integer ms only). Client addsgetServerTimeon the low-level actions andclient.getServerTime()onPublicPerpsActions, returning brandedEpochMillisecondswith the usual transport/rate-limit error guard. Docs stress this is a read-only probe and does not change how the SDK timestamps or signs Perps requests today.Coverage includes schema tests, type-level export checks, and a live integration assertion that server time is within ±60s of local wall clock. Minor version bumps are recorded for
@polymarket/bindingsand@polymarket/client.Reviewed by Cursor Bugbot for commit 1a2fe01. Bugbot is set up for automated code reviews on this repo. Configure here.