@gearbox-protocol/sdk 13.0.0-beta.1 → 13.0.0-beta.3
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/cjs/sdk/utils/assetsMath.js +149 -0
- package/dist/cjs/sdk/utils/bigintMath.js +33 -0
- package/dist/cjs/sdk/utils/creditAccount.js +409 -0
- package/dist/cjs/sdk/utils/endpoints.js +71 -0
- package/dist/cjs/sdk/utils/formatter.js +55 -2
- package/dist/cjs/sdk/utils/index.js +10 -0
- package/dist/cjs/sdk/utils/priceMath.js +35 -0
- package/dist/esm/sdk/utils/assetsMath.js +125 -0
- package/dist/esm/sdk/utils/bigintMath.js +9 -0
- package/dist/esm/sdk/utils/creditAccount.js +396 -0
- package/dist/esm/sdk/utils/endpoints.js +46 -0
- package/dist/esm/sdk/utils/formatter.js +37 -1
- package/dist/esm/sdk/utils/index.js +5 -0
- package/dist/esm/sdk/utils/priceMath.js +11 -0
- package/dist/types/sdk/utils/assetsMath.d.ts +42 -0
- package/dist/types/sdk/utils/bigintMath.d.ts +6 -0
- package/dist/types/sdk/utils/creditAccount.d.ts +128 -0
- package/dist/types/sdk/utils/endpoints.d.ts +19 -0
- package/dist/types/sdk/utils/formatter.d.ts +9 -0
- package/dist/types/sdk/utils/index.d.ts +5 -0
- package/dist/types/sdk/utils/priceMath.d.ts +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var assetsMath_exports = {};
|
|
20
|
+
__export(assetsMath_exports, {
|
|
21
|
+
AssetUtils: () => AssetUtils
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(assetsMath_exports);
|
|
24
|
+
var import__ = require("../index.js");
|
|
25
|
+
var import_creditAccount = require("./creditAccount.js");
|
|
26
|
+
class AssetUtils {
|
|
27
|
+
static nextAsset({
|
|
28
|
+
allowedTokens,
|
|
29
|
+
selectedAssets,
|
|
30
|
+
balances,
|
|
31
|
+
tokensList,
|
|
32
|
+
prices = {}
|
|
33
|
+
}) {
|
|
34
|
+
const selectedRecord = selectedAssets.reduce(
|
|
35
|
+
(acc, { token }) => {
|
|
36
|
+
acc[token.toLowerCase()] = true;
|
|
37
|
+
return acc;
|
|
38
|
+
},
|
|
39
|
+
{}
|
|
40
|
+
);
|
|
41
|
+
const notSelected = allowedTokens.filter((allowedToken) => {
|
|
42
|
+
const alreadySelected = selectedRecord[allowedToken.toLowerCase()];
|
|
43
|
+
return !alreadySelected;
|
|
44
|
+
});
|
|
45
|
+
const sorted = import_creditAccount.CreditAccountDataUtils.sortBalances(
|
|
46
|
+
AssetUtils.getBalances(notSelected, balances),
|
|
47
|
+
prices,
|
|
48
|
+
tokensList
|
|
49
|
+
);
|
|
50
|
+
const [address] = sorted[0] || [];
|
|
51
|
+
return address;
|
|
52
|
+
}
|
|
53
|
+
static getBalances(allowedTokens, externalBalances) {
|
|
54
|
+
return allowedTokens.reduce((acc, address) => {
|
|
55
|
+
const addressLc = address.toLowerCase();
|
|
56
|
+
return {
|
|
57
|
+
...acc,
|
|
58
|
+
[addressLc]: externalBalances[addressLc] || 0n
|
|
59
|
+
};
|
|
60
|
+
}, {});
|
|
61
|
+
}
|
|
62
|
+
static constructAssetRecord(a) {
|
|
63
|
+
const record = a.reduce((acc, asset) => {
|
|
64
|
+
acc[asset.token] = asset;
|
|
65
|
+
return acc;
|
|
66
|
+
}, {});
|
|
67
|
+
return record;
|
|
68
|
+
}
|
|
69
|
+
static memoWrap = (unwrappedAddress, wrappedAddress, prices, tokensList) => function wrap(assets) {
|
|
70
|
+
const assetsRecord = AssetUtils.constructAssetRecord(assets);
|
|
71
|
+
const unwrapped = assetsRecord[unwrappedAddress];
|
|
72
|
+
const wrapped = assetsRecord[wrappedAddress];
|
|
73
|
+
const { balance: wrappedAmount = 0n } = wrapped || {};
|
|
74
|
+
if (unwrapped) {
|
|
75
|
+
const { balance: unwrappedAmount = 0n } = unwrapped || {};
|
|
76
|
+
const unwrappedToken = tokensList[unwrappedAddress];
|
|
77
|
+
const unwrappedPrice = prices[unwrappedAddress] || 0n;
|
|
78
|
+
const wrappedToken = tokensList[wrappedAddress];
|
|
79
|
+
const wrappedPrice = prices[wrappedAddress] || 0n;
|
|
80
|
+
const unwrappedInWrapped = import__.PriceUtils.convertByPrice(
|
|
81
|
+
import__.PriceUtils.calcTotalPrice(
|
|
82
|
+
unwrappedPrice,
|
|
83
|
+
import__.BigIntMath.max(0n, unwrappedAmount),
|
|
84
|
+
unwrappedToken.decimals
|
|
85
|
+
),
|
|
86
|
+
{
|
|
87
|
+
price: wrappedPrice,
|
|
88
|
+
decimals: wrappedToken.decimals
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
assetsRecord[wrappedAddress] = {
|
|
92
|
+
token: wrappedAddress,
|
|
93
|
+
balance: import__.BigIntMath.max(0n, wrappedAmount) + unwrappedInWrapped
|
|
94
|
+
};
|
|
95
|
+
delete assetsRecord[unwrappedAddress];
|
|
96
|
+
return [Object.values(assetsRecord), unwrappedInWrapped, wrappedAmount];
|
|
97
|
+
}
|
|
98
|
+
return [Object.values(assetsRecord), 0n, wrappedAmount];
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Sums the the second assets list into the first assets list
|
|
102
|
+
* Balances cant be negative; creates new assets.
|
|
103
|
+
*/
|
|
104
|
+
static sumAssets(a, b) {
|
|
105
|
+
const aRecord = AssetUtils.constructAssetRecord(a);
|
|
106
|
+
const resRecord = b.reduce((acc, bAsset) => {
|
|
107
|
+
const aAsset = acc[bAsset.token];
|
|
108
|
+
const { balance: amount = 0n } = aAsset || {};
|
|
109
|
+
const amountSum = import__.BigIntMath.max(0n, bAsset.balance) + import__.BigIntMath.max(0n, amount);
|
|
110
|
+
const aOrB = aAsset || bAsset;
|
|
111
|
+
acc[bAsset.token] = {
|
|
112
|
+
...aOrB,
|
|
113
|
+
balance: amountSum
|
|
114
|
+
};
|
|
115
|
+
return acc;
|
|
116
|
+
}, aRecord);
|
|
117
|
+
return Object.values(resRecord);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Sums the the second assets list into the first assets list
|
|
121
|
+
* Balances cant be negative; doesn't create new assets.
|
|
122
|
+
*/
|
|
123
|
+
static addBalances(a, b) {
|
|
124
|
+
const bRecord = AssetUtils.constructAssetRecord(b);
|
|
125
|
+
return a.map((asset) => {
|
|
126
|
+
const bAsset = bRecord[asset.token];
|
|
127
|
+
const { balance: bAmount = 0n } = bAsset || {};
|
|
128
|
+
const amountSum = import__.BigIntMath.max(0n, asset.balance) + import__.BigIntMath.max(0n, bAmount);
|
|
129
|
+
return { ...asset, balance: amountSum };
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Subtracts the the second assets list from the first assets list
|
|
134
|
+
* Balances cant be negative; doesn't create new assets.
|
|
135
|
+
*/
|
|
136
|
+
static subAssets(a, b) {
|
|
137
|
+
const bRecord = AssetUtils.constructAssetRecord(b);
|
|
138
|
+
return a.map((asset) => {
|
|
139
|
+
const bAsset = bRecord[asset.token];
|
|
140
|
+
const { balance: bAmount = 0n } = bAsset || {};
|
|
141
|
+
const amountSub = import__.BigIntMath.max(0n, asset.balance) - import__.BigIntMath.max(0n, bAmount);
|
|
142
|
+
return { ...asset, balance: import__.BigIntMath.max(0n, amountSub) };
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
147
|
+
0 && (module.exports = {
|
|
148
|
+
AssetUtils
|
|
149
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var bigintMath_exports = {};
|
|
20
|
+
__export(bigintMath_exports, {
|
|
21
|
+
BigIntMath: () => BigIntMath
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(bigintMath_exports);
|
|
24
|
+
class BigIntMath {
|
|
25
|
+
static abs = (x) => x < 0n ? -x : x;
|
|
26
|
+
static max = (a, b) => a > b ? a : b;
|
|
27
|
+
static min = (a, b) => a < b ? a : b;
|
|
28
|
+
static neg = (a) => a > 0 ? a * -1n : a;
|
|
29
|
+
}
|
|
30
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
31
|
+
0 && (module.exports = {
|
|
32
|
+
BigIntMath
|
|
33
|
+
});
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var creditAccount_exports = {};
|
|
20
|
+
__export(creditAccount_exports, {
|
|
21
|
+
CreditAccountDataUtils: () => CreditAccountDataUtils
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(creditAccount_exports);
|
|
24
|
+
var import__ = require("../index.js");
|
|
25
|
+
const MAX_UINT16 = 65535;
|
|
26
|
+
class CreditAccountDataUtils {
|
|
27
|
+
constructor() {
|
|
28
|
+
}
|
|
29
|
+
static sortBalances(balances, prices, tokens) {
|
|
30
|
+
return Object.entries(balances).sort(
|
|
31
|
+
([addr1, amount1], [addr2, amount2]) => {
|
|
32
|
+
return CreditAccountDataUtils.assetComparator(
|
|
33
|
+
{
|
|
34
|
+
token: addr1,
|
|
35
|
+
balance: amount1
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
token: addr2,
|
|
39
|
+
balance: amount2
|
|
40
|
+
},
|
|
41
|
+
prices,
|
|
42
|
+
prices,
|
|
43
|
+
tokens,
|
|
44
|
+
tokens
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
static sortAssets(balances, prices, tokens) {
|
|
50
|
+
return [...balances].sort(
|
|
51
|
+
(t1, t2) => CreditAccountDataUtils.assetComparator(
|
|
52
|
+
t1,
|
|
53
|
+
t2,
|
|
54
|
+
prices,
|
|
55
|
+
prices,
|
|
56
|
+
tokens,
|
|
57
|
+
tokens
|
|
58
|
+
)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
static assetComparator(t1, t2, prices1, prices2, tokens1, tokens2) {
|
|
62
|
+
const addr1Lc = t1.token.toLowerCase();
|
|
63
|
+
const addr2Lc = t2.token.toLowerCase();
|
|
64
|
+
const token1 = tokens1?.[addr1Lc];
|
|
65
|
+
const token2 = tokens2?.[addr2Lc];
|
|
66
|
+
const price1 = prices1?.[addr1Lc] || import__.PRICE_DECIMALS;
|
|
67
|
+
const price2 = prices2?.[addr2Lc] || import__.PRICE_DECIMALS;
|
|
68
|
+
const totalPrice1 = import__.PriceUtils.calcTotalPrice(
|
|
69
|
+
price1,
|
|
70
|
+
t1.balance,
|
|
71
|
+
token1?.decimals
|
|
72
|
+
);
|
|
73
|
+
const totalPrice2 = import__.PriceUtils.calcTotalPrice(
|
|
74
|
+
price2,
|
|
75
|
+
t2.balance,
|
|
76
|
+
token2?.decimals
|
|
77
|
+
);
|
|
78
|
+
if (totalPrice1 === totalPrice2) {
|
|
79
|
+
return t1.balance === t2.balance ? CreditAccountDataUtils.tokensAbcComparator(token1, token2) : CreditAccountDataUtils.amountAbcComparator(t1.balance, t2.balance);
|
|
80
|
+
}
|
|
81
|
+
return CreditAccountDataUtils.amountAbcComparator(totalPrice1, totalPrice2);
|
|
82
|
+
}
|
|
83
|
+
static tokensAbcComparator(t1, t2) {
|
|
84
|
+
const { symbol: symbol1 = "" } = t1 || {};
|
|
85
|
+
const { symbol: symbol2 = "" } = t2 || {};
|
|
86
|
+
const symbol1LC = symbol1.toLowerCase();
|
|
87
|
+
const symbol2LC = symbol2.toLowerCase();
|
|
88
|
+
if (symbol1LC === symbol2LC) return 0;
|
|
89
|
+
return symbol1LC > symbol2LC ? 1 : -1;
|
|
90
|
+
}
|
|
91
|
+
static amountAbcComparator(t1, t2) {
|
|
92
|
+
return t1 > t2 ? -1 : 1;
|
|
93
|
+
}
|
|
94
|
+
static calcMaxDebtIncrease(healthFactor, debt, underlyingLT, minHf = Number(import__.PERCENTAGE_FACTOR)) {
|
|
95
|
+
const result = debt * BigInt(healthFactor - minHf) / BigInt(minHf - underlyingLT);
|
|
96
|
+
return import__.BigIntMath.max(0n, result);
|
|
97
|
+
}
|
|
98
|
+
static calcMaxLendingDebt({
|
|
99
|
+
assets,
|
|
100
|
+
liquidationThresholds,
|
|
101
|
+
underlyingToken,
|
|
102
|
+
prices,
|
|
103
|
+
tokensList,
|
|
104
|
+
targetHF = import__.PERCENTAGE_FACTOR
|
|
105
|
+
}) {
|
|
106
|
+
const assetsLTMoney = assets.reduce(
|
|
107
|
+
(acc, { token: tokenAddress, balance: amount }) => {
|
|
108
|
+
const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
|
|
109
|
+
const lt = liquidationThresholds[tokenAddress] || 0n;
|
|
110
|
+
const price = prices[tokenAddress] || 0n;
|
|
111
|
+
const tokenMoney = import__.PriceUtils.calcTotalPrice(
|
|
112
|
+
price,
|
|
113
|
+
amount,
|
|
114
|
+
tokenDecimals
|
|
115
|
+
);
|
|
116
|
+
const tokenLtMoney = tokenMoney * lt;
|
|
117
|
+
return acc + tokenLtMoney;
|
|
118
|
+
},
|
|
119
|
+
0n
|
|
120
|
+
);
|
|
121
|
+
const underlyingPrice = prices[underlyingToken] || 0n;
|
|
122
|
+
const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
|
|
123
|
+
const max = underlyingPrice > 0 ? assetsLTMoney * 10n ** BigInt(underlyingDecimals) / underlyingPrice / targetHF / 10n ** BigInt(import__.WAD_DECIMALS_POW - import__.PRICE_DECIMALS_POW) : 0n;
|
|
124
|
+
return max;
|
|
125
|
+
}
|
|
126
|
+
// [
|
|
127
|
+
// Sum(amount_i * price_i * apy_i - quota_i * quotaPrice * quotaRate_i * (1 + feeInterest)) -
|
|
128
|
+
// debt * debtPrice * baseRateWithFee
|
|
129
|
+
// ] / (totalValue - debt) * debtPrice
|
|
130
|
+
static calcOverallAPY({
|
|
131
|
+
caAssets,
|
|
132
|
+
lpAPY,
|
|
133
|
+
prices,
|
|
134
|
+
quotas,
|
|
135
|
+
quotaRates,
|
|
136
|
+
feeInterest,
|
|
137
|
+
totalValue,
|
|
138
|
+
debt,
|
|
139
|
+
baseRateWithFee,
|
|
140
|
+
underlyingToken,
|
|
141
|
+
tokensList
|
|
142
|
+
}) {
|
|
143
|
+
if (!lpAPY || !totalValue || totalValue <= 0n || !debt || totalValue <= debt)
|
|
144
|
+
return void 0;
|
|
145
|
+
const underlyingTokenDecimals = tokensList[underlyingToken]?.decimals || 18;
|
|
146
|
+
const underlyingPrice = prices[underlyingToken];
|
|
147
|
+
const assetAPYMoney = caAssets.reduce(
|
|
148
|
+
(acc, { token: tokenAddress, balance: amount }) => {
|
|
149
|
+
const apy = lpAPY[tokenAddress] || 0;
|
|
150
|
+
const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
|
|
151
|
+
const price = prices[tokenAddress] || 0n;
|
|
152
|
+
const money = import__.PriceUtils.calcTotalPrice(price, amount, tokenDecimals);
|
|
153
|
+
const apyMoney = money * BigInt(apy);
|
|
154
|
+
const { rate: quotaAPY = 0n, isActive = false } = quotaRates?.[tokenAddress] || {};
|
|
155
|
+
const { balance: quotaBalance = 0n } = quotas[tokenAddress] || {};
|
|
156
|
+
const quotaAmount = isActive ? quotaBalance : 0n;
|
|
157
|
+
const quotaMoney = import__.PriceUtils.calcTotalPrice(
|
|
158
|
+
underlyingPrice || 0n,
|
|
159
|
+
quotaAmount,
|
|
160
|
+
underlyingTokenDecimals
|
|
161
|
+
);
|
|
162
|
+
const quotaRate = quotaAPY * (BigInt(feeInterest) + import__.PERCENTAGE_FACTOR) / import__.PERCENTAGE_FACTOR;
|
|
163
|
+
const quotaAPYMoney = quotaMoney * quotaRate;
|
|
164
|
+
return acc + apyMoney - quotaAPYMoney;
|
|
165
|
+
},
|
|
166
|
+
0n
|
|
167
|
+
);
|
|
168
|
+
const debtMoney = import__.PriceUtils.calcTotalPrice(
|
|
169
|
+
underlyingPrice || 0n,
|
|
170
|
+
debt,
|
|
171
|
+
underlyingTokenDecimals
|
|
172
|
+
);
|
|
173
|
+
const debtAPYMoney = debtMoney * BigInt(baseRateWithFee);
|
|
174
|
+
const yourAssetsMoney = import__.PriceUtils.calcTotalPrice(
|
|
175
|
+
underlyingPrice || import__.PRICE_DECIMALS,
|
|
176
|
+
totalValue - debt,
|
|
177
|
+
underlyingTokenDecimals
|
|
178
|
+
);
|
|
179
|
+
const apyInPercent = (assetAPYMoney - debtAPYMoney) / yourAssetsMoney;
|
|
180
|
+
return apyInPercent;
|
|
181
|
+
}
|
|
182
|
+
static calcHealthFactor({
|
|
183
|
+
assets,
|
|
184
|
+
quotas,
|
|
185
|
+
quotasInfo,
|
|
186
|
+
liquidationThresholds,
|
|
187
|
+
underlyingToken,
|
|
188
|
+
debt,
|
|
189
|
+
prices,
|
|
190
|
+
tokensList
|
|
191
|
+
}) {
|
|
192
|
+
if (debt === 0n) return MAX_UINT16;
|
|
193
|
+
const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
|
|
194
|
+
const underlyingPrice = prices[underlyingToken] || 0n;
|
|
195
|
+
const assetMoney = assets.reduce(
|
|
196
|
+
(acc, { token: tokenAddress, balance: amount }) => {
|
|
197
|
+
const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
|
|
198
|
+
const lt = liquidationThresholds[tokenAddress] || 0n;
|
|
199
|
+
const price = prices[tokenAddress] || 0n;
|
|
200
|
+
const tokenMoney = import__.PriceUtils.calcTotalPrice(
|
|
201
|
+
price,
|
|
202
|
+
amount,
|
|
203
|
+
tokenDecimals
|
|
204
|
+
);
|
|
205
|
+
const tokenLtMoney = tokenMoney * lt / import__.PERCENTAGE_FACTOR;
|
|
206
|
+
const { isActive = false } = quotasInfo?.[tokenAddress] || {};
|
|
207
|
+
const quota = quotas[tokenAddress];
|
|
208
|
+
const quotaBalance = isActive ? quota?.balance || 0n : 0n;
|
|
209
|
+
const quotaMoney = import__.PriceUtils.calcTotalPrice(
|
|
210
|
+
underlyingPrice,
|
|
211
|
+
quotaBalance,
|
|
212
|
+
underlyingDecimals
|
|
213
|
+
);
|
|
214
|
+
const money = quota ? import__.BigIntMath.min(quotaMoney, tokenLtMoney) : tokenLtMoney;
|
|
215
|
+
return acc + money;
|
|
216
|
+
},
|
|
217
|
+
0n
|
|
218
|
+
);
|
|
219
|
+
const borrowedMoney = import__.PriceUtils.calcTotalPrice(
|
|
220
|
+
underlyingPrice || import__.PRICE_DECIMALS,
|
|
221
|
+
debt,
|
|
222
|
+
underlyingDecimals
|
|
223
|
+
);
|
|
224
|
+
const hfInPercent = borrowedMoney > 0n ? assetMoney * import__.PERCENTAGE_FACTOR / borrowedMoney : 0n;
|
|
225
|
+
return Number(hfInPercent);
|
|
226
|
+
}
|
|
227
|
+
static roundUpQuota(quotaChange) {
|
|
228
|
+
return quotaChange !== import__.MIN_INT96 ? quotaChange / import__.PERCENTAGE_FACTOR * import__.PERCENTAGE_FACTOR : quotaChange;
|
|
229
|
+
}
|
|
230
|
+
static calcRecommendedQuota({
|
|
231
|
+
amount,
|
|
232
|
+
debt,
|
|
233
|
+
lt,
|
|
234
|
+
quotaReserve
|
|
235
|
+
}) {
|
|
236
|
+
const recommendedBaseQuota = import__.BigIntMath.min(
|
|
237
|
+
debt,
|
|
238
|
+
amount * lt / import__.PERCENTAGE_FACTOR
|
|
239
|
+
);
|
|
240
|
+
const recommendedQuota = recommendedBaseQuota * (import__.PERCENTAGE_FACTOR + quotaReserve) / import__.PERCENTAGE_FACTOR;
|
|
241
|
+
return CreditAccountDataUtils.roundUpQuota(recommendedQuota);
|
|
242
|
+
}
|
|
243
|
+
static calcDefaultQuota({ amount, lt, quotaReserve }) {
|
|
244
|
+
const recommendedBaseQuota = amount * lt / import__.PERCENTAGE_FACTOR;
|
|
245
|
+
const recommendedQuota = recommendedBaseQuota * (import__.PERCENTAGE_FACTOR + quotaReserve) / import__.PERCENTAGE_FACTOR;
|
|
246
|
+
return CreditAccountDataUtils.roundUpQuota(recommendedQuota);
|
|
247
|
+
}
|
|
248
|
+
static calcQuotaUpdate(props) {
|
|
249
|
+
const { quotas, initialQuotas, maxDebt, allowedToSpend, allowedToObtain } = props;
|
|
250
|
+
const quotaDecrease = Object.keys(allowedToSpend).reduce((acc, token) => {
|
|
251
|
+
const ch = CreditAccountDataUtils.getSingleQuotaChange(
|
|
252
|
+
token,
|
|
253
|
+
0n,
|
|
254
|
+
props
|
|
255
|
+
);
|
|
256
|
+
if (ch && ch.balance < 0) acc[ch.token] = ch;
|
|
257
|
+
return acc;
|
|
258
|
+
}, {});
|
|
259
|
+
const quotaCap = CreditAccountDataUtils.roundUpQuota(maxDebt * 2n);
|
|
260
|
+
const quotaBought = Object.values(initialQuotas).reduce(
|
|
261
|
+
(sum, q) => sum + CreditAccountDataUtils.roundUpQuota(q?.quota || 0n),
|
|
262
|
+
0n
|
|
263
|
+
);
|
|
264
|
+
const quotaReduced = Object.values(quotaDecrease).reduce((sum, q) => {
|
|
265
|
+
const quotaBalance = q.balance || 0n;
|
|
266
|
+
const safeBalance = quotaBalance === import__.MIN_INT96 ? import__.BigIntMath.neg(
|
|
267
|
+
CreditAccountDataUtils.roundUpQuota(
|
|
268
|
+
initialQuotas[q.token]?.quota || 0n
|
|
269
|
+
)
|
|
270
|
+
) : quotaBalance;
|
|
271
|
+
return sum + safeBalance;
|
|
272
|
+
}, 0n);
|
|
273
|
+
const maxQuotaIncrease = CreditAccountDataUtils.roundUpQuota(
|
|
274
|
+
import__.BigIntMath.max(quotaCap - (quotaBought + quotaReduced), 0n)
|
|
275
|
+
);
|
|
276
|
+
const quotaIncrease = Object.keys(allowedToObtain).reduce((acc, token) => {
|
|
277
|
+
const ch = CreditAccountDataUtils.getSingleQuotaChange(
|
|
278
|
+
token,
|
|
279
|
+
maxQuotaIncrease,
|
|
280
|
+
props
|
|
281
|
+
);
|
|
282
|
+
if (ch && ch.balance > 0) acc[ch.token] = ch;
|
|
283
|
+
return acc;
|
|
284
|
+
}, {});
|
|
285
|
+
const quotaChange = {
|
|
286
|
+
...quotaDecrease,
|
|
287
|
+
...quotaIncrease
|
|
288
|
+
};
|
|
289
|
+
const desiredQuota = Object.values(quotas).reduce(
|
|
290
|
+
(acc, cmQuota) => {
|
|
291
|
+
const { token, isActive } = cmQuota;
|
|
292
|
+
const { quota: initialQuota = 0n } = initialQuotas[token] || {};
|
|
293
|
+
if (!isActive) {
|
|
294
|
+
acc[token] = {
|
|
295
|
+
balance: initialQuota,
|
|
296
|
+
token
|
|
297
|
+
};
|
|
298
|
+
} else {
|
|
299
|
+
const change = quotaChange[token]?.balance || 0n;
|
|
300
|
+
const quotaAfter = change === import__.MIN_INT96 ? 0n : initialQuota + change;
|
|
301
|
+
acc[token] = {
|
|
302
|
+
balance: quotaAfter,
|
|
303
|
+
token
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
return acc;
|
|
307
|
+
},
|
|
308
|
+
{}
|
|
309
|
+
);
|
|
310
|
+
return {
|
|
311
|
+
desiredQuota,
|
|
312
|
+
quotaDecrease: Object.values(quotaDecrease),
|
|
313
|
+
quotaIncrease: Object.values(quotaIncrease)
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
static getSingleQuotaChange(token, unsafeMaxQuotaIncrease, props) {
|
|
317
|
+
const { isActive = false } = props.quotas[token] || {};
|
|
318
|
+
const { quota: unsafeInitialQuota = 0n } = props.initialQuotas[token] || {};
|
|
319
|
+
if (!isActive) {
|
|
320
|
+
return void 0;
|
|
321
|
+
}
|
|
322
|
+
const assetAfter = props.assetsAfterUpdate[token];
|
|
323
|
+
const { amountInTarget = 0n } = assetAfter || {};
|
|
324
|
+
const lt = props.liquidationThresholds[token] || 0n;
|
|
325
|
+
const maxQuotaIncrease = CreditAccountDataUtils.roundUpQuota(
|
|
326
|
+
unsafeMaxQuotaIncrease
|
|
327
|
+
);
|
|
328
|
+
const initialQuota = CreditAccountDataUtils.roundUpQuota(unsafeInitialQuota);
|
|
329
|
+
const defaultQuota = props.calcModification?.type === "recommendedQuota" && props.calcModification.debt > 0 ? CreditAccountDataUtils.calcRecommendedQuota({
|
|
330
|
+
lt,
|
|
331
|
+
quotaReserve: props.quotaReserve,
|
|
332
|
+
amount: amountInTarget,
|
|
333
|
+
debt: props.calcModification.debt
|
|
334
|
+
}) : CreditAccountDataUtils.calcDefaultQuota({
|
|
335
|
+
lt,
|
|
336
|
+
quotaReserve: props.quotaReserve,
|
|
337
|
+
amount: amountInTarget
|
|
338
|
+
});
|
|
339
|
+
const unsafeQuotaChange = CreditAccountDataUtils.roundUpQuota(
|
|
340
|
+
defaultQuota - initialQuota
|
|
341
|
+
);
|
|
342
|
+
const quotaChange = unsafeQuotaChange > 0 ? import__.BigIntMath.min(maxQuotaIncrease, unsafeQuotaChange) : unsafeQuotaChange < 0 && import__.BigIntMath.abs(unsafeQuotaChange) >= initialQuota ? import__.MIN_INT96 : unsafeQuotaChange;
|
|
343
|
+
const correctIncrease = assetAfter && props.allowedToObtain[token] && quotaChange > 0;
|
|
344
|
+
const correctDecrease = assetAfter && props.allowedToSpend[token] && quotaChange < 0;
|
|
345
|
+
if (correctIncrease || correctDecrease) {
|
|
346
|
+
return {
|
|
347
|
+
balance: quotaChange,
|
|
348
|
+
token
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
return void 0;
|
|
352
|
+
}
|
|
353
|
+
static calcQuotaBorrowRate({ quotas, quotaRates }) {
|
|
354
|
+
const totalRateBalance = Object.values(quotas).reduce(
|
|
355
|
+
(acc, { token, balance }) => {
|
|
356
|
+
const { rate = 0, isActive = false } = quotaRates?.[token] || {};
|
|
357
|
+
const quotaBalance = isActive ? balance : 0n;
|
|
358
|
+
const rateBalance = quotaBalance * BigInt(rate);
|
|
359
|
+
return acc + rateBalance;
|
|
360
|
+
},
|
|
361
|
+
0n
|
|
362
|
+
);
|
|
363
|
+
return totalRateBalance;
|
|
364
|
+
}
|
|
365
|
+
static calcRelativeBaseBorrowRate({
|
|
366
|
+
debt,
|
|
367
|
+
baseRateWithFee,
|
|
368
|
+
assetAmountInUnderlying
|
|
369
|
+
}) {
|
|
370
|
+
return debt * BigInt(baseRateWithFee) * assetAmountInUnderlying;
|
|
371
|
+
}
|
|
372
|
+
static liquidationPrice({
|
|
373
|
+
liquidationThresholds,
|
|
374
|
+
debt,
|
|
375
|
+
underlyingToken,
|
|
376
|
+
targetToken,
|
|
377
|
+
assets,
|
|
378
|
+
tokensList
|
|
379
|
+
}) {
|
|
380
|
+
const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
|
|
381
|
+
const { balance: underlyingBalance = 0n } = assets[underlyingToken] || {};
|
|
382
|
+
const ltUnderlying = liquidationThresholds[underlyingToken] || 0n;
|
|
383
|
+
const effectiveDebt = (debt - underlyingBalance * ltUnderlying / import__.PERCENTAGE_FACTOR) * import__.WAD / 10n ** BigInt(underlyingDecimals);
|
|
384
|
+
const targetDecimals = tokensList[targetToken]?.decimals || 18;
|
|
385
|
+
const { balance: targetBalance = 0n } = assets[targetToken] || {};
|
|
386
|
+
const effectiveTargetBalance = targetBalance * import__.WAD / 10n ** BigInt(targetDecimals);
|
|
387
|
+
const lpLT = liquidationThresholds[targetToken] || 0n;
|
|
388
|
+
if (targetBalance <= 0n || lpLT <= 0n) return 0n;
|
|
389
|
+
return effectiveDebt * import__.PRICE_DECIMALS * import__.PERCENTAGE_FACTOR / (effectiveTargetBalance * lpLT);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Calculates the time remaining until liquidation for a credit account.
|
|
393
|
+
* @returns The time remaining until liquidation in milliseconds.
|
|
394
|
+
*/
|
|
395
|
+
static getTimeToLiquidation({
|
|
396
|
+
healthFactor,
|
|
397
|
+
totalBorrowRate_debt
|
|
398
|
+
}) {
|
|
399
|
+
if (healthFactor <= import__.PERCENTAGE_FACTOR || totalBorrowRate_debt === 0n)
|
|
400
|
+
return null;
|
|
401
|
+
const HF_1 = BigInt(healthFactor) - import__.PERCENTAGE_FACTOR;
|
|
402
|
+
const brPerYear = BigInt(import__.SECONDS_PER_YEAR) * import__.PERCENTAGE_FACTOR * import__.PERCENTAGE_DECIMALS / totalBorrowRate_debt;
|
|
403
|
+
return HF_1 * brPerYear * 1000n / import__.PERCENTAGE_FACTOR;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
407
|
+
0 && (module.exports = {
|
|
408
|
+
CreditAccountDataUtils
|
|
409
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var endpoints_exports = {};
|
|
20
|
+
__export(endpoints_exports, {
|
|
21
|
+
GearboxBackendApi: () => GearboxBackendApi,
|
|
22
|
+
URLApi: () => URLApi
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(endpoints_exports);
|
|
25
|
+
var import__ = require("../index.js");
|
|
26
|
+
const CHARTS_BACKEND_ADDRESS = "https://charts-server.fly.dev";
|
|
27
|
+
const STATIC_TOKEN = "https://static.gearbox.finance/tokens/";
|
|
28
|
+
class GearboxBackendApi {
|
|
29
|
+
constructor() {
|
|
30
|
+
}
|
|
31
|
+
static getChartsUrl = (url, chainId, options = { params: {} }, priceSource) => {
|
|
32
|
+
const domain = CHARTS_BACKEND_ADDRESS;
|
|
33
|
+
const priceSourceArr = priceSource ? [priceSource] : [];
|
|
34
|
+
const isMain = (0, import__.isSupportedNetwork)(chainId);
|
|
35
|
+
const relativePath = URLApi.getRelativeUrl(
|
|
36
|
+
url,
|
|
37
|
+
isMain ? {
|
|
38
|
+
...options,
|
|
39
|
+
params: { ...options.params, chainId }
|
|
40
|
+
} : options
|
|
41
|
+
);
|
|
42
|
+
return [domain, "api", ...priceSourceArr, relativePath].join("/");
|
|
43
|
+
};
|
|
44
|
+
static getStaticTokenUrl = () => STATIC_TOKEN;
|
|
45
|
+
static getRewardsMerkleUrl = (network, root, account) => {
|
|
46
|
+
const path = `${network}_${root.slice(2)}/${account.slice(2, 4)}`;
|
|
47
|
+
const url = `https://am.gearbox.finance/${path.toLowerCase()}.json`;
|
|
48
|
+
return url;
|
|
49
|
+
};
|
|
50
|
+
static getNFTMerkleUrl = (network, root) => {
|
|
51
|
+
const url = `https://dm.gearbox.finance/${network.toLowerCase()}_${root}.json`;
|
|
52
|
+
return url;
|
|
53
|
+
};
|
|
54
|
+
static apyAllRewards = () => URLApi.getRelativeUrl(
|
|
55
|
+
"https://state-cache.gearbox.foundation/apy-server/latest.json"
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
class URLApi {
|
|
59
|
+
constructor() {
|
|
60
|
+
}
|
|
61
|
+
static getRelativeUrl = (url, options) => {
|
|
62
|
+
const { params = {} } = options || {};
|
|
63
|
+
const paramsString = Object.entries(params).map(([key, value]) => `${key}=${value}`).join("&");
|
|
64
|
+
return [url, ...paramsString ? [paramsString] : []].join("?");
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
68
|
+
0 && (module.exports = {
|
|
69
|
+
GearboxBackendApi,
|
|
70
|
+
URLApi
|
|
71
|
+
});
|