@1delta/margin-fetcher 0.0.8 → 0.0.10
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/dist/abis/aave/AaveOracle.d.ts +10 -0
- package/dist/abis/aave/AaveOracle.d.ts.map +1 -1
- package/dist/abis/aave/AaveOracle.js +13 -0
- package/dist/abis/morpho/blue.d.ts +76 -0
- package/dist/abis/morpho/blue.d.ts.map +1 -0
- package/dist/abis/morpho/blue.js +99 -0
- package/dist/abis/morpho/lens.d.ts +16 -0
- package/dist/abis/morpho/lens.d.ts.map +1 -0
- package/dist/abis/morpho/lens.js +31 -0
- package/dist/abis/oracle/AaveOracle.d.ts +10 -0
- package/dist/abis/oracle/AaveOracle.d.ts.map +1 -1
- package/dist/abis/oracle/AaveOracle.js +13 -0
- package/dist/assets/index.d.ts +4 -4
- package/dist/assets/index.d.ts.map +1 -1
- package/dist/assets/index.js +7 -7
- package/dist/assets/liquidityThresholds.d.ts +29 -0
- package/dist/assets/liquidityThresholds.d.ts.map +1 -0
- package/dist/assets/liquidityThresholds.js +51 -0
- package/dist/flash-liquidity/index.d.ts +1 -0
- package/dist/flash-liquidity/index.d.ts.map +1 -1
- package/dist/flash-liquidity/index.js +1 -0
- package/dist/flash-liquidity/utils.d.ts +11 -0
- package/dist/flash-liquidity/utils.d.ts.map +1 -0
- package/dist/flash-liquidity/utils.js +17 -0
- package/dist/lending/aave-v2-type/publicCallParse.d.ts +2 -1
- package/dist/lending/aave-v2-type/publicCallParse.d.ts.map +1 -1
- package/dist/lending/aave-v2-type/publicCallParse.js +10 -7
- package/dist/lending/aave-v3-type/publicCallParse.d.ts +3 -2
- package/dist/lending/aave-v3-type/publicCallParse.d.ts.map +1 -1
- package/dist/lending/aave-v3-type/publicCallParse.js +11 -8
- package/dist/lending/aave-v3-type/types.d.ts +2 -0
- package/dist/lending/aave-v3-type/types.d.ts.map +1 -1
- package/dist/lending/addresses/compoundV3.d.ts +1 -1
- package/dist/lending/addresses/compoundV3.d.ts.map +1 -1
- package/dist/lending/addresses/compoundV3.js +8 -7
- package/dist/lending/compound-v3/publicCallParse.d.ts +2 -1
- package/dist/lending/compound-v3/publicCallParse.d.ts.map +1 -1
- package/dist/lending/compound-v3/publicCallParse.js +3 -2
- package/dist/lending/compound-v3/types.d.ts +2 -0
- package/dist/lending/compound-v3/types.d.ts.map +1 -1
- package/dist/lending/fetchLender.d.ts +2 -1
- package/dist/lending/fetchLender.d.ts.map +1 -1
- package/dist/lending/fetchLender.js +12 -8
- package/dist/lending/fetchLenderAll.d.ts +8 -0
- package/dist/lending/fetchLenderAll.d.ts.map +1 -0
- package/dist/lending/fetchLenderAll.js +12 -0
- package/dist/lending/fetchLenderExt.d.ts +8 -0
- package/dist/lending/fetchLenderExt.d.ts.map +1 -0
- package/dist/lending/fetchLenderExt.js +28 -0
- package/dist/lending/index.d.ts +1 -0
- package/dist/lending/index.d.ts.map +1 -1
- package/dist/lending/index.js +1 -0
- package/dist/lending/init/publicCallParse.d.ts +2 -1
- package/dist/lending/init/publicCallParse.d.ts.map +1 -1
- package/dist/lending/init/publicCallParse.js +3 -2
- package/dist/lending/init/types.d.ts +2 -0
- package/dist/lending/init/types.d.ts.map +1 -1
- package/dist/lending/morpho/convertPublic.d.ts +9 -0
- package/dist/lending/morpho/convertPublic.d.ts.map +1 -0
- package/dist/lending/morpho/convertPublic.js +115 -0
- package/dist/lending/morpho/fetchPublic.d.ts +3 -0
- package/dist/lending/morpho/fetchPublic.d.ts.map +1 -0
- package/dist/lending/morpho/fetchPublic.js +72 -0
- package/dist/lending/morpho/publicCallBuild.d.ts +8 -0
- package/dist/lending/morpho/publicCallBuild.d.ts.map +1 -0
- package/dist/lending/morpho/publicCallBuild.js +6 -0
- package/dist/lending/morpho/types.d.ts +106 -0
- package/dist/lending/morpho/types.d.ts.map +1 -0
- package/dist/lending/morpho/types.js +1 -0
- package/dist/lending/types/index.d.ts +18 -0
- package/dist/lending/types/index.d.ts.map +1 -0
- package/dist/lending/types/index.js +1 -0
- package/dist/lending/user-data/aave-v2-type/userCallBuild.d.ts.map +1 -1
- package/dist/lending/user-data/aave-v2-type/userCallBuild.js +4 -23
- package/dist/lending/user-data/aave-v2-type/userCallParse.d.ts.map +1 -1
- package/dist/lending/user-data/aave-v2-type/userCallParse.js +24 -11
- package/dist/lending/user-data/aave-v3-type/userCallBuild.d.ts.map +1 -1
- package/dist/lending/user-data/aave-v3-type/userCallBuild.js +1 -16
- package/dist/lending/user-data/aave-v3-type/userCallParse.d.ts.map +1 -1
- package/dist/lending/user-data/aave-v3-type/userCallParse.js +13 -6
- package/dist/lending/user-data/aave-v3-type/userCallParseYldr.d.ts.map +1 -1
- package/dist/lending/user-data/aave-v3-type/userCallParseYldr.js +12 -6
- package/dist/lending/user-data/compound-v3/addresses.d.ts.map +1 -1
- package/dist/lending/user-data/compound-v3/addresses.js +8 -7
- package/dist/lending/user-data/compound-v3/userCallParse.d.ts.map +1 -1
- package/dist/lending/user-data/compound-v3/userCallParse.js +2 -0
- package/dist/lending/user-data/morpho/decoder.d.ts +21 -0
- package/dist/lending/user-data/morpho/decoder.d.ts.map +1 -0
- package/dist/lending/user-data/morpho/decoder.js +52 -0
- package/dist/lending/user-data/morpho/morphoLib.d.ts +5 -0
- package/dist/lending/user-data/morpho/morphoLib.d.ts.map +1 -0
- package/dist/lending/user-data/morpho/morphoLib.js +21 -0
- package/dist/lending/user-data/morpho/types.d.ts +12 -0
- package/dist/lending/user-data/morpho/types.d.ts.map +1 -0
- package/dist/lending/user-data/morpho/types.js +13 -0
- package/dist/lending/user-data/morpho/userCallBuild.d.ts +6 -0
- package/dist/lending/user-data/morpho/userCallBuild.d.ts.map +1 -0
- package/dist/lending/user-data/morpho/userCallBuild.js +36 -0
- package/dist/lending/user-data/morpho/userCallParse.d.ts +11 -0
- package/dist/lending/user-data/morpho/userCallParse.d.ts.map +1 -0
- package/dist/lending/user-data/morpho/userCallParse.js +99 -0
- package/dist/lending/user-data/morpho/userCallParseNoDeploy.d.ts +11 -0
- package/dist/lending/user-data/morpho/userCallParseNoDeploy.d.ts.map +1 -0
- package/dist/lending/user-data/morpho/userCallParseNoDeploy.js +112 -0
- package/dist/lending-pairs/computeLendingPairs.d.ts +13 -0
- package/dist/lending-pairs/computeLendingPairs.d.ts.map +1 -1
- package/dist/lending-pairs/computeLendingPairs.js +129 -23
- package/dist/prices/main-prices/fetchOracleData.d.ts +1 -2
- package/dist/prices/main-prices/fetchOracleData.d.ts.map +1 -1
- package/dist/prices/main-prices/fetchOracleData.js +95 -55
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +41 -16
- package/dist/utils/parsing.d.ts.map +1 -1
- package/dist/utils/parsing.js +4 -2
- package/package.json +2 -2
- package/src/abis/aave/AaveOracle.ts +13 -0
- package/src/abis/oracle/AaveOracle.ts +13 -0
- package/src/assets/index.ts +70 -51
- package/src/assets/liquidityThresholds.ts +83 -0
- package/src/flash-liquidity/index.ts +2 -1
- package/src/flash-liquidity/utils.ts +22 -0
- package/src/lending/aave-v2-type/publicCallParse.ts +12 -7
- package/src/lending/aave-v3-type/publicCallParse.ts +13 -8
- package/src/lending/aave-v3-type/types.ts +2 -0
- package/src/lending/addresses/compoundV3.ts +29 -15
- package/src/lending/compound-v3/publicCallParse.ts +5 -2
- package/src/lending/compound-v3/types.ts +2 -0
- package/src/lending/fetchLender.ts +23 -17
- package/src/lending/index.ts +2 -1
- package/src/lending/init/publicCallParse.ts +5 -2
- package/src/lending/init/types.ts +3 -0
- package/src/lending/types/index.ts +16 -0
- package/src/lending/user-data/aave-v2-type/userCallBuild.ts +1 -25
- package/src/lending/user-data/aave-v2-type/userCallParse.ts +24 -11
- package/src/lending/user-data/aave-v3-type/userCallBuild.ts +1 -16
- package/src/lending/user-data/aave-v3-type/userCallParse.ts +15 -6
- package/src/lending/user-data/aave-v3-type/userCallParseYldr.ts +14 -6
- package/src/lending/user-data/compound-v3/addresses.ts +58 -39
- package/src/lending/user-data/compound-v3/userCallParse.ts +2 -2
- package/src/lending-pairs/computeLendingPairs.ts +421 -189
- package/src/prices/main-prices/fetchOracleData.ts +197 -107
- package/src/utils/index.ts +90 -58
- package/src/utils/parsing.ts +51 -51
- package/test/index.test.ts +15 -7
- package/test/userdata.test.ts +5 -5
|
@@ -1,213 +1,445 @@
|
|
|
1
|
-
import { getAssetMeta, toGenericPriceKey, toOracleKey } from "../assets"
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { getAssetMeta, toGenericPriceKey, toOracleKey } from "../assets";
|
|
2
|
+
import {
|
|
3
|
+
getLiquidityThresholds,
|
|
4
|
+
meetsLiquidityThresholds,
|
|
5
|
+
} from "../assets/liquidityThresholds";
|
|
6
|
+
import { ConfigEntry, LenderData, PoolData } from "../types";
|
|
7
|
+
import { isAaveV3Type, isInit } from "../utils";
|
|
4
8
|
|
|
5
9
|
export interface LendingPair {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
10
|
+
// lender info
|
|
11
|
+
chainId: string;
|
|
12
|
+
lender: string;
|
|
13
|
+
// asset addresses
|
|
14
|
+
assetLong: string;
|
|
15
|
+
assetShort: string;
|
|
16
|
+
|
|
17
|
+
// asset group for long asset
|
|
18
|
+
assetGroupLong: string;
|
|
19
|
+
// asset group for short asset
|
|
20
|
+
assetGroupShort: string;
|
|
21
|
+
// pair prices
|
|
22
|
+
price: number;
|
|
23
|
+
price24h: number;
|
|
24
|
+
priceChange: number;
|
|
25
|
+
|
|
26
|
+
// pair props
|
|
27
|
+
maxLeverage: number;
|
|
28
|
+
apr: number;
|
|
29
|
+
baseApr: number;
|
|
30
|
+
rewardApr: number;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
eMode?: number;
|
|
33
|
+
|
|
34
|
+
// liquidity data
|
|
35
|
+
longTotalDepositsUSD: number;
|
|
36
|
+
longTotalDebtUSD: number;
|
|
37
|
+
longTotalLiquidityUSD: number;
|
|
38
|
+
shortTotalDepositsUSD: number;
|
|
39
|
+
shortTotalDebtUSD: number;
|
|
40
|
+
shortTotalLiquidityUSD: number;
|
|
41
|
+
|
|
42
|
+
// status flags
|
|
43
|
+
longIsActive: boolean;
|
|
44
|
+
longIsFrozen: boolean;
|
|
45
|
+
shortIsActive: boolean;
|
|
46
|
+
shortIsFrozen: boolean;
|
|
47
|
+
shortBorrowingEnabled: boolean;
|
|
27
48
|
}
|
|
28
49
|
|
|
29
|
-
const isEMode = (longData: PoolData, shortData: PoolData) =>
|
|
30
|
-
|
|
50
|
+
const isEMode = (longData: PoolData, shortData: PoolData) =>
|
|
51
|
+
Boolean(longData.eMode)
|
|
52
|
+
? Number(longData.eMode?.category) > 0 &&
|
|
53
|
+
Number(longData.eMode?.category) === shortData.eMode?.category
|
|
54
|
+
: false;
|
|
31
55
|
|
|
32
56
|
const intersection = <T>(a0: T[], a1: T[]): T[] => {
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
const LENDER_MODE_NO_MODE = 0
|
|
57
|
+
return a0.filter((a) => a1.includes(a));
|
|
58
|
+
};
|
|
59
|
+
const LENDER_MODE_NO_MODE = 0;
|
|
36
60
|
|
|
37
61
|
// calculate the maximum leverage for a given pair
|
|
38
|
-
const getMaxLeverage = (
|
|
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
|
-
|
|
62
|
+
const getMaxLeverage = (
|
|
63
|
+
lender: string,
|
|
64
|
+
longData: PoolData,
|
|
65
|
+
shortData: PoolData
|
|
66
|
+
) => {
|
|
67
|
+
// for Aave V3 we check for eModes
|
|
68
|
+
if (isAaveV3Type(lender)) {
|
|
69
|
+
const cf = isEMode(longData, shortData)
|
|
70
|
+
? longData.config[longData.eMode?.category ?? 0]?.borrowCollateralFactor
|
|
71
|
+
: longData.config[LENDER_MODE_NO_MODE]?.borrowCollateralFactor;
|
|
72
|
+
return 1 / (1 - cf);
|
|
73
|
+
}
|
|
74
|
+
// for init, we match the modes and find the one with the highest collatearal factor
|
|
75
|
+
if (isInit(lender)) {
|
|
76
|
+
const modeIntersect = intersection(
|
|
77
|
+
Object.values(longData.config).map((c: ConfigEntry) => c.category),
|
|
78
|
+
Object.values(shortData.config).map((c: ConfigEntry) => c.category)
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (modeIntersect.length === 0) return 1;
|
|
82
|
+
const configId = Object.values(longData.config)
|
|
83
|
+
.filter((c: ConfigEntry) => modeIntersect.includes(c.category))
|
|
84
|
+
.sort((c: ConfigEntry, d: ConfigEntry) =>
|
|
85
|
+
c.borrowCollateralFactor < d.borrowCollateralFactor ? 1 : -1
|
|
86
|
+
)[0].category;
|
|
87
|
+
|
|
88
|
+
// we have to use the adjusted formula with the borrowFactor here
|
|
89
|
+
const cf = longData.config[configId]?.borrowCollateralFactor;
|
|
90
|
+
const bf = shortData.config[configId]?.borrowFactor;
|
|
91
|
+
return 1 / (1 - cf / bf);
|
|
92
|
+
}
|
|
93
|
+
// all other cases use the default mode no_mode without borrowFactor
|
|
94
|
+
const cf =
|
|
95
|
+
longData?.config?.[LENDER_MODE_NO_MODE]?.borrowCollateralFactor ?? 0.8;
|
|
96
|
+
return 1 / (1 - cf);
|
|
97
|
+
};
|
|
66
98
|
|
|
67
99
|
/** create array of pairs for given lender data */
|
|
68
|
-
export function generateLendingPairs(
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
100
|
+
export function generateLendingPairs(
|
|
101
|
+
lenderData: LenderData,
|
|
102
|
+
prices: { [k: string]: number },
|
|
103
|
+
histPrices: { [k: string]: number }
|
|
104
|
+
): LendingPair[] {
|
|
105
|
+
const pairs: LendingPair[] = [];
|
|
106
|
+
|
|
107
|
+
for (const chainId in lenderData) {
|
|
108
|
+
const chainEntry = lenderData[chainId];
|
|
109
|
+
const lenderToData = chainEntry.data ?? chainEntry;
|
|
110
|
+
|
|
111
|
+
for (const lender in lenderToData) {
|
|
112
|
+
const lenderEntry = lenderToData[lender];
|
|
113
|
+
|
|
114
|
+
// protect agaist error data
|
|
115
|
+
let pools: any[] = Object.values(
|
|
116
|
+
lenderEntry?.data ?? lenderEntry ?? {}
|
|
117
|
+
).map((a: any) => (a?.data ? a.data : a));
|
|
118
|
+
|
|
119
|
+
// sometimes error messages are included
|
|
120
|
+
const hasErrorMessages = pools.some(
|
|
121
|
+
(p: any) =>
|
|
122
|
+
typeof p === "string" &&
|
|
123
|
+
(p.includes("No lenders available") || p.includes("Failed to fetch"))
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
if (hasErrorMessages) continue;
|
|
127
|
+
|
|
128
|
+
// cast to poolData
|
|
129
|
+
const validPools: PoolData[] = pools.filter(
|
|
130
|
+
(p: any) => typeof p === "object" && p !== null
|
|
131
|
+
);
|
|
132
|
+
const poolArray = validPools.filter((p) => !p?.isFrozen);
|
|
133
|
+
|
|
134
|
+
// Loop through all ordered pairs of pools
|
|
135
|
+
for (let i = 0; i < poolArray.length; i++) {
|
|
136
|
+
for (let j = 0; j < poolArray.length; j++) {
|
|
137
|
+
if (i === j) continue;
|
|
138
|
+
|
|
139
|
+
const long = poolArray[i];
|
|
140
|
+
const short = poolArray[j];
|
|
141
|
+
if (!short.borrowingEnabled) continue;
|
|
142
|
+
|
|
143
|
+
// Skip same asset pairs
|
|
144
|
+
if (long.underlying === short.underlying) continue;
|
|
145
|
+
|
|
146
|
+
const maxDepositLeverage = getMaxLeverage(lender, long, short);
|
|
147
|
+
const borrowLeverage = maxDepositLeverage - 1;
|
|
148
|
+
const depositLeverage = borrowLeverage + 1;
|
|
149
|
+
let collateralRewards = 0;
|
|
150
|
+
let borrowRewards = 0;
|
|
151
|
+
const rewards: any = {};
|
|
152
|
+
// get the rewards from the collateral
|
|
153
|
+
for (const [rewardId, baseYields] of Object.entries(
|
|
154
|
+
long.rewards ?? {}
|
|
155
|
+
)) {
|
|
156
|
+
collateralRewards += baseYields.depositRate;
|
|
157
|
+
if (baseYields.depositRate > 0)
|
|
158
|
+
rewards[rewardId] = baseYields.depositRate * depositLeverage;
|
|
159
|
+
}
|
|
160
|
+
// get the rewards from debt
|
|
161
|
+
for (const [rewardId, baseYields] of Object.entries(
|
|
162
|
+
short.rewards ?? {}
|
|
163
|
+
)) {
|
|
164
|
+
const borrowRate =
|
|
165
|
+
baseYields.stableBorrowRate >= baseYields.variableBorrowRate
|
|
166
|
+
? baseYields.stableBorrowRate
|
|
167
|
+
: baseYields.variableBorrowRate;
|
|
168
|
+
borrowRewards += borrowRate;
|
|
169
|
+
if (borrowRate != 0)
|
|
170
|
+
rewards[rewardId] =
|
|
171
|
+
(rewards[rewardId] ?? 0) + borrowRate * borrowLeverage;
|
|
172
|
+
}
|
|
173
|
+
const depositApr = long.depositRate + long.stakingYield;
|
|
174
|
+
const borrowApr = short.variableBorrowRate + short.stakingYield;
|
|
175
|
+
|
|
176
|
+
const [assetGroupLong, keyLong] = getPriceKey(
|
|
177
|
+
long.underlying,
|
|
178
|
+
chainId
|
|
179
|
+
);
|
|
180
|
+
const [assetGroupShort, keyShort] = getPriceKey(
|
|
181
|
+
short.underlying,
|
|
182
|
+
chainId
|
|
183
|
+
);
|
|
184
|
+
const priceLong = prices[keyLong] ?? 0;
|
|
185
|
+
const priceShort = prices[keyShort] ?? 0;
|
|
186
|
+
|
|
187
|
+
const price24hLong = histPrices[keyLong] ?? priceLong;
|
|
188
|
+
const price24hShort = histPrices[keyShort] ?? priceShort;
|
|
189
|
+
|
|
190
|
+
const price = priceShort !== 0 ? priceLong / priceShort : 0;
|
|
191
|
+
const price24h =
|
|
192
|
+
price24hShort !== 0 ? price24hLong / price24hShort : 0;
|
|
193
|
+
|
|
194
|
+
// only base apr
|
|
195
|
+
const baseApr =
|
|
196
|
+
depositApr * depositLeverage - borrowApr * borrowLeverage;
|
|
197
|
+
|
|
198
|
+
// only rewards apr
|
|
199
|
+
const rewardApr =
|
|
200
|
+
collateralRewards * depositLeverage +
|
|
201
|
+
borrowRewards * borrowLeverage;
|
|
202
|
+
|
|
203
|
+
// total apr
|
|
204
|
+
const totalApr = baseApr + rewardApr;
|
|
205
|
+
|
|
206
|
+
pairs.push({
|
|
207
|
+
chainId,
|
|
208
|
+
lender,
|
|
209
|
+
assetLong: long.underlying,
|
|
210
|
+
assetShort: short.underlying,
|
|
211
|
+
price,
|
|
212
|
+
price24h,
|
|
213
|
+
assetGroupLong,
|
|
214
|
+
assetGroupShort,
|
|
215
|
+
priceChange: price24h === 0 ? 0 : (price - price24h) / price24h,
|
|
216
|
+
maxLeverage: maxDepositLeverage,
|
|
217
|
+
apr: totalApr,
|
|
218
|
+
baseApr,
|
|
219
|
+
rewardApr,
|
|
220
|
+
eMode: long.eMode?.category ?? 0,
|
|
221
|
+
longTotalDepositsUSD: long.totalDepositsUSD,
|
|
222
|
+
longTotalDebtUSD: long.totalDebtUSD,
|
|
223
|
+
longTotalLiquidityUSD: long.totalLiquidityUSD,
|
|
224
|
+
shortTotalDepositsUSD: short.totalDepositsUSD,
|
|
225
|
+
shortTotalDebtUSD: short.totalDebtUSD,
|
|
226
|
+
shortTotalLiquidityUSD: short.totalLiquidityUSD,
|
|
227
|
+
longIsActive: long.isActive,
|
|
228
|
+
longIsFrozen: long.isFrozen,
|
|
229
|
+
shortIsActive: short.isActive,
|
|
230
|
+
shortIsFrozen: short.isFrozen,
|
|
231
|
+
shortBorrowingEnabled: short.borrowingEnabled,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return pairs;
|
|
156
239
|
}
|
|
157
240
|
|
|
158
241
|
function getPriceKey(asset: string, chainId: string): [string, string] {
|
|
159
|
-
|
|
160
|
-
|
|
242
|
+
const assetGroup = getAssetMeta(chainId, asset)?.assetGroup;
|
|
243
|
+
return [
|
|
244
|
+
assetGroup,
|
|
245
|
+
toOracleKey(assetGroup) ?? toGenericPriceKey(asset, chainId),
|
|
246
|
+
];
|
|
161
247
|
}
|
|
162
248
|
|
|
163
|
-
const MAX_ENTRIES = 10
|
|
249
|
+
const MAX_ENTRIES = 10;
|
|
250
|
+
|
|
251
|
+
function filterPairsByCategory(
|
|
252
|
+
pairs: LendingPair[],
|
|
253
|
+
longFilter: (group: string) => boolean,
|
|
254
|
+
shortFilter: (group: string) => boolean
|
|
255
|
+
): LendingPair[] {
|
|
256
|
+
return pairs
|
|
257
|
+
.filter((p) => {
|
|
258
|
+
if (!longFilter(p.assetGroupLong) || !shortFilter(p.assetGroupShort)) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (
|
|
263
|
+
p.assetGroupShort?.includes("PT-") ||
|
|
264
|
+
p.assetGroupLong?.includes("PT-")
|
|
265
|
+
) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (
|
|
270
|
+
!p.longIsActive ||
|
|
271
|
+
p.longIsFrozen ||
|
|
272
|
+
!p.shortIsActive ||
|
|
273
|
+
p.shortIsFrozen
|
|
274
|
+
) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (!p.shortBorrowingEnabled) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// apply liquidity thresholds
|
|
283
|
+
const longThresholds = getLiquidityThresholds(
|
|
284
|
+
p.chainId,
|
|
285
|
+
p.assetLong,
|
|
286
|
+
p.assetGroupLong
|
|
287
|
+
);
|
|
288
|
+
const shortThresholds = getLiquidityThresholds(
|
|
289
|
+
p.chainId,
|
|
290
|
+
p.assetShort,
|
|
291
|
+
p.assetGroupShort
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
const longMeetsThresholds = meetsLiquidityThresholds(
|
|
295
|
+
{
|
|
296
|
+
totalDepositsUSD: p.longTotalDepositsUSD,
|
|
297
|
+
totalDebtUSD: p.longTotalDebtUSD,
|
|
298
|
+
totalLiquidityUSD: p.longTotalLiquidityUSD,
|
|
299
|
+
},
|
|
300
|
+
longThresholds
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
const shortMeetsThresholds = meetsLiquidityThresholds(
|
|
304
|
+
{
|
|
305
|
+
totalDepositsUSD: p.shortTotalDepositsUSD,
|
|
306
|
+
totalDebtUSD: p.shortTotalDebtUSD,
|
|
307
|
+
totalLiquidityUSD: p.shortTotalLiquidityUSD,
|
|
308
|
+
},
|
|
309
|
+
shortThresholds
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
if (!longMeetsThresholds || !shortMeetsThresholds) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return true;
|
|
317
|
+
})
|
|
318
|
+
.sort((a, b) => b.apr - a.apr)
|
|
319
|
+
.slice(0, MAX_ENTRIES);
|
|
320
|
+
}
|
|
164
321
|
|
|
165
322
|
export function getTopPairs(pairs: LendingPair[]) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
323
|
+
const stables = filterPairsByCategory(
|
|
324
|
+
pairs,
|
|
325
|
+
(group) => group?.includes("USD") ?? false,
|
|
326
|
+
(group) => group?.includes("USD") ?? false
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
const btcLst = filterPairsByCategory(
|
|
330
|
+
pairs,
|
|
331
|
+
(group) => group?.includes("BTC") ?? false,
|
|
332
|
+
(group) => group?.includes("BTC") ?? false
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
const ethLst = filterPairsByCategory(
|
|
336
|
+
pairs,
|
|
337
|
+
(group) => group?.includes("ETH") ?? false,
|
|
338
|
+
(group) => group?.includes("ETH") ?? false
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
return {
|
|
342
|
+
stables,
|
|
343
|
+
btcLst,
|
|
344
|
+
ethLst,
|
|
345
|
+
gainers: getDistinctPairsByShortAsset(pairs).slice(0, MAX_ENTRIES),
|
|
346
|
+
};
|
|
176
347
|
}
|
|
177
348
|
|
|
178
349
|
function isStable(assetGroup: string): boolean {
|
|
179
|
-
|
|
350
|
+
return assetGroup.includes("USD");
|
|
180
351
|
}
|
|
181
352
|
|
|
182
353
|
export function getDistinctPairsByShortAsset(
|
|
183
|
-
|
|
354
|
+
pairs: LendingPair[]
|
|
184
355
|
): LendingPair[] {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
356
|
+
const qualityPairs = pairs.filter((p) => {
|
|
357
|
+
if (!isFinite(p.apr) || !isFinite(p.priceChange)) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (
|
|
362
|
+
!p.longIsActive ||
|
|
363
|
+
p.longIsFrozen ||
|
|
364
|
+
!p.shortIsActive ||
|
|
365
|
+
p.shortIsFrozen
|
|
366
|
+
) {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (!p.shortBorrowingEnabled) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Apply liquidity thresholds
|
|
375
|
+
const longThresholds = getLiquidityThresholds(
|
|
376
|
+
p.chainId,
|
|
377
|
+
p.assetLong,
|
|
378
|
+
p.assetGroupLong
|
|
379
|
+
);
|
|
380
|
+
const shortThresholds = getLiquidityThresholds(
|
|
381
|
+
p.chainId,
|
|
382
|
+
p.assetShort,
|
|
383
|
+
p.assetGroupShort
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
const longMeetsThresholds = meetsLiquidityThresholds(
|
|
387
|
+
{
|
|
388
|
+
totalDepositsUSD: p.longTotalDepositsUSD,
|
|
389
|
+
totalDebtUSD: p.longTotalDebtUSD,
|
|
390
|
+
totalLiquidityUSD: p.longTotalLiquidityUSD,
|
|
391
|
+
},
|
|
392
|
+
longThresholds
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
const shortMeetsThresholds = meetsLiquidityThresholds(
|
|
396
|
+
{
|
|
397
|
+
totalDepositsUSD: p.shortTotalDepositsUSD,
|
|
398
|
+
totalDebtUSD: p.shortTotalDebtUSD,
|
|
399
|
+
totalLiquidityUSD: p.shortTotalLiquidityUSD,
|
|
400
|
+
},
|
|
401
|
+
shortThresholds
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
if (!longMeetsThresholds || !shortMeetsThresholds) {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (
|
|
409
|
+
p.assetGroupShort?.includes("PT-") ||
|
|
410
|
+
p.assetGroupLong?.includes("PT-")
|
|
411
|
+
) {
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return true;
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const sorted = [...qualityPairs].sort(
|
|
419
|
+
(a, b) => b.priceChange - a.priceChange
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
const blacklist = new Set<string>();
|
|
423
|
+
const blacklistLong = new Set<string>();
|
|
424
|
+
const result: LendingPair[] = [];
|
|
425
|
+
|
|
426
|
+
for (const pair of sorted) {
|
|
427
|
+
const shortGroup = pair.assetGroupShort;
|
|
428
|
+
const longGroup = pair.assetGroupLong;
|
|
429
|
+
|
|
430
|
+
if (blacklist.has(shortGroup) || blacklistLong.has(longGroup)) continue;
|
|
431
|
+
|
|
432
|
+
result.push(pair);
|
|
433
|
+
|
|
434
|
+
// Only blacklist if not a stablecoin
|
|
435
|
+
if (!isStable(shortGroup)) {
|
|
436
|
+
blacklist.add(shortGroup);
|
|
437
|
+
}
|
|
438
|
+
if (!isStable(longGroup)) {
|
|
439
|
+
blacklistLong.add(longGroup);
|
|
440
|
+
}
|
|
441
|
+
if (result.length >= 10) return result;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return result;
|
|
445
|
+
}
|