Skip to content

chore(runway): cherry-pick feat(predict): add Polymarket CLOB v2 support cp-7.73.1#29256

Merged
chloeYue merged 1 commit into
release/7.73.2from
cherry-pick-7-73-2-d9f38f2
Apr 23, 2026
Merged

chore(runway): cherry-pick feat(predict): add Polymarket CLOB v2 support cp-7.73.1#29256
chloeYue merged 1 commit into
release/7.73.2from
cherry-pick-7-73-2-d9f38f2

Conversation

@runway-github

@runway-github runway-github Bot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

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:

  • Primary remote flag: predictClobV2 (default false) enables the v2
    protocol
  • Temporary rollout flag: predictClobV2UseLegacyClobHost forces v2 to
    use https://clob-v2.polymarket.com during the migration window
  • Canonical/default v2 host remains https://clob.polymarket.com
  • Host selection is resolved once into protocol.transport.clobBaseUrl;
    lower-level helpers never read raw flags
  • v2 API key caching is host-aware to avoid reusing credentials across
    host changes
  • v2 getBalance() always returns Safe USDC.e + Safe pUSD — no
    branching on upgrade state
  • Trade path is relayer-only, Permit2-only fee collection on
    pUSD, always runs preflight before submission
  • Canonical v2 allowance requirement set defined once; inspector +
    compiler are small pure modules
  • Deposit/withdraw use release-time code choices for preferred vs
    fallback variant — not runtime flags
  • Wrap: always wraps entire current Safe USDC.e balance (never
    MaxUint256) when maintenance tx is already being emitted
  • Unwrap: always unwraps exact deficit needed — no over-unwrapping

Commits

This PR is now structured as 12 focused commits for easier review:

1. feat(predict): add CLOB v2 feature flag plumbing

Wires the predictClobV2 boolean through the Predict feature-flag
infrastructure:

  • Adds predictClobV2Enabled to PredictFeatureFlags interface
  • Adds selectPredictClobV2EnabledFlag selector
  • Extends resolvePredictFeatureFlags to resolve the new flag
  • Refactors resolveVersionGatedBooleanFlag helper to reduce
    duplication across the existing flag resolution logic
  • Adds selector and resolver tests

2. feat(predict): add CLOB v2 protocol and preflight foundation

Introduces the two new private modules that everything else builds on:

protocol/ — data-first protocol definitions:

  • definitions.ts: v1 and v2 PolymarketProtocolDefinition objects;
    protocol resolution; builder code env config
    (MM_PREDICT_BUILDER_CODE); deposit/withdraw execution mode types
  • orderCodec.ts: v2-aware order build, EIP-712 typed data, and relayer
    payload serialization
  • transport.ts: shared CLOB transport helpers parameterized by
    protocol endpoint; collapses v1/v2 endpoint differences

preflight/ — 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 satisfied
  • compileRequirementTransactions.ts: compiles missing requirements
    into SafeTransaction[]
  • core.ts: shared raw-fact readers, wrap/unwrap builders, and signed
    Safe execution helpers

All modules covered by unit tests.

3. feat(predict): add CLOB v2 buy and sell flow

Implements 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: placeOrder now resolves the protocol once,
    runs preflight under v2, builds the optional allowancesTx, and uses
    the protocol's orderCodec for order construction, EIP-712 signing, and
    relayer payload
  • utils.ts: adds encodeWrapUsdceTransaction and
    encodeUnwrapTransaction helpers (+ tests)
  • v2 preview keeps feeRateBps = '0' until the upstream fee endpoint is
    confirmed

4. feat(predict): add CLOB v2 deposit flow

Adds 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 tx
  • PolymarketProvider.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 preserved
  • Currently wired to the usdce-transfer fallback mode; flip
    depositMode in the protocol definition to switch to pUSD-native when
    that dependency lands

5. feat(predict): add CLOB v2 withdraw flow

Adds the v2 withdraw planner and wires both the prepareWithdraw /
signWithdraw contract:

  • 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, calls planWithdraw, and
    returns the user-requested amount (not any larger intermediate amount)
  • safe/utils.ts: adds parseTransactionCalldata helper to extract the
    withdraw amount from the stored template
  • Currently wired to the usdce-deficit-unwrap fallback mode; flip
    withdrawMode in the protocol definition to switch to pUSD-native

6. feat(predict): add CLOB v2 claim flow

Adds the v2 claim planner and wires it into
PolymarketProvider.claimWinnings:

  • preflight/claim.ts: planClaim — reads EOA USDC.e directly (not
    Safe balances or provider getBalance()); computes gasStationDeficit = 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 EOA
  • PolymarketProvider.claimWinnings: under v2, resolves protocol and
    delegates to planClaim; uses protocol-owned claim targets (pUSD as
    collateral) rather than per-position collateral metadata

