Home / Solutions / Prediction Markets
Prediction Markets

Prediction market data: fills, position transfers, and resolutions

Polymarket matches orders offchain, but every executed trade, position transfer, resolution, and redemption settles on Polygon as a contract event. SQD serves that stream decoded from one endpoint, across 225+ networks, with full history for backtesting. Odds and positions are computations you own downstream; the Portal serves the fills and transfers they derive from.

225+ Networks
Fills Executed prices
ERC-1155 Position transfers
Genesis Full history
The problem

An odds feed is a data product, and the chain is the only place the fills are recorded

Every price on the board, every open position, and every resolved market is read back off Polygon. Polymarket matches orders offchain, but each executed trade, position transfer, resolution, and redemption settles as a contract event, so the odds series, the position ledger, and the settlement record are all rebuilt from those logs. Rebuilt the naive way, that means paging eth_getLogs against per-provider block-range and result caps on an archive node, chasing exchange contracts that rotate out from under a hardcoded address, and decoding ERC-1155 outcome shares that carry no symbol or metadata. It is all onchain already; the cost is in how you read it.

How it works

The fill is the market: one OrderFilled, decoded

Every executed order settles on Polygon through the exchange contracts, which emit one OrderFilled log per filled order. On the main CTF Exchange, block 89,900,000 (2026-07-08, 23:56:35 UTC) carries 78 of them. The first decodes against the CTF Exchange V2 ABI to:

FieldValue
  • maker0xee65685de42f8de9a03b4c53ee77d56a20d2cfc9
  • taker0x0d7dfb4f0299335c81991c8c011df5d7cebb15c0
  • side0 = BUY
  • tokenId0x51bc63293c6fa772319a2c67aeaac8106e334e1690cb6a8104f1b46d52a07277
  • makerAmountFilled154,639
  • takerAmountFilled5,154,633
  • fee0
The first OrderFilled in block 89,900,000; amounts in the collateral token's 6-decimal units

The query is one filter on the exchange contract and the event's topic0, pinned to a block:

your terminal
curl -s -X POST https://portal.sqd.dev/datasets/polygon-mainnet/stream \
-H 'content-type: application/json' \
-d '{
"type": "evm",
"fromBlock": 89900000, "toBlock": 89900000,
"logs": [{
"address": ["0xe111180000d2663c0091e4f400237545b87b996b"],
"topic0": ["0xd543adfd945773f1a62f74f0ee55a5e3b9b1a28262980ba90b1a89f2ea84d8ee"]
}],
"fields": { "log": { "topics": true, "data": true, "transactionHash": true, "logIndex": true } }
}'

The maker bought 5.154633 shares of one outcome for 0.154639 collateral units: an executed price of 154,639 / 5,154,633, 3.0 cents per share. In the same transaction (0xb492…831d) the complementary order filled at 4,999,994 / 5,154,633, 97.0 cents, and 154,639 + 4,999,994 = 5,154,633: the exchange minted a fresh 5.154633-share complete set, handed one side to each buyer, and the two prices sum to exactly one dollar. The 97-cent side also paid a 10,490-unit fee, the fee field on its own fill row.

That 3.0 cents is the implied probability read. Every odds feed, price chart, and calibration study is this arithmetic run over the fill stream; the Portal serves the stream it runs on. The maker and taker sit on that same row, which is what an order-flow feed keys on: Polygains runs real-time Polymarket whale and insider alerts on SQD.

The first of the 78 rows it returns, verbatim:

the first OrderFilled row
{
"logIndex": 328,
"transactionHash": "0xb492fa7001d912413ecb52440877e85f843293bc53aa9219b2070044d62d831d",
"data": "0x00000000…00000000",
"topics": [
"0xd543adfd945773f1a62f74f0ee55a5e3b9b1a28262980ba90b1a89f2ea84d8ee",
"0xd540db43d8c3a1bf053b19149417144b7d63eb446179e3377d2363fadd48b3d6",
"0x000000000000000000000000ee65685de42f8de9a03b4c53ee77d56a20d2cfc9",
"0x0000000000000000000000000d7dfb4f0299335c81991c8c011df5d7cebb15c0"
]
}

