LZLZL/Prediction markets/Engineering
FREEDO IT G · EngineeringData traps

Eight API traps

2026-08-21 · all measured, all corrected — one of them after I published a wrong figure

Every one of these endpoints returns something that looks completely normal: data present, well-formed, no error. The problem is that it is not the thing you assumed — truncated, differently based, or a placeholder. All eight caught me; one of them made me publish a conclusion I later withdrew.

1A real failure, first

I ran a census of winners to answer a natural question: with $1,000 of capital, following the top players' approach, how far can you get?

The method looked fine: query each winner's profit from the leaderboard, query their holdings from another endpoint, divide the two for "capital efficiency", and scale to $1,000. The answer came out at $1,000 → $3,723.

It is wrong, and badly. One sentence explains it:

the numerator is "lifetime"; the denominator is "right now" dividing two different time scales produces nothing meaningful

The sample contained a wallet with $4.55M of lifetime profit and $5,700 of current holdings — a long-retired player who had withdrawn. Dividing made it a god that turned a few thousand into millions, and it dragged the entire estimate with it.

I withdrew the figure. The endpoint did not lie; I failed to ask which time scale it spoke in. The eight below are all versions of that same failure.

2The eight

#Endpoint / fieldYou assumeActually
activity feedthis wallet's full historyat most 5,500 rows; older data unreachable
the same, on a busy walletenough to compute a daily ratemay cover only hours
leaderboard /profitwhat this person earnedexcludes all subsidy income
/profit ÷ holdingscapital efficiencylifetime ÷ instant — meaningless
one large recipient addressa whalecontaminates every statistic; must be excluded
clobRewards: []this board has no rewardsdoes not follow; use the authoritative endpoint
public RPC eth_getLogsany provider will serve chain queriesmost refuse outright; the workable one is limited
/rebates/currentdocumented as public, returns rebatesreturns None

3Traps that break your rate calculations

① The activity feed is capped at 5,500 rows

Paging looks like it continues indefinitely. It stops at 5,500 — no error, no notice, simply nothing more. So what you hold is always a recent slice, never a lifetime, and how long that slice covers depends entirely on how active the wallet is. Two wallets I took apart differed by more than an order of magnitude:

Wallet type5,500 rows coveredIf you assume lifetime
mid-frequency arbitrage18.5 daysyou call two weeks a career
high-frequency market makingabout 30 hoursyou call one day a career

② So "per day" comes out wrong

⚠ Divide by the real elapsed span, not the number of days you assumed

On receiving the data, first check the gap between the first and last timestamps and use that as the denominator.

And the subtler part: the truncated portion may be its most profitable period. A wallet that was unusually active during a high-return phase generated the most rows then — exactly the rows the 5,500 cap discards. You are seeing its present, not its peak.

4Traps that make you misread other people

③ The leaderboard's "profit" excludes subsidies

This one matters most, because the leaderboard is where everyone starts copying. That field is trading P&L, and the venue's rewards and rebates are transfers, not trades — they do not enter it.

real net income = trading P&L + total received two queries, then add

It cuts both ways: you underrate players who live on subsidies (their leaderboard number can be poor or negative while they earn steadily), and if you count your own subsidies as strategy income you overrate your strategy. Detail in subsidies are not P&L.

④ Lifetime divided by instant

The §1 failure. The rule: before dividing, confirm both numbers share a time scale.

⚠ A related one: fields with no stated window

Some "volume traded" fields do not state their measurement window. A number with an unknown window must never be divided by one with a known window. No denominator, no division — that is a hard rule.

⑤ One address contaminates the statistics

Enumerating reward recipients you will meet an address receiving $600k to $920k per day inside the batches, with no corresponding trading record on the leaderboard.

It is plainly not an ordinary participant. Any per-capita, median or distribution statistic must exclude it first, or one address skews the whole shape.

BasisI state only that it contaminates the measurement. No identity attribution is made — I do not know whose it is and have not looked.

5Traps that mislead you about markets, or simply block you

⑥ An empty rewards array proves nothing

The obvious way to find boards with rewards is the clobRewards field on the events endpoint. An empty array does not license the conclusion "no pool".

The authoritative source is the matching layer's sampling-markets endpoint. Pulling it in full returned 8,631 boards carrying a genuinely live rate — an entirely different set from filtering on clobRewards.

⚠ Same family: a metadata field existing does not mean the thing happens

Board metadata carries fields like minimum size for rewards and maximum spread. Their presence does not mean money is paid — they are part of a config template.

