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.
- package/.idea/impermax-sdk.iml +12 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/workspace.xml +642 -0
- package/abis/ImpermaxABI.ts +3 -0
- package/abis/contracts/BAllowance.json +4735 -0
- package/abis/contracts/BDeployer.json +1195 -0
- package/abis/contracts/BInterestRateModel.json +10796 -0
- package/abis/contracts/BSetter.json +6219 -0
- package/abis/contracts/BStorage.json +2613 -0
- package/abis/contracts/Borrowable.json +19937 -0
- package/abis/contracts/CDeployer.json +1104 -0
- package/abis/contracts/CSetter.json +5094 -0
- package/abis/contracts/CStorage.json +516 -0
- package/abis/contracts/ClaimAggregator.json +2015 -0
- package/abis/contracts/Collateral.json +21615 -0
- package/abis/contracts/ERC20.json +819 -0
- package/abis/contracts/Factory.json +21986 -0
- package/abis/contracts/FarmingPool.json +8601 -0
- package/abis/contracts/IBDeployer.json +351 -0
- package/abis/contracts/IBorrowTracker.json +346 -0
- package/abis/contracts/IBorrowable.json +13207 -0
- package/abis/contracts/ICDeployer.json +294 -0
- package/abis/contracts/IClaimable.json +406 -0
- package/abis/contracts/ICollateral.json +8952 -0
- package/abis/contracts/IERC20.json +2376 -0
- package/abis/contracts/IFactory.json +3660 -0
- package/abis/contracts/IFarmingPool.json +3584 -0
- package/abis/contracts/IImpermaxCallee.json +679 -0
- package/abis/contracts/IMerkleDistributor.json +1134 -0
- package/abis/contracts/IPoolToken.json +5343 -0
- package/abis/contracts/IRouter01.json +6891 -0
- package/abis/contracts/IRouter02.json +7283 -0
- package/abis/contracts/ISimpleUniswapOracle.json +1469 -0
- package/abis/contracts/IStakedLPToken.json +7309 -0
- package/abis/contracts/IStakingRewards.json +1036 -0
- package/abis/contracts/IUniswapV2Callee.json +403 -0
- package/abis/contracts/IUniswapV2ERC20.json +3155 -0
- package/abis/contracts/IUniswapV2Factory.json +1690 -0
- package/abis/contracts/IUniswapV2Pair.json +6761 -0
- package/abis/contracts/IWETH.json +561 -0
- package/abis/contracts/ImpermaxChef.json +20945 -0
- package/abis/contracts/ImpermaxERC20.json +12095 -0
- package/abis/contracts/Math.json +1966 -0
- package/abis/contracts/MockERC20.json +8884 -0
- package/abis/contracts/PoolToken.json +10784 -0
- package/abis/contracts/Router01.json +43963 -0
- package/abis/contracts/SafeMath.json +6828 -0
- package/abis/contracts/SimpleUniswapOracle.json +9640 -0
- package/abis/contracts/TransferHelper.json +4875 -0
- package/abis/contracts/UQ112x112.json +1201 -0
- package/abis/contracts/UniswapV2ERC20.json +10969 -0
- package/abis/contracts/UniswapV2Factory.json +5521 -0
- package/abis/contracts/UniswapV2Library.json +13789 -0
- package/abis/contracts/UniswapV2Pair.json +30782 -0
- package/abis/contracts/WETH9.json +6613 -0
- package/config/amms.ts +199 -0
- package/config/contracts/claim-aggregators.ts +16 -0
- package/config/contracts/impermax-chef.ts +16 -0
- package/config/contracts/imxes.ts +16 -0
- package/config/contracts/merkle-distributors.ts +13 -0
- package/config/contracts/routers.ts +36 -0
- package/config/contracts/simple-uniswap-oracles.ts +33 -0
- package/config/contracts/weths.ts +18 -0
- package/config/debank-ids.ts +15 -0
- package/config/endpoints/merkle-distributors.ts +13 -0
- package/config/eth.ts +32 -0
- package/config/factories.ts +26 -0
- package/config/farms.ts +119 -0
- package/config/general.ts +8 -0
- package/config/subgraphs.ts +69 -0
- package/config/types.ts +81 -0
- package/impermax-router/Account.ts +123 -0
- package/impermax-router/AccountBorrowable.ts +110 -0
- package/impermax-router/AccountCollateral.ts +40 -0
- package/impermax-router/AccountLendingPool.ts +231 -0
- package/impermax-router/AccountPoolToken.ts +76 -0
- package/impermax-router/Borrowable.ts +86 -0
- package/impermax-router/Collateral.ts +26 -0
- package/impermax-router/ContractsHelper.ts +64 -0
- package/impermax-router/ImpermaxFactory.ts +47 -0
- package/impermax-router/Interactions.ts +94 -0
- package/impermax-router/InteractionsLendingPool.ts +129 -0
- package/impermax-router/InteractionsPoolToken.ts +187 -0
- package/impermax-router/LendingPool.ts +256 -0
- package/impermax-router/PoolToken.ts +112 -0
- package/impermax-router/index.ts +49 -0
- package/impermax-router/interfaces.ts +233 -0
- package/index.ts +5 -0
- package/package.json +23 -0
- package/subgraph/Account.ts +93 -0
- package/subgraph/AccountLendingPool.ts +60 -0
- package/subgraph/AccountPoolToken.ts +60 -0
- package/subgraph/LendingPool.ts +179 -0
- package/subgraph/PoolToken.ts +381 -0
- package/subgraph/PriceHelper.ts +150 -0
- package/subgraph/SolidexHelper.ts +54 -0
- package/subgraph/index.ts +166 -0
- package/subgraph/initializer.ts +509 -0
- package/subgraph/query.ts +224 -0
- package/tsconfig.json +16 -0
- package/utils/ether-utils.ts +22 -0
- 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
|
+
}
|