feat(signing): migrate order signing to CLOB V2/V3#28
Merged
Conversation
… ClobAuthenticator
…type guards in encodeValue()
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Polymarket cut production over to CLOB V2 on 2026-04-28; V1-signed orders are rejected. Sign the 11-field V2 order struct (timestamp, metadata, builder; taker/expiration/nonce/feeRateBps removed) against the V2/V3 exchange contracts with a matching domain version. - OrderPayloadV2: V2/V3 domains, neg-risk and per-chain contract selection, version validation; OrderPayload deprecated - SignatureType: canonical values incl. POLY_1271 (signing deferred) - Orders::post(): V2 wire format with postOnly, negRisk and version options; salt/timestamp/metadata/builder defaults - Server::getVersion(): expose GET /version for order-version resolution - Golden-value tests pinned against eth-account reference signatures Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… guard Rector CI resolves the latest rector (no committed composer.lock) and 2.4+ ships NegatedAndsToPositiveOrsRector, which flags the negated-and type guard added in the sign-orders work. Equivalent De Morgan form. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Polymarket cut production over to CLOB V2 on 2026-04-28 (see the official changelog): new Exchange contracts, a new 11-field EIP-712 order struct, domain version
"2", and no backward compatibility — V1-signed orders are rejected. This PR migrates the signing path soOrders::post()works on production again. It also supports the Exchange V3 domain already rolling out (same struct, domain version"3", resolvable viaGET /version).All struct fields, domain values, and contract addresses were verified against the official
py-clob-client-v2andclob-client-v2sources.What
OrderPayloadV2— V2/V3 EIP-712 order struct (timestamp,metadata,builderadded;taker/expiration/nonce/feeRateBpsremoved from the signed struct), domain version matching the order version, and contract auto-selection: V20xE111…996B, V2 neg-risk0xe222…0F59, V3 per chain.OrderPayload(V1) is kept but deprecated.Orders::post()— signs and sends the V2 wire format (saltas int,sideas string,expirationJSON-only defaulting to"0"), with newnegRisk,version, andpostOnlyoptions and official defaults (millisecond timestamp, zero-bytes32metadata/builder, random salt).SignatureType— canonical values:EOA=0,POLY_PROXY=1,POLY_GNOSIS_SAFE=2,POLY_1271=3.POLY_1271signing (nested SoladyTypedDataSignflow) is out of scope and throws a clearSigningException.Server::getVersion()— exposesGET /versionso callers can resolve the active order version like the official client (defaults to 2). No hidden HTTP calls inpost()."1"per the official docs.Testing
Developed test-first. The key evidence is four golden-signature tests: reference signatures were generated with
eth-account(the library the official Python SDK signs with) for the official test fixture, and our signer reproduces them byte-for-byte across V2 standard, V2 neg-risk, and V3 domains on Polygon and Amoy. Full suite: 282 tests / 656 assertions, PHPStan clean.Relationship to #27
This branch is based on #27 and includes its commits — it upgrades the V1 signing path introduced there to V2. Recommended order: merge #27 first, after which this PR reduces to the two migration commits (
cc4eae1design spec,5f9cf9cimplementation).Design doc:
docs/superpowers/specs/2026-07-11-clob-v2-order-signing-design.md🤖 Generated with Claude Code