The data field is a 450-character ABI-encoded blob, elided here to its first and last bytes; the curl above returns it in full, and every value it encodes is decoded in the table above.

Show the full raw row
the full raw row
{
"logIndex": 328,
"transactionHash": "0xb492fa7001d912413ecb52440877e85f843293bc53aa9219b2070044d62d831d",
"data": "0x000000000000000000000000000000000000000000000000000000000000000051bc63293c6fa772319a2c67aeaac8106e334e1690cb6a8104f1b46d52a072770000000000000000000000000000000000000000000000000000000000025c0f00000000000000000000000000000000000000000000000000000000004ea749000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"topics": [
"0xd543adfd945773f1a62f74f0ee55a5e3b9b1a28262980ba90b1a89f2ea84d8ee",
"0xd540db43d8c3a1bf053b19149417144b7d63eb446179e3377d2363fadd48b3d6",
"0x000000000000000000000000ee65685de42f8de9a03b4c53ee77d56a20d2cfc9",
"0x0000000000000000000000000d7dfb4f0299335c81991c8c011df5d7cebb15c0"
]
}

One gotcha before you sum volume: a matched trade emits OrderFilled twice, once per order, and on the taker order's row the taker field is the exchange contract itself. Adding both sides double-counts every trade; count executions from the single OrdersMatched event each match also emits, or from one side of the fills.

Settlement

Resolution and redemption ride the same log stream

Positions and settlement are events on one contract: outcome shares are ERC-1155 conditional tokens on ConditionalTokens, a market resolves when its oracle reports the payout vector, and each holder's claim is a PayoutRedemption event. Everything below is one 1,001-block window, queried live:

EventContractCount
  • OrderFilledCTF Exchange V2 + Neg Risk Exchange101,651
  • TransferSingleConditionalTokens113,498
  • TransferBatchConditionalTokens87,989
  • PayoutRedemptionConditionalTokens16,628
  • ConditionResolutionConditionalTokens193
  • OrderFilledlegacy exchange 0x4bFb…982E0
Polygon blocks 89,900,000 to 89,901,000, 2026-07-08 23:56:35 to 2026-07-09 00:21:35 UTC (25 minutes)

Inside that window, at block 89,900,184, condition 0xe9f2…acef resolved in transaction 0x1fc6…8fa3: a ConditionResolution event with payoutNumerators [0, 1], so the second outcome redeems at the full collateral unit and the first at zero. Its oracle topic is 0xd91E…5296, the Neg Risk Adapter in Polymarket's contract registry, so the resolving contract is part of the record, not an assumption.

The row that reads zero: the exchange address most tutorials and repos still carry, 0x4bFb…982E, emitted zero fills in this window; every one of the 101,651 came from the V2 contracts (0xE111…996B and 0xe222…0F59), whose OrderFilled also has a different topic0: V2 replaced the asset-id pair with side and tokenId and added builder and metadata fields. Sneakier still, the legacy contract emitted 158 TokenRegistered events in the same window, so a monitor pointed at it sees signs of life while reading zero trades. An address is a filter parameter here: following the rotation is adding the new contracts to the list and re-streaming, with both eras' history behind the same endpoint.

The volume is why this is harder over raw RPC: 201,487 ERC-1155 transfer events rode through ConditionalTokens in these 25 minutes alone, and a backfill to the contract's first market means paging eth_getLogs against per-provider block-range and result caps on an archive node. Conditional tokens also sit outside what curated token APIs model: an outcome share is an ERC-1155 position ID with no symbol and no metadata, so its transfers, splits, and merges exist only in the raw log stream the Portal serves.

Capabilities