There is exactly one dependable way to establish "does this pay": query the authoritative endpoint, or look on-chain for actual payments.

⑦ Most public RPC providers will refuse you

ProviderMeasured
publicnode / polygon-rpc / ankrall refused (403 / 401 / key required)
1rpcrate limited
drpcworks, but requires an address filter and ≤ 40 blocks per call

Chain-wide queries without an address filter are refused at every block range. So "pull all of a contract's events" becomes thousands of small calls on free tiers.

⚠ A hard one to diagnose: raw calls need a User-Agent

If you hand-assemble JSON-RPC requests rather than using a library, send a User-Agent header — otherwise you are silently refused. Library users never hit this, because libraries set one.

Silently is the operative word: it does not say "missing header", it just returns nothing. This is the hardest class of failure to diagnose, because it looks exactly like "there is no such record on-chain".

⑧ A documented endpoint that returns None

/rebates/current is documented as requiring no authentication. In practice it returns None, and I did not find the parameter shape.

Do not spend time on it: the same information is available from the activity feed — split income by record type, sum transfers and trades separately. Equally reliable, and verifiable.

There is a separate endpoint that does reconcile precisely (per-day, per-board detail), but it requires authentication and only serves your own account — useful for your own books, useless for censusing others.

6A few that missed the cut

TrapNote
Leaderboard capped at 50paging parameters are entirely ignored; ranks 100–200 are not exposed
Holder index lagsby minutes. A single snapshot is unreliable — union across snapshots
Rewards paid ~400 per batchnot a trap, a shape you must know to parse: hundreds of recipients in one transaction
Config "base fee" fieldsthe two base-fee values are raw config, not the actual rate. Do not compute with them

7The general rule

Abstract all eight and they are one mistake: taking what the endpoint gave you as what you wanted.

Anything that looks complete should be proven complete

The check is cheap and needs doing once:

① Count the rows. If the count is exactly a round number — 5,500, 50, 1,000 — you almost certainly hit a cap rather than the end.

② Read the first and last timestamps. What span does it really cover, and is that what you assumed?

③ Validate against a case whose answer you know. Take one of your own records, or something independently verifiable on-chain, and check the endpoint agrees.

④ Distinguish the kinds of empty. "There genuinely is none" and "this endpoint will not tell you" are completely different facts — and they return identical-looking data.

The fourth is the most expensive lesson here. I have paid for "absent read as non-existent" elsewhere too: once treating "no record in the activity feed" as "no loss" (off by eight times), and once treating "the position list is empty" as "the position is closed" when it was ingestion lag (the redeemable trap).

8One line to keep

These endpoints do not lie. They answer a slightly different question from the one you asked. So before dividing anything, ask three things: how long does it cover, what types does it include, and which kind of empty is this?

EvidenceCheck it yourself

The 5,500 cap two independent teardowns hit the same figure: one wallet at 18.5 days, another at 30 hours (5,377 trades + 60 merges + 61 redemptions + 2 maker rebates = exactly 5,500). Reproduce by paging any busy wallet.
The withdrawn estimate "$1,000 → $3,723" was published by me and later withdrawn; the cause is in §1. The withdrawal record stands and is not deleted.
/profit excludes subsidies sum one wallet's leaderboard profit and its on-chain receipts separately; they do not overlap.
Contaminating address $600k–920k per day inside the batches with no corresponding trading record. Publicly visible on-chain; no identity attribution is made here.
Authoritative reward source full pull of the sampling-markets endpoint gives 8,631 boards with live rates.
RPC behaviour the refusal codes from three public providers and drpc's 40-block ceiling, reproduced on three consecutive days during the census.
Checked 2026-07 to 2026-08. Endpoint behaviour changes; verify before relying on any of this.
Not included my own wallet addresses, hosts or keys, and any strategy parameters. Third-party addresses referenced here are public on-chain data, used only to illustrate a measurement basis, with no identity attribution.

NextWhere to go

G · ENGINEERING
589 shares evaporated
G · ENGINEERING
Subsidies do not appear in trading P&L
G · ENGINEERING
The redeemable trap
F · METHOD
Leaderboards are lagging indicators
This is an educational and research record. It is not investment advice, promises no returns, and offers no personalised trading recommendations. Rules and API behaviour are per the official documentation; this page states when it was checked and both can change without notice. Prediction markets are restricted or unavailable in some jurisdictions — confirm your own before taking part.