impermax-sdk 2.1.512 → 2.1.514
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/lib/offchain/offchain.d.ts +2 -1
- package/lib/offchain/offchain.js +62 -0
- package/lib/offchain/offchainMultichain.d.ts +2 -2
- package/lib/offchain/offchainMultichain.js +13 -15
- package/lib/offchain/offchainTypes.d.ts +9 -1
- package/lib/onchain/onchain.d.ts +2 -2
- package/lib/onchain/onchain.js +4 -1
- package/lib/onchain/onchainMulticall.d.ts +37 -0
- package/lib/onchain/onchainMulticall.js +85 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import OffchainLendingPool from './lendingPool';
|
|
|
3
3
|
import OffchainSolidexHelper from './offchainSolidexHelper';
|
|
4
4
|
import OffchainAccount from './account';
|
|
5
5
|
import { Address, AddressIndex, Factory, FactoryIndex, LendingPoolIndex, Networks, WhitelistState, Extension } from '../config/types';
|
|
6
|
-
import { LendingPoolData, VaultData, VaultPosition, TvlData, UserData, XIbexData, NftlpData, PoolChart, NewlyEarnedFees, NftlpStats, XIbexUserData, NewlyEarnedReward } from './offchainTypes';
|
|
6
|
+
import { LendingPoolData, VaultData, VaultPosition, TvlData, UserData, XIbexData, NftlpData, PoolChart, NewlyEarnedFees, NftlpStats, XIbexUserData, NewlyEarnedReward, NetworkTokenData } from './offchainTypes';
|
|
7
7
|
import OffchainVault from './vault/offchainVault';
|
|
8
8
|
import OffchainConfigManager from './configManager';
|
|
9
9
|
import { PairState } from '../config/whitelist';
|
|
@@ -121,4 +121,5 @@ export default class Offchain {
|
|
|
121
121
|
protected fetchNftlpsData: typeof initializer.fetchNftlpsData;
|
|
122
122
|
protected initializeNftlpsData: typeof initializer.initializeNftlpsData;
|
|
123
123
|
getPairsList(factory: Factory, state?: PairState): Address[];
|
|
124
|
+
getNetworkTokens(): Promise<NetworkTokenData[]>;
|
|
124
125
|
}
|
package/lib/offchain/offchain.js
CHANGED
|
@@ -205,5 +205,67 @@ class Offchain {
|
|
|
205
205
|
pairs.push(...blacklisted);
|
|
206
206
|
return pairs.map(i => i.toLowerCase());
|
|
207
207
|
}
|
|
208
|
+
async getNetworkTokens() {
|
|
209
|
+
const tokenMap = new Map();
|
|
210
|
+
try {
|
|
211
|
+
const lendingPoolsData = await this.getLendingPoolsData();
|
|
212
|
+
// 1. Go through each factory
|
|
213
|
+
const factoryPromises = Object.entries(lendingPoolsData).map(async ([factory, pools]) => {
|
|
214
|
+
// 2. Go through each pool in the factory
|
|
215
|
+
const poolPromises = Object.keys(pools).map(async (poolId) => {
|
|
216
|
+
try {
|
|
217
|
+
const lendingPool = await this.getLendingPool(factory, poolId);
|
|
218
|
+
if (!lendingPool)
|
|
219
|
+
return [];
|
|
220
|
+
// 3. Get both borrowables borrowables from this pool
|
|
221
|
+
const [borrowableA, borrowableB] = await Promise.all([lendingPool.getBorrowableA(), lendingPool.getBorrowableB()]);
|
|
222
|
+
// 4. Get underlying tokens from both borrowables
|
|
223
|
+
const tokenPromises = [borrowableA, borrowableB].map(async (borrowable) => {
|
|
224
|
+
try {
|
|
225
|
+
const [address, symbol, name, decimals] = await Promise.all([
|
|
226
|
+
borrowable.getUnderlyingAddress(),
|
|
227
|
+
borrowable.getSymbol(),
|
|
228
|
+
borrowable.getName(),
|
|
229
|
+
borrowable.getDecimals(),
|
|
230
|
+
]);
|
|
231
|
+
if (!address)
|
|
232
|
+
return null;
|
|
233
|
+
return {
|
|
234
|
+
token: `${this.network}:${address}`,
|
|
235
|
+
id: address,
|
|
236
|
+
symbol,
|
|
237
|
+
name,
|
|
238
|
+
decimals,
|
|
239
|
+
chainId: this.chainId,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
console.error(`Error getting token details for borrowable in pool ${poolId}:`, error);
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
// The token's data like symbol etc.
|
|
248
|
+
const tokens = await Promise.all(tokenPromises);
|
|
249
|
+
return tokens.filter((token) => token !== null);
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
console.error(`Error processing pool ${poolId} in factory ${factory} on ${this.network}:`, error);
|
|
253
|
+
return [];
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
const poolResults = await Promise.all(poolPromises);
|
|
257
|
+
return poolResults.flat();
|
|
258
|
+
});
|
|
259
|
+
const factoryResults = await Promise.all(factoryPromises);
|
|
260
|
+
const networkTokens = factoryResults.flat();
|
|
261
|
+
// Need to put then in a set to return unique tokens
|
|
262
|
+
networkTokens.forEach(tokenData => tokenMap.set(tokenData.token, tokenData));
|
|
263
|
+
return Array.from(tokenMap.values());
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
console.error(`Error processing network ${this.network}:`, error);
|
|
267
|
+
return [];
|
|
268
|
+
}
|
|
269
|
+
}
|
|
208
270
|
}
|
|
209
271
|
exports.default = Offchain;
|
|
@@ -14,7 +14,7 @@ import { AddressIndex } from "../config/types";
|
|
|
14
14
|
import OffchainAccount from "./account/offchainAccount";
|
|
15
15
|
import { PairState } from '../config/whitelist';
|
|
16
16
|
import { LlamaTvlChart } from './offchainAPRHelper';
|
|
17
|
-
import {
|
|
17
|
+
import { NetworkTokenData } from "./offchainTypes";
|
|
18
18
|
export declare enum SortDirection {
|
|
19
19
|
ASC = "asc",
|
|
20
20
|
DESC = "desc"
|
|
@@ -105,6 +105,6 @@ export default class OffchainMultichain {
|
|
|
105
105
|
*/
|
|
106
106
|
getTvlData(params?: MultichainTvlParams): Promise<MultichainTvlData>;
|
|
107
107
|
getImpermaxTvlChart(network?: Networks): Promise<LlamaTvlChart>;
|
|
108
|
-
getNetworkTokens(networks?: Networks[]): Promise<
|
|
108
|
+
getNetworkTokens(networks?: Networks[]): Promise<NetworkTokenData[]>;
|
|
109
109
|
}
|
|
110
110
|
export {};
|
|
@@ -296,21 +296,19 @@ class OffchainMultichain {
|
|
|
296
296
|
// ERC20 TOKENS
|
|
297
297
|
//
|
|
298
298
|
async getNetworkTokens(networks) {
|
|
299
|
-
const
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}));
|
|
313
|
-
return Array.from(tokenSet);
|
|
299
|
+
const allNetworks = networks || Object.values(types_1.Networks);
|
|
300
|
+
const networkPromises = allNetworks.map(async (network) => {
|
|
301
|
+
try {
|
|
302
|
+
const offchain = this.getOffchain(network);
|
|
303
|
+
return await offchain.getNetworkTokens();
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
console.error(`Error processing network ${network}:`, error);
|
|
307
|
+
return [];
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
const results = await Promise.all(networkPromises);
|
|
311
|
+
return results.flat();
|
|
314
312
|
}
|
|
315
313
|
}
|
|
316
314
|
exports.default = OffchainMultichain;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address, AddressIndex, PoolTokenType, ProposalState, WhitelistState, VaultType, Extension, Factory, Borrowable } from '../config/types';
|
|
1
|
+
import { Address, AddressIndex, PoolTokenType, ProposalState, WhitelistState, VaultType, Extension, Factory, Borrowable, Networks } from '../config/types';
|
|
2
2
|
import { Amms } from '../config/amms';
|
|
3
3
|
export declare const isV3Factory: (factory: string) => boolean;
|
|
4
4
|
export interface TokenData {
|
|
@@ -14,6 +14,14 @@ export interface PoolTokenData {
|
|
|
14
14
|
exchangeRate: string;
|
|
15
15
|
totalBalanceUSD: string;
|
|
16
16
|
}
|
|
17
|
+
export type NetworkTokenData = {
|
|
18
|
+
token: `${Networks}:${Address}`;
|
|
19
|
+
id: Address;
|
|
20
|
+
symbol: string;
|
|
21
|
+
name: string;
|
|
22
|
+
decimals: number;
|
|
23
|
+
chainId: number;
|
|
24
|
+
};
|
|
17
25
|
export interface BorrowableData extends PoolTokenData {
|
|
18
26
|
underlying: TokenData;
|
|
19
27
|
totalBorrows: string;
|
package/lib/onchain/onchain.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import OnchainInteractions from './interactions';
|
|
|
8
8
|
import { OnchainConfig } from './onchainTypes';
|
|
9
9
|
import OnchainConfigManager from './configManager';
|
|
10
10
|
import OnchainPermitHelper from "./onchainPermitHelper";
|
|
11
|
-
import
|
|
11
|
+
import OnchainMulticall from './onchainMulticall';
|
|
12
12
|
import OnchainStakingModule from './staking/onchainStakingModule';
|
|
13
13
|
export default class Onchain {
|
|
14
14
|
readonly network: Networks;
|
|
@@ -26,7 +26,7 @@ export default class Onchain {
|
|
|
26
26
|
protected lendingVaults: AddressIndex<OnchainLendingVault>;
|
|
27
27
|
protected accounts: AddressIndex<OnchainAccount>;
|
|
28
28
|
protected interactions: AddressIndex<OnchainInteractions>;
|
|
29
|
-
multicall:
|
|
29
|
+
multicall: OnchainMulticall;
|
|
30
30
|
protected stakingModule: OnchainStakingModule;
|
|
31
31
|
constructor(cfg: OnchainConfig);
|
|
32
32
|
cleanCache(): void;
|
package/lib/onchain/onchain.js
CHANGED
|
@@ -12,6 +12,7 @@ const interactions_1 = __importDefault(require("./interactions"));
|
|
|
12
12
|
const configManager_1 = __importDefault(require("./configManager"));
|
|
13
13
|
const onchainPermitHelper_1 = __importDefault(require("./onchainPermitHelper"));
|
|
14
14
|
const web3_multicall_1 = __importDefault(require("@dopex-io/web3-multicall"));
|
|
15
|
+
const onchainMulticall_1 = __importDefault(require("./onchainMulticall"));
|
|
15
16
|
const onchainStakingModule_1 = __importDefault(require("./staking/onchainStakingModule"));
|
|
16
17
|
class Onchain {
|
|
17
18
|
constructor(cfg) {
|
|
@@ -34,11 +35,13 @@ class Onchain {
|
|
|
34
35
|
this.accounts = {};
|
|
35
36
|
this.lendingVaults = {};
|
|
36
37
|
this.interactions = {};
|
|
37
|
-
|
|
38
|
+
const multicall = new web3_multicall_1.default({
|
|
38
39
|
chainId: cfg.chainId,
|
|
39
40
|
provider: cfg.web3,
|
|
40
41
|
multicallAddress: "0xcA11bde05977b3631167028862bE2a173976CA11"
|
|
41
42
|
});
|
|
43
|
+
// Using default settings, See OnchainMulticall constructor
|
|
44
|
+
this.multicall = new onchainMulticall_1.default(multicall);
|
|
42
45
|
}
|
|
43
46
|
cleanCache() {
|
|
44
47
|
for (const factory in this.factories) {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Multicall from '@dopex-io/web3-multicall';
|
|
2
|
+
interface MulticallConfig {
|
|
3
|
+
/** Max amount of transactions per multicall call */
|
|
4
|
+
batchSize: number;
|
|
5
|
+
/** Time in ms to wait before sending (0 still gets all from current event loop which is probably enough on most cases) */
|
|
6
|
+
timeWindow: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Similar to https://github.com/greg-schrammel/multicall-provider but for web3.js
|
|
10
|
+
*
|
|
11
|
+
* Example usage:
|
|
12
|
+
*
|
|
13
|
+
* const underlyingAddress = await this.getOnchain().multicall.call(poolToken.methods.underlying());
|
|
14
|
+
*
|
|
15
|
+
* Do not use call() when passing method! ie:
|
|
16
|
+
* wrong: onchain.multicall.call(poolToken.methods.underlying().call()):
|
|
17
|
+
* right: onchain.multicall.call(poolToken.methods.underlying())
|
|
18
|
+
*
|
|
19
|
+
* How it works:
|
|
20
|
+
* 1. onchainLendingVault: `onchain.multicall.call(methods.exchangeRate())` - adds to queue, timeoutId is null, sets timer to `timeWindow`
|
|
21
|
+
* 2. onchainPoolToken : `onchain.multicall.call(methods.totalSupply())` - adds to queue, clears old timer, sets new timer to `timeWindow`
|
|
22
|
+
* 3. onchainBorrowable : `onchain.multicall.call(methods.underlying())` - adds to queue, clears old timer, sets new timer to `timeWindow`
|
|
23
|
+
* ...
|
|
24
|
+
* 4. Process all when either `timeWindow` expires OR `batchSize` is reached
|
|
25
|
+
*/
|
|
26
|
+
export default class OnchainMulticall {
|
|
27
|
+
private multicall;
|
|
28
|
+
private config;
|
|
29
|
+
private queue;
|
|
30
|
+
private timeoutId;
|
|
31
|
+
private isProcessing;
|
|
32
|
+
constructor(multicall: Multicall, config?: MulticallConfig);
|
|
33
|
+
getEthBalance(address: string): any;
|
|
34
|
+
call<T = any>(contractMethod: any): Promise<T>;
|
|
35
|
+
private processBatch;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Similar to https://github.com/greg-schrammel/multicall-provider but for web3.js
|
|
5
|
+
*
|
|
6
|
+
* Example usage:
|
|
7
|
+
*
|
|
8
|
+
* const underlyingAddress = await this.getOnchain().multicall.call(poolToken.methods.underlying());
|
|
9
|
+
*
|
|
10
|
+
* Do not use call() when passing method! ie:
|
|
11
|
+
* wrong: onchain.multicall.call(poolToken.methods.underlying().call()):
|
|
12
|
+
* right: onchain.multicall.call(poolToken.methods.underlying())
|
|
13
|
+
*
|
|
14
|
+
* How it works:
|
|
15
|
+
* 1. onchainLendingVault: `onchain.multicall.call(methods.exchangeRate())` - adds to queue, timeoutId is null, sets timer to `timeWindow`
|
|
16
|
+
* 2. onchainPoolToken : `onchain.multicall.call(methods.totalSupply())` - adds to queue, clears old timer, sets new timer to `timeWindow`
|
|
17
|
+
* 3. onchainBorrowable : `onchain.multicall.call(methods.underlying())` - adds to queue, clears old timer, sets new timer to `timeWindow`
|
|
18
|
+
* ...
|
|
19
|
+
* 4. Process all when either `timeWindow` expires OR `batchSize` is reached
|
|
20
|
+
*/
|
|
21
|
+
class OnchainMulticall {
|
|
22
|
+
constructor(multicall, config = { batchSize: 25, timeWindow: 0 }) {
|
|
23
|
+
this.queue = [];
|
|
24
|
+
this.timeoutId = null;
|
|
25
|
+
this.isProcessing = false;
|
|
26
|
+
this.multicall = multicall;
|
|
27
|
+
this.config = config;
|
|
28
|
+
}
|
|
29
|
+
getEthBalance(address) {
|
|
30
|
+
return this.multicall.getEthBalance(address);
|
|
31
|
+
}
|
|
32
|
+
async call(contractMethod) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const queuedCall = { contractMethod, resolve, reject };
|
|
35
|
+
this.queue.push(queuedCall);
|
|
36
|
+
if (this.timeoutId)
|
|
37
|
+
clearTimeout(this.timeoutId);
|
|
38
|
+
this.timeoutId = setTimeout(() => this.processBatch(), this.config.timeWindow);
|
|
39
|
+
if (this.queue.length >= this.config.batchSize) {
|
|
40
|
+
if (this.timeoutId) {
|
|
41
|
+
clearTimeout(this.timeoutId);
|
|
42
|
+
this.timeoutId = null;
|
|
43
|
+
}
|
|
44
|
+
// Process all in next event loop
|
|
45
|
+
if (!this.isProcessing)
|
|
46
|
+
setTimeout(() => this.processBatch(), 0);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// TODO: Test fallback in case of multicall failure
|
|
51
|
+
async processBatch() {
|
|
52
|
+
if (this.isProcessing || this.queue.length === 0)
|
|
53
|
+
return;
|
|
54
|
+
this.isProcessing = true;
|
|
55
|
+
this.timeoutId = null;
|
|
56
|
+
const batch = this.queue.splice(0, Math.min(this.config.batchSize, this.queue.length));
|
|
57
|
+
try {
|
|
58
|
+
const contractMethods = batch.map(call => call.contractMethod);
|
|
59
|
+
// console.log("Multicall methods: ", contractMethods)
|
|
60
|
+
const results = await this.multicall.aggregate(contractMethods);
|
|
61
|
+
for (let i = 0; i < batch.length; i++) {
|
|
62
|
+
const call = batch[i];
|
|
63
|
+
const result = results[i];
|
|
64
|
+
call.resolve(result);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.log('Multicall failed, using fallback call: ', error);
|
|
69
|
+
for (const call of batch) {
|
|
70
|
+
try {
|
|
71
|
+
const result = await call.contractMethod.call();
|
|
72
|
+
call.resolve(result);
|
|
73
|
+
}
|
|
74
|
+
catch (singleCallError) {
|
|
75
|
+
call.reject(new Error(`Individual call failed: ${singleCallError.message}`));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
this.isProcessing = false;
|
|
80
|
+
// Execute again until queue is empty
|
|
81
|
+
if (this.queue.length > 0)
|
|
82
|
+
setTimeout(() => this.processBatch(), 0);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.default = OnchainMulticall;
|