Built for Prediction Markets at scale

The fill stream, decoded

One filter on the exchange contract and the OrderFilled topic0 returns every executed order: maker, taker, side, tokenId, amounts filled, and fee. The ratio of the amounts is the executed price of the outcome share, the number every odds feed is built on.

Positions as ERC-1155 transfers

Outcome shares are conditional tokens with no symbol and no metadata, so curated token APIs do not model them. The Portal serves their TransferSingle and TransferBatch stream raw: transfers, splits, and merges, keyed to the ConditionalTokens contract.

Resolution and redemption events

A market resolves when its oracle reports the payout vector: one ConditionResolution event with the oracle address in its topics. Each holder's claim is a PayoutRedemption event. Settlement rides the same log stream as trading, in the same query shape.

Venue rotation without re-indexing

An exchange address is a filter parameter. When a venue rotates contracts, as Polymarket did to its V2 exchanges, you add the new addresses and re-stream, with both eras' history behind the same endpoint. A venue on another chain is a dataset name change.

Why SQD

What you would build yourself

The fills, transfers, and resolutions are all public Polygon events; the work a provider saves is in reading them at volume and following the contracts that emit them.

  • Backfill depth
    Yourself Page eth_getLogs back to a market's first block against per-provider block-range and result caps, on an archive node.
    With SQD One filtered query on the contract streams the full history from the Portal, with no eth_getLogs paging to code around.
  • Venue rotation
    Yourself A monitor pinned to the exchange address most repos still carry reads zero fills after the venue rotates contracts, while trading continues on the new ones.
    With SQD An address is a filter parameter: add the new contracts to the list and re-stream, with both eras' history behind one endpoint.
  • Outcome positions
    Yourself Curated token APIs do not model conditional tokens: an outcome share is an ERC-1155 position id with no symbol and no metadata.
    With SQD The Portal serves the TransferSingle and TransferBatch stream raw, so splits, merges, and transfers all arrive in the log stream.
  • Other venues
    Yourself Each event market on another chain is a separate integration to build and run.
    With SQD A venue on another chain is a dataset name change in the same query shape.

See this on your own contracts

Tell us the chains and contracts you care about, and we will show you the query that returns them.

Use cases

What teams build with SQD

  • Odds and price-history feeds computed from executed fills
  • Market resolution and settlement monitoring
  • Position tracking from conditional-token transfers
  • Backtesting and calibration research on full fill history
  • Per-market volume and trader analytics
  • Redemption and payout reconciliation

Frequently asked questions

How do I get Polymarket data from an API?
Polymarket matches orders offchain, but every executed trade, position transfer, resolution, and redemption settles on Polygon as a contract event. One filtered query against SQD's polygon-mainnet dataset returns the OrderFilled stream from the current CTF Exchange contracts, and the same query shape reads the ERC-1155 transfers and resolution events from the ConditionalTokens contract. Market titles and categories are not onchain: Polymarket publishes those through its own metadata API, and you join them on tokenId or conditionId.
Can I compute live odds from this data?
Yes, as arithmetic on executed prices. Each OrderFilled carries makerAmountFilled and takerAmountFilled, and their ratio is the executed price of the outcome share, between 0 and 1, which is what a probability read off a prediction market is. SQD serves the fills as they confirm, plus the full history for backtesting; the last-price, mid, or time-weighted odds series is a computation you own downstream. The Portal does not return probabilities as a field.
Does this work for prediction markets other than Polymarket?
Yes. Any event market that settles on a public chain is the same work: pin the venue's contracts, decode its fill and resolution events against the ABI, and stream. SQD serves 225+ networks through one query shape, so a venue on another chain is a dataset name change, not a new integration. Levr.Bet runs its prediction-market data on SQD.
Get started

Your blockchain data infrastructure, handled.

Private Portal. Dedicated. Validated. Managed. Tell us what you're building, we'll show you what it looks like on SQD.