forked from goosedefi/goose-api
-
Notifications
You must be signed in to change notification settings - Fork 0
/
getTVL.js
142 lines (129 loc) · 5.58 KB
/
getTVL.js
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
import MultiCallAbi from "./abi/Multicall.json";
import erc20 from "./abi/erc20.json";
import BigNumber from "bignumber.js";
import {ContractAddresses} from "./configs/ContractAddresses";
import {Interface} from "@ethersproject/abi";
import {farmsConfig} from "./configs/farms";
import Web3 from "web3";
import {TokenSymbols} from "./configs/TokenSymbols";
import {failure, success} from "./response-lib";
const ZERO = new BigNumber(0);
const web3 = new Web3(process.env.Provider);
const multi = new web3.eth.Contract(MultiCallAbi, ContractAddresses.multiCall);
export async function getTVL() {
try {
const farms = await fetchFarms();
const bnbbusdFarm = farms.find(f => f.pid === 2);
const bnbPrice = bnbbusdFarm.tokenPriceVsQuote ? new BigNumber(bnbbusdFarm.tokenPriceVsQuote) : ZERO;
let value = new BigNumber(0);
for (let i = 0; i < farms.length; i++) {
const farm = farms[i]
if (farm.lpTotalInQuoteToken) {
let val;
if (farm.quoteTokenSymbol === TokenSymbols.BNB) {
val = (bnbPrice.times(farm.lpTotalInQuoteToken));
} else {
val = (farm.lpTotalInQuoteToken);
}
value = value.plus(val);
}
}
return success(value.toFixed(2));
} catch (e) {
return failure(e);
}
}
async function multicall(abi, calls) {
const itf = new Interface(abi)
const callData = calls.map((call) => [call.address.toLowerCase(), itf.encodeFunctionData(call.name, call.params)])
const {returnData} = await multi.methods.aggregate(callData).call()
const res = returnData.map((call, i) => itf.decodeFunctionResult(calls[i].name, call))
return res
}
const CHAIN_ID = 56;
async function fetchFarms() {
return await Promise.all(
farmsConfig.map(async (farmConfig) => {
const lpAddress = farmConfig.lpAddresses[CHAIN_ID]
const calls = [
// Balance of token in the LP contract
{
address: farmConfig.tokenAddresses[CHAIN_ID],
name: 'balanceOf',
params: [lpAddress],
},
// Balance of quote token on LP contract
{
address: farmConfig.quoteTokenAdresses[CHAIN_ID],
name: 'balanceOf',
params: [lpAddress],
},
// Balance of LP tokens in the master chef contract
{
address: farmConfig.isTokenOnly ? farmConfig.tokenAddresses[CHAIN_ID] : lpAddress,
name: 'balanceOf',
params: [ContractAddresses.masterChef],
},
// Total supply of LP tokens
{
address: lpAddress,
name: 'totalSupply',
},
// Token decimals
{
address: farmConfig.tokenAddresses[CHAIN_ID],
name: 'decimals',
},
// Quote token decimals
{
address: farmConfig.quoteTokenAdresses[CHAIN_ID],
name: 'decimals',
},
]
const [
tokenBalanceLP,
quoteTokenBlanceLP,
lpTokenBalanceMC,
lpTotalSupply,
tokenDecimals,
quoteTokenDecimals
] = await multicall(erc20, calls)
let tokenAmount;
let lpTotalInQuoteToken;
let tokenPriceVsQuote;
if (farmConfig.isTokenOnly) {
tokenAmount = new BigNumber(lpTokenBalanceMC).div(new BigNumber(10).pow(tokenDecimals));
if (farmConfig.tokenSymbol === TokenSymbols.BUSD && farmConfig.quoteTokenSymbol === TokenSymbols.BUSD) {
tokenPriceVsQuote = new BigNumber(1);
} else {
tokenPriceVsQuote = new BigNumber(quoteTokenBlanceLP).div(new BigNumber(tokenBalanceLP));
}
lpTotalInQuoteToken = tokenAmount.times(tokenPriceVsQuote);
} else {
// Ratio in % a LP tokens that are in staking, vs the total number in circulation
const lpTokenRatio = new BigNumber(lpTokenBalanceMC).div(new BigNumber(lpTotalSupply))
// Total value in staking in quote token value
lpTotalInQuoteToken = new BigNumber(quoteTokenBlanceLP)
.div(new BigNumber(10).pow(18))
.times(new BigNumber(2))
.times(lpTokenRatio)
// Amount of token in the LP that are considered staking (i.e amount of token * lp ratio)
tokenAmount = new BigNumber(tokenBalanceLP).div(new BigNumber(10).pow(tokenDecimals)).times(lpTokenRatio)
const quoteTokenAmount = new BigNumber(quoteTokenBlanceLP)
.div(new BigNumber(10).pow(quoteTokenDecimals))
.times(lpTokenRatio)
if (tokenAmount.comparedTo(0) > 0) {
tokenPriceVsQuote = quoteTokenAmount.div(tokenAmount);
} else {
tokenPriceVsQuote = new BigNumber(quoteTokenBlanceLP).div(new BigNumber(tokenBalanceLP));
}
}
return {
...farmConfig,
tokenAmount: tokenAmount.toJSON(),
lpTotalInQuoteToken: lpTotalInQuoteToken.toJSON(),
tokenPriceVsQuote: tokenPriceVsQuote.toJSON(),
}
}),
)
}