vike
Venues

Polymarket operations

The operational rules the generated venue page cannot carry — no testnet, the two opt-ins, the region pre-flight, resolution-aware settlement and auto-redeem, and the SOCKS egress.

The generated Polymarket page renders the capability tables. This page carries what a table cannot hold. This is the most trap-laden bridge in the workspace — no testnet, two opt-in gates, a region pre-flight, chain-verified settlement and a metered cancel lane — and every rule below exists because of something that happened.

No testnet, so the venue is opt-in twice

Every other venue has a demo tier. This one does not. mount.rs's poly_exec_enabled puts it plainly: "Polymarket has no testnet: every order this mounts is real money on Polygon mainnet, so the venue is opt-in twice over (creds AND this flag) rather than the usual once." The second gate exists so that "an operator who merely has keys in their .env — which the reconcile half, the data feeds and the redeem poller all legitimately want — cannot accidentally arm order placement."

Two independent gates, both the exact string "1" rather than a fuzzy truthy parse, read from the process environment first and the credential store second — where config.rs's first_token takes the first whitespace-separated token, so an annotated .env line (POLY_EXEC=1 # real money) still arms:

flagwhat it mounts
POLY_EXEC=1the live ExecutionClient — real orders, and inseparably the authenticated user-WS fill pump
POLY_RECONCILE=1the ReconClient, independently

"The two compose: exec-only, recon-only, both, or neither." Both unset — the default — builds nothing and makes no network call, and the arm compiles only under vike-mount's polymarket feature, so a default build has no arm at all. Mounting exec starts the fill pump whether you want it or not, deliberately: "on this venue every post-acceptance terminal arrives only on the user channel, so exec without the pump would accept orders that can never reach a terminal." Both halves share one registry and one L2 handshake, because "a fresh registry for the recon half makes every order report come back with no client order id."

The region pre-flight

Polymarket restricts order placement by region and nothing else: from a restricted egress "the market feeds stream, /auth/derive-api-key succeeds and every authenticated READ … comes back green, while a submit returns a 403". A wrong-region session looks healthy right up to the first order, so a live exec mount asks the venue first, through the same proxy the orders will use. geoblock_action is the decision: a Blocked verdict refuses the mount, naming the country and region; an Unknown verdict — probe unreachable, body unreadable — only warns, because "an unreachable pre-flight is evidence of nothing". Feeds are never gated on it. POLY_GEOBLOCK_OVERRIDE=1 skips the check, is read from the credential store only, and "ARMS nothing on its own".

The SOCKS egress

Every POLY_PROXY_* knob resolves through egress.rs's proxy_var: "the REAL process env first, the gitignored workspace .env map second". That second tier is a bug fix — values written where every other Polymarket setting lives "were SILENTLY IGNORED", and the failure hid because "the built-in defaults (enabled = true, 127.0.0.1:1080) happen to match the usual tunnel; move the tunnel to another port in .env and the agent kept dialling 1080." The fallback is a fixed five-key allow-list (PROXY_KEYS), read once and cached.

check_expected_egress asserts the tunnel is really carrying traffic. It is opt-in and inert: with POLY_EXPECT_EGRESS_COUNTRY unset it "performs no network call at all"; set it and a live smoke "fails LOUDLY, naming the observed IP/country, instead of limping on". It rides the same proxy-aware agent every REST call uses.

Settlement and auto-redeem

A market resolves on-chain, "the local book must flatten at its payout, and winning tokens must be redeemed for collateral — none of which any CLOB endpoint reports as a fill" (settlement/mod.rs). Nine modules answer that, all opt-in, with no composition-root wiring today: a default build "never opens a Polygon RPC socket, never posts to the gasless relayer". Three gates, one per driver — POLY_CHAIN_WATCH=1 (the read-only chain watcher, "never signs, never sends a transaction"), VIKE_PM_RESOLVE=1 (the local settlement fill that flattens a resolved position and moves no money), and POLY_AUTO_REDEEM=1 plus credentials, with the POLY_REDEEM_HALT kill switch checked every tick, for the poller that moves real money.

redeemable: true is a resolution flag, not a winner flag

Measured on this repository's own mainnet wallet on 2026-07-23: all four held positions came back redeemable: true, three of them plain losers (curPrice: 0, cashPnl: -100%). Settling off the flag would have fabricated roughly 29 USDC of profit; redeeming off it submitted four relayer calls where one paid. Both drivers now price from the CTF's own payoutNumerators and fail closed: the settlement poller through settlement/resolve.rs's PayoutSource::Chain, the default — "no chain verdict ⇒ the leg is not due and NOTHING is emitted this pass — a delay, never a guess" — and auto-redeem through RedeemDeps::payout ⇒ redeemable_by, which ProdDeps answers from the same numerators via a cached ChainOracle. An unreachable Polygon RPC means they settle nothing.

Chain payouts close three gaps the flag cannot: "a resolved LOSER with no redeemable row anywhere settles, an 'ambiguous' condition settles correctly instead of being skipped, and a SPLIT resolution (payoutNumerators [1,1] / 2) settles at its true 0.5." Auto-redeem then separates submitting from settling: a relayer HTTP 2xx "means it accepted a signed batch … not that the redemption was mined, and not that it succeeded", so each tick confirms in-flight redemptions against the chain before it discovers and submits, and writes its ledger record before the relayer is contacted.

Cancels are metered here, and only here

This is the one venue in the workspace that sheds a cancel. A Routine cancel — a strategy's own requote churn — is refused while the cancel bucket sits at or below its reserve and returns a non-terminal OrderCancelRejected, so the order is still resting and the caller must re-offer it. Every other intent fires. The account-wide bulk cancel is never to be called directly: "it debits one token up front plus one per order the venue actually cancels, which can drive the cancel bucket NEGATIVE and lock out every subsequent cancel."

Which reconcile policy is defensible

It depends on which gates are on, and PositionDrift — one of the two kinds hybrid actually folds — is the mechanism in both hazards. Reconciling without exec diffs live venue state against a paper engine, so on any token the paper engine also traded it "folds the LIVE account's position into the PAPER engine's books at the venue's avg price and books realized PnL the paper run never earned". Separately, a resolved market moves position to cash with no fill, which surfaces as drift too, and is what the chain watcher closes.

POLY_RECONCILE=1 alone means quarantine only

Run reconcile-without-exec under VIKE_RECONCILE_POLICY=quarantine. POLY_EXEC=1 plus POLY_RECONCILE=1 — and POLY_CHAIN_WATCH=1 for settlement truth — is what makes hybrid defensible: with exec mounted "both sides are the SAME account, so PositionDrift converges two views of one book instead of importing one into the other."

Market data is a separate matter — the feeds plane is keyless and links no signing crate — and the historical collectors are covered under data providers.

On this page