Skip to content

chore(v2): retire V1 paths post-cutover (closes #37)#51

Merged
smypmsa merged 6 commits intomainfrom
chore/v1-retire
Apr 28, 2026
Merged

chore(v2): retire V1 paths post-cutover (closes #37)#51
smypmsa merged 6 commits intomainfrom
chore/v1-retire

Conversation

@smypmsa
Copy link
Copy Markdown
Member

@smypmsa smypmsa commented Apr 28, 2026

⚠️ DRAFT — DO NOT MERGE BEFORE ~2026-05-05

Phase 3 of the V1 retirement plan. Open during the V2 soak window so the next agent session can pick it up with full context. Scaffold-only right now (empty commit) — real changes land when the soak completes and V2 is verified stable.

Closes #37.

Pre-merge gate

If any of those fail, hold this PR — V1 paths are the rollback escape hatch.

Scope (full V1 deletion)

Code deletion

  • backend/core/feature_flags.py — delete entire module
  • backend/core/trading/clob_client.py — delete _get_clob_client_v1, all V1 branches
  • backend/core/trading/clob.py — drop V1 order struct path
  • backend/core/trading/executor.py — drop V1 fee math (fees.py V1 path)
  • backend/core/positions/manager.py — drop V1 branches
  • backend/core/wallet/contracts.py — remove USDC_E, V1 CTF_EXCHANGE, V1 NEG_RISK_CTF_EXCHANGE entries
  • backend/core/wallet/manager.py::set_approvals — drop V1 approval branches
  • Helpers _collateral_address() / _exchange_addresses() — inline pUSD/V2 addresses directly at call sites
  • _split_position / _merge_tokens — drop the neg_risk parameter (kept only as log context after fix(v2): route NegRisk-flagged splits/merges through CTF, not the adapter #45; no longer affects routing)
  • Optionally: drop V1 NegRiskAdapter approvals from set_approvals (dead allowance after fix(v2): route NegRisk-flagged splits/merges through CTF, not the adapter #45)

Dependencies

  • backend/pyproject.toml — remove py-clob-client, keep py-clob-client-v2 only
  • uv lock after the dep removal

Tests

  • backend/tests/test_v2_collateral.py — drop V1 fixture + assertions, keep V2-only
  • backend/tests/test_v2_order_struct.py — drop V1 dataclass field-delta tests, keep V2-only
  • Any test that imports core.feature_flags — delete or rewrite

Schema/UI rename (optional but strongly recommended)

  • WalletBalances.usdc_epusd — cascade rename across:
    • backend/core/wallet/manager.py
    • backend/server/routers/wallet.py
    • frontend/components/** and frontend/hooks/** (wallet status consumers)
    • experiments/trading/* references

Experiments

Docs

Memory hygiene (out of repo)

  • Add polymarket_v1_retirement_plan.md to git so it travels with the repo (currently lives only in user's local memory at ~/.claude-corpo/.../memory/)

Post-merge operator step (not code)

  • Revoke V1 USDC.e approvals on the operator wallet (tx, manual)

Reference

Findings worth keeping (from live testing 2026-04-27, before deleting V1 code)

  • Gamma's negRisk: true is a UI grouping hint, not on-chain routing. Always route splits/merges through standard CTF using the conditionId Gamma returns (fixed in fix(v2): route NegRisk-flagged splits/merges through CTF, not the adapter #45). The neg_risk parameter on _split_position/_merge_tokens is now dead weight — remove it in this PR.
  • V1 NegRiskAdapter native split (splitPosition(bytes32,uint256)) is for true multi-outcome flows the bot does NOT use.
  • positions/service.py enrichment quirk: same wallet with multiple positions on same market+side shares on-chain CTF balance; each position's target_balance shows aggregate. Not V2-specific, pre-existing.
  • CTF.balanceOf(addr, gamma_clobTokenIds[0]) returns 0 — Gamma's clobTokenIds are CLOB identifiers, not on-chain CTF position IDs. Backend stores token IDs from split receipts, so this works in practice; do not "fix" by reading from Gamma.

Test plan (when this PR gets real changes)

  • pytest backend/tests/ green
  • ruff check backend/ clean
  • cd frontend && npm run typecheck clean (if usdc_epusd rename happens)
  • Pipeline runs end-to-end: make pipeline
  • /wallet/status returns expected pUSD balance
  • Live trade: POST /trading/buy-pair against V2 books
  • Position exit: POST /positions/{id}/exit works (sell + merge fallback)
  • Major version bump to v2.0.0 in any version file (semver — breaking change, V1 path removed)

Out of scope

  • Any behavior change beyond V1 deletion. Strictly cleanup.
  • New features. This is a removal PR.

🤖 Generated with Claude Code


Live V2 validation (2026-04-28, post-cutover)

Driven on real Polygon mainnet from wallet 0x1a0D3129Cf6bBA90ADC95C1048B60a9981CAFe71 after the cutover finished. Two extra fixes shaken out and bundled into this PR:

Fix 1 — V2 CLOB endpoint redirect

clob-v2.polymarket.com 301-redirects to clob.polymarket.com after Polymarket consolidated the V2 cutover. py_clob_client_v2's HTTP client doesn't follow redirects, so derive_api_key raised PolyApiException[status_code=301] and get_clob_client() returned None. Pointed CLOB_URL at the canonical host. (Same fix landed on main as c189a3c; this branch carries it forward so the squash-merge doesn't reintroduce the bug.)

Fix 2 — Gas estimation for split + merge

split and merge had gas: 300000 hardcoded. Chainstack RPC tightened limits post-cutover and started rejecting with INTERNAL_ERROR: gas limit is too high. Real usage is ~135k for split and ~90k for merge. Switched to estimate_gas() * 1.25. Verified live: a stuck $3 merge that failed at 300k went through cleanly with the estimate.

What was tested live (txn proofs)

Path Result Tx hash
Pipeline run (200 events) ✓ 180 portfolios, 76 profitable
Wallet unlock + status (V2 reads pUSD via active collateral)
/trading/buy-pair estimate
Split (CTF.splitPosition with pUSD) — target 0x0e03f82e29fe4d3aa49456dd52c2691b09094808ab84da6b0616d73414688496
Split — cover 0xb15ccd996c29a149d724dfe91691fef4db81c2a3860809498422558ca83eb803
Merge (CTF.mergePositions → pUSD) — target 0x6c6ddbb73e85f7dd34f904b6c78aa959b9c0f17d615d1966e07efbd53b344db4
Merge — cover 0x9c84cb6121edba06151137e573b9353d81bc83484c66962f5035591031cb425b
Merge under gas-fix (post-RPC ceiling tightening) — target 0x14fbf7ef6100dce158a7923069ed9415035d4da56d9502a975d5d0d04c6fd20c
Merge under gas-fix — cover 0x5a375146c607e83b979a048affee6b83da602a3e078ae2b763a09d3bd589b983
V2 CLOB client init (EIP-712 v2 derive_api_key)
Offramp.unwrap (pUSD → USDC.e) 0xff6cfb7e25c728feb3f324c9e14f59bde28e54e296c4410cb2263a2d9ea65c1f
Onramp.wrap (USDC.e → pUSD) 0x9bea271da849444bad6c9f7c559aa477fb52d7b057f0cc5aef555fc708f4acd9

Round-trip math: pUSD started 28.383236, ended 28.383236 after multiple buy/exit cycles + offramp/wrap roundtrip. Exact reversal. POL gas total: ~0.13 across 11 txns.

What's still untested (deferred, not blockers)

  • CLOB sell order signed + posted + filled. The V2 SDK init succeeds against the canonical host, but actual order posting hit 403 Trading restricted in your region — enable proxy from Polymarket's geo-block. Behaviour-correct for our IP, but the EIP-712 v2 signature post path can only be verified from a permitted region or via residential proxy. No code change indicated.
  • CTF.redeemPositions after a market resolves — we have no resolved market to test against. The bot has no built-in redeem endpoint; users redeem manually until that ships.
  • Fresh-wallet WalletManager.set_approvals() — current wallet already has approvals set. The V2 approval list is correct in code (5 calls: pUSD→CTF/CTF_EXCHANGE/NEG_RISK_CTF_EXCHANGE + CTF→CTF_EXCHANGE/NEG_RISK_CTF_EXCHANGE) but only verified via approvals_set: true read, not by running set_approvals from scratch.

Out of scope for this PR

  • The POST /pipeline/run/production background task wedges silently if the LLM step fails during the run (status keeps reading running: true even after the bg task dies). Cosmetic, not migration-related; file as a separate issue.

Summary by CodeRabbit

Release Notes

  • Documentation

    • Updated guides to reflect Polymarket V2 as the sole trading platform; legacy V1 support retired as of 2026-04-28.
  • Chores

    • Removed feature-flag-based configuration; system now operates exclusively on V2.
    • Consolidated collateral to pUSD; all wallet balances and trading now use pUSD instead of USDC.e.
    • Simplified wallet approval flow to support only V2 exchange contracts.

Empty marker commit so the draft PR can exist. Real changes will be
pushed when this branch is picked up post-soak.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

Warning

Rate limit exceeded

@smypmsa has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 58 minutes and 24 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d9cce6e2-46c6-44cb-bf21-08335f61a1bc

📥 Commits

Reviewing files that changed from the base of the PR and between c189a3c and 94c7a0e.

⛔ Files ignored due to path filters (1)
  • backend/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • .claude/skills/alphapoly-enter-position/SKILL.md
  • .claude/skills/alphapoly-enter-position/api-reference.md
  • .claude/skills/alphapoly-exit-position/api-reference.md
  • .env.example
  • CLAUDE.md
  • README.md
  • backend/core/feature_flags.py
  • backend/core/positions/manager.py
  • backend/core/trading/clob.py
  • backend/core/trading/clob_client.py
  • backend/core/trading/executor.py
  • backend/core/wallet/contracts.py
  • backend/core/wallet/manager.py
  • backend/pyproject.toml
  • backend/server/routers/trading.py
  • backend/server/routers/wallet.py
  • backend/tests/test_v2_collateral.py
  • backend/tests/test_v2_order_struct.py
  • experiments/trading/01_setup_wallet.py
  • experiments/trading/02_swap_to_usdc_e.py
  • experiments/trading/03_buy_position.py
  • experiments/trading/04_transfer_tokens.py
  • frontend/components/PortfolioModal.tsx
  • frontend/components/terminal/WalletDropdown.tsx
  • frontend/hooks/useWallet.tsx
📝 Walkthrough

Walkthrough

This PR completes the Polymarket V2 cutover by removing all V1 code paths, deleting the POLYMARKET_V2_ENABLED feature flag, and consolidating the system to exclusively use Polymarket V2 with pUSD collateral. Legacy imports, branching logic, contract addresses, and V1 dependencies are eliminated throughout the backend, frontend, and experiment scripts.

Changes

Cohort / File(s) Summary
Documentation & Examples
.claude/skills/alphapoly-enter-position/SKILL.md, .claude/skills/alphapoly-enter-position/api-reference.md, .claude/skills/alphapoly-exit-position/api-reference.md, CLAUDE.md, README.md, .env.example
Updated to reflect V2-only usage with pUSD collateral; removed references to POLYMARKET_V2_ENABLED feature flag, cutover timing logic, and V1 fallback guidance.
Feature Flag Removal
backend/core/feature_flags.py
Deleted entire module containing v2_enabled() function that parsed POLYMARKET_V2_ENABLED environment variable.
Contract & Collateral Management
backend/core/wallet/contracts.py, backend/core/wallet/manager.py
Consolidated contract addresses to V2-only set; removed legacy USDC_E, V2_CONTRACTS dict, and NEG_RISK_ADAPTER; updated WalletBalances to use pusd instead of usdc_e for stablecoin tracking.
Trading & Position Management
backend/core/trading/clob.py, backend/core/trading/clob_client.py, backend/core/trading/executor.py, backend/core/positions/manager.py
Removed all V1 CLOB client branches and feature-flag-based routing; always use py_clob_client_v2; simplified position merging to always use CTF with pUSD collateral; replaced fixed gas limits with dynamic estimation; updated balance tracking to use pusd.
Server Routes & API
backend/server/routers/trading.py, backend/server/routers/wallet.py
Updated endpoint balance reporting and sufficiency checks from usdc_e to pusd; updated user guidance messaging to reference pUSD.
Test Suite
backend/tests/test_v2_collateral.py, backend/tests/test_v2_order_struct.py
Deleted feature-flag routing tests and V1 collateral tests; refactored V2 order struct tests to validate V2 fields only (removed V1-specific assertions).
Dependencies
backend/pyproject.toml
Removed py-clob-client>=0.34.5 dependency; retained only py-clob-client-v2==1.0.0.
Frontend Components
frontend/components/PortfolioModal.tsx, frontend/components/terminal/WalletDropdown.tsx, frontend/hooks/useWallet.tsx
Updated TradeResult and WalletBalances interfaces and balance display logic from usdc_e to pusd; changed wallet balance rendering to use pUSD field.
Experiment Scripts
experiments/trading/01_setup_wallet.py, experiments/trading/02_swap_to_usdc_e.py, experiments/trading/03_buy_position.py, experiments/trading/04_transfer_tokens.py
Removed feature-flag parsing and V1 branching; fixed scripts to use only V2 CLOB client and pUSD collateral; updated approval/balance logic to query pUSD token only; updated on-chain interactions and user messaging to reference pUSD.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 The V1 paths now rest, their branching code set free,
pUSD reigns where USDC.e once used to be,
Feature flags fade as V2 takes the crown,
One true path forward—no more switching down! 🎉

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/v1-retire

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

smypmsa and others added 5 commits April 28, 2026 13:52
V1 endpoints stopped accepting orders at 2026-04-28 11:00 UTC. The
POLYMARKET_V2_ENABLED flag flipped default in PR #49 (commit 306cbcb);
this PR removes the V1 code path entirely.

Backend:
- Delete core/feature_flags.py and the V2_CONTRACTS namespace; merge V2
  addresses into CONTRACTS (CTF_EXCHANGE / NEG_RISK_CTF_EXCHANGE now hold
  V2 addresses, plus PUSD / onramp / offramp).
- core/wallet/manager.py: drop _collateral_address/_exchange_addresses
  helpers, drop NEG_RISK_ADAPTER approvals (dead allowance after #45),
  rename WalletBalances.usdc_e -> pusd.
- core/trading/clob_client.py: delete _get_clob_client_v1 and the V1
  endpoint; CLOB client is V2 only.
- core/trading/clob.py: drop V1 import branch.
- core/trading/executor.py and core/positions/manager.py: drop V1
  collateral helpers and the vestigial neg_risk parameter on
  _split_position / _merge_tokens (Gamma's negRisk is a UI hint, not
  on-chain routing — see #45).
- pyproject.toml: drop py-clob-client dep, keep py-clob-client-v2.

Tests:
- Delete test_v2_collateral.py (V1/V2 branch tests no longer meaningful).
- Strip V1 fixtures from test_v2_order_struct.py.

Routers / frontend: cascade rename usdc_e -> pusd through
server/routers/wallet.py, server/routers/trading.py,
hooks/useWallet.tsx, components/PortfolioModal.tsx,
components/terminal/WalletDropdown.tsx (label updated to "pUSD").

Experiments: remove duplicated _v2_enabled() in 01_setup_wallet.py,
03_buy_position.py, 04_transfer_tokens.py; hardcode V2 paths.

Docs: drop the V2 cutover banner from README.md and the cutover section
in CLAUDE.md; drop POLYMARKET_V2_ENABLED line from .env.example.

Operator post-merge step (not code): revoke V1 USDC.e approvals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update collateral terminology to match V2: rename `usdc_e` -> `pusd` in
example wallet/balance JSON, swap "USDC.e" -> "pUSD" in instructional
prose. The other four alphapoly skills (feature, experiment, pipeline,
portfolios) had no V1 references and were left alone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Main got a fix at c189a3c — Polymarket consolidated clob-v2.polymarket.com
into clob.polymarket.com post-cutover. This branch was rewriting the same
file with the old URL, which would have re-introduced the bug at squash-merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hardcoded gas: 300000 was rejected by Chainstack RPC under stricter
post-cutover limits ('INTERNAL_ERROR: gas limit is too high'). Actual
usage is ~135k for split and ~90k for merge. Estimate live and apply
25% headroom.

Verified live during V2 validation: a stuck $3 merge that failed under
the old hardcoded limit went through cleanly with the estimate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	backend/core/trading/clob_client.py
@smypmsa smypmsa marked this pull request as ready for review April 28, 2026 14:39
@smypmsa smypmsa merged commit c4491d0 into main Apr 28, 2026
1 check was pending
@smypmsa smypmsa deleted the chore/v1-retire branch April 28, 2026 14:39
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.

chore(v2): retire V1 paths post-cutover

1 participant