Example: Query Engine vs. Uniswap v2 Subgraph
To illustrate the differences between the subgraph and Query Engine approaches, take 24h volume on a Uniswap V2 fork:
event Swap(
address indexed sender,
uint amount0In, uint amount1In,
uint amount0Out, uint amount1Out,
address indexed to
);
Network ID | Transaction Hash | Event Emitter (Contract Address) | Event Name | Event Data (JSONB in Postgres/Query Engine) | sender | amount0In | amount1In | amount0Out | amount1Out | to |
---|---|---|---|---|---|---|---|---|---|---|
1 | 0xbbafabd4e4833c016c04a4ef875d8e892ed7ff7fa820532d2f09a5e86ba4f274 | 0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc | Trade | {"sender":0x7a25.., "amount0In": 100000000000000000,"amount0Out": 163428202, "amount1Out": 0, ...} | 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D | 0 | 100000000000000000 | 163428202 | 0 | 0x5083b16dA538c5022744526122243cF3BDDb3bF2 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
Query Engine with PostgreSQL
- On new protocol event
- Decode and import into database
Reporting API
- On new protocol event
- Rerun query for 24 hour volume
Subgraph
A rough sketch of how the Uniswap V2 subgraph will import data is as follows:
- When I get a new block (or if I have not caught up to present block)
- Fetch new block
- Run any block handlers
- Run and event log handlers
- Update a row storing the 24hr volume for a Uniswap pair
export function handleSwap(event: Swap): void {
…
// only accounts for volume through white listed tokens
let trackedAmountUSD = getTrackedVolumeUSD(
amount0Total, token0 as Token, amount1Total, token1 as Token, pair as Pair)
uniswapDayData.dailyVolumeUSD = uniswapDayData.dailyVolumeUSD.plus(trackedAmountUSD)
uniswapDayData.dailyVolumeETH = uniswapDayData.dailyVolumeETH.plus(trackedAmountETH)
uniswapDayData.dailyVolumeUntracked = uniswapDayData.dailyVolumeUntracked.plus(derivedAmountUSD)
uniswapDayData.save()
…
}