Skip to content

Commit

Permalink
Merge pull request #14 from ianlapham/testing
Browse files Browse the repository at this point in the history
Setup testing
  • Loading branch information
ianlapham committed Jun 22, 2020
2 parents 57e3377 + 3209e95 commit 407b4e8
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 220 deletions.
53 changes: 2 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,4 @@
# Uniswap V2 Subgraph
# Uniswap V2 Subgraph Testing

[Uniswap](https://uniswap.org/) is a decentralized protocol for automated token exchange on Ethereum.
This subgraph is for testing specifc interactions on a limited set of pairs.

This subgraph dynamically tracks any pair created by the uniswap factory. It tracks of the current state of Uniswap contracts, and contains derived stats for things like historical data and USD prices.

- aggregated data across pairs and tokens,
- data on individual pairs and tokens,
- data on transactions
- data on liquidity providers
- historical data on Uniswap, pairs or tokens, aggregated by day

## Running Locally

Make sure to update package.json settings to point to your own graph account.

## Queries

Below are a few ways to show how to query the uniswap-subgraph for data. The queries show most of the information that is queryable, but there are many other filtering options that can be used, just check out the [querying api](https://thegraph.com/docs/graphql-api). These queries can be used locally or in The Graph Explorer playground.

## Key Entity Overviews

#### UniswapFactory

Contains data across all of Uniswap V2. This entity tracks important things like total liquidity (in ETH and USD, see below), all time volume, transaction count, number of pairs and more.

#### Token
Contains data on a specific token. This token specific data is aggregated across all pairs, and is updated whenever there is a transaction involving that token.

#### Pair
Contains data on a specific pair.

#### Transaction
Every transaction on Uniswap is stored. Each transaction contains an array of mints, burns, and swaps that occured within it.

#### Mint, Burn, Swap
These contain specifc information about a transaction. Things like which pair triggered the transaction, amounts, sender, recipient, and more. Each is linked to a parent Transaction entity.

## Example Queries

### Querying Aggregated Uniswap Data

This query fetches aggredated data from all uniswap pairs and tokens, to give a view into how much activity is happening within the whole protocol.

```graphql
{
uniswapFactory(id: "1") {
pairCount
totalVolumeUSD
totalLiquidityUSD
}
}
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"build": "graph build",
"create-local": "graph create davekaj/uniswap --node http://127.0.0.1:8020",
"deploy-local": "graph deploy davekaj/uniswap --debug --ipfs http://localhost:5001 --node http://127.0.0.1:8020",
"deploy": "graph deploy uniswap/uniswap-v2 --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/ --debug",
"deploy": "graph deploy ianlapham/uniswapbackup --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/ --debug",
"deploy-staging": "graph deploy $THE_GRAPH_GITHUB_USER/$THE_GRAPH_SUBGRAPH_NAME /Uniswap --ipfs https://api.staging.thegraph.com/ipfs/ --node https://api.staging.thegraph.com/deploy/",
"watch-local": "graph deploy graphprotocol/Uniswap2 --watch --debug --node http://127.0.0.1:8020/ --ipfs http://localhost:5001"
},
Expand Down
28 changes: 26 additions & 2 deletions schema.graphql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
type UniswapFactory @entity {
type UniswapFactory @entity {
# factory address
id: ID!
id: ID!

# pair info
pairCount: Int!
Expand Down Expand Up @@ -96,6 +96,7 @@ type Pair @entity {
type User @entity {
id: ID!
liquidityPositions: [LiquidityPosition!] @derivedFrom(field: "user")
usdSwapped: BigDecimal!
}

type LiquidityPosition @entity {
Expand Down Expand Up @@ -160,6 +161,9 @@ type Burn @entity {
# derived amount based on available prices of tokens
amountUSD: BigDecimal

# mark uncomplete in ETH case
needsComplete: Boolean

# optional fee fields, if a Transfer event is fired in _mintFee
feeTo: Bytes
feeLiquidity: BigDecimal
Expand Down Expand Up @@ -213,6 +217,26 @@ type UniswapDayData @entity {
txCount: BigInt!
}


type PairHourData @entity {
id: ID!
hourStartUnix: Int!
pair: Pair!

# reserves
reserve0: BigDecimal!
reserve1: BigDecimal!

# derived liquidity
reserveUSD: BigDecimal!

# volume stats
hourlyVolumeToken0: BigDecimal!
hourlyVolumeToken1: BigDecimal!
hourlyVolumeUSD: BigDecimal!
hourlyTxns: BigInt!
}

# Data accumulated and condensed into day stats for each exchange
type PairDayData @entity {
id: ID!
Expand Down
92 changes: 75 additions & 17 deletions src/mappings/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
Bundle
} from '../types/schema'
import { Pair as PairContract, Mint, Burn, Swap, Transfer, Sync } from '../types/templates/Pair/Pair'
import { updatePairDayData, updateTokenDayData, updateUniswapDayData } from './dayUpdates'
import { updatePairDayData, updateTokenDayData, updateUniswapDayData, updatePairHourData } from './dayUpdates'
import { getEthPriceInUSD, findEthPerToken, getTrackedVolumeUSD, getTrackedLiquidityUSD } from './pricing'
import {
convertTokenToDecimal,
Expand All @@ -32,6 +32,11 @@ function isCompleteMint(mintId: string): boolean {
}

export function handleTransfer(event: Transfer): void {
// ignore initial transfers for first adds
if (event.params.to.toHexString() == ADDRESS_ZERO && event.params.value.equals(BigInt.fromI32(1000))) {
return
}

let factory = UniswapFactory.load(FACTORY_ADDRESS)
let transactionHash = event.transaction.hash.toHexString()

Expand Down Expand Up @@ -91,12 +96,8 @@ export function handleTransfer(event: Transfer): void {
}
}

// burn
if (event.params.to.toHexString() == ADDRESS_ZERO && event.params.from.toHexString() == pair.id) {
pair.totalSupply = pair.totalSupply.minus(value)
pair.save()

// this is a new instance of a logical burn
// case where direct send first on ETH withdrawls
if (event.params.to.toHexString() == pair.id) {
let burns = transaction.burns
let burn = new BurnEvent(
event.transaction.hash
Expand All @@ -107,6 +108,49 @@ export function handleTransfer(event: Transfer): void {
burn.pair = pair.id
burn.liquidity = value
burn.timestamp = transaction.timestamp
burn.to = event.params.to
burn.sender = event.params.from
burn.needsComplete = true
burn.save()
burns.push(burn.id)
transaction.burns = burns
transaction.save()
}

// burn
if (event.params.to.toHexString() == ADDRESS_ZERO && event.params.from.toHexString() == pair.id) {
pair.totalSupply = pair.totalSupply.minus(value)
pair.save()

// this is a new instance of a logical burn
let burns = transaction.burns
let burn: BurnEvent
if (burns.length > 0) {
let currentBurn = BurnEvent.load(burns[burns.length - 1])
if (currentBurn.needsComplete) {
burn = currentBurn as BurnEvent
} else {
burn = new BurnEvent(
event.transaction.hash
.toHexString()
.concat('-')
.concat(BigInt.fromI32(burns.length).toString())
)
burn.pair = pair.id
burn.liquidity = value
burn.timestamp = transaction.timestamp
}
} else {
burn = new BurnEvent(
event.transaction.hash
.toHexString()
.concat('-')
.concat(BigInt.fromI32(burns.length).toString())
)
burn.pair = pair.id
burn.liquidity = value
burn.timestamp = transaction.timestamp
}

// if this logical burn included a fee mint, account for this
if (mints.length !== 0 && !isCompleteMint(mints[mints.length - 1])) {
Expand All @@ -120,10 +164,18 @@ export function handleTransfer(event: Transfer): void {
transaction.mints = mints
transaction.save()
}

burn.save()
burns.push(burn.id)
transaction.burns = burns

// if accessing last one, replace it
if (burn.needsComplete) {
burns[burns.length - 1] = burn.id
}
// else add new one
else {
burns.push(burn.id)
}
transaction.burns = burns
transaction.save()
}

Expand Down Expand Up @@ -181,12 +233,14 @@ export function handleSync(event: Sync): void {
token1.save()

// get tracked liquidity - will be 0 if neither is in whitelist
let trackedLiquidityETH: BigDecimal = getTrackedLiquidityUSD(
pair.reserve0,
token0 as Token,
pair.reserve1,
token1 as Token
).div(bundle.ethPrice)
let trackedLiquidityETH: BigDecimal
if (bundle.ethPrice.notEqual(ZERO_BD)) {
trackedLiquidityETH = getTrackedLiquidityUSD(pair.reserve0, token0 as Token, pair.reserve1, token1 as Token).div(
bundle.ethPrice
)
} else {
trackedLiquidityETH = ZERO_BD
}

// use derived amounts within pair
pair.trackedReserveETH = trackedLiquidityETH
Expand Down Expand Up @@ -253,6 +307,7 @@ export function handleMint(event: Mint): void {

// update day entities
updatePairDayData(event)
updatePairHourData(event)
updateUniswapDayData(event)
updateTokenDayData(token0 as Token, event)
updateTokenDayData(token1 as Token, event)
Expand Down Expand Up @@ -298,16 +353,17 @@ export function handleBurn(event: Burn): void {
uniswap.save()

// update burn
burn.sender = event.params.sender
// burn.sender = event.params.sender
burn.amount0 = token0Amount as BigDecimal
burn.amount1 = token1Amount as BigDecimal
burn.to = event.params.to
// burn.to = event.params.to
burn.logIndex = event.logIndex
burn.amountUSD = amountTotalUSD as BigDecimal
burn.save()

// update day entities
updatePairDayData(event)
updatePairHourData(event)
updateUniswapDayData(event)
updateTokenDayData(token0 as Token, event)
updateTokenDayData(token1 as Token, event)
Expand Down Expand Up @@ -338,6 +394,7 @@ 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)

let trackedAmountETH: BigDecimal
if (bundle.ethPrice.equals(ZERO_BD)) {
trackedAmountETH = ZERO_BD
Expand Down Expand Up @@ -417,6 +474,7 @@ export function handleSwap(event: Swap): void {

// update day entities
updatePairDayData(event)
updatePairHourData(event)
updateUniswapDayData(event)
updateTokenDayData(token0 as Token, event)
updateTokenDayData(token1 as Token, event)
Expand Down

0 comments on commit 407b4e8

Please sign in to comment.