From b3848b10606e9df5558df502b86b103817423e47 Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Thu, 14 Apr 2022 13:43:01 +0300 Subject: [PATCH 01/10] add stableswap subgraph queries, refactor chef program to work with stableswap --- src/constants/index.ts | 3 +++ src/graphql/index.ts | 15 +++++++++++- src/graphql/query.ts | 17 ++++++++++++++ src/rewards/ChefRewardProgram.ts | 32 ++++++++++--------------- src/utils/fetchChefPairInfo.ts | 40 ++++++++++++++++++++++---------- src/utils/index.ts | 22 ++++++++++-------- 6 files changed, 86 insertions(+), 43 deletions(-) diff --git a/src/constants/index.ts b/src/constants/index.ts index 1fa1762..017d449 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -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/t0mcr8se/stableswap-subgraph' export const MASTERCHEF_V2_ADDRESS = '0xc71E27C7e128d9CAEb2b8cA756647f7F199cF39e' export const MASTERCHEF_V3_ADDRESS = '0xE3e184a7b75D0Ae6E17B58F5283b91B4E0A2604F' @@ -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'] diff --git a/src/graphql/index.ts b/src/graphql/index.ts index e4220f2..2e95669 100644 --- a/src/graphql/index.ts +++ b/src/graphql/index.ts @@ -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 }), @@ -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() +}) diff --git a/src/graphql/query.ts b/src/graphql/query.ts index 61f44e0..a04d7ac 100644 --- a/src/graphql/query.ts +++ b/src/graphql/query.ts @@ -23,6 +23,23 @@ export function pairQuery (address: string) { ` } +export function stablePoolQuery (poolAddress: string) { + return gql` + { + swaps(id: "${poolAddress.toLowerCase()}") { + numTokens + balances + lpTokenSupply + virtualPrice + tokens { + id + decimals + } + } + } + ` +} + export function tokenPriceQuery (address: string) { return gql` { diff --git a/src/rewards/ChefRewardProgram.ts b/src/rewards/ChefRewardProgram.ts index a60c319..783cae6 100644 --- a/src/rewards/ChefRewardProgram.ts +++ b/src/rewards/ChefRewardProgram.ts @@ -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[0] = [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 } @@ -157,13 +151,11 @@ export default class ChefRewardProgram extends RewardProgram { return { globalTotalStake, rewardsInfo, - token0, - token1, + tokens, totalStakedUSD, globalTotalStakeUSD, pairPrice, - reserve0, - reserve1 + reserves } } diff --git a/src/utils/fetchChefPairInfo.ts b/src/utils/fetchChefPairInfo.ts index a3da69a..54e2bb8 100644 --- a/src/utils/fetchChefPairInfo.ts +++ b/src/utils/fetchChefPairInfo.ts @@ -1,18 +1,34 @@ 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, weiToNumber } from '.' +import fetchTokenPrice from './fetchTokenPrice' 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?.map((token) => token?.id) + const reserves = result?.data?.swaps?.balances + const pooledTokensUsd = result?.data?.swaps?.balanes?.map(async (balance, i) => (await fetchTokenPrice(tokens[i], NetworkId.FUSE)) * balance) + return { + reserveUSD: pooledTokensUsd?.reduce((mem, balanceUsd, i) => mem + weiToNumber(balanceUsd, result?.data?.swaps?.tokens?.[i]?.decimals)), + 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] + } } } diff --git a/src/utils/index.ts b/src/utils/index.ts index 49df805..3986385 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -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' @@ -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 ( @@ -52,3 +50,7 @@ export function getChefSubgraph (chef: Chef) { return masterChefV3Client } } + +export function isStableswap (address: string) { + return STABLESWAP_POOLS.includes(address) +} From 53970e3ddd81a7e9e0255dcea59d99cc8bebf197 Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Thu, 14 Apr 2022 13:45:34 +0300 Subject: [PATCH 02/10] fix typo --- src/rewards/ChefRewardProgram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rewards/ChefRewardProgram.ts b/src/rewards/ChefRewardProgram.ts index 783cae6..7f44aa7 100644 --- a/src/rewards/ChefRewardProgram.ts +++ b/src/rewards/ChefRewardProgram.ts @@ -80,7 +80,7 @@ export default class ChefRewardProgram extends RewardProgram { if (pairAddress.toLowerCase() === xVOLT.toLowerCase()) { tokens = [await fetchTokenInfo(xVOLT, this.web3), null] - reserves[0] = [globalTotalStake, null] + reserves = [globalTotalStake, null] pairPrice = await fetchVoltageTokenPrice(VOLT, networkId) } else { From 50b56357e8ab2a0d4785ae7ecc7de69637ca400b Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Thu, 14 Apr 2022 13:57:26 +0300 Subject: [PATCH 03/10] fix occurances of calculateReserves --- src/rewards/MultiRewardProgram.ts | 3 +-- src/rewards/SingleRewardProgram.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/rewards/MultiRewardProgram.ts b/src/rewards/MultiRewardProgram.ts index 8e71ada..61ba08d 100644 --- a/src/rewards/MultiRewardProgram.ts +++ b/src/rewards/MultiRewardProgram.ts @@ -168,8 +168,7 @@ export default class MultiRewardProgram extends RewardProgram { const [reserve0, reserve1] = calculateReserves( globalTotalStake, totalSupply, - totalReserve0, - totalReserve1 + [totalReserve0, totalReserve1] ) const pairPrice = reserveUSD / totalSupply diff --git a/src/rewards/SingleRewardProgram.ts b/src/rewards/SingleRewardProgram.ts index 997e760..d68fabe 100644 --- a/src/rewards/SingleRewardProgram.ts +++ b/src/rewards/SingleRewardProgram.ts @@ -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( From 4301ca3ffbc24b82074d6fef43a29fb38020274b Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Sun, 17 Apr 2022 13:29:49 +0300 Subject: [PATCH 04/10] use voltfinance/stableswap subgraph --- src/constants/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants/index.ts b/src/constants/index.ts index 017d449..469d68f 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -8,7 +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/t0mcr8se/stableswap-subgraph' +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' From 7d7b7267ed6f23140ed860add44cb278f30f73da Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Sun, 17 Apr 2022 13:33:17 +0300 Subject: [PATCH 05/10] simplify tvl --- src/utils/fetchChefPairInfo.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utils/fetchChefPairInfo.ts b/src/utils/fetchChefPairInfo.ts index 54e2bb8..95192fa 100644 --- a/src/utils/fetchChefPairInfo.ts +++ b/src/utils/fetchChefPairInfo.ts @@ -1,8 +1,7 @@ import { NetworkId } from '../constants' import { pairQuery, stablePoolQuery } from '../graphql/query' import { stableswapClient, voltageClient } from '../graphql' -import { isStableswap, weiToNumber } from '.' -import fetchTokenPrice from './fetchTokenPrice' +import { isStableswap } from '.' async function fetchPairInfoVoltage (address: string) { let result @@ -12,9 +11,8 @@ async function fetchPairInfoVoltage (address: string) { }) const tokens = result?.data?.swaps?.tokens?.map((token) => token?.id) const reserves = result?.data?.swaps?.balances - const pooledTokensUsd = result?.data?.swaps?.balanes?.map(async (balance, i) => (await fetchTokenPrice(tokens[i], NetworkId.FUSE)) * balance) return { - reserveUSD: pooledTokensUsd?.reduce((mem, balanceUsd, i) => mem + weiToNumber(balanceUsd, result?.data?.swaps?.tokens?.[i]?.decimals)), + reserveUSD: result?.data?.swaps?.lpTokenSupply * 1, totalSupply: result?.data?.swaps?.lpTokenSupply, tokens, totalReserves: reserves From 4e57b5b7c032b189d32cd2100de53a883084af6a Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Mon, 18 Apr 2022 12:24:27 +0300 Subject: [PATCH 06/10] modify stableswap query to fit interface --- src/graphql/query.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graphql/query.ts b/src/graphql/query.ts index a04d7ac..b12341b 100644 --- a/src/graphql/query.ts +++ b/src/graphql/query.ts @@ -33,7 +33,8 @@ export function stablePoolQuery (poolAddress: string) { virtualPrice tokens { id - decimals + name + symbol } } } From d3a5884e526ae1698b7156762584d6a361c88ff0 Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Mon, 18 Apr 2022 12:27:34 +0300 Subject: [PATCH 07/10] fix tokens attribute --- src/utils/fetchChefPairInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/fetchChefPairInfo.ts b/src/utils/fetchChefPairInfo.ts index 95192fa..1267a54 100644 --- a/src/utils/fetchChefPairInfo.ts +++ b/src/utils/fetchChefPairInfo.ts @@ -9,7 +9,7 @@ async function fetchPairInfoVoltage (address: string) { result = await stableswapClient.query({ query: stablePoolQuery(address) }) - const tokens = result?.data?.swaps?.tokens?.map((token) => token?.id) + const tokens = result?.data?.swaps?.tokens const reserves = result?.data?.swaps?.balances return { reserveUSD: result?.data?.swaps?.lpTokenSupply * 1, From 9a855436b31c9cd912868b9f3974d120ee9b64fd Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Tue, 19 Apr 2022 02:21:25 +0300 Subject: [PATCH 08/10] refactor multi rewards --- src/rewards/MultiRewardProgram.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/rewards/MultiRewardProgram.ts b/src/rewards/MultiRewardProgram.ts index 61ba08d..596db62 100644 --- a/src/rewards/MultiRewardProgram.ts +++ b/src/rewards/MultiRewardProgram.ts @@ -180,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()] } } From 1ea5dabffdde31896abec0c8c541d866af505588 Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Tue, 19 Apr 2022 02:22:26 +0300 Subject: [PATCH 09/10] refactor single rewards --- src/rewards/SingleRewardProgram.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/rewards/SingleRewardProgram.ts b/src/rewards/SingleRewardProgram.ts index d68fabe..86314eb 100644 --- a/src/rewards/SingleRewardProgram.ts +++ b/src/rewards/SingleRewardProgram.ts @@ -233,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() } } From 0d7504c60b86fdcef541434cf18c89ab9fa13254 Mon Sep 17 00:00:00 2001 From: t0mcr8se Date: Tue, 19 Apr 2022 16:51:32 +0300 Subject: [PATCH 10/10] v1.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc3da77..9f9f58d 100644 --- a/package.json +++ b/package.json @@ -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",