@evaafi/sdk 0.6.0-a → 0.6.1
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/api/liquidation.d.ts +136 -0
- package/dist/api/liquidation.js +252 -0
- package/dist/api/math.d.ts +34 -7
- package/dist/api/math.js +94 -30
- package/dist/constants/assets.d.ts +12 -0
- package/dist/constants/assets.js +25 -13
- package/dist/constants/general.d.ts +3 -0
- package/dist/constants/general.js +5 -1
- package/dist/constants/pools.js +1 -1
- package/dist/contracts/MasterContract.d.ts +5 -1
- package/dist/contracts/MasterContract.js +15 -9
- package/dist/contracts/UserContract.d.ts +1 -0
- package/dist/contracts/UserContract.js +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +20 -2
- package/dist/types/Master.d.ts +3 -0
- package/dist/types/User.d.ts +7 -0
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.js +6 -1
- package/package.json +2 -1
- package/src/api/liquidation.ts +346 -0
- package/src/api/math.ts +166 -75
- package/src/constants/assets.ts +26 -12
- package/src/constants/general.ts +7 -1
- package/src/constants/pools.ts +1 -1
- package/src/contracts/MasterContract.ts +18 -11
- package/src/contracts/UserContract.ts +1 -0
- package/src/index.ts +30 -6
- package/src/types/Master.ts +4 -1
- package/src/types/User.ts +8 -0
- package/src/utils/utils.ts +4 -0
package/src/api/math.ts
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AgregatedBalances,
|
|
3
|
+
AssetConfig,
|
|
4
|
+
AssetData,
|
|
5
|
+
AssetInterest,
|
|
6
|
+
ExtendedAssetData,
|
|
7
|
+
ExtendedAssetsConfig,
|
|
8
|
+
ExtendedAssetsData,
|
|
9
|
+
MasterConstants,
|
|
10
|
+
PoolConfig
|
|
11
|
+
} from '../types/Master';
|
|
2
12
|
import { Dictionary } from '@ton/core';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
13
|
+
import {
|
|
14
|
+
BalanceChangeType,
|
|
15
|
+
BalanceType,
|
|
16
|
+
HealthParamsArgs,
|
|
17
|
+
LiquidationData,
|
|
18
|
+
PredictHealthFactorArgs,
|
|
19
|
+
UserBalance
|
|
20
|
+
} from '../types/User';
|
|
21
|
+
import { UNDEFINED_ASSET } from '../constants/assets';
|
|
22
|
+
import { addReserve, isBadDebt } from './liquidation';
|
|
7
23
|
|
|
8
24
|
export function mulFactor(decimal: bigint, a: bigint, b: bigint): bigint {
|
|
9
25
|
return (a * b) / decimal;
|
|
@@ -19,13 +35,20 @@ export function mulDivC(x: bigint, y: bigint, z: bigint): bigint {
|
|
|
19
35
|
return BigInt(Math.ceil(Number(x * y) / Number(z)));
|
|
20
36
|
}
|
|
21
37
|
|
|
38
|
+
export function bigAbs(value: bigint) {
|
|
39
|
+
return value > 0n ? value : -value;
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
export function bigIntMax(...args: bigint[]): bigint {
|
|
23
43
|
return args.reduce((m, e) => (e > m ? e : m));
|
|
24
44
|
}
|
|
45
|
+
|
|
25
46
|
export function bigIntMin(...args: bigint[]): bigint {
|
|
26
47
|
return args.reduce((m, e) => (e < m ? e : m));
|
|
27
48
|
}
|
|
28
49
|
|
|
50
|
+
export const BigMath = { mulFactor, mulDiv, mulDivC, abs: bigAbs, min: bigIntMin, max: bigIntMax };
|
|
51
|
+
|
|
29
52
|
export function calculatePresentValue(index: bigint, principalValue: bigint, masterConstants: MasterConstants): bigint {
|
|
30
53
|
return (principalValue * index) / masterConstants.FACTOR_SCALE;
|
|
31
54
|
}
|
|
@@ -45,7 +68,7 @@ export function calculateCurrentRates(assetConfig: AssetConfig, assetData: Asset
|
|
|
45
68
|
bRate: updatedBRate,
|
|
46
69
|
supplyInterest,
|
|
47
70
|
borrowInterest,
|
|
48
|
-
now
|
|
71
|
+
now
|
|
49
72
|
};
|
|
50
73
|
}
|
|
51
74
|
|
|
@@ -54,7 +77,7 @@ export function calculateCurrentRates(assetConfig: AssetConfig, assetData: Asset
|
|
|
54
77
|
bRate: assetData.bRate,
|
|
55
78
|
supplyInterest,
|
|
56
79
|
borrowInterest,
|
|
57
|
-
now
|
|
80
|
+
now
|
|
58
81
|
};
|
|
59
82
|
}
|
|
60
83
|
|
|
@@ -82,7 +105,7 @@ export function calculateAssetData(
|
|
|
82
105
|
return {
|
|
83
106
|
...data,
|
|
84
107
|
...{ supplyInterest, borrowInterest },
|
|
85
|
-
...{ supplyApy, borrowApy }
|
|
108
|
+
...{ supplyApy, borrowApy }
|
|
86
109
|
};
|
|
87
110
|
}
|
|
88
111
|
|
|
@@ -108,19 +131,19 @@ export function calculateAssetInterest(assetConfig: AssetConfig, assetData: Asse
|
|
|
108
131
|
mulFactor(
|
|
109
132
|
masterConstants.FACTOR_SCALE,
|
|
110
133
|
assetConfig.borrowRateSlopeHigh,
|
|
111
|
-
utilization - assetConfig.targetUtilization
|
|
134
|
+
utilization - assetConfig.targetUtilization
|
|
112
135
|
);
|
|
113
136
|
}
|
|
114
137
|
|
|
115
138
|
supplyInterest = mulDiv(
|
|
116
139
|
mulDiv(borrowInterest, utilization, masterConstants.FACTOR_SCALE),
|
|
117
140
|
masterConstants.ASSET_RESERVE_FACTOR_SCALE - assetConfig.reserveFactor,
|
|
118
|
-
masterConstants.ASSET_RESERVE_FACTOR_SCALE
|
|
141
|
+
masterConstants.ASSET_RESERVE_FACTOR_SCALE
|
|
119
142
|
);
|
|
120
143
|
|
|
121
144
|
return {
|
|
122
145
|
supplyInterest,
|
|
123
|
-
borrowInterest
|
|
146
|
+
borrowInterest
|
|
124
147
|
};
|
|
125
148
|
}
|
|
126
149
|
|
|
@@ -128,37 +151,36 @@ export function checkNotInDebtAtAll(principals: Dictionary<bigint, bigint>): boo
|
|
|
128
151
|
return principals.values().every(x => x >= 0n);
|
|
129
152
|
}
|
|
130
153
|
|
|
131
|
-
export function getAgregatedBalances
|
|
154
|
+
export function getAgregatedBalances(
|
|
132
155
|
assetsData: ExtendedAssetsData,
|
|
133
156
|
assetsConfig: ExtendedAssetsConfig,
|
|
134
157
|
principals: Dictionary<bigint, bigint>,
|
|
135
158
|
prices: Dictionary<bigint, bigint>,
|
|
136
|
-
masterConstants: MasterConstants
|
|
137
|
-
|
|
159
|
+
masterConstants: MasterConstants
|
|
160
|
+
): AgregatedBalances {
|
|
138
161
|
let user_total_supply = 0n;
|
|
139
162
|
let user_total_borrow = 0n;
|
|
140
|
-
|
|
141
|
-
for (const [assetId, principal] of principals) {
|
|
142
163
|
|
|
164
|
+
for (const [assetId, principal] of principals) {
|
|
143
165
|
if (principal) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
166
|
+
|
|
167
|
+
if (!prices.has(assetId)) {
|
|
168
|
+
return { totalSupply: 0n, totalBorrow: 0n };
|
|
169
|
+
}
|
|
170
|
+
const price = prices.get(assetId)!;
|
|
171
|
+
const assetData = assetsData.get(assetId)!;
|
|
172
|
+
const assetConfig = assetsConfig.get(assetId)!;
|
|
173
|
+
// console.log('price', price);
|
|
174
|
+
if (principal < 0) {
|
|
175
|
+
user_total_borrow += presentValue(assetData.sRate, assetData.bRate, principal, masterConstants).amount * price / 10n ** assetConfig.decimals;
|
|
176
|
+
} else {
|
|
177
|
+
user_total_supply += presentValue(assetData.sRate, assetData.bRate, principal, masterConstants).amount * price / 10n ** assetConfig.decimals;
|
|
178
|
+
}
|
|
179
|
+
// console.log('aggregated', assetId, presentValue(assetData.sRate, assetData.bRate, principal, masterConstants).type, presentValue(assetData.sRate, assetData.bRate, principal, masterConstants).amount * price / 10n ** assetConfig.decimals)
|
|
156
180
|
}
|
|
157
|
-
// console.log('aggregated', assetId, presentValue(assetData.sRate, assetData.bRate, principal, masterConstants).type, presentValue(assetData.sRate, assetData.bRate, principal, masterConstants).amount * price / 10n ** assetConfig.decimals)
|
|
158
|
-
}
|
|
159
181
|
}
|
|
160
|
-
return {totalSupply: user_total_supply, totalBorrow: user_total_borrow};
|
|
161
|
-
|
|
182
|
+
return { totalSupply: user_total_supply, totalBorrow: user_total_borrow };
|
|
183
|
+
}
|
|
162
184
|
|
|
163
185
|
export function calculateMaximumWithdrawAmount(
|
|
164
186
|
assetsConfig: ExtendedAssetsConfig,
|
|
@@ -166,7 +188,7 @@ export function calculateMaximumWithdrawAmount(
|
|
|
166
188
|
principals: Dictionary<bigint, bigint>,
|
|
167
189
|
prices: Dictionary<bigint, bigint>,
|
|
168
190
|
masterConstants: MasterConstants,
|
|
169
|
-
assetId: bigint
|
|
191
|
+
assetId: bigint
|
|
170
192
|
): bigint {
|
|
171
193
|
let withdrawAmountMax = 0n;
|
|
172
194
|
|
|
@@ -176,8 +198,8 @@ export function calculateMaximumWithdrawAmount(
|
|
|
176
198
|
|
|
177
199
|
if (oldPrincipal > assetConfig.dust) {
|
|
178
200
|
const oldPresentValue = presentValue(assetData.sRate, assetData.bRate, oldPrincipal, masterConstants);
|
|
179
|
-
if(checkNotInDebtAtAll(principals)) {
|
|
180
|
-
withdrawAmountMax = oldPresentValue.amount;
|
|
201
|
+
if (checkNotInDebtAtAll(principals)) {
|
|
202
|
+
withdrawAmountMax = oldPresentValue.amount;
|
|
181
203
|
} else {
|
|
182
204
|
if (!prices.has(assetId)) {
|
|
183
205
|
return 0n;
|
|
@@ -190,17 +212,16 @@ export function calculateMaximumWithdrawAmount(
|
|
|
190
212
|
|
|
191
213
|
if (assetConfig.collateralFactor == 0n) {
|
|
192
214
|
maxAmountToReclaim = oldPresentValue.amount;
|
|
193
|
-
}
|
|
194
|
-
else if (price > 0) {
|
|
215
|
+
} else if (price > 0) {
|
|
195
216
|
maxAmountToReclaim =
|
|
196
|
-
bigIntMax(0n,
|
|
217
|
+
bigIntMax(0n,
|
|
197
218
|
mulDiv(
|
|
198
219
|
mulDiv(borrowable, masterConstants.ASSET_COEFFICIENT_SCALE, assetConfig.collateralFactor),
|
|
199
220
|
10n ** assetConfig.decimals, price)
|
|
200
221
|
- calculatePresentValue(assetData.sRate, assetConfig.dust, masterConstants) / 2n
|
|
201
222
|
);
|
|
202
223
|
}
|
|
203
|
-
|
|
224
|
+
|
|
204
225
|
withdrawAmountMax = bigIntMin(
|
|
205
226
|
maxAmountToReclaim,
|
|
206
227
|
oldPresentValue.amount
|
|
@@ -235,9 +256,9 @@ export function getAvailableToBorrow(
|
|
|
235
256
|
const price = prices.get(assetID) as bigint;
|
|
236
257
|
const principal = principals.get(assetID) as bigint;
|
|
237
258
|
|
|
238
|
-
if (principal <
|
|
259
|
+
if (principal < 0n) {
|
|
239
260
|
borrowAmount += mulDiv(calculatePresentValue(assetData.bRate, -principal, masterConstants), price, 10n ** assetConfig.decimals);
|
|
240
|
-
} else if (principal >
|
|
261
|
+
} else if (principal > 0n) {
|
|
241
262
|
borrowLimit +=
|
|
242
263
|
mulDiv(
|
|
243
264
|
mulDiv(calculatePresentValue(assetData.sRate, principal, masterConstants), price, 10n ** assetConfig.decimals),
|
|
@@ -249,32 +270,96 @@ export function getAvailableToBorrow(
|
|
|
249
270
|
return borrowLimit - borrowAmount;
|
|
250
271
|
}
|
|
251
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Calculates balance value for asset principal.
|
|
275
|
+
* @param sRate asset supply rate
|
|
276
|
+
* @param bRate asset borrow rate
|
|
277
|
+
* @param principalValue asset principal value
|
|
278
|
+
* @param masterConstants pool constants
|
|
279
|
+
*/
|
|
252
280
|
export function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint, masterConstants: MasterConstants): UserBalance {
|
|
253
281
|
if (principalValue > 0) {
|
|
254
282
|
return {
|
|
255
283
|
amount: calculatePresentValue(sRate, principalValue, masterConstants),
|
|
256
|
-
type: BalanceType.supply
|
|
284
|
+
type: BalanceType.supply
|
|
257
285
|
};
|
|
258
286
|
} else if (principalValue < 0) {
|
|
259
287
|
return {
|
|
260
288
|
amount: calculatePresentValue(bRate, -principalValue, masterConstants),
|
|
261
|
-
type: BalanceType.borrow
|
|
289
|
+
type: BalanceType.borrow
|
|
262
290
|
};
|
|
263
291
|
} else {
|
|
264
292
|
return {
|
|
265
293
|
amount: 0n,
|
|
266
|
-
type: undefined
|
|
294
|
+
type: undefined
|
|
267
295
|
};
|
|
268
296
|
}
|
|
269
297
|
}
|
|
270
298
|
|
|
271
299
|
/**
|
|
272
|
-
*
|
|
273
|
-
* @param
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
300
|
+
* Calculates health parameters of the specified user account based on its parameters
|
|
301
|
+
* @param parameters
|
|
302
|
+
*/
|
|
303
|
+
export function calculateHealthParams(parameters: HealthParamsArgs) {
|
|
304
|
+
const {
|
|
305
|
+
principals, prices,
|
|
306
|
+
assetsData, assetsConfig,
|
|
307
|
+
poolConfig
|
|
308
|
+
} = parameters;
|
|
309
|
+
|
|
310
|
+
const { ASSET_LIQUIDATION_THRESHOLD_SCALE } = poolConfig.masterConstants;
|
|
311
|
+
|
|
312
|
+
let totalSupply = 0n;
|
|
313
|
+
let totalDebt = 0n;
|
|
314
|
+
let totalLimit = 0n;
|
|
315
|
+
|
|
316
|
+
for (const asset of poolConfig.poolAssetsConfig) {
|
|
317
|
+
if (!principals.has(asset.assetId)) continue;
|
|
318
|
+
const assetPrincipal = principals.get(asset.assetId)!;
|
|
319
|
+
|
|
320
|
+
if (!assetsConfig.has(asset.assetId)) throw (`No config for ${asset.name}:${asset.assetId}`);
|
|
321
|
+
const assetConfig = assetsConfig.get(asset.assetId)!;
|
|
322
|
+
|
|
323
|
+
if (!assetsData.has(asset.assetId)) throw (`No data for asset ${asset.name}:${asset.assetId}`);
|
|
324
|
+
const assetData = assetsData.get(asset.assetId)!;
|
|
325
|
+
|
|
326
|
+
if (!prices.has(asset.assetId)) throw (`No price for asset ${asset.name}:${asset.assetId}`);
|
|
327
|
+
const assetPrice = prices.get(asset.assetId)! as bigint;
|
|
328
|
+
const assetScale = 10n ** assetConfig.decimals;
|
|
329
|
+
|
|
330
|
+
const { sRate, bRate } = assetData;
|
|
331
|
+
const assetBalance = presentValue(sRate, bRate, assetPrincipal, poolConfig.masterConstants);
|
|
332
|
+
const assetWorth = assetBalance.amount * assetPrice / assetScale;
|
|
333
|
+
if (assetBalance.type === BalanceType.supply) {
|
|
334
|
+
totalSupply += assetWorth;
|
|
335
|
+
totalLimit += assetWorth * assetConfig.liquidationThreshold / ASSET_LIQUIDATION_THRESHOLD_SCALE;
|
|
336
|
+
} else if (assetBalance.type === BalanceType.borrow) {
|
|
337
|
+
totalDebt += assetWorth;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const _isLiquidable = totalLimit < totalDebt;
|
|
342
|
+
|
|
343
|
+
// the `bad debt` condition depends on certain asset's liquidation bonus parameter
|
|
344
|
+
// , so it is not a user constant, but depends on certain asset
|
|
345
|
+
const _isBadDebt = (liquidationBonus: bigint): boolean => {
|
|
346
|
+
return isBadDebt(totalSupply, totalDebt, liquidationBonus, poolConfig.masterConstants) as boolean;
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
totalDebt, totalLimit, totalSupply,
|
|
351
|
+
isLiquidatable: _isLiquidable,
|
|
352
|
+
isBadDebt: _isBadDebt
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Calculates liquidation data for greatest loan and collateral assets
|
|
358
|
+
* @param assetsConfig assets config dictionary
|
|
359
|
+
* @param assetsData assets data dictionary
|
|
360
|
+
* @param principals principals dictionary
|
|
361
|
+
* @param prices prices dictionary
|
|
362
|
+
* @param poolConfig pool config
|
|
278
363
|
* @returns can return UNDEFINED_ASSET if there are no assets
|
|
279
364
|
*/
|
|
280
365
|
export function calculateLiquidationData(
|
|
@@ -282,7 +367,7 @@ export function calculateLiquidationData(
|
|
|
282
367
|
assetsData: ExtendedAssetsData,
|
|
283
368
|
principals: Dictionary<bigint, bigint>,
|
|
284
369
|
prices: Dictionary<bigint, bigint>,
|
|
285
|
-
poolConfig: PoolConfig
|
|
370
|
+
poolConfig: PoolConfig
|
|
286
371
|
): LiquidationData {
|
|
287
372
|
let collateralValue = 0n;
|
|
288
373
|
let collateralAsset = UNDEFINED_ASSET;
|
|
@@ -291,25 +376,31 @@ export function calculateLiquidationData(
|
|
|
291
376
|
let totalDebt = 0n;
|
|
292
377
|
let totalLimit = 0n;
|
|
293
378
|
|
|
379
|
+
const {
|
|
380
|
+
ASSET_SRATE_SCALE, ASSET_BRATE_SCALE,
|
|
381
|
+
COLLATERAL_WORTH_THRESHOLD
|
|
382
|
+
} = poolConfig.masterConstants;
|
|
383
|
+
|
|
294
384
|
for (const asset of poolConfig.poolAssetsConfig) {
|
|
295
|
-
if (!principals.has(asset.assetId)) {
|
|
296
|
-
continue;
|
|
297
|
-
}
|
|
298
385
|
const principal = principals.get(asset.assetId)!;
|
|
386
|
+
if (!principal) continue;
|
|
299
387
|
const assetConfig = assetsConfig.get(asset.assetId)!;
|
|
300
388
|
const assetData = assetsData.get(asset.assetId)!;
|
|
301
|
-
const balance =
|
|
302
|
-
|
|
389
|
+
const balance = principal > 0 ?
|
|
390
|
+
(principal * assetData.sRate) / ASSET_SRATE_SCALE :
|
|
391
|
+
(principal * assetData.bRate) / ASSET_BRATE_SCALE;
|
|
392
|
+
|
|
393
|
+
const assetWorth = (bigAbs(balance) * prices.get(asset.assetId)!) / 10n ** assetConfig.decimals;
|
|
303
394
|
if (balance > 0) {
|
|
304
|
-
const assetWorth = (balance * prices.get(asset.assetId)!) / 10n ** assetConfig.decimals;
|
|
305
395
|
totalLimit += (assetWorth * assetConfig.liquidationThreshold) / poolConfig.masterConstants.ASSET_COEFFICIENT_SCALE;
|
|
396
|
+
// get the greatest collateral
|
|
306
397
|
if (assetWorth > collateralValue) {
|
|
307
398
|
collateralValue = assetWorth;
|
|
308
399
|
collateralAsset = asset;
|
|
309
400
|
}
|
|
310
401
|
} else if (balance < 0) {
|
|
311
|
-
const assetWorth = (-balance * prices.get(asset.assetId)!) / 10n ** assetConfig.decimals;
|
|
312
402
|
totalDebt += assetWorth;
|
|
403
|
+
// get the greatest loan
|
|
313
404
|
if (assetWorth > loanValue) {
|
|
314
405
|
loanValue = assetWorth;
|
|
315
406
|
loanAsset = asset;
|
|
@@ -325,11 +416,11 @@ export function calculateLiquidationData(
|
|
|
325
416
|
const liquidationBonus = collateralAssetConfig.liquidationBonus;
|
|
326
417
|
const loanScale = 10n ** loanAssetConfig.decimals;
|
|
327
418
|
values.push(
|
|
328
|
-
(bigIntMax(collateralValue / 2n, bigIntMin(collateralValue,
|
|
419
|
+
(bigIntMax(collateralValue / 2n, bigIntMin(collateralValue, COLLATERAL_WORTH_THRESHOLD)) *
|
|
329
420
|
loanScale *
|
|
330
421
|
poolConfig.masterConstants.ASSET_COEFFICIENT_SCALE) /
|
|
331
|
-
|
|
332
|
-
|
|
422
|
+
liquidationBonus /
|
|
423
|
+
loanAssetPrice
|
|
333
424
|
);
|
|
334
425
|
values.push((loanValue * loanScale) / loanAssetPrice);
|
|
335
426
|
|
|
@@ -338,11 +429,11 @@ export function calculateLiquidationData(
|
|
|
338
429
|
const collateralDecimal = 10n ** collateralAssetConfig.decimals;
|
|
339
430
|
let minCollateralAmount =
|
|
340
431
|
(((liquidationAmount * loanAssetPrice * liquidationBonus) / poolConfig.masterConstants.ASSET_LIQUIDATION_BONUS_SCALE) * collateralDecimal) /
|
|
341
|
-
|
|
342
|
-
|
|
432
|
+
collateralAssetPrice /
|
|
433
|
+
loanScale -
|
|
343
434
|
10n;
|
|
344
435
|
minCollateralAmount = (minCollateralAmount * 97n) / 100n;
|
|
345
|
-
if (minCollateralAmount
|
|
436
|
+
if (minCollateralAmount > 0n) {
|
|
346
437
|
return {
|
|
347
438
|
greatestCollateralAsset: collateralAsset,
|
|
348
439
|
greatestCollateralValue: collateralValue,
|
|
@@ -351,8 +442,8 @@ export function calculateLiquidationData(
|
|
|
351
442
|
totalDebt,
|
|
352
443
|
totalLimit,
|
|
353
444
|
liquidable: true,
|
|
354
|
-
liquidationAmount,
|
|
355
|
-
minCollateralAmount
|
|
445
|
+
liquidationAmount: addReserve(liquidationAmount, loanAssetConfig.liquidationReserveFactor, poolConfig.masterConstants.ASSET_RESERVE_FACTOR_SCALE),
|
|
446
|
+
minCollateralAmount
|
|
356
447
|
};
|
|
357
448
|
}
|
|
358
449
|
}
|
|
@@ -364,29 +455,29 @@ export function calculateLiquidationData(
|
|
|
364
455
|
greatestLoanValue: loanValue,
|
|
365
456
|
totalDebt,
|
|
366
457
|
totalLimit,
|
|
367
|
-
liquidable: false
|
|
458
|
+
liquidable: false
|
|
368
459
|
};
|
|
369
460
|
}
|
|
370
461
|
|
|
371
462
|
export function predictHealthFactor(args: PredictHealthFactorArgs): number {
|
|
372
|
-
const
|
|
463
|
+
const healthParams = calculateHealthParams(args);
|
|
373
464
|
const assetId = args.asset.assetId;
|
|
374
|
-
|
|
465
|
+
|
|
375
466
|
const assetConfig = args.assetsConfig.get(assetId)!;
|
|
376
467
|
const assetPrice = Number(args.prices.get(assetId)!);
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
let totalLimit = Number(
|
|
380
|
-
let totalBorrow = Number(
|
|
468
|
+
const assetData = args.assetsData.get(assetId)!;
|
|
469
|
+
|
|
470
|
+
let totalLimit = Number(healthParams.totalLimit);
|
|
471
|
+
let totalBorrow = Number(healthParams.totalDebt);
|
|
381
472
|
|
|
382
473
|
const currentAmount = args.amount;
|
|
383
474
|
|
|
384
|
-
const decimals = Number(assetConfig.decimals)
|
|
475
|
+
const decimals = Number(assetConfig.decimals);
|
|
385
476
|
|
|
386
477
|
const currentBalance = assetPrice * Number(currentAmount) / Math.pow(10, decimals);
|
|
387
478
|
const changeType = args.balanceChangeType;
|
|
388
479
|
|
|
389
|
-
if (currentAmount != null && currentAmount != 0n) {
|
|
480
|
+
if (currentAmount != null && currentAmount != 0n) {
|
|
390
481
|
if (changeType == BalanceChangeType.Borrow) {
|
|
391
482
|
totalBorrow += currentBalance * (1 + Number(assetConfig.originationFee) / Number(args.poolConfig.masterConstants.ASSET_ORIGINATION_FEE_SCALE));
|
|
392
483
|
} else if (changeType == BalanceChangeType.Repay) {
|
package/src/constants/assets.ts
CHANGED
|
@@ -3,6 +3,19 @@ import { PoolAssetConfig } from "../types/Master";
|
|
|
3
3
|
import { sha256Hash } from "../utils/sha256BigInt";
|
|
4
4
|
import { JETTON_WALLET_STANDART_CODE, JETTON_WALLET_STANDART_CODE_TESTNET, NULL_ADDRESS } from "./general";
|
|
5
5
|
|
|
6
|
+
export const ASSET_ID = {
|
|
7
|
+
TON: sha256Hash('TON'),
|
|
8
|
+
USDT: sha256Hash('USDT'),
|
|
9
|
+
jUSDT: sha256Hash('jUSDT'),
|
|
10
|
+
jUSDC: sha256Hash('jUSDC'),
|
|
11
|
+
stTON: sha256Hash('stTON'),
|
|
12
|
+
tsTON: sha256Hash('tsTON'),
|
|
13
|
+
TONUSDT_DEDUST: sha256Hash('TONUSDT_DEDUST'),
|
|
14
|
+
TONUSDT_STONFI: sha256Hash('TONUSDT_STONFI'),
|
|
15
|
+
TON_STORM: sha256Hash('TON_STORM'),
|
|
16
|
+
USDT_STORM: sha256Hash('USDT_STORM'),
|
|
17
|
+
};
|
|
18
|
+
|
|
6
19
|
export const UNDEFINED_ASSET: PoolAssetConfig = {
|
|
7
20
|
name: 'undefined_asset',
|
|
8
21
|
assetId: -1n,
|
|
@@ -12,7 +25,7 @@ export const UNDEFINED_ASSET: PoolAssetConfig = {
|
|
|
12
25
|
|
|
13
26
|
export const TON_MAINNET: PoolAssetConfig = {
|
|
14
27
|
name: 'TON',
|
|
15
|
-
assetId:
|
|
28
|
+
assetId: ASSET_ID.TON,
|
|
16
29
|
jettonMasterAddress: NULL_ADDRESS, // fake
|
|
17
30
|
jettonWalletCode: Cell.EMPTY
|
|
18
31
|
}
|
|
@@ -20,21 +33,21 @@ export const TON_TESTNET = TON_MAINNET;
|
|
|
20
33
|
|
|
21
34
|
export const JUSDT_MAINNET: PoolAssetConfig = {
|
|
22
35
|
name: 'jUSDT',
|
|
23
|
-
assetId:
|
|
36
|
+
assetId: ASSET_ID.jUSDT,
|
|
24
37
|
jettonMasterAddress: Address.parse('EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA'),
|
|
25
38
|
jettonWalletCode: JETTON_WALLET_STANDART_CODE
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
export const JUSDC_MAINNET: PoolAssetConfig = {
|
|
29
42
|
name: 'jUSDC',
|
|
30
|
-
assetId:
|
|
43
|
+
assetId: ASSET_ID.jUSDC,
|
|
31
44
|
jettonMasterAddress: Address.parse('EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728'),
|
|
32
45
|
jettonWalletCode: JETTON_WALLET_STANDART_CODE
|
|
33
46
|
}
|
|
34
47
|
|
|
35
48
|
export const STTON_MAINNET: PoolAssetConfig = {
|
|
36
49
|
name: 'stTON',
|
|
37
|
-
assetId:
|
|
50
|
+
assetId: ASSET_ID.stTON,
|
|
38
51
|
jettonMasterAddress: Address.parse('EQDNhy-nxYFgUqzfUzImBEP67JqsyMIcyk2S5_RwNNEYku0k'),
|
|
39
52
|
jettonWalletCode: Cell.fromBase64(
|
|
40
53
|
'te6cckECEgEAA2IAART/APSkE/S88sgLAQIBYgIDAgLMBAUAG6D2BdqJofQB9IH0gahhAgHUBgcCASAJCgHPCDHAJJfBOAB0NMDAXGwlRNfA/AN4PpA+kAx+gAxcdch+gAx+gAwc6m0AALTHyGCEA+KfqW6lTE0WfAK4CGCEBeNRRm6ljFERAPwC+AhghBZXwe8upUxNFnwDOAUXwTABOMCMIQP8vCAIABE+kQwwADy4U2AAfO1E0PoA+kD6QNQwECNfAwGCCJiWgKFtgBByIm6zIJFxkXDiA8jLBVAGzxZQBPoCy2oDk1jMAZEw4gHJAfsAAgFYCwwCAUgQEQHxAPTP/oA+kAh8AHtRND6APpA+kDUMFE2oVIqxwXy4sEowv/y4sJUNEJwVCATVBQDyFAE+gJYzxYBzxbMySLIywES9AD0AMsAySD5AHB0yMsCygfL/8nQBPpA9AQx+gAg10nCAPLixHeAGMjLBVAIzxZw+gIXy2sTzIA0C9ztRND6APpA+kDUMAjTP/oAUVGgBfpA+kBTW8cFVHNtcFQgE1QUA8hQBPoCWM8WAc8WzMkiyMsBEvQA9ADLAMn5AHB0yMsCygfL/8nQUA3HBRyx8uLDCvoAUaihggiYloBmtgihggjk4cCgGKEnlxBJEDg3XwTjDSXXCwGAODwCeghAXjUUZyMsfGcs/UAf6AiLPFlAGzxYl+gJQA88WyVAFzCORcpFx4lAIqBOgggpiWgCgFLzy4sUEyYBA+wAQI8hQBPoCWM8WAc8WzMntVABwUnmgGKGCEHNi0JzIyx9SMMs/WPoCUAfPFlAHzxbJcYAQyMsFJM8WUAb6AhXLahTMyXH7ABAkECMAfMMAI8IAsI4hghDVMnbbcIAQyMsFUAjPFlAE+gIWy2oSyx8Syz/JcvsAkzVsIeIDyFAE+gJYzxYBzxbMye1UAMkMO1E0PoA+kD6QNQwBtM/+gAwUUShUjfHBfLiwSXC//LiwgSCC5OHAL7y4sWCEHvdl97Iyx8Uyz9Y+gIhzxbJcYAYyMsFJM8WcPoCy2rMyYBA+wBAE8hQBPoCWM8WAc8WzMntVIACBIAg1yHtRND6APpA+kDUMATTHyGCEBeNRRm6AoIQe92X3roSsfLgyNM/MfoAMBOgUCPIUAT6AljPFgHPFszJ7VSBpMmqD'
|
|
@@ -43,7 +56,7 @@ export const STTON_MAINNET: PoolAssetConfig = {
|
|
|
43
56
|
|
|
44
57
|
export const TSTON_MAINNET: PoolAssetConfig = {
|
|
45
58
|
name: 'tsTON',
|
|
46
|
-
assetId:
|
|
59
|
+
assetId: ASSET_ID.tsTON,
|
|
47
60
|
jettonMasterAddress: Address.parse('EQC98_qAmNEptUtPc7W6xdHh_ZHrBUFpw5Ft_IzNU20QAJav'),
|
|
48
61
|
jettonWalletCode: Cell.fromBase64(
|
|
49
62
|
'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'
|
|
@@ -52,7 +65,7 @@ export const TSTON_MAINNET: PoolAssetConfig = {
|
|
|
52
65
|
|
|
53
66
|
export const USDT_MAINNET: PoolAssetConfig = {
|
|
54
67
|
name: 'USDT',
|
|
55
|
-
assetId:
|
|
68
|
+
assetId: ASSET_ID.USDT,
|
|
56
69
|
jettonMasterAddress: Address.parse('EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs'),
|
|
57
70
|
jettonWalletCode: Cell.fromBoc(
|
|
58
71
|
Buffer.from(
|
|
@@ -64,21 +77,21 @@ export const USDT_MAINNET: PoolAssetConfig = {
|
|
|
64
77
|
|
|
65
78
|
export const JUSDT_TESTNET: PoolAssetConfig = {
|
|
66
79
|
name: 'jUSDT',
|
|
67
|
-
assetId:
|
|
80
|
+
assetId: ASSET_ID.jUSDT,
|
|
68
81
|
jettonMasterAddress: Address.parse('kQBe4gtSQMxM5RpMYLr4ydNY72F8JkY-icZXG1NJcsju8XM7'),
|
|
69
82
|
jettonWalletCode: JETTON_WALLET_STANDART_CODE_TESTNET
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
export const JUSDC_TESTNET: PoolAssetConfig = {
|
|
73
86
|
name: 'jUSDC',
|
|
74
|
-
assetId:
|
|
87
|
+
assetId: ASSET_ID.jUSDC,
|
|
75
88
|
jettonMasterAddress: Address.parse('kQDaY5yUatYnHei73HBqRX_Ox9LK2XnR7XuCY9MFC2INbfYI'),
|
|
76
89
|
jettonWalletCode: JETTON_WALLET_STANDART_CODE_TESTNET
|
|
77
90
|
}
|
|
78
91
|
|
|
79
92
|
export const STTON_TESTNET: PoolAssetConfig = {
|
|
80
93
|
name: 'stTON',
|
|
81
|
-
assetId:
|
|
94
|
+
assetId: ASSET_ID.stTON,
|
|
82
95
|
jettonMasterAddress: Address.parse('kQC3Duw3dg8k98xf5S7Bm7YOWVJ5QW8hm3iLqFfJfa_g9h07'),
|
|
83
96
|
jettonWalletCode: Cell.fromBoc(
|
|
84
97
|
Buffer.from(
|
|
@@ -90,7 +103,7 @@ export const STTON_TESTNET: PoolAssetConfig = {
|
|
|
90
103
|
|
|
91
104
|
export const TONUSDT_DEDUST_MAINNET: PoolAssetConfig = {
|
|
92
105
|
name: 'TONUSDT_DEDUST',
|
|
93
|
-
assetId:
|
|
106
|
+
assetId: ASSET_ID.TONUSDT_DEDUST,
|
|
94
107
|
jettonMasterAddress: Address.parse('EQA-X_yo3fzzbDbJ_0bzFWKqtRuZFIRa1sJsveZJ1YpViO3r'),
|
|
95
108
|
jettonWalletCode: Cell.fromBoc(
|
|
96
109
|
Buffer.from(
|
|
@@ -102,7 +115,7 @@ export const TONUSDT_DEDUST_MAINNET: PoolAssetConfig = {
|
|
|
102
115
|
|
|
103
116
|
export const TON_STORM_MAINNET: PoolAssetConfig = {
|
|
104
117
|
name: 'TON_STORM',
|
|
105
|
-
assetId:
|
|
118
|
+
assetId: ASSET_ID.TON_STORM,
|
|
106
119
|
jettonMasterAddress: Address.parse('EQCNY2AQ3ZDYwJAqx_nzl9i9Xhd_Ex7izKJM6JTxXRnO6n1F'),
|
|
107
120
|
jettonWalletCode: Cell.fromBoc(
|
|
108
121
|
Buffer.from(
|
|
@@ -110,11 +123,12 @@ export const TON_STORM_MAINNET: PoolAssetConfig = {
|
|
|
110
123
|
'hex',
|
|
111
124
|
),
|
|
112
125
|
)[0],
|
|
126
|
+
|
|
113
127
|
}
|
|
114
128
|
|
|
115
129
|
export const USDT_STORM_MAINNET: PoolAssetConfig = {
|
|
116
130
|
name: 'USDT_STORM',
|
|
117
|
-
assetId:
|
|
131
|
+
assetId: ASSET_ID.USDT_STORM,
|
|
118
132
|
jettonMasterAddress: Address.parse('EQCup4xxCulCcNwmOocM9HtDYPU8xe0449tQLp6a-5BLEegW'),
|
|
119
133
|
jettonWalletCode: Cell.fromBoc(
|
|
120
134
|
Buffer.from(
|
package/src/constants/general.ts
CHANGED
|
@@ -2,15 +2,21 @@ import { Address, Cell, toNano } from '@ton/core';
|
|
|
2
2
|
import { sha256Hash } from '../utils/sha256BigInt';
|
|
3
3
|
import { OracleNFT } from '../types/Master';
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
const ASSET_PRICE_SCALE = BigInt(1e9);
|
|
7
|
+
|
|
5
8
|
export const MASTER_CONSTANTS = {
|
|
6
9
|
FACTOR_SCALE: BigInt(1e12),
|
|
7
10
|
ASSET_COEFFICIENT_SCALE: 10000n,
|
|
8
|
-
ASSET_PRICE_SCALE
|
|
11
|
+
ASSET_PRICE_SCALE,
|
|
9
12
|
ASSET_RESERVE_FACTOR_SCALE: 10000n,
|
|
10
13
|
ASSET_LIQUIDATION_RESERVE_FACTOR_SCALE: 10000n,
|
|
11
14
|
ASSET_ORIGINATION_FEE_SCALE: BigInt(1e9),
|
|
12
15
|
ASSET_LIQUIDATION_THRESHOLD_SCALE: 10_000n,
|
|
13
16
|
ASSET_LIQUIDATION_BONUS_SCALE: 10_000n,
|
|
17
|
+
ASSET_SRATE_SCALE: BigInt(1e12),
|
|
18
|
+
ASSET_BRATE_SCALE: BigInt(1e12),
|
|
19
|
+
COLLATERAL_WORTH_THRESHOLD: 100n * ASSET_PRICE_SCALE, // literally 100$
|
|
14
20
|
};
|
|
15
21
|
|
|
16
22
|
export const NULL_ADDRESS = Address.parse('UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ');
|