T4 of the autotrade build wired up ClobMarketData, the real MarketData impl that the scheduler will call at runtime to resolve a condition ID into a ResolvedMarket before placing an order.

What was built

  • crates/polymarket-fetch/src/pmv2/autotrade/market_data.rs — new file

    • pub fn assemble(meta: MarketMeta, book: &BookTop, category: Option<String>) -> ResolvedMarket — pure, #[must_use], 1:1 field mapper from clob types to engine types. Takes &BookTop (not by value) to satisfy the clippy pedantic needless_pass_by_value lint; fields are Copy Decimals so the borrow is costless.

    • pub struct ClobMarketData<'a> — holds &'a ClobClient, &'a GammaClient, &'a PgPool. Borrow-based so construction is cheap on every scheduler tick.

    • #[async_trait] impl MarketData for ClobMarketData<'_> — calls clob.market_meta(condition_id), resolves outcome_index to token_id via clob_token_ids, calls clob.book_top(&token_id), calls resolve_category(pool, gamma, event_slug), then delegates to assemble().

    • Unit test assembles_resolved_market_from_parts — exercises assemble() in isolation, no I/O.

  • crates/polymarket-fetch/src/pmv2/autotrade/mod.rs — added pub mod market_data; in alphabetical order among module declarations.

Clippy gotcha

Pedantic lint needless_pass_by_value fired on the original book: BookTop parameter to assemble(). Fix was straightforward: change to book: &BookTop. Because BookTop fields are Copy Decimals there is no ergonomic cost to borrowing.

Gate result

EXIT_CODE=0, 245 tests passed.