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

pricing #183

Draft
wants to merge 1 commit into
base: 12-06-remove_sync
Choose a base branch
from
Draft
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
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]
}