7. test(predict): add CLOB v2 integration coverage

Adds 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 into v1 / v2 describe
    blocks; covers protocol routing (flag off → v1, flag on → v2), v2
    getBalance() aggregation, all four trade preflight outcomes (none /
    allowances-only / wrap-only / allowances+wrap), deposit/withdraw
    preferred vs fallback shape, and claim ordering

8. fix: preserve EIP-712 field order in buildProtocolUnsignedOrder

Fixes 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:

  • forwards requirement.tokenAddress into the ERC-1155 operator
    approval read instead of relying on a hardcoded contract address
  • adds assertions proving the token address is propagated correctly
    through the read path

10. refactor(predict): tighten CLOB v2 preflight workflow seams

Addresses follow-up review feedback without changing behavior:

  • makes lower-level transaction compilers private where possible
  • keeps getClaimRequirements exported for focused pure testing
  • tightens preflight/workflows.test.ts to assert through planner entry
    points instead of private helpers
  • renames claim gas-top-up terminology for clarity
    (MIN_GAS_STATION_USDCE_BALANCE_RAW, gasStationDeficit) while keeping
    eoaUsdceBalance unchanged

11. feat(predict): add configurable CLOB v2 host override

Adds temporary host-migration plumbing while keeping canonical host
resolution centralized:

  • introduces canonical and legacy CLOB host constants
  • resolves the selected host into protocol.transport.clobBaseUrl
  • threads the resolved host through API key creation, order-book reads,
    and preview flow
  • isolates API key cache entries by protocol + host + address

12. refactor(predict): gate legacy CLOB v2 host with boolean flag

Simplifies the rollout shape for internal RC testing:

  • replaces the nested raw predictClobV2.clobBaseUrl rollout control
    with a second version-gated boolean flag:
    predictClobV2UseLegacyClobHost
  • keeps the lower-level host plumbing from commit 11 intact
  • allows internal RC builds to enable the legacy host remotely while
    internal users locally toggle predictClobV2

Changelog

CHANGELOG entry: null

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-817

Manual testing steps

Feature: Polymarket CLOB v2 trading

  Scenario: user trades with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled
    And the user has an active Polymarket Safe

    When user places a buy or sell order
    Then the provider runs preflight and submits any needed allowance/wrap tx first
    And the order is submitted via the relayer with X-Clob-Version: 2

  Scenario: internal RC uses the legacy v2 CLOB host
    Given the predictClobV2UseLegacyClobHost remote flag is enabled
    And predictClobV2 is enabled via local override

    When user places a buy or sell order
    Then v2 CLOB requests use https://clob-v2.polymarket.com
    And API keys are cached separately from canonical-host credentials

  Scenario: user deposits with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled

    When user initiates a deposit
    Then the deposit plan includes an optional maintenance tx (allowance repair + wrap pre-existing USDC.e)
    And the newly deposited amount is not included in the wrap

  Scenario: user withdraws with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled
    And the user requests a specific withdrawal amount

    When user confirms the withdraw
    Then only the exact USDC.e deficit is unwrapped (not all pUSD)
    And the reported amount matches the user-requested amount

  Scenario: user claims winnings with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled
    And the user has winning positions

    When user claims
    Then all missing v2 allowances are repaired first
    And the entire pre-existing Safe USDC.e is wrapped
    And claim subcalls execute after
    And only the exact EOA gas-top-up deficit is unwrapped to USDC.e

  Scenario: CLOB v2 flag is disabled (v1 behavior)
    Given the predictClobV2 remote flag is disabled

    When user interacts with any predict flow
    Then v1 protocol is used unchanged

Screenshots/Recordings

https://www.loom.com/share/155120bd46c44723a8b838172b4fd45b

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
  • Use these power-user
    SRPs

    to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production
    performance metrics
  • See trace() for usage and
    addToken
    for an example

For performance guidelines and tooling, see the Performance
Guide
.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the
    app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described
    in the ticket it closes and includes the necessary testing evidence such
    as recordings and or screenshots.

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
(predictClobV2Enabled plus optional legacy host override), with
host-aware API key caching and endpoint selection.

Refactors PolymarketProvider to resolve a protocol definition once
and route preview + order submission through a new protocol/
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 for
MM_PREDICT_BUILDER_CODE.

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

