Skip to content

Migrate to Polymarket v2 + pUSD (April 28 2026 exchange upgrade)#61

Draft
petrarka wants to merge 1 commit into
BrainDAO:mainfrom
petrarka:migrate-v2-pusd
Draft

Migrate to Polymarket v2 + pUSD (April 28 2026 exchange upgrade)#61
petrarka wants to merge 1 commit into
BrainDAO:mainfrom
petrarka:migrate-v2-pusd

Conversation

@petrarka

Copy link
Copy Markdown

Summary

Polymarket migrated the exchange and collateral on April 28 2026: USDC.e → pUSD (1:1 USDC wrapper) and CLOB v1 → v2. The legacy @polymarket/clob-client (v1) is no longer compatible — orders signed against the v1 contracts are rejected by the new exchange. This PR ports the server to the v2 SDK (@polymarket/clob-client-v2) and updates collateral / exchange addresses accordingly.

Changes

  • Dependency swap: @polymarket/clob-client@^4.22.8@polymarket/clob-client-v2@^1.0.6, plus viem as supporting dep.
  • services/trading.ts: v2 SDK uses an object-form constructor ({ host, chain, signer, ... }), chainId is renamed to chain, and createOrDeriveApiKey() replaces the separate deriveApiKey() / createApiKey() calls. UserOrder / UserMarketOrder become UserOrderV2 / UserMarketOrderV2 — the v2 types drop feeRateBps, nonce, and taker (server-side now); order construction was updated accordingly.
  • services/config.ts: collateral now points to pUSD (0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB); CTF Exchange v2 (0xE111180000d2663C0091e4f400237545B87B996B) and NegRisk Exchange v2 (0xe2222d279d744050d28e00520010520000310F59). Added USDCE_ADDRESS, COLLATERAL_ONRAMP_ADDRESS, COLLATERAL_OFFRAMP_ADDRESS constants for future wrap/unwrap tooling.
  • services/approvals.ts: collateral allowances target pUSD on the v2 exchanges. Renamed helper getUsdcContractgetCollateralContract. Rationale message updated.
  • services/redemption.ts: redeemPositions passes pUSD (not USDC.e) as the collateral token.
  • services/api.ts: dropped the v1 PolymarketSDK usage from @jsr/hk__polymarket in favor of a direct /book fetch — the endpoint is public, so this also removes the need to construct a CLOB client just to read order books. GammaSDK is retained (Gamma API was not affected by the upgrade).
  • tools/get-balance-allowance.ts, tools/update-balance-allowance.ts: AssetType import path updated to v2 SDK.

signatureType + funderAddress continue to work — the v2 SDK still accepts them in ClobClientOptions, so existing proxy-wallet / Safe flows are unchanged.

Tests

Adds smoke-test.mjs — 8-check regression harness that hits live Polymarket APIs read-only by default. Exercises trading-client init (createOrDeriveApiKey, getBalanceAllowance, getMarketInfo) only when POLYMARKET_PRIVATE_KEY is set, and never places orders.

Run with node smoke-test.mjs after pnpm install && pnpm build.

Local run on this branch (signer = a fresh empty Polygon EOA):

✅ api.listActiveMarkets — returns array of active markets
✅ api.searchMarkets — query 'counter strike' returns results
✅ api.getMarketsByTag — find CS2 / esports markets
✅ api.getOrderBook — fetch real order book for a live token (35 bids / 29 asks, 0.5/0.52)
✅ trading.getSignerAddress — returns wallet address
✅ trading.getServerTime — CLOB v2 server reachable (drift 0.2s vs local)
✅ trading.getBalanceAllowance — pUSD balance + allowance
✅ trading.getMarketInfo — fetch tickSize/negRisk for a live token (0.01 / false / 1000bps)
Total: 8, Pass: 8, Fail: 0

Test plan

  • pnpm install (lockfile is regenerated in this branch)
  • pnpm build succeeds
  • node smoke-test.mjs — 4 read-only checks pass without env config
  • With POLYMARKET_PRIVATE_KEY set, the 4 additional trading-client init checks pass
  • Manual: place a small order in a non-prod context and verify it goes through the v2 exchange

Notes for reviewers

  • The @jsr/hk__polymarket Gamma SDK still transitively pulls @polymarket/clob-client (v1). It's unused by us now but I left it as a transitive dep to keep the Gamma read path untouched. Happy to also drop Gamma SDK + inline the few Gamma fetch calls if you'd prefer.
  • I picked minor for the changeset since this is a hard break for anyone running 0.0.18 against the live exchange. Tweak as you see fit.

Co-authored with Claude (Opus 4.7). Migration steps were derived from https://docs.polymarket.com/v2-migration and the official @polymarket/clob-client-v2 package types.

Polymarket migrated the exchange and collateral on April 28 2026:
USDC.e -> pUSD (1:1 USDC wrapper) and CLOB v1 -> v2. The legacy
@polymarket/clob-client (v1) is no longer compatible with the live
exchange — orders signed against the v1 contracts are rejected.

Changes:

- Swap @polymarket/clob-client@^4.22.8 for @polymarket/clob-client-v2@^1.0.6
  (plus viem as supporting dep). The v2 SDK uses an object-form
  constructor ({ host, chain, signer }), renames chainId -> chain,
  and exposes a single createOrDeriveApiKey() call.

- UserOrder / UserMarketOrder become UserOrderV2 / UserMarketOrderV2.
  The v2 types drop feeRateBps, nonce, and taker (server-side now);
  order construction in services/trading.ts updated accordingly.

- services/config.ts: collateral address points to pUSD
  (0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB), exchange addresses
  updated to v2 (0xE111180... and 0xe2222d2...). Added constants for
  USDC.e, CollateralOnramp, and CollateralOfframp to support future
  wrap/unwrap tooling.

- services/approvals.ts: collateral allowances target pUSD on the
  v2 exchanges. Renamed helper getUsdcContract -> getCollateralContract.

- services/redemption.ts: redeemPositions passes pUSD (not USDC.e) as
  the collateral token.

- services/api.ts: dropped PolymarketSDK (v1) from @jsr/hk__polymarket
  in favor of a direct /book fetch — the endpoint is public so this
  also removes the need to construct a CLOB client just to read order
  books. GammaSDK retained for market discovery (unaffected by the
  upgrade).

- tools/get-balance-allowance.ts, tools/update-balance-allowance.ts:
  AssetType imported from the v2 SDK.

Adds smoke-test.mjs — 8-check regression harness that hits live
Polymarket APIs read-only by default. Exercises trading-client init
(createOrDeriveApiKey, getBalanceAllowance, getMarketInfo) only when
POLYMARKET_PRIVATE_KEY is set, and never places orders.

Default signatureType semantics are unchanged — v2 ClobClient still
accepts signatureType + funderAddress for proxy-wallet flows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant