Skip to content

Conversation

@md0x
Copy link
Contributor

@md0x md0x commented Jan 28, 2026

Motivation

After aggregating fetchOrderFilledEventsBounded across all proposal tokens, FILL_EVENTS_LOOKBACK_SECONDS and FILL_EVENTS_PROPOSAL_GAP_SECONDS no longer applied
per-proposal. The code computed per-proposal fromBlocks but only used the global minimum, with no subsequent filtering.

Summary

Pass a per-proposal fromTimestamp into processProposal and filter trades by timestamp >= fromTimestamp before checking price discrepancies.

Details

  • Added fromTimestamp to ProposalProcessingContext
  • Pre-compute fromTimestampsMap for each proposal based on its specific fromBlock
  • Filter trades in processProposal before discrepancy checks

Testing

  • Existing tests adequate, no new tests required
  • All existing tests pass

Issue(s)

Fixes UMA-3016

md0x added 4 commits January 26, 2026 14:51
…onitor

Replace API-based deeplink fetching with deterministic URL calculation.
The new format is: {baseUrl}/{proposalHash}?index={eventIndex}

- Remove fetchLatestAIDeepLink() and related async HTTP request logic
- Add simple generateAIDeepLink() function
- Remove AIConfig interface, use aiResultsBaseUrl string directly
- Remove aiDeeplinkHttpClient and aiDeeplinkTimeout from MonitoringParams
- Require AI_RESULTS_BASE_URL environment variable
After aggregating fetchOrderFilledEventsBounded across all proposal
tokens, FILL_EVENTS_LOOKBACK_SECONDS and FILL_EVENTS_PROPOSAL_GAP_SECONDS
no longer applied per-proposal. The code computed per-proposal fromBlocks
but only used the global minimum, with no subsequent per-proposal filtering.

Pass a per-proposal fromTimestamp into processProposal and filter trades
by timestamp >= fromTimestamp before checking price discrepancies.
@linear
Copy link

linear bot commented Jan 28, 2026

@md0x md0x changed the title Pablo/uma 3016 per proposal time filtering missing after aggregated fill fix(monitor-v2): add per-proposal time filtering for fill events Jan 28, 2026
md0x added 3 commits January 28, 2026 14:18
Adds a test that specifically verifies FILL_EVENTS_PROPOSAL_GAP_SECONDS
and FILL_EVENTS_LOOKBACK_SECONDS apply per-proposal:

- Creates two proposals at different blocks (5000 and 9000)
- Sets up a trade with a timestamp that falls between the two proposals'
  fromTimestamp thresholds
- Verifies only the older proposal triggers an alert, while the newer
  proposal correctly filters out the trade
… data flow

Instead of maintaining separate fromTimestampsMap and aiDeeplinksMap,
augment the bundles directly with per-proposal context (fromTimestamp,
aiDeeplink, fromBlock). This:
- Eliminates map lookups and duplicate key computations
- Removes non-null assertions
- Makes data flow more explicit - each bundle owns its context
- Reduces code by ~10 lines

Also makes aiDeeplink non-optional in ProposalProcessingContext since
it's always computed, and fixes test timing issues with trade timestamps.
@md0x md0x force-pushed the pablo/uma-3016-per-proposal-time-filtering-missing-after-aggregated-fill branch from 2afa6b4 to 23345aa Compare January 28, 2026 16:55
@md0x md0x marked this pull request as ready for review January 29, 2026 07:58
Comment on lines 333 to 334
const fromBlock = Math.max(Number(proposal.proposalBlockNumber) + gapBlocks, currentBlock - lookbackBlocks);
const fromTimestamp = currentTimestamp - Math.round((currentBlock - fromBlock) / blocksPerSecond);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces slight inconsistency as fromBlock is derived from the latest block number while fromTimestamp derives from bot's system time. Not that it is critical for the trade filtering case, but we could optimize this to drop timestamps altogether and do trade filtering only based on block numbers. But I recognize this also might involve reworking quite some of the tests, so could be left as a follow-up.

boundedTradesMap: Map<string, PolymarketTradeInformation[]>;
aiDeeplink?: string;
aiDeeplink: string;
fromTimestamp: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: might want to expand the naming to make it clear that this is used for trade data filtering

- Fetch currentTimestamp from provider.getBlock() instead of Date.now()
  to ensure consistency with block-derived fromBlock calculation
- Rename fromTimestamp to tradeFilterFromTimestamp for clarity
- Update test mocks to include getBlock stub
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.

3 participants