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", diff --git a/src/constants/index.ts b/src/constants/index.ts index 1fa1762..469d68f 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/voltfinance/stableswap' 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..b12341b 100644 --- a/src/graphql/query.ts +++ b/src/graphql/query.ts @@ -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` { diff --git a/src/rewards/ChefRewardProgram.ts b/src/rewards/ChefRewardProgram.ts index a60c319..7f44aa7 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 = [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/rewards/MultiRewardProgram.ts b/src/rewards/MultiRewardProgram.ts index 8e71ada..596db62 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 @@ -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()] } } diff --git a/src/rewards/SingleRewardProgram.ts b/src/rewards/SingleRewardProgram.ts index 997e760..86314eb 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( @@ -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() } } diff --git a/src/utils/fetchChefPairInfo.ts b/src/utils/fetchChefPairInfo.ts index a3da69a..1267a54 100644 --- a/src/utils/fetchChefPairInfo.ts +++ b/src/utils/fetchChefPairInfo.ts @@ -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] + } } } 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) +}