feat(predict): add Polymarket CLOB v2 support cp-7.73.1#29076
Conversation
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Replacing spread-based object construction with explicit field-by-field literals to guarantee correct field ordering. Using object spread caused the 'taker' field in the v1 path to land after 'expiration' instead of after 'signer', producing an invalid API error. Added a comment to prevent future regressions.
Pass requirement.tokenAddress to readIsApprovedForAll instead of hardcoding the contract address inside getIsApprovedForAll. The Erc1155OperatorRequirement type already carries tokenAddress; now it flows all the way through to the on-chain call. Updated safe/utils.ts to pass MATIC_CONTRACTS.conditionalTokens explicitly, and added an assertion to each test suite to verify the tokenAddress is forwarded correctly.
bbc4900 to
dc5e54b
Compare
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
SmokePredictions is directly required as the core Polymarket provider changes affect all prediction market flows: opening positions, cashing out, claiming winnings, and error handling. SmokeWalletPlatform is required per SmokePredictions tag description (Predictions is a section inside the Trending tab). SmokeConfirmations is required per SmokePredictions tag description (opening/closing positions are on-chain transactions). Performance Test Selection: |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5df04d5. Configure here.
|
|
✅ E2E Fixture Validation — Schema is up to date |




Description
This PR implements Polymarket CLOB v2 support for MetaMask Predict (7.74 target), introducing a clean coexistence architecture that keeps v1 working while v2 is toggled on via
predictClobV2. During the temporary CLOB host migration window, a companion rollout flag (predictClobV2UseLegacyClobHost) can force v2 traffic onto the legacy host for internal RC testing without turning v2 on for everyone by default.The implementation is designed with deletion in mind — after the v1/v2 coexistence window, v1 can be cleanly removed with minimal surgery. The work follows the "data-first protocol definition" architecture from the internal plan: a private
protocol/module owns all version-specific differences and is resolved once at the provider entry point. Lower-level helpers never read feature flags directly.Key design decisions:
predictClobV2(defaultfalse) enables the v2 protocolpredictClobV2UseLegacyClobHostforces v2 to usehttps://clob-v2.polymarket.comduring the migration windowhttps://clob.polymarket.comprotocol.transport.clobBaseUrl; lower-level helpers never read raw flagsgetBalance()always returnsSafe USDC.e + Safe pUSD— no branching on upgrade stateMaxUint256) when maintenance tx is already being emittedCommits
This PR is now structured as 12 focused commits for easier review:
1.
feat(predict): add CLOB v2 feature flag plumbingWires the
predictClobV2boolean through the Predict feature-flag infrastructure:predictClobV2EnabledtoPredictFeatureFlagsinterfaceselectPredictClobV2EnabledFlagselectorresolvePredictFeatureFlagsto resolve the new flagresolveVersionGatedBooleanFlaghelper to reduce duplication across the existing flag resolution logic2.
feat(predict): add CLOB v2 protocol and preflight foundationIntroduces the two new private modules that everything else builds on:
protocol/— data-first protocol definitions:definitions.ts: v1 and v2PolymarketProtocolDefinitionobjects; protocol resolution; builder code env config (MM_PREDICT_BUILDER_CODE); deposit/withdraw execution mode typesorderCodec.ts: v2-aware order build, EIP-712 typed data, and relayer payload serializationtransport.ts: shared CLOB transport helpers parameterized by protocol endpoint; collapses v1/v2 endpoint differencespreflight/— private readiness inspection and Safe plan construction:v2AllowanceRequirements.ts: canonical declarative list of all 10 v2 allowance requirements (7 ERC-20, 3 ERC-1155)inspectMissingRequirements.ts: reads on-chain state and returns the subset of requirements not yet satisfiedcompileRequirementTransactions.ts: compiles missing requirements intoSafeTransaction[]core.ts: shared raw-fact readers, wrap/unwrap builders, and signed Safe execution helpersAll modules covered by unit tests.
3.
feat(predict): add CLOB v2 buy and sell flowImplements the full v2 trade path inside
PolymarketProvider:preflight/trade.ts:planTradePreflight+buildTradeAllowancesTx— inspects missing v2 allowances and Safe USDC.e balance; compiles optional maintenance tx (allowances-only / wrap-only / allowances+wrap / none)PolymarketProvider:placeOrdernow resolves the protocol once, runs preflight under v2, builds the optionalallowancesTx, and uses the protocol'sorderCodecfor order construction, EIP-712 signing, and relayer payloadutils.ts: addsencodeWrapUsdceTransactionandencodeUnwrapTransactionhelpers (+ tests)feeRateBps = '0'until the upstream fee endpoint is confirmed4.
feat(predict): add CLOB v2 deposit flowAdds the v2 deposit maintenance planner and wires it into
PolymarketProvider.prepareDeposit:preflight/deposit.ts:planDepositMaintenance+compileDepositMaintenanceTransactions— inspects missing v2 allowances and pre-existing Safe USDC.e balance (does not incorporate the just-entered deposit amount); emits optional maintenance txPolymarketProvider.prepareDeposit: under v2, resolves protocol, runs the maintenance planner, and attaches the optional maintenance tx to the deposit plan — the 3-step shape (optional deploy → transfer funding asset → optional maintenance tx) is preservedusdce-transferfallback mode; flipdepositModein the protocol definition to switch to pUSD-native when that dependency lands5.
feat(predict): add CLOB v2 withdraw flowAdds the v2 withdraw planner and wires both the
prepareWithdraw/signWithdrawcontract:preflight/withdraw.ts:planWithdraw— reads missing v2 allowances and Safe USDC.e balance; computes the exact USDC.e deficit; compiles the final MultiSend (allowance repair → exact-deficit unwrap-to-Safe → USDC.e transfer to EOA)PolymarketProvider.signWithdraw: under v2, parses the requested amount from the original template calldata, callsplanWithdraw, and returns the user-requested amount (not any larger intermediate amount)safe/utils.ts: addsparseTransactionCalldatahelper to extract the withdraw amount from the stored templateusdce-deficit-unwrapfallback mode; flipwithdrawModein the protocol definition to switch to pUSD-native6.
feat(predict): add CLOB v2 claim flowAdds the v2 claim planner and wires it into
PolymarketProvider.claimWinnings:preflight/claim.ts:planClaim— reads EOA USDC.e directly (not Safe balances or providergetBalance()); computesgasStationDeficit = max(0, MIN_GAS_STATION_USDCE_BALANCE - eoaUsdceBalance); proactively wraps the entire current Safe USDC.e balance; compiles the MultiSend in the required order: (1) missing allowance/operator repair, (2) wrap-all current Safe USDC.e, (3) claim subcalls, (4) optional exact-deficit unwrap to EOAPolymarketProvider.claimWinnings: under v2, resolves protocol and delegates toplanClaim; uses protocol-owned claim targets (pUSD as collateral) rather than per-position collateral metadata7.
test(predict): add CLOB v2 integration coverageAdds integration-level tests and reorganizes the provider test suite:
preflight/workflows.test.ts: end-to-end workflow planner tests covering all four preflight paths (trade, deposit, claim, withdraw) with concrete on-chain mock scenarios — verifies MultiSend ordering invariant (approvals first, then wraps/claims/transfers)PolymarketProvider.test.ts: reorganized intov1/v2describe blocks; covers protocol routing (flag off → v1, flag on → v2), v2getBalance()aggregation, all four trade preflight outcomes (none / allowances-only / wrap-only / allowances+wrap), deposit/withdraw preferred vs fallback shape, and claim ordering8.
fix: preserve EIP-712 field order in buildProtocolUnsignedOrderFixes the v2 order-signing codec so the generated typed data preserves the expected field ordering for EIP-712 signing.
9.
codex: address PR review feedback (#29076)Addresses review feedback in the allowance inspector path:
requirement.tokenAddressinto the ERC-1155 operator approval read instead of relying on a hardcoded contract address10.
refactor(predict): tighten CLOB v2 preflight workflow seamsAddresses follow-up review feedback without changing behavior:
getClaimRequirementsexported for focused pure testingpreflight/workflows.test.tsto assert through planner entry points instead of private helpersMIN_GAS_STATION_USDCE_BALANCE_RAW,gasStationDeficit) while keepingeoaUsdceBalanceunchanged11.
feat(predict): add configurable CLOB v2 host overrideAdds temporary host-migration plumbing while keeping canonical host resolution centralized:
protocol.transport.clobBaseUrl12.
refactor(predict): gate legacy CLOB v2 host with boolean flagSimplifies the rollout shape for internal RC testing:
predictClobV2.clobBaseUrlrollout control with a second version-gated boolean flag:predictClobV2UseLegacyClobHostpredictClobV2Changelog
CHANGELOG entry: null
Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/PRED-817
Manual testing steps
Screenshots/Recordings
https://www.loom.com/share/155120bd46c44723a8b838172b4fd45b
Pre-merge author checklist
Performance checks (if applicable)
trace()for usage andaddTokenfor an exampleFor performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Note
High Risk
High risk because it changes Polymarket trade/claim/deposit/withdraw transaction construction and relayer submission paths, including new Safe preflight logic and EIP-712 signing for a new protocol version.
Overview
Adds Polymarket CLOB v2 support behind new Predict feature flags (
predictClobV2Enabledplus optional legacy host override), with host-aware API key caching and endpoint selection.Refactors
PolymarketProviderto resolve a protocol definition once and route preview + order submission through a newprotocol/module (v2 uses new order schema/typed data, zero preview fee rate, and a relayer request header for v2 routing).Introduces a
preflight/layer that inspects on-chain allowance/approval requirements and builds signed Safe executions for trade allowances, deposit maintenance, claim, and withdraw (including wrap/unwrap flows and balance aggregation across USDC.e + pUSD for v2). Adds extensive unit/integration tests and updates Safe utilities (raw USDC amount decoding, token-address-aware approvals, Permit2 token selection) plus CI env wiring forMM_PREDICT_BUILDER_CODE.Reviewed by Cursor Bugbot for commit 5df04d5. Bugbot is set up for automated code reviews on this repo. Configure here.