Skip to content

Commit

Permalink
pricing
Browse files Browse the repository at this point in the history
  • Loading branch information
mzywang committed Dec 11, 2024
1 parent 802e1f8 commit d566818
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 6 deletions.
5 changes: 5 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ type Token @entity {
decimals: BigInt!

totalLiquidity: BigDecimal!
stablecoinPairs: [Pair!]!
primaryUsdPrice: BigDecimal!
primaryUsdLiquidity: BigDecimal!

pairsAsToken0: [Pair!]! @derivedFrom(field: "token0")
pairsAsToken1: [Pair!]! @derivedFrom(field: "token1")
Expand All @@ -28,6 +31,8 @@ type Pair @entity {
reserve0: BigDecimal!
reserve1: BigDecimal!

primaryUsdLiquidity: BigDecimal!

mints: [Mint!]! @derivedFrom(field: "pair")
burns: [Burn!]! @derivedFrom(field: "pair")
swaps: [Swap!]! @derivedFrom(field: "pair")
Expand Down
35 changes: 30 additions & 5 deletions src/mappings/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import { PairCreated } from '../types/Factory/Factory'
import { Pair, Token, UniswapFactory } from '../types/schema'
import { Pair as PairTemplate } from '../types/templates'
import { FACTORY_ADDRESS, fetchTokenDecimals, ONE_BI, ZERO_BD } from './helpers'
import { getBestPrimaryUsdPrice, isStablecoin } from './pricing'

export function handleNewPair(event: PairCreated): void {
if (event.params.param3.equals(ONE_BI)) {
const factory = new UniswapFactory(FACTORY_ADDRESS)
factory.save()
}

if (Token.load(event.params.token0.toHexString()) === null) {
let token0 = Token.load(event.params.token0.toHexString())
let token1 = Token.load(event.params.token1.toHexString())

if (token0 === null) {
const decimals = fetchTokenDecimals(event.params.token0)
if (decimals === null) {
log.warning('Could not fetch decimals for token {}, skipping creation of pair {}.', [
Expand All @@ -22,13 +26,16 @@ export function handleNewPair(event: PairCreated): void {
return
}

const token0 = new Token(event.params.token0.toHexString())
token0 = new Token(event.params.token0.toHexString())
token0.decimals = decimals
token0.totalLiquidity = ZERO_BD
token0.stablecoinPairs = []
token0.primaryUsdPrice = ZERO_BD
token0.primaryUsdLiquidity = ZERO_BD
token0.save()
}

if (Token.load(event.params.token1.toHexString()) === null) {
if (token1 === null) {
const decimals = fetchTokenDecimals(event.params.token1)
if (decimals === null) {
log.warning('Could not fetch decimals for token {}, skipping creation of pair {}.', [
Expand All @@ -37,10 +44,12 @@ export function handleNewPair(event: PairCreated): void {
])
return
}

const token1 = new Token(event.params.token1.toHexString())
token1 = new Token(event.params.token1.toHexString())
token1.decimals = decimals
token1.totalLiquidity = ZERO_BD
token1.stablecoinPairs = []
token1.primaryUsdPrice = ZERO_BD
token1.primaryUsdLiquidity = ZERO_BD
token1.save()
}

Expand All @@ -51,7 +60,23 @@ export function handleNewPair(event: PairCreated): void {
pair.createdAtBlockNumber = event.block.number
pair.reserve0 = ZERO_BD
pair.reserve1 = ZERO_BD
pair.primaryUsdLiquidity = ZERO_BD
pair.save()

if (isStablecoin(event.params.token1.toHexString())) {
const stablecoinPairs = token0.stablecoinPairs
stablecoinPairs.push(event.params.pair.toHexString())
token0.stablecoinPairs = stablecoinPairs
token0.primaryUsdPrice = getBestPrimaryUsdPrice(stablecoinPairs, token0.id)
token0.save()
}
if (isStablecoin(event.params.token0.toHexString())) {
const stablecoinPairs = token1.stablecoinPairs
stablecoinPairs.push(event.params.pair.toHexString())
token1.stablecoinPairs = stablecoinPairs
token1.primaryUsdPrice = getBestPrimaryUsdPrice(stablecoinPairs, token1.id)
token1.save()
}

PairTemplate.create(event.params.pair)
}
37 changes: 36 additions & 1 deletion src/mappings/pair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { log } from '@graphprotocol/graph-ts'
import { Burn as BurnEntity, Mint as MintEntity, Pair, Swap as SwapEntity, Token } from '../types/schema'
import { Burn, Mint, Swap } from '../types/templates/Pair/Pair'
import { convertTokenToDecimal } from './helpers'
import { getBestPrimaryUsdPrice } from './pricing'

export function handleMint(event: Mint): void {
const block = event.block
Expand Down Expand Up @@ -36,10 +37,21 @@ export function handleMint(event: Mint): void {
mint.amount1 = token1Amount as BigDecimal
mint.save()

token0.primaryUsdPrice = getBestPrimaryUsdPrice(token0.stablecoinPairs, token0.id)
token1.primaryUsdPrice = getBestPrimaryUsdPrice(token1.stablecoinPairs, token1.id)
token0.totalLiquidity = token0.totalLiquidity.plus(token0Amount)
token1.totalLiquidity = token1.totalLiquidity.plus(token1Amount)
token0.primaryUsdLiquidity = token0.primaryUsdPrice.times(token0.totalLiquidity)
token1.primaryUsdLiquidity = token1.primaryUsdPrice.times(token1.totalLiquidity)
token0.save()
token1.save()

pair.reserve0 = pair.reserve0.plus(token0Amount)
pair.reserve1 = pair.reserve1.plus(token1Amount)
pair.primaryUsdLiquidity = pair.reserve0
.times(token0.primaryUsdPrice)
.plus(pair.reserve1.times(token1.primaryUsdPrice))
pair.save()
}

export function handleBurn(event: Burn): void {
Expand All @@ -66,10 +78,22 @@ export function handleBurn(event: Burn): void {
burn.to = event.params.to
burn.save()


token0.primaryUsdPrice = getBestPrimaryUsdPrice(token0.stablecoinPairs, token0.id)
token1.primaryUsdPrice = getBestPrimaryUsdPrice(token1.stablecoinPairs, token1.id)
token0.totalLiquidity = token0.totalLiquidity.minus(token0Amount)
token1.totalLiquidity = token1.totalLiquidity.minus(token1Amount)
token0.primaryUsdLiquidity = token0.primaryUsdPrice.times(token0.totalLiquidity)
token1.primaryUsdLiquidity = token1.primaryUsdPrice.times(token1.totalLiquidity)
token0.save()
token1.save()

pair.reserve0 = pair.reserve0.minus(token0Amount)
pair.reserve1 = pair.reserve1.minus(token1Amount)
pair.primaryUsdLiquidity = pair.reserve0
.times(token0.primaryUsdPrice)
.plus(pair.reserve1.times(token1.primaryUsdPrice))
pair.save()
}

export function handleSwap(event: Swap): void {
Expand Down Expand Up @@ -100,8 +124,19 @@ export function handleSwap(event: Swap): void {
swap.to = event.params.to
swap.save()

token0.primaryUsdPrice = getBestPrimaryUsdPrice(token0.stablecoinPairs, token0.id)
token1.primaryUsdPrice = getBestPrimaryUsdPrice(token1.stablecoinPairs, token1.id)
token0.totalLiquidity = token0.totalLiquidity.minus(token0AmountOut).plus(token0AmountIn)
token1.totalLiquidity = token1.totalLiquidity.minus(token1AmountOut).plus(token1AmountIn)
token0.primaryUsdLiquidity = token0.primaryUsdPrice.times(token0.totalLiquidity)
token1.primaryUsdLiquidity = token1.primaryUsdPrice.times(token1.totalLiquidity)
token0.save()
token1.save()
}

pair.reserve0 = pair.reserve0.minus(token0AmountOut).plus(token0AmountIn)
pair.reserve1 = pair.reserve1.minus(token1AmountOut).plus(token1AmountIn)
pair.primaryUsdLiquidity = pair.reserve0
.times(token0.primaryUsdPrice)
.plus(pair.reserve1.times(token1.primaryUsdPrice))
pair.save()
}
87 changes: 87 additions & 0 deletions src/mappings/pricing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { BigDecimal } from '@graphprotocol/graph-ts'

import { Pair, Token } from '../types/schema'
import { ZERO_BD } from './helpers'

const STABLECOINS: string[] = [
'0x6b175474e89094c44da98b954eedeac495271d0f', // DAI
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
]

export function isStablecoin(token: string): boolean {
return STABLECOINS.includes(token)
}

export function updatePrimaryUsdPrices(pair: Pair, token0: Token, token1: Token): void {
if (isStablecoin(pair.token0) && isStablecoin(pair.token1)) {
return
}

if (isStablecoin(pair.token0)) {
token1.primaryUsdPrice = pair.reserve0.div(pair.reserve1)
} else if (isStablecoin(pair.token1)) {
token0.primaryUsdPrice = pair.reserve1.div(pair.reserve0)
}
}

export function safeDiv(a: BigDecimal, b: BigDecimal): BigDecimal {
if (b.equals(ZERO_BD)) {
return ZERO_BD
}

return a.div(b)
}

export function getPrimaryUsdLiquidity(pair: Pair): BigDecimal {
if (isStablecoin(pair.token0) && isStablecoin(pair.token1)) {
return pair.reserve0.plus(pair.reserve1)
}

if (isStablecoin(pair.token0)) {
return pair.reserve0
}

if (isStablecoin(pair.token1)) {
return pair.reserve1
}

return ZERO_BD
}

export function getUsdPrice(pair: Pair, tokenAddress: string): BigDecimal {
if (isStablecoin(tokenAddress)) {
return BigDecimal.fromString('1.0')
}

if (isStablecoin(pair.token0)) {
return safeDiv(pair.reserve0, pair.reserve1)
}

if (isStablecoin(pair.token1)) {
return safeDiv(pair.reserve1, pair.reserve0)
}

return ZERO_BD
}

// returns [maxUsdLiquidity, bestUsdPrice]
export function getBestPrimaryUsdPrice(stablecoinPairAddresses: string[], tokenAddress: string): [BigDecimal, BigDecimal] {
if (isStablecoin(tokenAddress)) {
return [ZERO_BD, BigDecimal.fromString('1.0')]
}

let maxUsdLiquidity = ZERO_BD
let bestUsdPrice = ZERO_BD

for (let i = 0; i < stablecoinPairAddresses.length; i++) {
const pair = Pair.load(stablecoinPairAddresses[i])!
const primaryUsdLiquidity = getPrimaryUsdLiquidity(pair)
if (primaryUsdLiquidity.gt(maxUsdLiquidity)) {
maxUsdLiquidity = primaryUsdLiquidity
bestUsdPrice = getUsdPrice(pair, tokenAddress)
}
}

return [maxUsdLiquidity, bestUsdPrice]
}

0 comments on commit d566818

Please sign in to comment.