@curvefi/llamalend-api 2.0.3 → 2.0.5
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/docs/SUPPORT_LLv2.md +42 -0
- package/lib/interfaces.d.ts +1 -0
- package/lib/lendMarkets/LendMarketTemplate.js +12 -11
- package/lib/lendMarkets/interfaces/v1/statsV1.d.ts +4 -1
- package/lib/lendMarkets/interfaces/v2/statsV2.d.ts +4 -1
- package/lib/lendMarkets/modules/common/statsBase.d.ts +23 -4
- package/lib/lendMarkets/modules/common/statsBase.js +146 -143
- package/lib/lendMarkets/modules/common/vault.js +2 -2
- package/lib/lendMarkets/modules/v2/statsV2.d.ts +16 -0
- package/lib/lendMarkets/modules/v2/statsV2.js +66 -0
- package/lib/lendMarkets/utils.d.ts +14 -0
- package/lib/lendMarkets/utils.js +33 -0
- package/package.json +1 -1
- package/src/interfaces.ts +1 -0
- package/src/lendMarkets/LendMarketTemplate.ts +12 -11
- package/src/lendMarkets/interfaces/v1/statsV1.ts +2 -1
- package/src/lendMarkets/interfaces/v2/statsV2.ts +2 -1
- package/src/lendMarkets/modules/common/statsBase.ts +149 -148
- package/src/lendMarkets/modules/common/vault.ts +2 -2
- package/src/lendMarkets/modules/v2/statsV2.ts +59 -1
- package/src/lendMarkets/utils.ts +46 -0
package/docs/SUPPORT_LLv2.md
CHANGED
|
@@ -143,6 +143,48 @@ This document tracks feature support across market versions.
|
|
|
143
143
|
| ammBalances() | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
144
144
|
| capAndAvailable() | ✅ | ✅ | ❌ | ✅ | ❌ |
|
|
145
145
|
|
|
146
|
+
### Update for `capAndAvailable` method
|
|
147
|
+
|
|
148
|
+
Previously the `capAndAvailable` method returned:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
{
|
|
152
|
+
cap: string
|
|
153
|
+
available: string
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Now it returns:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
{
|
|
161
|
+
totalAssets: string
|
|
162
|
+
borrowCap: string
|
|
163
|
+
available: string
|
|
164
|
+
availableForBorrow: string
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### Important clarification
|
|
169
|
+
|
|
170
|
+
Previously the value called **`cap`** was incorrectly named.
|
|
171
|
+
|
|
172
|
+
On the frontend, the value that we now return as **`totalAssets`** corresponds to what was previously treated as **`cap`**.
|
|
173
|
+
|
|
174
|
+
#### Summary
|
|
175
|
+
|
|
176
|
+
- `totalAssets` → total assets deposited in the vault (what was previously used as `cap` on the frontend)
|
|
177
|
+
- `borrowCap` → maximum total debt allowed by the controller (LLv2 only; `Infinity` for LLv1)
|
|
178
|
+
- `available` → balance of borrowed token available in the controller
|
|
179
|
+
- `availableForBorrow` → effective amount available to borrow: `min(available, borrowCap - totalDebt)`
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
## Stats Module (`market.stats`) new methods
|
|
183
|
+
| Method | v1 | v2 | Same logic | Same params | Same type |
|
|
184
|
+
|--------|----|----|-----------------|----------------------|-----------------------|
|
|
185
|
+
| adminPercentage() | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
186
|
+
|
|
187
|
+
|
|
146
188
|
---
|
|
147
189
|
|
|
148
190
|
## Wallet Module (`market.wallet`)
|
package/lib/interfaces.d.ts
CHANGED
|
@@ -68,19 +68,20 @@ export class LendMarketTemplate {
|
|
|
68
68
|
getCurrentLeverageParams: userPosition.getCurrentLeverageParams.bind(userPosition),
|
|
69
69
|
};
|
|
70
70
|
this.stats = {
|
|
71
|
-
parameters: stats.statsParameters.bind(
|
|
72
|
-
rates: stats.statsRates.bind(
|
|
73
|
-
futureRates: stats.statsFutureRates.bind(
|
|
74
|
-
balances: stats.statsBalances.bind(
|
|
75
|
-
bandsInfo: stats.statsBandsInfo.bind(
|
|
76
|
-
bandBalances: stats.statsBandBalances.bind(
|
|
77
|
-
bandsBalances: stats.statsBandsBalances.bind(
|
|
78
|
-
totalDebt: stats.statsTotalDebt.bind(
|
|
79
|
-
ammBalances: stats.statsAmmBalances.bind(
|
|
80
|
-
capAndAvailable: stats.statsCapAndAvailable.bind(
|
|
71
|
+
parameters: stats.statsParameters.bind(stats),
|
|
72
|
+
rates: stats.statsRates.bind(stats),
|
|
73
|
+
futureRates: stats.statsFutureRates.bind(stats),
|
|
74
|
+
balances: stats.statsBalances.bind(stats),
|
|
75
|
+
bandsInfo: stats.statsBandsInfo.bind(stats),
|
|
76
|
+
bandBalances: stats.statsBandBalances.bind(stats),
|
|
77
|
+
bandsBalances: stats.statsBandsBalances.bind(stats),
|
|
78
|
+
totalDebt: stats.statsTotalDebt.bind(stats),
|
|
79
|
+
ammBalances: stats.statsAmmBalances.bind(stats),
|
|
80
|
+
capAndAvailable: stats.statsCapAndAvailable.bind(stats),
|
|
81
|
+
adminPercentage: stats.statsAdminPercentage.bind(stats),
|
|
81
82
|
};
|
|
82
83
|
this.wallet = {
|
|
83
|
-
balances: wallet.balances.bind(
|
|
84
|
+
balances: wallet.balances.bind(wallet),
|
|
84
85
|
};
|
|
85
86
|
this.prices = {
|
|
86
87
|
A: prices.A.bind(prices),
|
|
@@ -43,7 +43,10 @@ export interface IStatsV1 {
|
|
|
43
43
|
collateral: string;
|
|
44
44
|
}>;
|
|
45
45
|
capAndAvailable: (isGetter?: boolean, useAPI?: boolean) => Promise<{
|
|
46
|
-
|
|
46
|
+
borrowCap: string;
|
|
47
47
|
available: string;
|
|
48
|
+
totalAssets: string;
|
|
49
|
+
availableForBorrow: string;
|
|
48
50
|
}>;
|
|
51
|
+
adminPercentage: () => Promise<string>;
|
|
49
52
|
}
|
|
@@ -43,7 +43,10 @@ export interface IStatsV2 {
|
|
|
43
43
|
collateral: string;
|
|
44
44
|
}>;
|
|
45
45
|
capAndAvailable: (isGetter?: boolean, useAPI?: boolean) => Promise<{
|
|
46
|
-
|
|
46
|
+
borrowCap: string;
|
|
47
47
|
available: string;
|
|
48
|
+
totalAssets: string;
|
|
49
|
+
availableForBorrow: string;
|
|
48
50
|
}>;
|
|
51
|
+
adminPercentage: () => Promise<string>;
|
|
49
52
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import memoize from "memoizee";
|
|
2
|
-
import { TAmount } from "../../../interfaces";
|
|
2
|
+
import { TAmount, IMarketDataAPI } from "../../../interfaces";
|
|
3
3
|
import type { LendMarketTemplate } from "../../LendMarketTemplate";
|
|
4
4
|
import { Llamalend } from "../../../llamalend";
|
|
5
5
|
export declare class StatsBaseModule {
|
|
6
6
|
protected market: LendMarketTemplate;
|
|
7
7
|
protected llamalend: Llamalend;
|
|
8
8
|
constructor(market: LendMarketTemplate);
|
|
9
|
+
protected _fetchMarketDataFromAPI(): Promise<IMarketDataAPI>;
|
|
10
|
+
protected _fetchAdminPercentage: () => Promise<bigint>;
|
|
11
|
+
protected _fetchAdminFee: () => Promise<bigint>;
|
|
12
|
+
protected _getAdminFeesXY(isGetter: boolean): Promise<[bigint, bigint]>;
|
|
13
|
+
private _getRate;
|
|
14
|
+
private _getFutureRate;
|
|
9
15
|
statsParameters: (() => Promise<{
|
|
10
16
|
fee: string;
|
|
11
17
|
admin_fee: string;
|
|
@@ -21,8 +27,6 @@ export declare class StatsBaseModule {
|
|
|
21
27
|
base_price: string;
|
|
22
28
|
A: string;
|
|
23
29
|
}>>;
|
|
24
|
-
private _getRate;
|
|
25
|
-
private _getFutureRate;
|
|
26
30
|
statsRates(isGetter?: boolean, useAPI?: boolean): Promise<{
|
|
27
31
|
borrowApr: string;
|
|
28
32
|
lendApr: string;
|
|
@@ -62,8 +66,23 @@ export declare class StatsBaseModule {
|
|
|
62
66
|
borrowed: string;
|
|
63
67
|
collateral: string;
|
|
64
68
|
}>;
|
|
69
|
+
protected _statsCapAndAvailableFromAPI(): Promise<{
|
|
70
|
+
borrowCap: string;
|
|
71
|
+
available: string;
|
|
72
|
+
totalAssets: string;
|
|
73
|
+
availableForBorrow: string;
|
|
74
|
+
}>;
|
|
75
|
+
protected _statsCapAndAvailableOnChain(isGetter: boolean): Promise<{
|
|
76
|
+
borrowCap: string;
|
|
77
|
+
available: string;
|
|
78
|
+
totalAssets: string;
|
|
79
|
+
availableForBorrow: string;
|
|
80
|
+
}>;
|
|
65
81
|
statsCapAndAvailable(isGetter?: boolean, useAPI?: boolean): Promise<{
|
|
66
|
-
|
|
82
|
+
borrowCap: string;
|
|
67
83
|
available: string;
|
|
84
|
+
totalAssets: string;
|
|
85
|
+
availableForBorrow: string;
|
|
68
86
|
}>;
|
|
87
|
+
statsAdminPercentage: () => Promise<string>;
|
|
69
88
|
}
|
|
@@ -8,23 +8,55 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import memoize from "memoizee";
|
|
11
|
-
import { parseUnits,
|
|
11
|
+
import { parseUnits, toBN, formatUnits, formatNumber, } from "../../../utils";
|
|
12
12
|
import { _getMarketsData } from "../../../external-api";
|
|
13
13
|
import { cacheKey, cacheStats } from "../../../cache";
|
|
14
|
+
import { computeRatesFromRate, fetchMarketDataByVault } from "../../utils";
|
|
15
|
+
const PRECISION = BigInt("1000000000000000000"); // 1e18
|
|
14
16
|
export class StatsBaseModule {
|
|
15
17
|
constructor(market) {
|
|
18
|
+
this._fetchAdminPercentage = () => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
return BigInt(0);
|
|
20
|
+
});
|
|
21
|
+
this._fetchAdminFee = () => __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
return this.llamalend.contracts[this.market.addresses.amm].contract.admin_fee(this.llamalend.constantOptions);
|
|
23
|
+
});
|
|
24
|
+
this._getRate = (...args_1) => __awaiter(this, [...args_1], void 0, function* (isGetter = true) {
|
|
25
|
+
if (isGetter) {
|
|
26
|
+
const _rate = cacheStats.get(cacheKey(this.market.addresses.amm, 'rate'));
|
|
27
|
+
const _adminPercentage = yield this._fetchAdminPercentage();
|
|
28
|
+
return _rate * (PRECISION - _adminPercentage) / PRECISION;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
const [_rate, _adminPercentage] = yield Promise.all([
|
|
32
|
+
this.llamalend.contracts[this.market.addresses.amm].contract.rate(this.llamalend.constantOptions),
|
|
33
|
+
this._fetchAdminPercentage(),
|
|
34
|
+
]);
|
|
35
|
+
cacheStats.set(cacheKey(this.market.addresses.controller, 'rate'), _rate);
|
|
36
|
+
return _rate * (PRECISION - _adminPercentage) / PRECISION;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
this._getFutureRate = (_dReserves, _dDebt) => __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
const mpContract = this.llamalend.contracts[this.market.addresses.monetary_policy].contract;
|
|
41
|
+
const [_rate, _adminPercentage] = yield Promise.all([
|
|
42
|
+
mpContract.future_rate(this.market.addresses.controller, _dReserves, _dDebt),
|
|
43
|
+
this._fetchAdminPercentage(),
|
|
44
|
+
]);
|
|
45
|
+
return _rate * (PRECISION - _adminPercentage) / PRECISION;
|
|
46
|
+
});
|
|
16
47
|
this.statsParameters = memoize(() => __awaiter(this, void 0, void 0, function* () {
|
|
17
48
|
const llammaContract = this.llamalend.contracts[this.market.addresses.amm].multicallContract;
|
|
18
49
|
const controllerContract = this.llamalend.contracts[this.market.addresses.controller].multicallContract;
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
50
|
+
const [[_fee, _liquidation_discount, _loan_discount, _base_price, _A], _admin_fee] = yield Promise.all([
|
|
51
|
+
this.llamalend.multicallProvider.all([
|
|
52
|
+
llammaContract.fee(),
|
|
53
|
+
controllerContract.liquidation_discount(),
|
|
54
|
+
controllerContract.loan_discount(),
|
|
55
|
+
llammaContract.get_base_price(),
|
|
56
|
+
llammaContract.A(),
|
|
57
|
+
]),
|
|
58
|
+
this._fetchAdminFee(),
|
|
59
|
+
]);
|
|
28
60
|
const A = formatUnits(_A, 0);
|
|
29
61
|
const base_price = formatUnits(_base_price);
|
|
30
62
|
const [fee, admin_fee, liquidation_discount, loan_discount] = [_fee, _admin_fee, _liquidation_discount, _loan_discount]
|
|
@@ -34,21 +66,6 @@ export class StatsBaseModule {
|
|
|
34
66
|
promise: true,
|
|
35
67
|
maxAge: 5 * 60 * 1000, // 5m
|
|
36
68
|
});
|
|
37
|
-
this._getRate = (...args_1) => __awaiter(this, [...args_1], void 0, function* (isGetter = true) {
|
|
38
|
-
let _rate;
|
|
39
|
-
if (isGetter) {
|
|
40
|
-
_rate = cacheStats.get(cacheKey(this.market.addresses.amm, 'rate'));
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
_rate = yield this.llamalend.contracts[this.market.addresses.amm].contract.rate(this.llamalend.constantOptions);
|
|
44
|
-
cacheStats.set(cacheKey(this.market.addresses.controller, 'rate'), _rate);
|
|
45
|
-
}
|
|
46
|
-
return _rate;
|
|
47
|
-
});
|
|
48
|
-
this._getFutureRate = (_dReserves, _dDebt) => __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
const mpContract = this.llamalend.contracts[this.market.addresses.monetary_policy].contract;
|
|
50
|
-
return yield mpContract.future_rate(this.market.addresses.controller, _dReserves, _dDebt);
|
|
51
|
-
});
|
|
52
69
|
this.statsBandsInfo = memoize(() => __awaiter(this, void 0, void 0, function* () {
|
|
53
70
|
const ammContract = this.llamalend.contracts[this.market.addresses.amm].multicallContract;
|
|
54
71
|
const calls = [
|
|
@@ -68,42 +85,32 @@ export class StatsBaseModule {
|
|
|
68
85
|
});
|
|
69
86
|
this.statsAmmBalances = (...args_1) => __awaiter(this, [...args_1], void 0, function* (isGetter = true, useAPI = false) {
|
|
70
87
|
if (useAPI) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
collateral: market.ammBalances.ammBalanceCollateral.toString(),
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
throw new Error('Market not found in API');
|
|
81
|
-
}
|
|
88
|
+
const market = yield this._fetchMarketDataFromAPI();
|
|
89
|
+
return {
|
|
90
|
+
borrowed: market.ammBalances.ammBalanceBorrowed.toString(),
|
|
91
|
+
collateral: market.ammBalances.ammBalanceCollateral.toString(),
|
|
92
|
+
};
|
|
82
93
|
}
|
|
83
94
|
else {
|
|
84
95
|
const borrowedContract = this.llamalend.contracts[this.market.addresses.borrowed_token].multicallContract;
|
|
85
96
|
const collateralContract = this.llamalend.contracts[this.market.addresses.collateral_token].multicallContract;
|
|
86
|
-
|
|
87
|
-
let
|
|
97
|
+
let _balance_x, _balance_y;
|
|
98
|
+
let _fee_x, _fee_y;
|
|
88
99
|
if (isGetter) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
cacheStats.get(cacheKey(this.market.addresses.collateral_token, 'balanceOf', this.market.addresses.amm)),
|
|
93
|
-
cacheStats.get(cacheKey(this.market.addresses.amm, 'admin_fees_y')),
|
|
94
|
-
];
|
|
100
|
+
_balance_x = cacheStats.get(cacheKey(this.market.addresses.borrowed_token, 'balanceOf', this.market.addresses.amm));
|
|
101
|
+
_balance_y = cacheStats.get(cacheKey(this.market.addresses.collateral_token, 'balanceOf', this.market.addresses.amm));
|
|
102
|
+
[_fee_x, _fee_y] = yield this._getAdminFeesXY(true);
|
|
95
103
|
}
|
|
96
104
|
else {
|
|
97
|
-
[_balance_x,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
[[_balance_x, _balance_y], [_fee_x, _fee_y]] = (yield Promise.all([
|
|
106
|
+
this.llamalend.multicallProvider.all([
|
|
107
|
+
borrowedContract.balanceOf(this.market.addresses.amm),
|
|
108
|
+
collateralContract.balanceOf(this.market.addresses.amm),
|
|
109
|
+
]),
|
|
110
|
+
this._getAdminFeesXY(false),
|
|
111
|
+
]));
|
|
103
112
|
cacheStats.set(cacheKey(this.market.addresses.borrowed_token, 'balanceOf', this.market.addresses.amm), _balance_x);
|
|
104
|
-
cacheStats.set(cacheKey(this.market.addresses.amm, 'admin_fees_x'), _fee_x);
|
|
105
113
|
cacheStats.set(cacheKey(this.market.addresses.collateral_token, 'balanceOf', this.market.addresses.amm), _balance_y);
|
|
106
|
-
cacheStats.set(cacheKey(this.market.addresses.amm, 'admin_fees_y'), _fee_y);
|
|
107
114
|
}
|
|
108
115
|
return {
|
|
109
116
|
borrowed: toBN(_balance_x, this.market.borrowed_token.decimals).minus(toBN(_fee_x, this.market.borrowed_token.decimals)).toString(),
|
|
@@ -111,42 +118,52 @@ export class StatsBaseModule {
|
|
|
111
118
|
};
|
|
112
119
|
}
|
|
113
120
|
});
|
|
121
|
+
this.statsAdminPercentage = () => __awaiter(this, void 0, void 0, function* () {
|
|
122
|
+
const _adminPercentage = yield this._fetchAdminPercentage();
|
|
123
|
+
return formatUnits(_adminPercentage * BigInt(100));
|
|
124
|
+
});
|
|
114
125
|
this.market = market;
|
|
115
126
|
this.llamalend = market.getLlamalend();
|
|
116
127
|
}
|
|
128
|
+
_fetchMarketDataFromAPI() {
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
return fetchMarketDataByVault(this.llamalend.constants.NETWORK_NAME, this.market.addresses.vault, _getMarketsData);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
_getAdminFeesXY(isGetter) {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
if (isGetter) {
|
|
136
|
+
return [
|
|
137
|
+
cacheStats.get(cacheKey(this.market.addresses.amm, 'admin_fees_x')),
|
|
138
|
+
cacheStats.get(cacheKey(this.market.addresses.amm, 'admin_fees_y')),
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
const ammContract = this.llamalend.contracts[this.market.addresses.amm].multicallContract;
|
|
142
|
+
const [_fee_x, _fee_y] = yield this.llamalend.multicallProvider.all([
|
|
143
|
+
ammContract.admin_fees_x(),
|
|
144
|
+
ammContract.admin_fees_y(),
|
|
145
|
+
]);
|
|
146
|
+
cacheStats.set(cacheKey(this.market.addresses.amm, 'admin_fees_x'), _fee_x);
|
|
147
|
+
cacheStats.set(cacheKey(this.market.addresses.amm, 'admin_fees_y'), _fee_y);
|
|
148
|
+
return [_fee_x, _fee_y];
|
|
149
|
+
});
|
|
150
|
+
}
|
|
117
151
|
statsRates() {
|
|
118
152
|
return __awaiter(this, arguments, void 0, function* (isGetter = true, useAPI = false) {
|
|
119
153
|
if (useAPI) {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
lendApy: (market.rates.lendApy * 100).toString(),
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
throw new Error('Market not found in API');
|
|
132
|
-
}
|
|
154
|
+
const market = yield this._fetchMarketDataFromAPI();
|
|
155
|
+
return {
|
|
156
|
+
borrowApr: (market.rates.borrowApr * 100).toString(),
|
|
157
|
+
lendApr: (market.rates.lendApr * 100).toString(),
|
|
158
|
+
borrowApy: (market.rates.borrowApy * 100).toString(),
|
|
159
|
+
lendApy: (market.rates.lendApy * 100).toString(),
|
|
160
|
+
};
|
|
133
161
|
}
|
|
134
162
|
else {
|
|
135
163
|
const _rate = yield this._getRate(isGetter);
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
let lendApr = "0";
|
|
140
|
-
let lendApy = "0";
|
|
141
|
-
const debt = yield this.statsTotalDebt(isGetter);
|
|
142
|
-
if (Number(debt) > 0) {
|
|
143
|
-
const { cap } = yield this.statsCapAndAvailable(isGetter);
|
|
144
|
-
lendApr = toBN(_rate).times(365).times(86400).times(debt).div(cap).times(100).toString();
|
|
145
|
-
// lendApy = (debt * e**(rate*365*86400) - debt) / cap
|
|
146
|
-
const debtInAYearBN = BN(debt).times(Math.pow(2.718281828459, (toBN(_rate).times(365).times(86400)).toNumber()));
|
|
147
|
-
lendApy = debtInAYearBN.minus(debt).div(cap).times(100).toString();
|
|
148
|
-
}
|
|
149
|
-
return { borrowApr, lendApr, borrowApy, lendApy };
|
|
164
|
+
const debt = yield this.statsTotalDebt(isGetter, false);
|
|
165
|
+
const { totalAssets } = Number(debt) > 0 ? yield this.statsCapAndAvailable(isGetter, false) : { totalAssets: "0" };
|
|
166
|
+
return computeRatesFromRate(_rate, debt, totalAssets);
|
|
150
167
|
}
|
|
151
168
|
});
|
|
152
169
|
}
|
|
@@ -155,34 +172,22 @@ export class StatsBaseModule {
|
|
|
155
172
|
const _dReserves = parseUnits(dReserves, this.market.borrowed_token.decimals);
|
|
156
173
|
const _dDebt = parseUnits(dDebt, this.market.borrowed_token.decimals);
|
|
157
174
|
const _rate = yield this._getFutureRate(_dReserves, _dDebt);
|
|
158
|
-
const borrowApr = toBN(_rate).times(365).times(86400).times(100).toString();
|
|
159
|
-
// borrowApy = e**(rate*365*86400) - 1
|
|
160
|
-
const borrowApy = String(((Math.pow(2.718281828459, (toBN(_rate).times(365).times(86400)).toNumber())) - 1) * 100);
|
|
161
|
-
let lendApr = "0";
|
|
162
|
-
let lendApy = "0";
|
|
163
175
|
const debt = Number(yield this.statsTotalDebt()) + Number(dDebt);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
lendApr = toBN(_rate).times(365).times(86400).times(debt).div(cap).times(100).toString();
|
|
167
|
-
// lendApy = (debt * e**(rate*365*86400) - debt) / cap
|
|
168
|
-
const debtInAYearBN = BN(debt).times(Math.pow(2.718281828459, (toBN(_rate).times(365).times(86400)).toNumber()));
|
|
169
|
-
lendApy = debtInAYearBN.minus(debt).div(cap).times(100).toString();
|
|
170
|
-
}
|
|
171
|
-
return { borrowApr, lendApr, borrowApy, lendApy };
|
|
176
|
+
const cap = Number((yield this.statsCapAndAvailable(true, useAPI)).totalAssets) + Number(dReserves);
|
|
177
|
+
return computeRatesFromRate(_rate, debt, cap);
|
|
172
178
|
});
|
|
173
179
|
}
|
|
174
180
|
statsBalances() {
|
|
175
181
|
return __awaiter(this, void 0, void 0, function* () {
|
|
176
182
|
const borrowedContract = this.llamalend.contracts[this.market.borrowed_token.address].multicallContract;
|
|
177
183
|
const collateralContract = this.llamalend.contracts[this.market.collateral_token.address].multicallContract;
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
];
|
|
185
|
-
const [_borrowedBalance, _collateralBalance, _borrowedAdminFees, _collateralAdminFees] = yield this.llamalend.multicallProvider.all(calls);
|
|
184
|
+
const [[_borrowedBalance, _collateralBalance], [_borrowedAdminFees, _collateralAdminFees]] = yield Promise.all([
|
|
185
|
+
this.llamalend.multicallProvider.all([
|
|
186
|
+
borrowedContract.balanceOf(this.market.addresses.amm),
|
|
187
|
+
collateralContract.balanceOf(this.market.addresses.amm),
|
|
188
|
+
]),
|
|
189
|
+
this._getAdminFeesXY(false),
|
|
190
|
+
]);
|
|
186
191
|
return [
|
|
187
192
|
formatUnits(_borrowedBalance - _borrowedAdminFees, this.market.borrowed_token.decimals),
|
|
188
193
|
formatUnits(_collateralBalance - _collateralAdminFees, this.market.collateral_token.decimals),
|
|
@@ -226,14 +231,8 @@ export class StatsBaseModule {
|
|
|
226
231
|
statsTotalDebt() {
|
|
227
232
|
return __awaiter(this, arguments, void 0, function* (isGetter = true, useAPI = true) {
|
|
228
233
|
if (useAPI) {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
if (market) {
|
|
232
|
-
return market.borrowed.total.toString();
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
throw new Error('Market not found in API');
|
|
236
|
-
}
|
|
234
|
+
const market = yield this._fetchMarketDataFromAPI();
|
|
235
|
+
return market.borrowed.total.toString();
|
|
237
236
|
}
|
|
238
237
|
else {
|
|
239
238
|
let _debt;
|
|
@@ -248,44 +247,48 @@ export class StatsBaseModule {
|
|
|
248
247
|
}
|
|
249
248
|
});
|
|
250
249
|
}
|
|
251
|
-
|
|
252
|
-
return __awaiter(this,
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
250
|
+
_statsCapAndAvailableFromAPI() {
|
|
251
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
252
|
+
const market = yield this._fetchMarketDataFromAPI();
|
|
253
|
+
return {
|
|
254
|
+
totalAssets: market.totalSupplied.total.toString(),
|
|
255
|
+
borrowCap: Infinity.toString(),
|
|
256
|
+
available: market.availableToBorrow.total.toString(),
|
|
257
|
+
availableForBorrow: market.availableToBorrow.total.toString(),
|
|
258
|
+
};
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
_statsCapAndAvailableOnChain(isGetter) {
|
|
262
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
263
|
+
const vaultContract = this.llamalend.contracts[this.market.addresses.vault].multicallContract;
|
|
264
|
+
const borrowedContract = this.llamalend.contracts[this.market.addresses.borrowed_token].multicallContract;
|
|
265
|
+
let _cap, _available;
|
|
266
|
+
if (isGetter) {
|
|
267
|
+
_cap = cacheStats.get(cacheKey(this.market.addresses.vault, 'totalAssets', this.market.addresses.controller));
|
|
268
|
+
_available = cacheStats.get(cacheKey(this.market.addresses.borrowed_token, 'balanceOf', this.market.addresses.controller));
|
|
265
269
|
}
|
|
266
270
|
else {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
[_cap, _available] = yield this.llamalend.multicallProvider.all([
|
|
276
|
-
vaultContract.totalAssets(this.market.addresses.controller),
|
|
277
|
-
borrowedContract.balanceOf(this.market.addresses.controller),
|
|
278
|
-
]);
|
|
279
|
-
cacheStats.set(cacheKey(this.market.addresses.vault, 'totalAssets', this.market.addresses.controller), _cap);
|
|
280
|
-
cacheStats.set(cacheKey(this.market.addresses.borrowed_token, 'balanceOf', this.market.addresses.controller), _available);
|
|
281
|
-
}
|
|
282
|
-
return {
|
|
283
|
-
cap: this.llamalend.formatUnits(_cap, this.market.borrowed_token.decimals),
|
|
284
|
-
available: this.llamalend.formatUnits(_available, this.market.borrowed_token.decimals),
|
|
285
|
-
};
|
|
286
|
-
// cap -> totalAssets
|
|
287
|
-
// add cap: controller.borrow_cap() // Display
|
|
271
|
+
[_cap, _available] = yield this.llamalend.multicallProvider.all([
|
|
272
|
+
vaultContract.totalAssets(this.market.addresses.controller),
|
|
273
|
+
borrowedContract.balanceOf(this.market.addresses.controller),
|
|
274
|
+
]);
|
|
275
|
+
cacheStats.set(cacheKey(this.market.addresses.vault, 'totalAssets', this.market.addresses.controller), _cap);
|
|
276
|
+
cacheStats.set(cacheKey(this.market.addresses.borrowed_token, 'balanceOf', this.market.addresses.controller), _available);
|
|
288
277
|
}
|
|
278
|
+
const available = this.llamalend.formatUnits(_available, this.market.borrowed_token.decimals);
|
|
279
|
+
return {
|
|
280
|
+
totalAssets: this.llamalend.formatUnits(_cap, this.market.borrowed_token.decimals),
|
|
281
|
+
borrowCap: Infinity.toString(),
|
|
282
|
+
available,
|
|
283
|
+
availableForBorrow: available,
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
statsCapAndAvailable() {
|
|
288
|
+
return __awaiter(this, arguments, void 0, function* (isGetter = true, useAPI = false) {
|
|
289
|
+
if (useAPI)
|
|
290
|
+
return this._statsCapAndAvailableFromAPI();
|
|
291
|
+
return this._statsCapAndAvailableOnChain(isGetter);
|
|
289
292
|
});
|
|
290
293
|
}
|
|
291
294
|
}
|
|
@@ -415,9 +415,9 @@ export class VaultModule {
|
|
|
415
415
|
}
|
|
416
416
|
vaultTotalLiquidity() {
|
|
417
417
|
return __awaiter(this, arguments, void 0, function* (useAPI = true) {
|
|
418
|
-
const {
|
|
418
|
+
const { totalAssets } = yield this.market.stats.capAndAvailable(true, useAPI);
|
|
419
419
|
const price = yield _getUsdRate.call(this.llamalend, this.market.addresses.borrowed_token);
|
|
420
|
-
return BN(
|
|
420
|
+
return BN(totalAssets).times(price).toFixed(6);
|
|
421
421
|
});
|
|
422
422
|
}
|
|
423
423
|
vaultCrvApr() {
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
import memoize from "memoizee";
|
|
1
2
|
import { StatsBaseModule } from "../common/statsBase.js";
|
|
2
3
|
export declare class StatsV2Module extends StatsBaseModule {
|
|
4
|
+
protected _fetchAdminPercentage: (() => Promise<bigint>) & memoize.Memoized<() => Promise<bigint>>;
|
|
5
|
+
protected _fetchAdminFee: () => Promise<bigint>;
|
|
6
|
+
protected _getAdminFeesXY: () => Promise<[bigint, bigint]>;
|
|
7
|
+
protected _statsCapAndAvailableFromAPI(): Promise<{
|
|
8
|
+
totalAssets: string;
|
|
9
|
+
borrowCap: string;
|
|
10
|
+
available: string;
|
|
11
|
+
availableForBorrow: string;
|
|
12
|
+
}>;
|
|
13
|
+
protected _statsCapAndAvailableOnChain(isGetter: boolean): Promise<{
|
|
14
|
+
borrowCap: string;
|
|
15
|
+
available: string;
|
|
16
|
+
totalAssets: string;
|
|
17
|
+
availableForBorrow: string;
|
|
18
|
+
}>;
|
|
3
19
|
}
|
|
@@ -1,3 +1,69 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import memoize from "memoizee";
|
|
1
11
|
import { StatsBaseModule } from "../common/statsBase.js";
|
|
12
|
+
import { cacheKey, cacheStats } from "../../../cache";
|
|
13
|
+
import BigNumber from "bignumber.js";
|
|
14
|
+
import { BN } from "../../../utils";
|
|
2
15
|
export class StatsV2Module extends StatsBaseModule {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
this._fetchAdminPercentage = memoize(() => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
return yield this.llamalend.contracts[this.market.addresses.controller].contract.admin_percentage(this.llamalend.constantOptions);
|
|
20
|
+
}), {
|
|
21
|
+
promise: true,
|
|
22
|
+
maxAge: 30 * 60 * 1000, // 30m
|
|
23
|
+
});
|
|
24
|
+
this._fetchAdminFee = () => __awaiter(this, void 0, void 0, function* () { return BigInt(0); });
|
|
25
|
+
this._getAdminFeesXY = () => __awaiter(this, void 0, void 0, function* () { return [BigInt(0), BigInt(0)]; });
|
|
26
|
+
}
|
|
27
|
+
_statsCapAndAvailableFromAPI() {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
const market = yield this._fetchMarketDataFromAPI();
|
|
30
|
+
return {
|
|
31
|
+
totalAssets: market.totalSupplied.total.toString(),
|
|
32
|
+
borrowCap: market.borrowCap.total.toString(),
|
|
33
|
+
available: market.availableToBorrow.total.toString(),
|
|
34
|
+
availableForBorrow: market.availableToBorrow.total.toString(),
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
_statsCapAndAvailableOnChain(isGetter) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
const vaultContract = this.llamalend.contracts[this.market.addresses.vault].multicallContract;
|
|
41
|
+
const controllerContract = this.llamalend.contracts[this.market.addresses.controller].multicallContract;
|
|
42
|
+
let _cap, _available, _totalAssets, _totalDebt;
|
|
43
|
+
if (isGetter) {
|
|
44
|
+
_totalAssets = cacheStats.get(cacheKey(this.market.addresses.vault, 'totalAssets', this.market.addresses.controller));
|
|
45
|
+
_cap = cacheStats.get(cacheKey(this.market.addresses.controller, 'borrow_cap'));
|
|
46
|
+
_available = cacheStats.get(cacheKey(this.market.addresses.controller, 'available_balance'));
|
|
47
|
+
_totalDebt = cacheStats.get(cacheKey(this.market.addresses.controller, 'total_debt'));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
[_totalAssets, _available, _cap, _totalDebt] = yield this.llamalend.multicallProvider.all([
|
|
51
|
+
vaultContract.totalAssets(this.market.addresses.controller),
|
|
52
|
+
controllerContract.available_balance(),
|
|
53
|
+
controllerContract.borrow_cap(),
|
|
54
|
+
controllerContract.total_debt(),
|
|
55
|
+
]);
|
|
56
|
+
cacheStats.set(cacheKey(this.market.addresses.vault, 'totalAssets', this.market.addresses.controller), _totalAssets);
|
|
57
|
+
cacheStats.set(cacheKey(this.market.addresses.controller, 'borrow_cap'), _cap);
|
|
58
|
+
cacheStats.set(cacheKey(this.market.addresses.controller, 'available_balance'), _available);
|
|
59
|
+
cacheStats.set(cacheKey(this.market.addresses.controller, 'total_debt'), _totalDebt);
|
|
60
|
+
}
|
|
61
|
+
const totalAssets = this.llamalend.formatUnits(_totalAssets, this.market.borrowed_token.decimals);
|
|
62
|
+
const borrowCap = this.llamalend.formatUnits(_cap, this.market.borrowed_token.decimals);
|
|
63
|
+
const available = this.llamalend.formatUnits(_available, this.market.borrowed_token.decimals);
|
|
64
|
+
const totalDebt = this.llamalend.formatUnits(_totalDebt, this.market.borrowed_token.decimals);
|
|
65
|
+
const availableForBorrow = BigNumber.min(BN(available), BN(borrowCap).minus(BN(totalDebt))).toFixed();
|
|
66
|
+
return { totalAssets, borrowCap, available, availableForBorrow };
|
|
67
|
+
});
|
|
68
|
+
}
|
|
3
69
|
}
|