impermax-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/.idea/impermax-sdk.iml +12 -0
  2. package/.idea/misc.xml +6 -0
  3. package/.idea/modules.xml +8 -0
  4. package/.idea/workspace.xml +642 -0
  5. package/abis/ImpermaxABI.ts +3 -0
  6. package/abis/contracts/BAllowance.json +4735 -0
  7. package/abis/contracts/BDeployer.json +1195 -0
  8. package/abis/contracts/BInterestRateModel.json +10796 -0
  9. package/abis/contracts/BSetter.json +6219 -0
  10. package/abis/contracts/BStorage.json +2613 -0
  11. package/abis/contracts/Borrowable.json +19937 -0
  12. package/abis/contracts/CDeployer.json +1104 -0
  13. package/abis/contracts/CSetter.json +5094 -0
  14. package/abis/contracts/CStorage.json +516 -0
  15. package/abis/contracts/ClaimAggregator.json +2015 -0
  16. package/abis/contracts/Collateral.json +21615 -0
  17. package/abis/contracts/ERC20.json +819 -0
  18. package/abis/contracts/Factory.json +21986 -0
  19. package/abis/contracts/FarmingPool.json +8601 -0
  20. package/abis/contracts/IBDeployer.json +351 -0
  21. package/abis/contracts/IBorrowTracker.json +346 -0
  22. package/abis/contracts/IBorrowable.json +13207 -0
  23. package/abis/contracts/ICDeployer.json +294 -0
  24. package/abis/contracts/IClaimable.json +406 -0
  25. package/abis/contracts/ICollateral.json +8952 -0
  26. package/abis/contracts/IERC20.json +2376 -0
  27. package/abis/contracts/IFactory.json +3660 -0
  28. package/abis/contracts/IFarmingPool.json +3584 -0
  29. package/abis/contracts/IImpermaxCallee.json +679 -0
  30. package/abis/contracts/IMerkleDistributor.json +1134 -0
  31. package/abis/contracts/IPoolToken.json +5343 -0
  32. package/abis/contracts/IRouter01.json +6891 -0
  33. package/abis/contracts/IRouter02.json +7283 -0
  34. package/abis/contracts/ISimpleUniswapOracle.json +1469 -0
  35. package/abis/contracts/IStakedLPToken.json +7309 -0
  36. package/abis/contracts/IStakingRewards.json +1036 -0
  37. package/abis/contracts/IUniswapV2Callee.json +403 -0
  38. package/abis/contracts/IUniswapV2ERC20.json +3155 -0
  39. package/abis/contracts/IUniswapV2Factory.json +1690 -0
  40. package/abis/contracts/IUniswapV2Pair.json +6761 -0
  41. package/abis/contracts/IWETH.json +561 -0
  42. package/abis/contracts/ImpermaxChef.json +20945 -0
  43. package/abis/contracts/ImpermaxERC20.json +12095 -0
  44. package/abis/contracts/Math.json +1966 -0
  45. package/abis/contracts/MockERC20.json +8884 -0
  46. package/abis/contracts/PoolToken.json +10784 -0
  47. package/abis/contracts/Router01.json +43963 -0
  48. package/abis/contracts/SafeMath.json +6828 -0
  49. package/abis/contracts/SimpleUniswapOracle.json +9640 -0
  50. package/abis/contracts/TransferHelper.json +4875 -0
  51. package/abis/contracts/UQ112x112.json +1201 -0
  52. package/abis/contracts/UniswapV2ERC20.json +10969 -0
  53. package/abis/contracts/UniswapV2Factory.json +5521 -0
  54. package/abis/contracts/UniswapV2Library.json +13789 -0
  55. package/abis/contracts/UniswapV2Pair.json +30782 -0
  56. package/abis/contracts/WETH9.json +6613 -0
  57. package/config/amms.ts +199 -0
  58. package/config/contracts/claim-aggregators.ts +16 -0
  59. package/config/contracts/impermax-chef.ts +16 -0
  60. package/config/contracts/imxes.ts +16 -0
  61. package/config/contracts/merkle-distributors.ts +13 -0
  62. package/config/contracts/routers.ts +36 -0
  63. package/config/contracts/simple-uniswap-oracles.ts +33 -0
  64. package/config/contracts/weths.ts +18 -0
  65. package/config/debank-ids.ts +15 -0
  66. package/config/endpoints/merkle-distributors.ts +13 -0
  67. package/config/eth.ts +32 -0
  68. package/config/factories.ts +26 -0
  69. package/config/farms.ts +119 -0
  70. package/config/general.ts +8 -0
  71. package/config/subgraphs.ts +69 -0
  72. package/config/types.ts +81 -0
  73. package/impermax-router/Account.ts +123 -0
  74. package/impermax-router/AccountBorrowable.ts +110 -0
  75. package/impermax-router/AccountCollateral.ts +40 -0
  76. package/impermax-router/AccountLendingPool.ts +231 -0
  77. package/impermax-router/AccountPoolToken.ts +76 -0
  78. package/impermax-router/Borrowable.ts +86 -0
  79. package/impermax-router/Collateral.ts +26 -0
  80. package/impermax-router/ContractsHelper.ts +64 -0
  81. package/impermax-router/ImpermaxFactory.ts +47 -0
  82. package/impermax-router/Interactions.ts +94 -0
  83. package/impermax-router/InteractionsLendingPool.ts +129 -0
  84. package/impermax-router/InteractionsPoolToken.ts +187 -0
  85. package/impermax-router/LendingPool.ts +256 -0
  86. package/impermax-router/PoolToken.ts +112 -0
  87. package/impermax-router/index.ts +49 -0
  88. package/impermax-router/interfaces.ts +233 -0
  89. package/index.ts +5 -0
  90. package/package.json +23 -0
  91. package/subgraph/Account.ts +93 -0
  92. package/subgraph/AccountLendingPool.ts +60 -0
  93. package/subgraph/AccountPoolToken.ts +60 -0
  94. package/subgraph/LendingPool.ts +179 -0
  95. package/subgraph/PoolToken.ts +381 -0
  96. package/subgraph/PriceHelper.ts +150 -0
  97. package/subgraph/SolidexHelper.ts +54 -0
  98. package/subgraph/index.ts +166 -0
  99. package/subgraph/initializer.ts +509 -0
  100. package/subgraph/query.ts +224 -0
  101. package/tsconfig.json +16 -0
  102. package/utils/ether-utils.ts +22 -0
  103. package/utils/index.ts +12 -0