[d9f38f2](https://github.com/MetaMask/metamask-mobile/commit/d9f38f27a9d345abc4331284e2a5df92b5411b88)

@runway-github runway-github Bot requested review from a team as code owners April 23, 2026 12:56
@github-actions

Copy link
Copy Markdown
Contributor

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.

@metamaskbotv2 metamaskbotv2 Bot added the team-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label Apr 23, 2026
@chloeYue chloeYue added the skip-smart-e2e-selection Skip Smart E2E selection, i.e. select all E2E tests to run label Apr 23, 2026
@github-actions github-actions Bot added size-XL risk-high Extensive testing required · High bug introduction risk labels Apr 23, 2026
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:**
- Primary remote flag: `predictClobV2` (default `false`) enables the v2
protocol
- Temporary rollout flag: `predictClobV2UseLegacyClobHost` forces v2 to
use `https://clob-v2.polymarket.com` during the migration window
- Canonical/default v2 host remains `https://clob.polymarket.com`
- Host selection is resolved once into `protocol.transport.clobBaseUrl`;
lower-level helpers never read raw flags
- v2 API key caching is host-aware to avoid reusing credentials across
host changes
- v2 `getBalance()` always returns `Safe USDC.e + Safe pUSD` — no
branching on upgrade state
- Trade path is **relayer-only**, **Permit2-only** fee collection on
pUSD, always runs preflight before submission
- Canonical v2 allowance requirement set defined once; inspector +
compiler are small pure modules
- Deposit/withdraw use **release-time code choices** for preferred vs
fallback variant — not runtime flags
- Wrap: always wraps **entire current Safe USDC.e balance** (never
`MaxUint256`) when maintenance tx is already being emitted
- Unwrap: always unwraps **exact deficit** needed — no over-unwrapping

---

This PR is now structured as 12 focused commits for easier review:

Wires the `predictClobV2` boolean through the Predict feature-flag
infrastructure:
- Adds `predictClobV2Enabled` to `PredictFeatureFlags` interface
- Adds `selectPredictClobV2EnabledFlag` selector
- Extends `resolvePredictFeatureFlags` to resolve the new flag
- Refactors `resolveVersionGatedBooleanFlag` helper to reduce
duplication across the existing flag resolution logic
- Adds selector and resolver tests

Introduces the two new private modules that everything else builds on:

**`protocol/`** — data-first protocol definitions:
- `definitions.ts`: v1 and v2 `PolymarketProtocolDefinition` objects;
protocol resolution; builder code env config
(`MM_PREDICT_BUILDER_CODE`); deposit/withdraw execution mode types
- `orderCodec.ts`: v2-aware order build, EIP-712 typed data, and relayer
payload serialization
- `transport.ts`: shared CLOB transport helpers parameterized by
protocol endpoint; collapses v1/v2 endpoint differences

**`preflight/`** — 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 satisfied
- `compileRequirementTransactions.ts`: compiles missing requirements
into `SafeTransaction[]`
- `core.ts`: shared raw-fact readers, wrap/unwrap builders, and signed
Safe execution helpers

All modules covered by unit tests.

Implements 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`: `placeOrder` now resolves the protocol once,
runs preflight under v2, builds the optional `allowancesTx`, and uses
the protocol's `orderCodec` for order construction, EIP-712 signing, and
relayer payload
- `utils.ts`: adds `encodeWrapUsdceTransaction` and
`encodeUnwrapTransaction` helpers (+ tests)
- v2 preview keeps `feeRateBps = '0'` until the upstream fee endpoint is
confirmed

Adds 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 tx
- `PolymarketProvider.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 preserved
- Currently wired to the `usdce-transfer` fallback mode; flip
`depositMode` in the protocol definition to switch to pUSD-native when
that dependency lands

Adds the v2 withdraw planner and wires both the `prepareWithdraw` /
`signWithdraw` contract:
- `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, calls `planWithdraw`, and
returns the user-requested amount (not any larger intermediate amount)
- `safe/utils.ts`: adds `parseTransactionCalldata` helper to extract the
withdraw amount from the stored template
- Currently wired to the `usdce-deficit-unwrap` fallback mode; flip
`withdrawMode` in the protocol definition to switch to pUSD-native

Adds the v2 claim planner and wires it into
`PolymarketProvider.claimWinnings`:
- `preflight/claim.ts`: `planClaim` — reads EOA USDC.e directly (not
Safe balances or provider `getBalance()`); computes `gasStationDeficit =
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 EOA
- `PolymarketProvider.claimWinnings`: under v2, resolves protocol and
delegates to `planClaim`; uses protocol-owned claim targets (pUSD as
collateral) rather than per-position collateral metadata

Adds 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 into `v1` / `v2` describe
blocks; covers protocol routing (flag off → v1, flag on → v2), v2
`getBalance()` aggregation, all four trade preflight outcomes (none /
allowances-only / wrap-only / allowances+wrap), deposit/withdraw
preferred vs fallback shape, and claim ordering

Fixes the v2 order-signing codec so the generated typed data preserves
the expected field ordering for EIP-712 signing.

Addresses review feedback in the allowance inspector path:
- forwards `requirement.tokenAddress` into the ERC-1155 operator
approval read instead of relying on a hardcoded contract address
- adds assertions proving the token address is propagated correctly
through the read path

Addresses follow-up review feedback without changing behavior:
- makes lower-level transaction compilers private where possible
- keeps `getClaimRequirements` exported for focused pure testing
- tightens `preflight/workflows.test.ts` to assert through planner entry
points instead of private helpers
- renames claim gas-top-up terminology for clarity
(`MIN_GAS_STATION_USDCE_BALANCE_RAW`, `gasStationDeficit`) while keeping
`eoaUsdceBalance` unchanged

Adds temporary host-migration plumbing while keeping canonical host
resolution centralized:
- introduces canonical and legacy CLOB host constants
- resolves the selected host into `protocol.transport.clobBaseUrl`
- threads the resolved host through API key creation, order-book reads,
and preview flow
- isolates API key cache entries by protocol + host + address

Simplifies the rollout shape for internal RC testing:
- replaces the nested raw `predictClobV2.clobBaseUrl` rollout control
with a second version-gated boolean flag:
`predictClobV2UseLegacyClobHost`
- keeps the lower-level host plumbing from commit 11 intact
- allows internal RC builds to enable the legacy host remotely while
internal users locally toggle `predictClobV2`

---

CHANGELOG entry: null

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-817

```gherkin
Feature: Polymarket CLOB v2 trading

  Scenario: user trades with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled
    And the user has an active Polymarket Safe

    When user places a buy or sell order
    Then the provider runs preflight and submits any needed allowance/wrap tx first
    And the order is submitted via the relayer with X-Clob-Version: 2

  Scenario: internal RC uses the legacy v2 CLOB host
    Given the predictClobV2UseLegacyClobHost remote flag is enabled
    And predictClobV2 is enabled via local override

    When user places a buy or sell order
    Then v2 CLOB requests use https://clob-v2.polymarket.com
    And API keys are cached separately from canonical-host credentials

  Scenario: user deposits with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled

    When user initiates a deposit
    Then the deposit plan includes an optional maintenance tx (allowance repair + wrap pre-existing USDC.e)
    And the newly deposited amount is not included in the wrap

  Scenario: user withdraws with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled
    And the user requests a specific withdrawal amount

    When user confirms the withdraw
    Then only the exact USDC.e deficit is unwrapped (not all pUSD)
    And the reported amount matches the user-requested amount

  Scenario: user claims winnings with CLOB v2 enabled
    Given the predictClobV2 remote flag is enabled
    And the user has winning positions

    When user claims
    Then all missing v2 allowances are repaired first
    And the entire pre-existing Safe USDC.e is wrapped
    And claim subcalls execute after
    And only the exact EOA gas-top-up deficit is unwrapped to USDC.e

  Scenario: CLOB v2 flag is disabled (v1 behavior)
    Given the predictClobV2 remote flag is disabled

    When user interacts with any predict flow
    Then v1 protocol is used unchanged
```

https://www.loom.com/share/155120bd46c44723a8b838172b4fd45b

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!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
(`predictClobV2Enabled` plus optional legacy host override), with
host-aware API key caching and endpoint selection.
>
> Refactors `PolymarketProvider` to resolve a protocol definition once
and route **preview + order submission** through a new `protocol/`
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 for
`MM_PREDICT_BUILDER_CODE`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5df04d5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

(cherry picked from commit d9f38f2)
@matallui matallui force-pushed the cherry-pick-7-73-2-d9f38f2 branch from 0cfa90a to 94bec69 Compare April 23, 2026 13:24
@github-actions github-actions Bot added risk-high Extensive testing required · High bug introduction risk and removed risk-high Extensive testing required · High bug introduction risk labels Apr 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - skip-smart-e2e-selection label found

All E2E tests pre-selected.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
17 value mismatches detected (expected — fixture represents an existing user).
View details

@chloeYue chloeYue merged commit ecd00a3 into release/7.73.2 Apr 23, 2026
185 of 190 checks passed
@chloeYue chloeYue deleted the cherry-pick-7-73-2-d9f38f2 branch April 23, 2026 14:45
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

risk-high Extensive testing required · High bug introduction risk size-XL skip-smart-e2e-selection Skip Smart E2E selection, i.e. select all E2E tests to run team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants