Skip to content

Commit

Permalink
Stableswap Masterchef refactor (#31)
Browse files Browse the repository at this point in the history
* add stableswap subgraph queries, refactor chef program to work with stableswap

* fix typo

* fix occurances of calculateReserves

* use voltfinance/stableswap subgraph

* simplify tvl

* modify stableswap query to fit interface

* fix tokens attribute

* refactor multi rewards

* refactor single rewards

* v1.0.0
  • Loading branch information
t0mcr8se authored Apr 20, 2022
1 parent 249ae5d commit 2a176b3
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 56 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fuseio/earn-sdk",
"version": "0.4.4",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const UNISWAP_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/uni
export const FUSESWAP_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/fuseio/fuseswap'
export const VOLTAGE_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/voltfinance/voltage-exchange'
export const PANCAKESWAP_SUBGRAPH_URL = 'https://bsc.streamingfast.io/subgraphs/name/pancakeswap/exchange-v2'
export const STABLESWAP_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/voltfinance/stableswap'

export const MASTERCHEF_V2_ADDRESS = '0xc71E27C7e128d9CAEb2b8cA756647f7F199cF39e'
export const MASTERCHEF_V3_ADDRESS = '0xE3e184a7b75D0Ae6E17B58F5283b91B4E0A2604F'
Expand All @@ -17,3 +18,5 @@ export const MASTERCHEF_V3_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/na

export const xVOLT = '0x97a6e78c9208c21afaDa67e7E61d7ad27688eFd1'
export const VOLT = '0x34Ef2Cc892a88415e9f02b91BfA9c91fC0bE6bD4'

export const STABLESWAP_POOLS = ['0x2a68D7C6Ea986fA06B2665d08b4D08F5e7aF960c', '0x83D158Beadbb3445AC901cFd0ca33FB30CCC8f53']
15 changes: 14 additions & 1 deletion src/graphql/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import fetch from 'cross-fetch'
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client/core'
import { UNISWAP_SUBGRAPH_URL, FUSESWAP_SUBGRAPH_URL, PANCAKESWAP_SUBGRAPH_URL, MASTERCHEF_V2_SUBGRAPH_URL, MASTERCHEF_V3_SUBGRAPH_URL, VOLTAGE_SUBGRAPH_URL } from '../constants'
import {
UNISWAP_SUBGRAPH_URL,
FUSESWAP_SUBGRAPH_URL,
PANCAKESWAP_SUBGRAPH_URL,
MASTERCHEF_V2_SUBGRAPH_URL,
MASTERCHEF_V3_SUBGRAPH_URL,
VOLTAGE_SUBGRAPH_URL,
STABLESWAP_SUBGRAPH_URL
} from '../constants'

export const uniswapClient = new ApolloClient({
link: new HttpLink({ uri: UNISWAP_SUBGRAPH_URL, fetch }),
Expand Down Expand Up @@ -31,3 +39,8 @@ export const masterChefV3Client = new ApolloClient({
link: new HttpLink({ uri: MASTERCHEF_V3_SUBGRAPH_URL, fetch }),
cache: new InMemoryCache()
})

export const stableswapClient = new ApolloClient({
link: new HttpLink({ uri: STABLESWAP_SUBGRAPH_URL, fetch }),
cache: new InMemoryCache()
})
18 changes: 18 additions & 0 deletions src/graphql/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ export function pairQuery (address: string) {
`
}

export function stablePoolQuery (poolAddress: string) {
return gql`
{
swaps(id: "${poolAddress.toLowerCase()}") {
numTokens
balances
lpTokenSupply
virtualPrice
tokens {
id
name
symbol
}
}
}
`
}

export function tokenPriceQuery (address: string) {
return gql`
{
Expand Down
32 changes: 12 additions & 20 deletions src/rewards/ChefRewardProgram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,36 +75,30 @@ export default class ChefRewardProgram extends RewardProgram {
const globalTotalStake = pool?.balance
const userTotalStaked = weiToNumber(user?.amount).toString()

let reserve0, reserve1, token0, token1, pairPrice
let reserves, tokens, pairPrice

if (pairAddress.toLowerCase() === xVOLT.toLowerCase()) {
token0 = await fetchTokenInfo(xVOLT, this.web3)
token1 = null
tokens = [await fetchTokenInfo(xVOLT, this.web3), null]

reserve0 = globalTotalStake
reserve1 = null
reserves = [globalTotalStake, null]

pairPrice = await fetchVoltageTokenPrice(VOLT, networkId)
} else {
const {
reserveUSD,
totalSupply,
token0: token0Info,
token1: token1Info,
totalReserve0,
totalReserve1
tokens: tokensInfo,
totalReserves
} = await fetchChefPairInfo(pairAddress, networkId)

const reserves = calculateReserves(
const _reserves = calculateReserves(
globalTotalStake,
totalSupply,
totalReserve0,
totalReserve1
totalReserves
)

token0 = token0Info
token1 = token1Info
reserve0 = reserves[0].toFixed()
reserve1 = reserves[1].toFixed()
tokens = tokensInfo
reserves = _reserves.map((reserve) => reserve.toFixed())
pairPrice = reserveUSD / totalSupply
}

Expand Down Expand Up @@ -157,13 +151,11 @@ export default class ChefRewardProgram extends RewardProgram {
return {
globalTotalStake,
rewardsInfo,
token0,
token1,
tokens,
totalStakedUSD,
globalTotalStakeUSD,
pairPrice,
reserve0,
reserve1
reserves
}
}

Expand Down
9 changes: 3 additions & 6 deletions src/rewards/MultiRewardProgram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ export default class MultiRewardProgram extends RewardProgram {
const [reserve0, reserve1] = calculateReserves(
globalTotalStake,
totalSupply,
totalReserve0,
totalReserve1
[totalReserve0, totalReserve1]
)

const pairPrice = reserveUSD / totalSupply
Expand All @@ -181,13 +180,11 @@ export default class MultiRewardProgram extends RewardProgram {
return {
globalTotalStake,
rewardsInfo,
token0,
token1,
tokens: [token0, token1],
totalStakedUSD,
globalTotalStakeUSD,
pairPrice,
reserve0: reserve0.toFixed(),
reserve1: reserve1.toFixed()
reserves: [reserve0.toFixed(), reserve1.toFixed()]
}
}

Expand Down
9 changes: 3 additions & 6 deletions src/rewards/SingleRewardProgram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,7 @@ export default class SingleRewardProgram extends RewardProgram {
const [reserve0, reserve1] = calculateReserves(
globalTotalStake,
totalSupply,
totalReserve0,
totalReserve1
[totalReserve0, totalReserve1]
)

const lockedRewards = new BigNumber(totalRewards).minus(
Expand Down Expand Up @@ -234,13 +233,11 @@ export default class SingleRewardProgram extends RewardProgram {
apyPercent
}
],
token0,
token1,
tokens: [token0, token1],
totalStakedUSD,
globalTotalStakeUSD,
pairPrice,
reserve0: reserve0.toFixed(),
reserve1: reserve1.toFixed(),
reserves: [reserve0.toFixed(), reserve1.toFixed()],
lockedRewards: lockedRewards.toFixed()
}
}
Expand Down
38 changes: 26 additions & 12 deletions src/utils/fetchChefPairInfo.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import { NetworkId } from '../constants'
import { pairQuery } from '../graphql/query'
import { voltageClient } from '../graphql'
import { pairQuery, stablePoolQuery } from '../graphql/query'
import { stableswapClient, voltageClient } from '../graphql'
import { isStableswap } from '.'

async function fetchPairInfoVoltage (address: string) {
const result = await voltageClient.query({
query: pairQuery(address)
})
return {
reserveUSD: result?.data?.pair?.reserveUSD,
totalSupply: result?.data?.pair?.totalSupply,
token0: result?.data?.pair?.token0,
token1: result?.data?.pair?.token1,
totalReserve0: result?.data?.pair?.reserve0,
totalReserve1: result?.data?.pair?.reserve1
let result
if (isStableswap(address)) {
result = await stableswapClient.query({
query: stablePoolQuery(address)
})
const tokens = result?.data?.swaps?.tokens
const reserves = result?.data?.swaps?.balances
return {
reserveUSD: result?.data?.swaps?.lpTokenSupply * 1,
totalSupply: result?.data?.swaps?.lpTokenSupply,
tokens,
totalReserves: reserves
}
} else {
result = await voltageClient.query({
query: pairQuery(address)
})
return {
reserveUSD: result?.data?.pair?.reserveUSD,
totalSupply: result?.data?.pair?.totalSupply,
tokens: [result?.data?.pair?.token0, result?.data?.pair?.token1],
totalReserves: [result?.data?.pair?.reserve0, result?.data?.pair?.reserve1]
}
}
}

Expand Down
22 changes: 12 additions & 10 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BigNumber } from 'bignumber.js'
import { MASTERCHEF_V2_ADDRESS, MASTERCHEF_V3_ADDRESS } from '../constants'
import { MASTERCHEF_V2_ADDRESS, MASTERCHEF_V3_ADDRESS, STABLESWAP_POOLS } from '../constants'
import { masterChefV2Client, masterChefV3Client } from '../graphql'
import { Chef } from '../rewards/ChefRewardProgram'

Expand All @@ -16,16 +16,14 @@ export function numberToWei (value: string, decimals = 18): string {
export function calculateReserves (
globalTotalStake: string,
totalSupply: string,
totalReserve0: string,
totalReserve1: string
totalReserves: string[]
) {
const reserve0 = new BigNumber(globalTotalStake)
.div(numberToWei(totalSupply))
.multipliedBy(numberToWei(totalReserve0))
const reserve1 = new BigNumber(globalTotalStake)
.div(numberToWei(totalSupply))
.multipliedBy(numberToWei(totalReserve1))
return [reserve0, reserve1]
const reserves = totalReserves.map(
(totalReserve) =>
new BigNumber(globalTotalStake)
.div(numberToWei(totalSupply))
.multipliedBy(numberToWei(totalReserve)))
return reserves
}

export function calculateApy (
Expand All @@ -52,3 +50,7 @@ export function getChefSubgraph (chef: Chef) {
return masterChefV3Client
}
}

export function isStableswap (address: string) {
return STABLESWAP_POOLS.includes(address)
}

0 comments on commit 2a176b3

Please sign in to comment.