Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unichain sepolia #172

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,43 @@ type Pair @entity {
liquidityProviderCount: BigInt! # used to detect new exchanges
# derived fields
pairHourData: [PairHourData!]! @derivedFrom(field: "pair")
liquidityPositions: [LiquidityPosition!]! @derivedFrom(field: "pair")
liquidityPositionSnapshots: [LiquidityPositionSnapshot!]! @derivedFrom(field: "pair")
mints: [Mint!]! @derivedFrom(field: "pair")
burns: [Burn!]! @derivedFrom(field: "pair")
swaps: [Swap!]! @derivedFrom(field: "pair")
}

type User @entity {
id: ID!
liquidityPositions: [LiquidityPosition!] @derivedFrom(field: "user")
usdSwapped: BigDecimal!
}

type LiquidityPosition @entity {
id: ID!
user: User!
pair: Pair!
liquidityTokenBalance: BigDecimal!
}

# saved over time for return calculations, gets created and never updated
type LiquidityPositionSnapshot @entity {
id: ID!
liquidityPosition: LiquidityPosition!
timestamp: Int! # saved for fast historical lookups
block: Int! # saved for fast historical lookups
user: User! # reference to user
pair: Pair! # reference to pair
token0PriceUSD: BigDecimal! # snapshot of token0 price
token1PriceUSD: BigDecimal! # snapshot of token1 price
reserve0: BigDecimal! # snapshot of pair token0 reserves
reserve1: BigDecimal! # snapshot of pair token1 reserves
reserveUSD: BigDecimal! # snapshot of pair reserves in USD
liquidityTokenTotalSupply: BigDecimal! # snapshot of pool token supply
liquidityTokenBalance: BigDecimal! # snapshot of users pool token balance
}

