Skip to main content
This page is for integrators who want to listen to on-chain events to discover and track Paragraph coins. Today, Paragraph coins are created via Doppler. Paragraph currently deploys on Doppler v3 and is migrating to Doppler v4. You’ll primarily listen to Airlock (factory) events, then follow the price-discovery surface (Uniswap v3/v2 for v3, the Doppler Hook for v4).
Note: We are building this functionality into our SDK to make coin interactions easier.

Overview

Paragraph coins are deployed via Doppler. To integrate with these coins, you have several options:
  • Listen to the onchain events
  • Query the Doppler indexer directly via GraphQL
  • [coming soon] Use the SDK to watch the onchain events
  • [coming soon] Listen to our own contracts
The remainder of this document focuses on listening to the onchain events, as it’s the most complex.

TL;DR

  1. Subscribe to Airlock.Create (v3 & v4) on Base.
  2. Verify it’s a Paragraph coin: Airlock.getAssetData(asset).integrator === PARAGRAPH_INTEGRATOR[chainId].
  3. Persist asset (ERC-20), numeraire, initializer, and poolOrHook.
  4. If v3: poolOrHook is a Uniswap v3 pool → track pool events
  5. If v4: poolOrHook is the Doppler Hook → track Swap, Rebalance, EarlyExit, InsufficientProceeds.
  6. (Optional) Track Airlock.Collect for protocol/integrator fee withdrawals.

Supported networks & addresses

Use the Doppler SDK address maps to resolve canonical contracts:
Paragraph integrator (for verification via getAssetData(asset).integrator):
  • Base Mainnet (8453): 0x805F3d7A8F8E50d8A5a444e8231BBfb5F97d5196
  • Base Sepolia (84532): 0x5902f7E444EAc22BE910B999DDD14cafc9d9D079 (Historic test you may see in old mainnet data: 0x797B89c60E561B5ff345D92E75344A106De4e531)
WETH on Base (common numeraire): 0x4200000000000000000000000000000000000006

What to listen to

Airlock (common to v3 & v4)

Identify Paragraph coins Primary: getAssetData(asset).integrator === PARAGRAPH_INTEGRATOR[chainId] Secondary: DERC20(asset).tokenURI() points to https://api.paragraph.com/coins/metadata/<id>.

Price-discovery surface (differs by version)

  • v3 (Uniswap v3)
    • From Create, poolOrHook is the Uniswap v3 pool.
    • Track pool events: Swap, Mint, Burn.
    • Note: Paragraph uses a no-op migrator (0x6ddfed58d238ca3195e49d8ac3d4cea6386e5c33), so no migration occurs.
  • v4 (Uniswap v4 + Doppler Hook)
    • From Create, poolOrHook is the Doppler Hook. Track these hook events:
    • Progress / price: normalize decimals and approximate avgPrice (numeraire per asset) ≈ totalProceeds / totalTokensSold

Quickstart (indexer flow)

1

Subscribe to Airlock.Create (v3 & v4)

For each chain, subscribe to Airlock.Create on both the v3 and v4 Airlock addresses (from the SDK maps).
2

Verify Paragraph coin

Read getAssetData(asset).integrator and compare to the Paragraph integrator address for the chain.
3

Persist core pointers

Store asset (ERC-20), numeraire, initializer, and poolOrHook. These are your canonical references.
4

Route by version

If initializer === DOPPLER_V3_ADDRESSES[chainId].lockableV3Initializerv3. Otherwise treat as v4.
5

Track discovery surface

  • v3: follow Uniswap v3 pool events
  • v4: subscribe to the Doppler Hook’s Swap, Rebalance, EarlyExit, InsufficientProceeds.
6

(Optional) Fees

Listen for Airlock.Collect if you want to surface protocol/integrator fee withdrawals.

Minimal watcher (TypeScript + viem)

Reorg safety: range-scan historical logs and delay finalization by ~10–20 blocks before marking records as confirmed.

Event glossary (quick reference)

  • Airlock.Create → canonical birth of a coin. Source of truth for:
    • asset (ERC-20), numeraire, initializer, poolOrHook (v3 pool or v4 hook).
  • Doppler Hook (v4):
    • Swap → updates cumulative totalProceeds & totalTokensSold.
    • Rebalance → epoch step; new slug placement/range.
    • EarlyExit → cap reached; sale ends early.
    • InsufficientProceeds → refund/buyback phase at average clearing price.
  • Airlock.Collect → fee withdrawals by protocol/integrator.

Practical tips

  • Paragraph detection (recommended):
    1. getAssetData(asset).integrator == PARAGRAPH_INTEGRATOR[chainId]
    2. DERC20.tokenURI() starts with https://api.paragraph.com/coins/metadata/…
  • Version detection: compare initializer from Create against known v3/v4 initializer addresses from the SDK maps.
  • Decimals: normalize both the asset and the numeraire for any price math.
  • State reads: you can always query Doppler contracts directly (e.g., v4 hook public state) to reconstruct state between events.

What changes with v4?

  • Airlock.Create remains your discovery source, but poolOrHook now points to a hook (not a V3 pool).