Skip to content

feat: add 'watchAddress' and 'unwatchAddress' for a real-time address watching system#55

Open
ZihaoXue1995 wants to merge 23 commits intopmxt-dev:mainfrom
ZihaoXue1995:feat/address-watch
Open

feat: add 'watchAddress' and 'unwatchAddress' for a real-time address watching system#55
ZihaoXue1995 wants to merge 23 commits intopmxt-dev:mainfrom
ZihaoXue1995:feat/address-watch

Conversation

@ZihaoXue1995
Copy link

What this PR adds (Close Issue #50 )

A real-time address watching system for prediction market wallets - the equivalent of CCXT Pro's watchOrderBook but for user's positions, trades, and balances.

New abstractions (core/src/subscriber)

subscriber/base.ts - Core interfaces:

  • SubscriptionOption — 'trades' | 'positions' | 'balances'
  • SubscribedAddressSnapshot — unified snapshot of trades, positions, balances for an address
  • SubscribedActivityBuilder — converts raw event data into a partial snapshot; allows exchange-specific logic to decode on-chain events directly without a REST roundtrip
  • BaseSubscriber — interface for pluggable polling/push backends

subscriber/watcher.ts - AddressWatcher orchestrates the CCXT Pro pattern:

  • First watch() call returns the initial snapshot immediately; subsequent calls block until something changes (same pattern as watchOrderBook)
  • Hybrid fetch: activity builder runs first on event data; only missing types fall back to REST/RPC
  • getChanged() computes incremental diffs — only new trade IDs, positions whose size changed, balances whose total changed are dispatched; empty diffs are suppressed
  • unwatch() / close() for lifecycle management

subscriber/external/goldsky.ts — Goldsky subgraph subscriber:

  • GoldSkySubscriber — polls one or more Goldsky GraphQL endpoints on a configurable interval, with per-address AbortController to cancel stale in-flight requests
  • POLYMARKET_DEFAULT_SUBSCRIPTION — orchestrates three parallel + one sequential subgraph query:
  • Trades: two indexed queries (maker + taker) merged by ID to avoid the or filter statement timeout
  • Positions: PNL subgraph (userPositions) → extract tokenIds → tokenIdConditions for market metadata (avoids the unindexed user + asset_in join that causes timeouts on
    userBalances)
  • All queries use orderBy: id to avoid timeouts on unindexed sort columns
  • LIMITLESS_DEFAULT_SUBSCRIPTION — two parallel from/to queries for USDC transfers, same or-split pattern
  • buildPolymarketActivity, buildPolymarketPositionsActivity, buildLimitlessBalanceActivity — activity builders that decode subgraph payloads into typed Trade[], Position[],
    Balance[]

Exchange changes

Polymarket (watchAddress + unwatchAddress)

  • trades — Goldsky CTF Exchange OrderFilled events
  • positions — Goldsky PNL subgraph and tokenIdConditions
  • balances — on-chain Polygon RPC, USDC.e at 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
  • fetchPositions(address?) and fetchBalance(address?) now accept an optional address and skip ensureAuth() when offered

Key design

  • BaseSubscriber offers basic interfaces to be plugable into AddressWatcher so users can easily replace GoldSkySubscriber with others.
  • Indexer is always faster than exchange's restful APIs, so here goldsky is integrated. But goldsky is HTTP-only GraphQL; no Websocket subscription protocol available. (The graph supports websocket subscription with more complicated customized setup)
  • Incremental diff dispatch: Callers receive only what changed (new trades, moved positions, shifted balances) and no need to diff on the caller side

Testing (core/examples/social)

  • pytest unit tests passed
  • Contains track_whale.ts and track_whale.py two testing examples
  • Sometimes goldsky subgraph graphql might timeout, users can replace the default graphql endpoint with self-deployed goldsky project endpoint
  • On-chain rpc for balance calls failed locally, code remains untouched in the production
Screenshot from 2026-03-06 10-39-54

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.

1 participant