type Transaction @entity {
id: ID! # txn hash
blockNumber: BigInt!
Expand Down
29 changes: 26 additions & 3 deletions src/mappings/core.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable prefer-const */
import { BigDecimal, BigInt, store } from '@graphprotocol/graph-ts'
import { Address, BigDecimal, BigInt, store } from '@graphprotocol/graph-ts'

import {
Bundle,
Expand All @@ -11,9 +11,9 @@ import {
Transaction,
UniswapFactory,
} from '../types/schema'
import { Burn, Mint, Swap, Sync, Transfer } from '../types/templates/Pair/Pair'
import { Pair as PairContract, Burn, Mint, Swap, Sync, Transfer } from '../types/templates/Pair/Pair'
import { updatePairDayData, updatePairHourData, updateTokenDayData, updateUniswapDayData } from './dayUpdates'
import { ADDRESS_ZERO, BI_18, convertTokenToDecimal, createUser, FACTORY_ADDRESS, ONE_BI, ZERO_BD } from './helpers'
import { ADDRESS_ZERO, BI_18, convertTokenToDecimal, createUser, FACTORY_ADDRESS, ONE_BI, ZERO_BD, createLiquiditySnapshot, createLiquidityPosition } from './helpers'
import { findEthPerToken, getEthPriceInUSD, getTrackedLiquidityUSD, getTrackedVolumeUSD } from './pricing'

function isCompleteMint(mintId: string): boolean {
Expand All @@ -37,6 +37,8 @@ export function handleTransfer(event: Transfer): void {

// get pair and load contract
let pair = Pair.load(event.address.toHexString())!
let pairContract = PairContract.bind(event.address)


// liquidity token amount being transfered
let value = convertTokenToDecimal(event.params.value, BI_18)
Expand Down Expand Up @@ -187,6 +189,19 @@ export function handleTransfer(event: Transfer): void {
transaction.save()
}

if (from.toHexString() != ADDRESS_ZERO && from.toHexString() != pair.id) {
let fromUserLiquidityPosition = createLiquidityPosition(event.address, from)
fromUserLiquidityPosition.liquidityTokenBalance = convertTokenToDecimal(pairContract.balanceOf(from), BI_18)
fromUserLiquidityPosition.save()
createLiquiditySnapshot(fromUserLiquidityPosition, event)
}
if (event.params.to.toHexString() != ADDRESS_ZERO && to.toHexString() != pair.id) {
let toUserLiquidityPosition = createLiquidityPosition(event.address, to)
toUserLiquidityPosition.liquidityTokenBalance = convertTokenToDecimal(pairContract.balanceOf(to), BI_18)
toUserLiquidityPosition.save()
createLiquiditySnapshot(toUserLiquidityPosition, event)
}

transaction.save()
}

Expand Down Expand Up @@ -314,6 +329,10 @@ export function handleMint(event: Mint): void {
mint.amountUSD = amountTotalUSD as BigDecimal
mint.save()

// update the LP position
let liquidityPosition = createLiquidityPosition(event.address, Address.fromBytes(mint.to))
createLiquiditySnapshot(liquidityPosition, event)

// update day entities
updatePairDayData(event)
updatePairHourData(event)
Expand Down Expand Up @@ -380,6 +399,10 @@ export function handleBurn(event: Burn): void {
burn.amountUSD = amountTotalUSD as BigDecimal
burn.save()

// update the LP position
let liquidityPosition = createLiquidityPosition(event.address, event.params.sender)
createLiquiditySnapshot(liquidityPosition, event)

// update day entities
updatePairDayData(event)
updatePairHourData(event)
Expand Down
49 changes: 47 additions & 2 deletions src/mappings/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* eslint-disable prefer-const */
import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts'
import { log, Address, BigDecimal, BigInt, ethereum } from '@graphprotocol/graph-ts'

import { ERC20 } from '../types/Factory/ERC20'
import { ERC20NameBytes } from '../types/Factory/ERC20NameBytes'
import { ERC20SymbolBytes } from '../types/Factory/ERC20SymbolBytes'
import { User } from '../types/schema'
import { User, Bundle, Token, LiquidityPosition, LiquidityPositionSnapshot, Pair } from '../types/schema'
import { Factory as FactoryContract } from '../types/templates/Pair/Factory'
import { TokenDefinition } from './tokenDefinition'

Expand Down Expand Up @@ -148,6 +148,26 @@ export function fetchTokenDecimals(tokenAddress: Address): BigInt | null {
return null
}

export function createLiquidityPosition(exchange: Address, user: Address): LiquidityPosition {
let id = exchange
.toHexString()
.concat('-')
.concat(user.toHexString())
let liquidityTokenBalance = LiquidityPosition.load(id)
if (liquidityTokenBalance === null) {
let pair = Pair.load(exchange.toHexString())!
pair.liquidityProviderCount = pair.liquidityProviderCount.plus(ONE_BI)
liquidityTokenBalance = new LiquidityPosition(id)
liquidityTokenBalance.liquidityTokenBalance = ZERO_BD
liquidityTokenBalance.pair = exchange.toHexString()
liquidityTokenBalance.user = user.toHexString()
liquidityTokenBalance.save()
pair.save()
}
if (liquidityTokenBalance === null) log.error('LiquidityTokenBalance is null', [id])
return liquidityTokenBalance as LiquidityPosition
}

export function createUser(address: Address): void {
let user = User.load(address.toHexString())
if (user === null) {
Expand All @@ -156,3 +176,28 @@ export function createUser(address: Address): void {
user.save()
}
}

export function createLiquiditySnapshot(position: LiquidityPosition, event: ethereum.Event): void {
let timestamp = event.block.timestamp.toI32()
let bundle = Bundle.load('1')!
let pair = Pair.load(position.pair)!
let token0 = Token.load(pair.token0)!
let token1 = Token.load(pair.token1)!
// create new snapshot
let snapshot = new LiquidityPositionSnapshot(position.id.concat(timestamp.toString()))
snapshot.liquidityPosition = position.id
snapshot.timestamp = timestamp
snapshot.block = event.block.number.toI32()
snapshot.user = position.user
snapshot.pair = position.pair
snapshot.token0PriceUSD = token0.derivedETH.times(bundle.ethPrice)
snapshot.token1PriceUSD = token1.derivedETH.times(bundle.ethPrice)
snapshot.reserve0 = pair.reserve0
snapshot.reserve1 = pair.reserve1
snapshot.reserveUSD = pair.reserveUSD
snapshot.liquidityTokenTotalSupply = pair.totalSupply
snapshot.liquidityTokenBalance = position.liquidityTokenBalance
snapshot.liquidityPosition = position.id
snapshot.save()
position.save()
}
57 changes: 8 additions & 49 deletions src/mappings/pricing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,23 @@
import { Bundle, Pair, Token } from '../types/schema'
import { ADDRESS_ZERO, factoryContract, ONE_BD, UNTRACKED_PAIRS, ZERO_BD } from './helpers'

const WETH_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
const USDC_WETH_PAIR = '0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc' // created 10008355
const DAI_WETH_PAIR = '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11' // created block 10042267
const USDT_WETH_PAIR = '0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852' // created block 10093341
const WETH_ADDRESS = '0x4200000000000000000000000000000000000006'
const USDC_WETH_PAIR = '0x7bdA50eDFFddB9C8b020Bfc1ed1ce5E37d56ba71'

export function getEthPriceInUSD(): BigDecimal {
// fetch eth prices for each stablecoin
let daiPair = Pair.load(DAI_WETH_PAIR) // dai is token0
let usdcPair = Pair.load(USDC_WETH_PAIR) // usdc is token0
let usdtPair = Pair.load(USDT_WETH_PAIR) // usdt is token1

// all 3 have been created
if (daiPair !== null && usdcPair !== null && usdtPair !== null) {
let totalLiquidityETH = daiPair.reserve1.plus(usdcPair.reserve1).plus(usdtPair.reserve0)
let daiWeight = daiPair.reserve1.div(totalLiquidityETH)
let usdcWeight = usdcPair.reserve1.div(totalLiquidityETH)
let usdtWeight = usdtPair.reserve0.div(totalLiquidityETH)
return daiPair.token0Price
.times(daiWeight)
.plus(usdcPair.token0Price.times(usdcWeight))
.plus(usdtPair.token1Price.times(usdtWeight))
// dai and USDC have been created
} else if (daiPair !== null && usdcPair !== null) {
let totalLiquidityETH = daiPair.reserve1.plus(usdcPair.reserve1)
let daiWeight = daiPair.reserve1.div(totalLiquidityETH)
let usdcWeight = usdcPair.reserve1.div(totalLiquidityETH)
return daiPair.token0Price.times(daiWeight).plus(usdcPair.token0Price.times(usdcWeight))
// USDC is the only pair so far
} else if (usdcPair !== null) {
return usdcPair.token0Price
let usdcPair = Pair.load(USDC_WETH_PAIR) // usdc is token1
if (usdcPair !== null) {
return usdcPair.token1Price
} else {
return ZERO_BD
}
}

// token where amounts should contribute to tracked volume and liquidity
let WHITELIST: string[] = [
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH
'0x6b175474e89094c44da98b954eedeac495271d0f', // DAI
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
'0x0000000000085d4780b73119b644ae5ecd22b376', // TUSD
'0x5d3a536e4d6dbd6114cc1ead35777bab948e3643', // cDAI
'0x39aa39c021dfbae8fac545936693ac917d5e7563', // cUSDC
'0x86fadb80d8d2cff3c3680819e4da99c10232ba0f', // EBASE
'0x57ab1ec28d129707052df4df418d58a2d46d5f51', // sUSD
'0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', // MKR
'0xc00e94cb662c3520282e6f5717214004a7f26888', // COMP
'0x514910771af9ca656af840dff83e8264ecf986ca', //LINK
'0x960b236a07cf122663c4303350609a66a7b288c0', //ANT
'0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f', //SNX
'0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e', //YFI
'0xdf5e0e81dff6faf3a7e52ba697820c5e32d806a8', // yCurv
'0x853d955acef822db058eb8505911ed77f175b99e', // FRAX
'0xa47c8bf37f92abed4a126bda807a7b7498661acd', // WUST
'0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', // UNI
'0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', // WBTC
'0x956f47f50a910163d8bf957cf5846d573e7f87ca', // FEI
]

Check failure on line 22 in src/mappings/pricing.ts

View workflow job for this annotation

GitHub Actions / lint

'STABLECOINS' is assigned a value but never used. Allowed unused vars must match /^_/u
const STABLECOINS: string[] = [
]

// minimum liquidity required to count towards tracked volume for pairs with small # of Lps
Expand Down
6 changes: 3 additions & 3 deletions subgraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ schema:
dataSources:
- kind: ethereum/contract
name: Factory
network: mainnet
network: unichain-sepolia
source:
address: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f'
abi: Factory
startBlock: 10000834
startBlock: 1743590
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand All @@ -34,7 +34,7 @@ dataSources:
templates:
- kind: ethereum/contract
name: Pair
network: mainnet
network: unichain-sepolia
source:
abi: Pair
mapping:
Expand Down
Loading