@@ -0,0 +1,166 @@
1
+ import { LendingPoolData, TvlData, UserData, XimxData } from "../impermax-router/interfaces";
2
+
3
+ import * as initializer from "./initializer";
4
+ import LendingPool from "./LendingPool";
5
+ import PriceHelper from "./PriceHelper";
6
+ import SolidexHelper from "./SolidexHelper";
7
+ import Account from "./Account";
8
+ import { Address, Factory, FactoryIndex, LendingPoolIndex, Networks } from '../config/types';
9
+
10
+ export interface SubgraphCfg {
11
+ network: Networks;
12
+ chainId: number;
13
+ whitelistedPairs?: FactoryIndex<Address[]>;
14
+ }
15
+
16
+ export default class Subgraph {
17
+ network: Networks;
18
+ chainId: number;
19
+ whitelistedPairs?: FactoryIndex<Address[]>;
20
+ lendingPools: LendingPoolIndex<LendingPool>;
21
+ accounts: {
22
+ [key in Address]?: Account
23
+ };
24
+ priceHelper: PriceHelper;
25
+ solidexHelper: SolidexHelper;
26
+ lendingPoolsData: Promise<LendingPoolIndex<LendingPoolData>>;
27
+ usersData: {
28
+ [key in Address]?: Promise<FactoryIndex<UserData>>
29
+ };
30
+ tvlData: Promise<TvlData>;
31
+ ximxData: Promise<XimxData>;
32
+
33
+ constructor(cfg: SubgraphCfg) {
34
+ this.network = cfg.network as Networks;
35
+ this.chainId = cfg.chainId;
36
+ this.whitelistedPairs = cfg.whitelistedPairs;
37
+ this.priceHelper = new PriceHelper(this);
38
+ this.solidexHelper = new SolidexHelper(this);
39
+ this.accounts = {};
40
+ this.usersData = {};
41
+ }
42
+
43
+ cleanCache() {
44
+ this.lendingPoolsData = null;
45
+ this.usersData = {};
46
+ this.tvlData = null;
47
+ this.ximxData = null;
48
+ this.priceHelper.cleanCache();
49
+ this.solidexHelper.cleanCache();
50
+ }
51
+
52
+ async getLendingPool(factory: Factory, pairAddress: Address) : Promise<LendingPool> {
53
+ await this.getLendingPoolsData(); // make sure that lending pools are initialized
54
+ return this.lendingPools[factory][pairAddress];
55
+ }
56
+
57
+ getAccount(account: Address) : Account {
58
+ if (!this.accounts[account]) this.accounts[account] = new Account(this, account);
59
+ return this.accounts[account];
60
+ }
61
+
62
+ /**
63
+ * TODO
64
+ * Potrei organizzare in:
65
+ * - lendingPoolData
66
+ * - usersData
67
+ * - tvlData
68
+ * - ximxData
69
+ */
70
+
71
+ // Fetchers
72
+ public apolloFetcher = initializer.apolloFetcher;
73
+ public fetchLendingPools = initializer.fetchLendingPools;
74
+ public fetchLendingPoolsPast = initializer.fetchLendingPoolsPast;
75
+ public fetchPastVolume = initializer.fetchPastVolume;
76
+ public fetchCurrentVolumeAndReserves = initializer.fetchCurrentVolumeAndReserves;
77
+ public fetchImpermaxChefRewardRates = initializer.fetchImpermaxChefRewardRates;
78
+ public fetchUniswapAPR = initializer.fetchUniswapAPR;
79
+ public fetchBlockByTimestamp = initializer.fetchBlockByTimestamp;
80
+ public initializeLendingPoolsData = initializer.initializeLendingPoolsData;
81
+ public getLendingPoolsData = initializer.getLendingPoolsData;
82
+ public getLendingPoolData = initializer.getLendingPoolData;
83
+ public initializeTvlData = initializer.initializeTvlData;
84
+ public getTvlData = initializer.getTvlData;
85
+ public fetchUserData = initializer.fetchUserData;
86
+ public initializeUserData = initializer.initializeUserData;
87
+ public getUserData = initializer.getUserData;
88
+ public initializeXimxData = initializer.initializeXimxData;
89
+ public getXimxData = initializer.getXimxData;
90
+
91
+ /**
92
+ * DATA GETTERS
93
+ */
94
+
95
+ // Pair List
96
+ /*async getPairListOld() : Promise<FactoryIndex<Address[]>> {
97
+ const result: FactoryIndex<Address[]> = {};
98
+ const lendingPoolData = await this.getLendingPoolsData();
99
+ for (const factory of Object.keys(lendingPoolData) as Factory[]) {
100
+ result[factory] = Object.keys(lendingPoolData[factory]);
101
+ }
102
+ return result;
103
+ }
104
+ async getPairListWithData() {
105
+ const pairList = await this.getPairList();
106
+ if (!pairList) return null;
107
+ const requests = [];
108
+ for (const factory of Object.keys(pairList) as Factory[]) {
109
+ for (const pairAddress of pairList[factory]) {
110
+ requests.push(this.getPairData(factory, pairAddress));
111
+ }
112
+ }
113
+ console.log("length", requests.length)
114
+ return Promise.all(requests);
115
+ }*/
116
+ async getPairList() {
117
+ const result = [];
118
+ const lendingPoolData = await this.getLendingPoolsData();
119
+ for (const factory of Object.keys(lendingPoolData) as Factory[]) {
120
+ for (const pairAddress of Object.keys(lendingPoolData[factory])) {
121
+ result.push({pairAddress, factory});
122
+ }
123
+ }
124
+ return result;
125
+ }
126
+ private async getPairData(factory: Factory, pairAddress: Address) {
127
+ const lendingPool = await this.getLendingPool(factory, pairAddress);
128
+ const totalBorrowsUSD = await lendingPool.getTotalBorrowsUSD();
129
+ return {pairAddress, factory, totalBorrowsUSD};
130
+ }
131
+ async getPairListWithData(pairList: {
132
+ pairAddress: string;
133
+ factory: Factory;
134
+ }[]) {
135
+ const requests = [];
136
+ for (const pair of pairList) {
137
+ requests.push(this.getPairData(pair.factory, pair.pairAddress));
138
+ }
139
+ return Promise.all(requests);
140
+ }
141
+
142
+ // TVL Data
143
+ async getCrossChainTVL() : Promise<number> {
144
+ const tvlData = await this.getTvlData();
145
+ return tvlData.crossChainTVLUSD;
146
+ }
147
+ async getTotalValueLocked() : Promise<number> {
148
+ const tvlData = await this.getTvlData();
149
+ return tvlData.totalBalanceUSD;
150
+ }
151
+ async getTotalValueSupplied() : Promise<number> {
152
+ const tvlData = await this.getTvlData();
153
+ return tvlData.totalSupplyUSD;
154
+ }
155
+ async getTotalValueBorrowed() : Promise<number> {
156
+ const tvlData = await this.getTvlData();
157
+ return tvlData.totalBorrowsUSD;
158
+ }
159
+
160
+ // IMX Staking
161
+ async getXIMXAPY() : Promise<number> {
162
+ const ximxData = await this.getXimxData();
163
+ if (!ximxData) return 0;
164
+ return Math.pow(1 + parseFloat(ximxData.dailyAPR), 365) - 1;
165
+ }
166
+ }
@@ -0,0 +1,509 @@
1
+ import { LendingPoolData, TvlData, UserData, CollateralPosition, SupplyPosition, BorrowPosition, XimxData } from "../impermax-router/interfaces";
2
+ import ApolloClient from "apollo-client";
3
+ import { HttpLink } from "apollo-link-http";
4
+ import { InMemoryCache } from "apollo-cache-inmemory";
5
+ import Subgraph from ".";
6
+ import { DocumentNode, } from "graphql";
7
+ import * as query from "./query";
8
+ import LendingPool from "./LendingPool";
9
+ import {
10
+ BLOCKS_SUBGRAPH_URL,
11
+ IMPERMAX_CHEF_SUBGRAPH_URL,
12
+ IMPERMAX_SUBGRAPH_URL,
13
+ XIMX_SUBGRAPH_URL
14
+ } from '../config/subgraphs';
15
+ import {
16
+ Address,
17
+ AddressIndex, Amms,
18
+ Factory,
19
+ FactoryIndex,
20
+ LendingPoolIndex,
21
+ Networks,
22
+ PoolTokenType
23
+ } from '../config/types';
24
+ import { AMM_LP_FEE, AMM_SUBGRAPH_URLS, getAmmByFactory } from '../config/amms';
25
+
26
+ const SECONDS_IN_YEAR = 60 * 60 * 24 * 365;
27
+
28
+ export async function apolloFetcher(subgraphUrl: string, query: DocumentNode) {
29
+ const client = new ApolloClient({
30
+ link: new HttpLink({
31
+ uri: subgraphUrl,
32
+ }),
33
+ cache: new InMemoryCache(),
34
+ });
35
+ return client.query({
36
+ query: query,
37
+ fetchPolicy: 'cache-first',
38
+ });
39
+ }
40
+
41
+ export async function fetchBlockByTimestamp(this: Subgraph, timestamp: number) : Promise<number> {
42
+ const result = await this.apolloFetcher(
43
+ BLOCKS_SUBGRAPH_URL[this.network],
44
+ query.blockQuery(timestamp)
45
+ );
46
+ console.log(result.data._meta.block.number);
47
+ return result.data.blocks[0].number;
48
+ }
49
+
50
+ // Fetch Lending Pools
51
+ export async function fetchLendingPools(this: Subgraph) : Promise<FactoryIndex<LendingPoolData[]>> {
52
+ const calls = [];
53
+ for (const factory of Object.keys(IMPERMAX_SUBGRAPH_URL[this.network]) as Factory[]) {
54
+ const subgraph = IMPERMAX_SUBGRAPH_URL[this.network][factory];
55
+ calls.push(this.apolloFetcher(subgraph, query.lendingPoolsQuery(factory, [])));
56
+ }
57
+ const results = await Promise.all(calls);
58
+ const lendingPools: FactoryIndex<LendingPoolData[]> = {};
59
+ let i = 0;
60
+ for (const factory of Object.keys(IMPERMAX_SUBGRAPH_URL[this.network])) {
61
+ lendingPools[factory as Factory] = results[i++].data.lendingPools;
62
+ }
63
+ return lendingPools;
64
+ }
65
+ export async function fetchLendingPoolsPast(this: Subgraph, seconds: number) : Promise<FactoryIndex<any[]>> {
66
+ const timestamp = Math.floor((new Date).getTime() / 1000);
67
+ const blockNumber = await this.fetchBlockByTimestamp(timestamp - seconds);
68
+ try {
69
+ const calls = [];
70
+ for (const factory of Object.keys(IMPERMAX_SUBGRAPH_URL[this.network]) as Factory[]) {
71
+ const subgraph = IMPERMAX_SUBGRAPH_URL[this.network][factory];
72
+ calls.push(this.apolloFetcher(subgraph, query.lendingPoolsPastQuery(blockNumber, this.whitelistedPairs[factory])));
73
+ }
74
+ const results = await Promise.all(calls);
75
+ const lendingPools: FactoryIndex<any[]> = {};
76
+ let i = 0;
77
+ for (const factory of Object.keys(IMPERMAX_SUBGRAPH_URL[this.network])) {
78
+ lendingPools[factory as Factory] = results[i++].data.lendingPools;
79
+ }
80
+ return lendingPools;
81
+ }
82
+ catch { return null }
83
+ }
84
+
85
+ // Farming APR
86
+
87
+ export async function fetchImpermaxChefRewardRates(this: Subgraph) : Promise<AddressIndex<Array<{
88
+ rewardToken: Address,
89
+ rewardRate: number
90
+ }>>> {
91
+ if (!IMPERMAX_CHEF_SUBGRAPH_URL[this.network]) return null;
92
+ const result = await this.apolloFetcher(
93
+ IMPERMAX_CHEF_SUBGRAPH_URL[this.network],
94
+ query.impermaxChefQuery()
95
+ );
96
+
97
+ const rewards: AddressIndex<Array<{
98
+ rewardToken: Address,
99
+ rewardRate: number
100
+ }>> = {};
101
+
102
+ let rewardToken = result.data.impermaxChefs[0].rewardToken;
103
+ let rewardPerSec = parseFloat(result.data.impermaxChefs[0].rewardPerSec);
104
+ let totalAllocPoint = parseFloat(result.data.impermaxChefs[0].totalAllocPoint);
105
+ const impermaxRewarders: Array<{
106
+ rewardToken: string,
107
+ rewardPerSec: string,
108
+ totalAllocPoint: string,
109
+ pools: Array<{
110
+ borrowable: string,
111
+ allocPoint: string,
112
+ }>
113
+ }> = result.data.impermaxRewarders;
114
+
115
+ for (const pool of result.data.pools) {
116
+ rewards[pool.id as Address] = [];
117
+ rewards[pool.id as Address].push({
118
+ rewardToken,
119
+ rewardRate: parseFloat(pool.allocPoint) / totalAllocPoint * rewardPerSec
120
+ });
121
+ }
122
+
123
+ for (const impermaxRewarder of impermaxRewarders) {
124
+ rewardToken = impermaxRewarder.rewardToken;
125
+ rewardPerSec = parseFloat(impermaxRewarder.rewardPerSec);
126
+ totalAllocPoint = parseFloat(impermaxRewarder.totalAllocPoint);
127
+ for (const pool of impermaxRewarder.pools) {
128
+ if (!(pool.borrowable in rewards)) rewards[pool.borrowable] = [];
129
+ rewards[pool.borrowable].push({
130
+ rewardToken,
131
+ rewardRate: parseFloat(pool.allocPoint) / totalAllocPoint * rewardPerSec
132
+ });
133
+ }
134
+ }
135
+
136
+ return rewards;
137
+ }
138
+
139
+ // Uniswap APR
140
+
141
+ export async function fetchPastVolume(this: Subgraph, amm: Amms, lendingPools: LendingPoolData[], seconds: number) : Promise<AddressIndex<number>> {
142
+ const timestamp = Math.floor((new Date).getTime() / 1000);
143
+ const blockNumber = await this.fetchBlockByTimestamp(timestamp - seconds);
144
+ let result;
145
+ const pastVolume: AddressIndex<number> = {};
146
+ try {
147
+ result = await this.apolloFetcher(
148
+ AMM_SUBGRAPH_URLS[this.network][amm],
149
+ query.pastVolumeQuery(blockNumber, lendingPools.map(lendingPool => lendingPool.pair.uniswapV2PairAddress))
150
+ );
151
+ for (const pair of result.data.pairs) {
152
+ pastVolume[pair.id] = parseInt(pair.volumeUSD);
153
+ }
154
+ }
155
+ catch (e) {
156
+ console.error(e);
157
+ }
158
+ return pastVolume;
159
+ }
160
+
161
+ export async function fetchCurrentVolumeAndReserves(this: Subgraph, amm: Amms, lendingPools: LendingPoolData[]) : Promise<{
162
+ currentVolume: AddressIndex<number>,
163
+ currentReserve: AddressIndex<number>,
164
+ }> {
165
+ let result;
166
+ const currentVolume: AddressIndex<number> = {};
167
+ const currentReserve: AddressIndex<number> = {};
168
+ try {
169
+ result = await this.apolloFetcher(
170
+ AMM_SUBGRAPH_URLS[this.network][amm],
171
+ query.currentVolumeAndReservesQuery(lendingPools.map(lendingPool => lendingPool.pair.uniswapV2PairAddress))
172
+ );
173
+ for (const pair of result.data.pairs) {
174
+ currentVolume[pair.id] = parseInt(pair.volumeUSD);
175
+ currentReserve[pair.id] = parseInt(pair.reserveUSD);
176
+ }
177
+ }
178
+ catch (e) {
179
+ console.error(e);
180
+ }
181
+ return { currentReserve, currentVolume };
182
+ }
183
+
184
+ export async function fetchUniswapAPR(this: Subgraph, lendingPoolsByAmm: {[key in Amms]?: LendingPoolData[]}, seconds: number = 60 * 60 * 24 * 7) : Promise<AddressIndex<number>> {
185
+ const uniswapAPR: AddressIndex<number> = {};
186
+ const amms = Object.keys(lendingPoolsByAmm) as Amms[];
187
+
188
+ const promises = [];
189
+ for (const amm of amms) {
190
+ if (!AMM_SUBGRAPH_URLS[this.network][amm]) continue;
191
+ promises.push(Promise.all([
192
+ amm,
193
+ this.fetchPastVolume(amm, lendingPoolsByAmm[amm], seconds),
194
+ this.fetchCurrentVolumeAndReserves(amm, lendingPoolsByAmm[amm]),
195
+ ]));
196
+ }
197
+
198
+ const ammsData = await Promise.all(promises);
199
+ for (const data of ammsData) {
200
+ const [
201
+ amm,
202
+ pastVolume,
203
+ { currentVolume, currentReserve },
204
+ ] = data;
205
+
206
+ for (const lendingPool of lendingPoolsByAmm[amm]) {
207
+ const uniswapV2PairAddress = lendingPool.pair.uniswapV2PairAddress;
208
+ if (!currentReserve[uniswapV2PairAddress]) {
209
+ uniswapAPR[lendingPool.id] = 0;
210
+ continue;
211
+ }
212
+ const cumVolumePast = pastVolume[uniswapV2PairAddress] ? pastVolume[uniswapV2PairAddress] : 0;
213
+ const cumVolumeNow = currentVolume[uniswapV2PairAddress];
214
+ const reserveUSD = currentReserve[uniswapV2PairAddress];
215
+ const volumeUSD = cumVolumeNow - cumVolumePast;
216
+ const yearlyVolume = volumeUSD * SECONDS_IN_YEAR / seconds;
217
+ const yearlyFee = yearlyVolume * AMM_LP_FEE[this.network][amm];
218
+ uniswapAPR[lendingPool.id] = yearlyFee / reserveUSD;
219
+ }
220
+ }
221
+ return uniswapAPR;
222
+ }
223
+
224
+ // LendingPool Data
225
+ export async function initializeLendingPoolsData(this: Subgraph) : Promise<LendingPoolIndex<LendingPoolData>> {
226
+ const lendingPoolsData: LendingPoolIndex<LendingPoolData> = {};
227
+
228
+ // Get raw data
229
+ const [
230
+ lendingPools,
231
+ lendingPoolsPast24h,
232
+ lendingPoolsPast7d,
233
+ impermaxChefRewardRates,
234
+ ] = await Promise.all([
235
+ this.fetchLendingPools(),
236
+ this.fetchLendingPoolsPast(24 * 3600),
237
+ this.fetchLendingPoolsPast(7 * 24 * 3600),
238
+ this.fetchImpermaxChefRewardRates(),
239
+ ]);
240
+
241
+ // Get Uniswap APR
242
+ const lendingPoolsByAmm: {[key in Amms]?: LendingPoolData[]} = {};
243
+ for (const factory of Object.keys(lendingPools) as Factory[]) {
244
+ for (const lendingPool of lendingPools[factory]) {
245
+ const amm = getAmmByFactory(this.network, lendingPool.pair.uniswapV2Factory);
246
+ if (!amm) continue;
247
+ if (!lendingPoolsByAmm[amm]) lendingPoolsByAmm[amm] = [];
248
+ lendingPoolsByAmm[amm].push(lendingPool);
249
+ }
250
+ }
251
+ const uniswapAPR = await this.fetchUniswapAPR(lendingPoolsByAmm);
252
+
253
+ // Organize lending pools data
254
+ for (const factory of Object.keys(lendingPools) as Factory[]) {
255
+ for (const lendingPool of lendingPools[factory]) {
256
+ lendingPool.pair.uniswapAPR = uniswapAPR[lendingPool.id] || 0;
257
+ if (impermaxChefRewardRates) {
258
+ lendingPool.borrowable0.rewards = impermaxChefRewardRates[lendingPool.borrowable0.id];
259
+ lendingPool.borrowable1.rewards = impermaxChefRewardRates[lendingPool.borrowable1.id];
260
+ }
261
+ // If one of the price of the 2 tokens is 0, fix the collateral price by doubling it
262
+ if (parseFloat(lendingPool.borrowable0.underlying.derivedUSD) === 0 || parseFloat(lendingPool.borrowable1.underlying.derivedUSD) === 0) {
263
+ lendingPool.pair.derivedUSD = (parseFloat(lendingPool.pair.derivedUSD) * 2).toString();
264
+ }
265
+ if (!lendingPoolsData[factory]) lendingPoolsData[factory] = {};
266
+ lendingPoolsData[factory][lendingPool.id] = lendingPool;
267
+ }
268
+ // Add past data
269
+ if (lendingPoolsPast24h && lendingPoolsPast24h[factory]) {
270
+ for (const lendingPool of lendingPoolsPast24h[factory]) {
271
+ lendingPoolsData[factory][lendingPool.id].past24h = lendingPool;
272
+ }
273
+ }
274
+ if (lendingPoolsPast7d && lendingPoolsPast7d[factory]) {
275
+ for (const lendingPool of lendingPoolsPast7d[factory]) {
276
+ lendingPoolsData[factory][lendingPool.id].past7d = lendingPool;
277
+ }
278
+ }
279
+ }
280
+
281
+ // Initialize LendingPool objects
282
+ this.lendingPools = {};
283
+ for (const factory of Object.keys(lendingPools) as Factory[]) {
284
+ this.lendingPools[factory] = {};
285
+ for (const lendingPool of lendingPools[factory]) {
286
+ this.lendingPools[factory][lendingPool.id] = new LendingPool(this, factory, lendingPool.id);
287
+ }
288
+ }
289
+
290
+
291
+ // Quickfix for MIM and SPELL
292
+
293
+ if (this.network === Networks.Arbitrum) {
294
+ //const ETH_MIM = '0xa6e69dd0c36f3b59539e2c7afd274ef91b5c70f9';
295
+ //const ETH_SPELL = '0x35b44b303eacb71114aa62fe8dae6f9c5de0f680';
296
+ const ETH_gGOHM = '0x6d94f7e67c6ae0b0257c35754e059fdfb249d998';
297
+ const ETH_MAGIC = '0x88a0b00bbe918ee00e3482f71962070dc052984b';
298
+ const ETH_RDNT = '0xfb468ad210d427d65c9a765a480649d5754ca325';
299
+ if (lendingPoolsData[Factory.V2V1_1][ETH_gGOHM]) {
300
+ //lendingPoolsData[Factory.V2V1_1][ETH_SPELL].pair.rewards[0].rewardRate = '8.44';
301
+ //lendingPoolsData[Factory.V2V1_1][ETH_MIM].pair.rewards[0].rewardRate = '30.64';
302
+ //lendingPoolsData[Factory.V2V1_1][ETH_gGOHM].pair.rewards[0].rewardRate = '0.000009129';
303
+ lendingPoolsData[Factory.V2V1_1][ETH_MAGIC].pair.rewards[0].rewardRate = '0.135';
304
+ }
305
+ if (lendingPoolsData[Factory.V2V2][ETH_RDNT]) {
306
+ lendingPoolsData[Factory.V2V2][ETH_RDNT].pair.rewards[0].rewardRate = (parseFloat(lendingPoolsData[Factory.V2V2][ETH_RDNT].pair.rewards[0].rewardRate) / 2).toString();
307
+ }
308
+ }
309
+
310
+ if (this.network === Networks.Polygon) {
311
+ const GNS_DAI = '0xf9221c5edc736d26ffc4ddccddfa15a4b958862e';
312
+ if (lendingPoolsData[Factory.V2V2][GNS_DAI]) {
313
+ const GNS = lendingPoolsData[Factory.V2V2][GNS_DAI].borrowable1.underlying;
314
+ lendingPoolsData[Factory.V2V2][GNS_DAI].pair.rewards[0] = {
315
+ id: '',
316
+ rewardsToken: GNS,
317
+ rewardRate: '0.00608',
318
+ periodFinish: '0',
319
+ };
320
+ lendingPoolsData[Factory.V2V2][GNS_DAI].pair.stakedTotalSupply = '1640000';
321
+ }
322
+ }
323
+
324
+ if (this.network === Networks.Avalanche) {
325
+ const QI_AVAX = '0x3e2a4dcd46e0e339aec603080d90bd939a163062';
326
+ if (lendingPoolsData[Factory.V2V1_2][QI_AVAX]) {
327
+ const QI = lendingPoolsData[Factory.V2V1_2][QI_AVAX].borrowable0.underlying;
328
+ lendingPoolsData[Factory.V2V1_2][QI_AVAX].pair.rewards[0] = {
329
+ id: '',
330
+ rewardsToken: QI,
331
+ rewardRate: '4.54',
332
+ periodFinish: '0',
333
+ };
334
+ // TODO -> this is wrong
335
+ lendingPoolsData[Factory.V2V1_2][QI_AVAX].pair.stakedTotalSupply = '0.000000992210460243'; //https://snowtrace.io/token/0xe530dc2095ef5653205cf5ea79f8979a7028065c?a=0x784da19e61cf348a8c54547531795ecfee2affd1
336
+ }
337
+ /*REWARD STOPPED const sAVAX_AVAX = '0x5b588f4481035b0f765393fc9f4752615a6d0498';
338
+ if (lendingPoolsData[Factory.V2V1_2][sAVAX_AVAX]) {
339
+ const QI = lendingPoolsData[Factory.V2V1_2][QI_AVAX].borrowable0.underlying;
340
+ lendingPoolsData[Factory.V2V1_2][sAVAX_AVAX].pair.rewards[1] = {
341
+ id: '',
342
+ rewardsToken: QI,
343
+ rewardRate: '1.74',
344
+ periodFinish: '0',
345
+ };
346
+ }
347
+ const UST_AVAX = '0xc6e68d77d0f4fa925a1cf2611dab6b10900eaf2b';
348
+ if (lendingPoolsData[Factory.V2V1_2][UST_AVAX]) {
349
+ const AVAX = lendingPoolsData[Factory.V2V1_2][UST_AVAX].borrowable1.underlying;
350
+ lendingPoolsData[Factory.V2V1_2][UST_AVAX].pair.rewards[0].rewardRate = '0.000099';
351
+ lendingPoolsData[Factory.V2V1_2][UST_AVAX].pair.rewards[2] = {
352
+ id: '',
353
+ rewardsToken: AVAX,
354
+ rewardRate: '0.00047',
355
+ periodFinish: '0',
356
+ };
357
+ }
358
+ const UST_USDC = '0x69c1c44e8742b66d892294a7eeb9aac51891b0eb';
359
+ if (lendingPoolsData[Factory.V2V1_2][UST_USDC]) {
360
+ const AVAX = lendingPoolsData[Factory.V2V1_2][UST_AVAX].borrowable1.underlying;
361
+ lendingPoolsData[Factory.V2V1_2][UST_USDC].pair.rewards[0].rewardRate = '0.000099';
362
+ lendingPoolsData[Factory.V2V1_2][UST_USDC].pair.rewards[2] = {
363
+ id: '',
364
+ rewardsToken: AVAX,
365
+ rewardRate: '0.00047',
366
+ periodFinish: '0',
367
+ };
368
+ }*/
369
+ }
370
+
371
+ return lendingPoolsData;
372
+ }
373
+ export async function getLendingPoolsData(this: Subgraph) : Promise<LendingPoolIndex<LendingPoolData>> {
374
+ if (!this.lendingPoolsData) this.lendingPoolsData = this.initializeLendingPoolsData();
375
+ return this.lendingPoolsData;
376
+ }
377
+ export async function getLendingPoolData(this: Subgraph, factory: Factory, uniswapV2PairAddress: Address) : Promise<LendingPoolData> {
378
+ return (await this.getLendingPoolsData())[factory][uniswapV2PairAddress.toLowerCase()];
379
+ }
380
+
381
+ // TVL Data
382
+ export async function initializeTvlData(this: Subgraph) : Promise<TvlData> {
383
+ const networks: Networks[] = [
384
+ Networks.Mainnet,
385
+ Networks.Arbitrum,
386
+ Networks.Polygon,
387
+ Networks.Avalanche,
388
+ Networks.Moonriver,
389
+ Networks.Fantom
390
+ ]; // exclude ropsten
391
+ const calls = [];
392
+ for (const network of networks) {
393
+ for (const factory of Object.keys(IMPERMAX_SUBGRAPH_URL[network])) {
394
+ const subgraph = IMPERMAX_SUBGRAPH_URL[network][factory as Factory];
395
+ calls.push(this.apolloFetcher(subgraph, query.tvlQuery()));
396
+ }
397
+ }
398
+ const results = await Promise.all(calls);
399
+ let crossChainTVLUSD = 0;
400
+ let thisChainTVLUSD = 0;
401
+ let thisChainSupplyUSD = 0;
402
+ let thisChainBorrowUSD = 0;
403
+ let i = 0;
404
+ for (const network of networks) {
405
+ let chainTvlUSD = 0;
406
+ for (const factory of Object.keys(IMPERMAX_SUBGRAPH_URL[network])) {
407
+ const data = results[i].data.impermaxFactories[0];
408
+ chainTvlUSD += parseFloat(data.totalBalanceUSD);
409
+ if (network === this.network) {
410
+ thisChainTVLUSD += parseFloat(data.totalBalanceUSD);
411
+ thisChainSupplyUSD += parseFloat(data.totalSupplyUSD);
412
+ thisChainBorrowUSD += parseFloat(data.totalBorrowsUSD);
413
+ }
414
+ i++;
415
+ }
416
+ crossChainTVLUSD += chainTvlUSD;
417
+ }
418
+ return {
419
+ crossChainTVLUSD,
420
+ totalBalanceUSD: thisChainTVLUSD,
421
+ totalSupplyUSD: thisChainSupplyUSD,
422
+ totalBorrowsUSD: thisChainBorrowUSD,
423
+ };
424
+ }
425
+ export async function getTvlData(this: Subgraph) : Promise<TvlData> {
426
+ if (!this.tvlData) this.tvlData = this.initializeTvlData();
427
+ return this.tvlData;
428
+ }
429
+
430
+ // User Data
431
+ export async function fetchUserData(this: Subgraph, account: Address) : Promise<FactoryIndex<{
432
+ collateralPositions: CollateralPosition[],
433
+ supplyPositions: SupplyPosition[],
434
+ borrowPositions: BorrowPosition[],
435
+ }>> {
436
+ const positions: FactoryIndex<{
437
+ collateralPositions: CollateralPosition[],
438
+ supplyPositions: SupplyPosition[],
439
+ borrowPositions: BorrowPosition[],
440
+ }> = {};
441
+ for (const factory of Object.keys(IMPERMAX_SUBGRAPH_URL[this.network]) as Factory[]) {
442
+ const subgraph = IMPERMAX_SUBGRAPH_URL[this.network][factory];
443
+ const result = await this.apolloFetcher(subgraph, query.userQuery(account));
444
+ const user = result.data.user;
445
+ if (!user) continue;
446
+ positions[factory as Factory] = {
447
+ collateralPositions: user.collateralPositions,
448
+ supplyPositions: user.supplyPositions,
449
+ borrowPositions: user.borrowPositions,
450
+ }
451
+ }
452
+ return positions;
453
+
454
+ // TODO parallelize calls
455
+ }
456
+ export async function initializeUserData(this: Subgraph, account: Address) : Promise<FactoryIndex<UserData>> {
457
+ const result: FactoryIndex<UserData> = {};
458
+ const userData = await this.fetchUserData(account);
459
+ if (!userData) return null;
460
+ for (const factory of Object.keys(userData) as Factory[]) {
461
+ result[factory] = {
462
+ collateralPositions: {},
463
+ supplyPositions: {},
464
+ borrowPositions: {},
465
+ };
466
+ const data = userData[factory];
467
+ for (const collateralPosition of data.collateralPositions) {
468
+ result[factory].collateralPositions[collateralPosition.collateral.lendingPool.id] = collateralPosition;
469
+ }
470
+ for (const supplyPositions of data.supplyPositions) {
471
+ const uniswapV2PairAddress = supplyPositions.borrowable.lendingPool.id;
472
+ const underlyingAddress = supplyPositions.borrowable.underlying.id;
473
+ const borrowableA = (await this.getLendingPool(factory, uniswapV2PairAddress)).poolTokens[PoolTokenType.BorrowableA];
474
+ const addressA = await borrowableA.getUnderlyingAddress();
475
+ const poolTokenType = underlyingAddress === addressA ? PoolTokenType.BorrowableA : PoolTokenType.BorrowableB;
476
+ if (!(uniswapV2PairAddress in result[factory].supplyPositions)) result[factory].supplyPositions[uniswapV2PairAddress] = {};
477
+ result[factory].supplyPositions[uniswapV2PairAddress][poolTokenType] = supplyPositions;
478
+ }
479
+ for (const borrowPositions of data.borrowPositions) {
480
+ const uniswapV2PairAddress = borrowPositions.borrowable.lendingPool.id;
481
+ const underlyingAddress = borrowPositions.borrowable.underlying.id;
482
+ const borrowableA = (await this.getLendingPool(factory, uniswapV2PairAddress)).poolTokens[PoolTokenType.BorrowableA];
483
+ const addressA = await borrowableA.getUnderlyingAddress();
484
+ const poolTokenType = underlyingAddress === addressA ? PoolTokenType.BorrowableA : PoolTokenType.BorrowableB;
485
+ if (!(uniswapV2PairAddress in result[factory].borrowPositions)) result[factory].borrowPositions[uniswapV2PairAddress] = {};
486
+ result[factory].borrowPositions[uniswapV2PairAddress][poolTokenType] = borrowPositions;
487
+ }
488
+ }
489
+ return result;
490
+ }
491
+ export async function getUserData(this: Subgraph, account: Address) : Promise<FactoryIndex<UserData>> {
492
+ if (!(account in this.usersData)) this.usersData[account] = this.initializeUserData(account);
493
+ return this.usersData[account];
494
+ }
495
+
496
+ // IMX Staking
497
+
498
+ export async function initializeXimxData(this: Subgraph): Promise<XimxData> {
499
+ const result = await apolloFetcher(
500
+ XIMX_SUBGRAPH_URL,
501
+ query.ximxQuery()
502
+ );
503
+
504
+ return result.data.ximxes[0];
505
+ }
506
+ export async function getXimxData(this: Subgraph): Promise<XimxData> {
507
+ if (!this.ximxData) this.ximxData = this.initializeXimxData();
508
+ return this.ximxData;
509
+ }