-
Notifications
You must be signed in to change notification settings - Fork 467
/
pricing.ts
167 lines (151 loc) · 6.49 KB
/
pricing.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import { BigDecimal, BigInt } from '@graphprotocol/graph-ts'
import { exponentToBigDecimal, safeDiv } from '../utils/index'
import { Bundle, Pool, Token } from './../types/schema'
import { ONE_BD, ZERO_BD, ZERO_BI } from './constants'
export const WETH_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
export const USDC_WETH_03_POOL = '0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8'
export const STABLECOIN_IS_TOKEN0 = true
// token where amounts should contribute to tracked volume and liquidity
// usually tokens that many tokens are paired with s
export const WHITELIST_TOKENS: string[] = [
WETH_ADDRESS, // WETH
'0x6b175474e89094c44da98b954eedeac495271d0f', // DAI
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
'0x0000000000085d4780b73119b644ae5ecd22b376', // TUSD
'0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', // WBTC
'0x5d3a536e4d6dbd6114cc1ead35777bab948e3643', // cDAI
'0x39aa39c021dfbae8fac545936693ac917d5e7563', // cUSDC
'0x86fadb80d8d2cff3c3680819e4da99c10232ba0f', // EBASE
'0x57ab1ec28d129707052df4df418d58a2d46d5f51', // sUSD
'0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', // MKR
'0xc00e94cb662c3520282e6f5717214004a7f26888', // COMP
'0x514910771af9ca656af840dff83e8264ecf986ca', // LINK
'0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f', // SNX
'0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e', // YFI
'0x111111111117dc0aa78b770fa6a738034120c302', // 1INCH
'0xdf5e0e81dff6faf3a7e52ba697820c5e32d806a8', // yCurv
'0x956f47f50a910163d8bf957cf5846d573e7f87ca', // FEI
'0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', // MATIC
'0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9', // AAVE
'0xfe2e637202056d30016725477c5da089ab0a043a', // sETH2
]
export const STABLE_COINS: string[] = [
'0x6b175474e89094c44da98b954eedeac495271d0f',
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
'0x0000000000085d4780b73119b644ae5ecd22b376',
'0x956f47f50a910163d8bf957cf5846d573e7f87ca',
'0x4dd28568d05f09b02220b09c2cb307bfd837cb95',
]
export const MINIMUM_ETH_LOCKED = BigDecimal.fromString('60')
const Q192 = BigInt.fromI32(2).pow(192 as u8)
export function sqrtPriceX96ToTokenPrices(sqrtPriceX96: BigInt, token0: Token, token1: Token): BigDecimal[] {
const num = sqrtPriceX96.times(sqrtPriceX96).toBigDecimal()
const denom = BigDecimal.fromString(Q192.toString())
const price1 = num.div(denom).times(exponentToBigDecimal(token0.decimals)).div(exponentToBigDecimal(token1.decimals))
const price0 = safeDiv(BigDecimal.fromString('1'), price1)
return [price0, price1]
}
export function getNativePriceInUSD(
stablecoinWrappedNativePoolAddress: string,
stablecoinIsToken0: boolean,
): BigDecimal {
const stablecoinWrappedNativePool = Pool.load(stablecoinWrappedNativePoolAddress)
if (stablecoinWrappedNativePool !== null) {
return stablecoinIsToken0 ? stablecoinWrappedNativePool.token0Price : stablecoinWrappedNativePool.token1Price
} else {
return ZERO_BD
}
}
/**
* Search through graph to find derived Eth per token.
* @todo update to be derived ETH (add stablecoin estimates)
**/
export function findNativePerToken(
token: Token,
wrappedNativeAddress: string,
stablecoinAddresses: string[],
minimumNativeLocked: BigDecimal,
): BigDecimal {
if (token.id == wrappedNativeAddress) {
return ONE_BD
}
const whiteList = token.whitelistPools
// for now just take USD from pool with greatest TVL
// need to update this to actually detect best rate based on liquidity distribution
let largestLiquidityETH = ZERO_BD
let priceSoFar = ZERO_BD
const bundle = Bundle.load('1')!
// hardcoded fix for incorrect rates
// if whitelist includes token - get the safe price
if (stablecoinAddresses.includes(token.id)) {
priceSoFar = safeDiv(ONE_BD, bundle.ethPriceUSD)
} else {
for (let i = 0; i < whiteList.length; ++i) {
const poolAddress = whiteList[i]
const pool = Pool.load(poolAddress)
if (pool) {
if (pool.liquidity.gt(ZERO_BI)) {
if (pool.token0 == token.id) {
// whitelist token is token1
const token1 = Token.load(pool.token1)
// get the derived ETH in pool
if (token1) {
const ethLocked = pool.totalValueLockedToken1.times(token1.derivedETH)
if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(minimumNativeLocked)) {
largestLiquidityETH = ethLocked
// token1 per our token * Eth per token1
priceSoFar = pool.token1Price.times(token1.derivedETH as BigDecimal)
}
}
}
if (pool.token1 == token.id) {
const token0 = Token.load(pool.token0)
// get the derived ETH in pool
if (token0) {
const ethLocked = pool.totalValueLockedToken0.times(token0.derivedETH)
if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(minimumNativeLocked)) {
largestLiquidityETH = ethLocked
// token0 per our token * ETH per token0
priceSoFar = pool.token0Price.times(token0.derivedETH as BigDecimal)
}
}
}
}
}
}
}
return priceSoFar // nothing was found return 0
}
/**
* Accepts tokens and amounts, return tracked amount based on token whitelist
* If one token on whitelist, return amount in that token converted to USD * 2.
* If both are, return sum of two amounts
* If neither is, return 0
*/
export function getTrackedAmountUSD(
tokenAmount0: BigDecimal,
token0: Token,
tokenAmount1: BigDecimal,
token1: Token,
whitelistTokens: string[],
): BigDecimal {
const bundle = Bundle.load('1')!
const price0USD = token0.derivedETH.times(bundle.ethPriceUSD)
const price1USD = token1.derivedETH.times(bundle.ethPriceUSD)
// both are whitelist tokens, return sum of both amounts
if (whitelistTokens.includes(token0.id) && whitelistTokens.includes(token1.id)) {
return tokenAmount0.times(price0USD).plus(tokenAmount1.times(price1USD))
}
// take double value of the whitelisted token amount
if (whitelistTokens.includes(token0.id) && !whitelistTokens.includes(token1.id)) {
return tokenAmount0.times(price0USD).times(BigDecimal.fromString('2'))
}
// take double value of the whitelisted token amount
if (!whitelistTokens.includes(token0.id) && whitelistTokens.includes(token1.id)) {
return tokenAmount1.times(price1USD).times(BigDecimal.fromString('2'))
}
// neither token is on white list, tracked amount is 0
return ZERO_BD
}