@evaafi/sdk 0.6.0 → 0.6.1-a

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.
@@ -18,10 +18,16 @@ class Evaa {
18
18
  */
19
19
  constructor(parameters) {
20
20
  this.lastSync = 0;
21
- this.poolConfig = parameters?.poolConfig ?? __1.MAINNET_POOL_CONFIG;
22
- this.address = this.poolConfig.masterAddress;
21
+ this._poolConfig = parameters?.poolConfig ?? __1.MAINNET_POOL_CONFIG;
22
+ this.address = this._poolConfig.masterAddress;
23
23
  this.debug = parameters?.debug;
24
24
  }
25
+ /**
26
+ * Returns pool config
27
+ */
28
+ get poolConfig() {
29
+ return this._poolConfig;
30
+ }
25
31
  /**
26
32
  * Create supply message
27
33
  * @returns supply message as a cell
@@ -101,7 +107,7 @@ class Evaa {
101
107
  // the exact amount of transferred jettons for liquidation is known
102
108
  .storeUint(0, 64)
103
109
  .storeRef((0, core_1.beginCell)()
104
- .storeUint(parameters.forwardAmount ?? 0, 64) // idk .. ) todo check
110
+ .storeUint(parameters.payloadForwardAmount ?? 0, 64)
105
111
  .storeRef(parameters.payload)
106
112
  .endCell())
107
113
  .storeRef(parameters.priceData)
@@ -119,7 +125,7 @@ class Evaa {
119
125
  .storeInt(parameters.includeUserCode ? -1 : 0, 2)
120
126
  .storeUint(parameters.liquidationAmount, 64)
121
127
  .storeRef((0, core_1.beginCell)()
122
- .storeUint(parameters.forwardAmount ?? 0, 64) // idk .. ) todo check
128
+ .storeUint(parameters.payloadForwardAmount ?? 0, 64)
123
129
  .storeRef(parameters.payload)
124
130
  .endCell())
125
131
  .storeRef(parameters.priceData)
@@ -152,7 +158,7 @@ class Evaa {
152
158
  * @returns user contract
153
159
  */
154
160
  openUserContract(userAddress) {
155
- return UserContract_1.EvaaUser.createFromAddress(this.calculateUserSCAddr(userAddress, this.poolConfig.lendingCode), this.poolConfig);
161
+ return UserContract_1.EvaaUser.createFromAddress(this.calculateUserSCAddr(userAddress, this._poolConfig.lendingCode), this._poolConfig);
156
162
  }
157
163
  getOpenedUserContract(provider, userAddress) {
158
164
  return provider.open(this.openUserContract(userAddress));
@@ -190,7 +196,7 @@ class Evaa {
190
196
  }
191
197
  async sendLiquidation(provider, via, value, parameters) {
192
198
  const message = this.createLiquidationMessage(parameters);
193
- if (!(0, __1.isTonAsset)(parameters.asset)) {
199
+ if (!(0, __1.isTonAssetId)(parameters.loanAsset)) {
194
200
  if (!via.address) {
195
201
  throw Error('Via address is required for jetton liquidation');
196
202
  }
@@ -226,9 +232,9 @@ class Evaa {
226
232
  async getSync(provider) {
227
233
  const state = (await provider.getState()).state;
228
234
  if (state.type === 'active') {
229
- this._data = (0, parser_1.parseMasterData)(state.data.toString('base64'), this.poolConfig.poolAssetsConfig, this.poolConfig.masterConstants);
230
- if (this._data.upgradeConfig.masterCodeVersion !== this.poolConfig.masterVersion) {
231
- throw Error(`Outdated SDK pool version. It supports only master code version ${this.poolConfig.masterVersion}, but the current master code version is ${this._data.upgradeConfig.masterCodeVersion}`);
235
+ this._data = (0, parser_1.parseMasterData)(state.data.toString('base64'), this._poolConfig.poolAssetsConfig, this._poolConfig.masterConstants);
236
+ if (this._data.upgradeConfig.masterCodeVersion !== this._poolConfig.masterVersion) {
237
+ throw Error(`Outdated SDK pool version. It supports only master code version ${this._poolConfig.masterVersion}, but the current master code version is ${this._data.upgradeConfig.masterCodeVersion}`);
232
238
  }
233
239
  this.lastSync = Math.floor(Date.now() / 1000);
234
240
  }
@@ -238,10 +244,10 @@ class Evaa {
238
244
  }
239
245
  async getPrices(provider, endpoints) {
240
246
  if ((endpoints?.length ?? 0) > 0) {
241
- return await (0, __1.getPrices)(endpoints, this.poolConfig);
247
+ return await (0, __1.getPrices)(endpoints, this._poolConfig);
242
248
  }
243
249
  else {
244
- return await (0, __1.getPrices)(undefined, this.poolConfig);
250
+ return await (0, __1.getPrices)(undefined, this._poolConfig);
245
251
  }
246
252
  }
247
253
  }
@@ -14,10 +14,11 @@ export declare class EvaaUser implements Contract {
14
14
  /**
15
15
  * Create user contract wrapper from address
16
16
  * @param address user contract address
17
+ * @param poolConfig pool config
17
18
  */
18
19
  static createFromAddress(address: Address, poolConfig?: PoolConfig): EvaaUser;
19
20
  private constructor();
20
- getSyncLite(provider: ContractProvider, assetsData: ExtendedAssetsData, assetsConfig: ExtendedAssetsConfig): Promise<void>;
21
+ getSyncLite(provider: ContractProvider, assetsData: ExtendedAssetsData, assetsConfig: ExtendedAssetsConfig, applyDust?: boolean): Promise<void>;
21
22
  /**
22
23
  * Calculate full user data from lite data and prices
23
24
  * @param assetsData assets data
@@ -31,7 +32,7 @@ export declare class EvaaUser implements Contract {
31
32
  * @param forwardPayload - payload that will be forwarded to the address which requested the data
32
33
  */
33
34
  sendOnchainGetter(provider: ContractProvider, via: Sender, value: bigint, queryID: bigint, forwardPayload: Cell): Promise<void>;
34
- getSync(provider: ContractProvider, assetsData: ExtendedAssetsData, assetsConfig: ExtendedAssetsConfig, prices: Dictionary<bigint, bigint>): Promise<void>;
35
+ getSync(provider: ContractProvider, assetsData: ExtendedAssetsData, assetsConfig: ExtendedAssetsConfig, prices: Dictionary<bigint, bigint>, applyDust?: boolean): Promise<void>;
35
36
  /**
36
37
  * Get user contract lite data
37
38
  * @returns user lite data if available, otherwise undefined
@@ -13,6 +13,7 @@ class EvaaUser {
13
13
  /**
14
14
  * Create user contract wrapper from address
15
15
  * @param address user contract address
16
+ * @param poolConfig pool config
16
17
  */
17
18
  static createFromAddress(address, poolConfig = pools_1.MAINNET_POOL_CONFIG) {
18
19
  return new EvaaUser(address, poolConfig);
@@ -22,10 +23,10 @@ class EvaaUser {
22
23
  this.address = address;
23
24
  this.poolConfig = poolConfig;
24
25
  }
25
- async getSyncLite(provider, assetsData, assetsConfig) {
26
+ async getSyncLite(provider, assetsData, assetsConfig, applyDust = false) {
26
27
  const state = (await provider.getState()).state;
27
28
  if (state.type === 'active') {
28
- this._liteData = (0, parser_1.parseUserLiteData)(state.data.toString('base64'), assetsData, assetsConfig, this.poolConfig);
29
+ this._liteData = (0, parser_1.parseUserLiteData)(state.data.toString('base64'), assetsData, assetsConfig, this.poolConfig, applyDust);
29
30
  this.lastSync = Math.floor(Date.now() / 1000);
30
31
  }
31
32
  else {
@@ -62,11 +63,11 @@ class EvaaUser {
62
63
  .endCell(),
63
64
  });
64
65
  }
65
- async getSync(provider, assetsData, assetsConfig, prices) {
66
+ async getSync(provider, assetsData, assetsConfig, prices, applyDust = false) {
66
67
  const state = (await provider.getState()).state;
67
68
  if (state.type === 'active') {
68
- this._liteData = (0, parser_1.parseUserLiteData)(state.data.toString('base64'), assetsData, assetsConfig, this.poolConfig);
69
- this._data = (0, parser_1.parseUserData)(this._liteData, assetsData, assetsConfig, prices, this.poolConfig);
69
+ this._liteData = (0, parser_1.parseUserLiteData)(state.data.toString('base64'), assetsData, assetsConfig, this.poolConfig, applyDust);
70
+ this._data = (0, parser_1.parseUserData)(this._liteData, assetsData, assetsConfig, prices, this.poolConfig, applyDust);
70
71
  this.lastSync = Math.floor(Date.now() / 1000);
71
72
  }
72
73
  else {
package/dist/index.d.ts CHANGED
@@ -1,15 +1,16 @@
1
- export { mulFactor, mulDiv, bigIntMin, bigIntMax, calculatePresentValue, calculateCurrentRates, calculateAssetData, calculateAssetInterest, getAvailableToBorrow, calculateMaximumWithdrawAmount, presentValue, calculateLiquidationData, predictHealthFactor } from './api/math';
1
+ export { mulFactor, mulDiv, bigIntMin, bigIntMax, calculatePresentValue, calculateCurrentRates, calculateAssetData, calculateAssetInterest, getAvailableToBorrow, calculateMaximumWithdrawAmount, presentValue, calculateLiquidationData, predictHealthFactor, calculateHealthParams, BigMath, } from './api/math';
2
+ export { calculateLiquidationAmounts, calculateMinCollateralByTransferredAmount, isLiquidatable, isBadDebt, addReserve, deductReserve, addLiquidationBonus, deductLiquidationBonus, toAssetAmount, toAssetWorth, PreparedAssetInfo, PreparedAssetInfoResult, prepareAssetInfo, findAssetById, selectGreatestAssets, calculateAssetsValues, AssetsValues, SelectedAssets, } from './api/liquidation';
2
3
  export { createAssetData, createAssetConfig, parseMasterData, parseUserData, parseUserLiteData } from './api/parser';
3
4
  export { getPrices } from './api/prices';
4
5
  export { JettonWallet } from './contracts/JettonWallet';
5
- export { EvaaParameters, WithdrawParameters, LiquidationBaseData, LiquidationParameters, Evaa, } from './contracts/MasterContract';
6
+ export { EvaaParameters, WithdrawParameters, LiquidationBaseData, LiquidationParameters, Evaa } from './contracts/MasterContract';
6
7
  export { EvaaUser } from './contracts/UserContract';
7
8
  export { PriceData } from './types/Common';
8
9
  export { UpgradeConfig, AssetConfig, MasterConfig, AssetData, AssetInterest, AssetApy, ExtendedAssetData, MasterData, PoolConfig, ExtendedAssetsData, ExtendedAssetsConfig, PoolAssetConfig, PoolAssetsConfig, MasterConstants } from './types/Master';
9
10
  export { BalanceType, UserBalance, UserLiqudationData, LiquidableData, NonLiquidableData, LiquidationData, UserDataInactive, UserDataActive, UserData, BalanceChangeType } from './types/User';
10
11
  export { EVAA_MASTER_MAINNET, MAINNET_VERSION, EVAA_MASTER_TESTNET, TESTNET_VERSION, LENDING_CODE, OPCODES, FEES, MASTER_CONSTANTS } from './constants/general';
11
- export { MAINNET_POOL_CONFIG, TESTNET_POOL_CONFIG, MAINNET_LP_POOL_CONFIG, } from './constants/pools';
12
- export { UNDEFINED_ASSET, TON_MAINNET, USDT_MAINNET, TONUSDT_DEDUST_MAINNET, TON_STORM_MAINNET, USDT_STORM_MAINNET, JUSDT_MAINNET, JUSDC_MAINNET, STTON_MAINNET, TSTON_MAINNET, JUSDT_TESTNET, JUSDC_TESTNET, STTON_TESTNET, } from './constants/assets';
12
+ export { MAINNET_POOL_CONFIG, TESTNET_POOL_CONFIG, MAINNET_LP_POOL_CONFIG } from './constants/pools';
13
+ export { ASSET_ID, UNDEFINED_ASSET, TON_MAINNET, USDT_MAINNET, TONUSDT_DEDUST_MAINNET, TON_STORM_MAINNET, USDT_STORM_MAINNET, JUSDT_MAINNET, JUSDC_MAINNET, STTON_MAINNET, TSTON_MAINNET, JUSDT_TESTNET, JUSDC_TESTNET, STTON_TESTNET } from './constants/assets';
13
14
  export * from './constants/assets';
14
15
  export * from './utils/utils';
15
16
  export { getLastSentBoc, getTonConnectSender } from './utils/tonConnectSender';
package/dist/index.js CHANGED
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.getTonConnectSender = exports.getLastSentBoc = exports.STTON_TESTNET = exports.JUSDC_TESTNET = exports.JUSDT_TESTNET = exports.TSTON_MAINNET = exports.STTON_MAINNET = exports.JUSDC_MAINNET = exports.JUSDT_MAINNET = exports.USDT_STORM_MAINNET = exports.TON_STORM_MAINNET = exports.TONUSDT_DEDUST_MAINNET = exports.USDT_MAINNET = exports.TON_MAINNET = exports.UNDEFINED_ASSET = exports.MAINNET_LP_POOL_CONFIG = exports.TESTNET_POOL_CONFIG = exports.MAINNET_POOL_CONFIG = exports.MASTER_CONSTANTS = exports.FEES = exports.OPCODES = exports.LENDING_CODE = exports.TESTNET_VERSION = exports.EVAA_MASTER_TESTNET = exports.MAINNET_VERSION = exports.EVAA_MASTER_MAINNET = exports.BalanceChangeType = exports.BalanceType = exports.EvaaUser = exports.Evaa = exports.JettonWallet = exports.getPrices = exports.parseUserLiteData = exports.parseUserData = exports.parseMasterData = exports.createAssetConfig = exports.createAssetData = exports.predictHealthFactor = exports.calculateLiquidationData = exports.presentValue = exports.calculateMaximumWithdrawAmount = exports.getAvailableToBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.bigIntMax = exports.bigIntMin = exports.mulDiv = exports.mulFactor = void 0;
18
- exports.getUserJettonWallet = void 0;
17
+ exports.TESTNET_POOL_CONFIG = exports.MAINNET_POOL_CONFIG = exports.MASTER_CONSTANTS = exports.FEES = exports.OPCODES = exports.LENDING_CODE = exports.TESTNET_VERSION = exports.EVAA_MASTER_TESTNET = exports.MAINNET_VERSION = exports.EVAA_MASTER_MAINNET = exports.BalanceChangeType = exports.BalanceType = exports.EvaaUser = exports.Evaa = exports.JettonWallet = exports.getPrices = exports.parseUserLiteData = exports.parseUserData = exports.parseMasterData = exports.createAssetConfig = exports.createAssetData = exports.calculateAssetsValues = exports.selectGreatestAssets = exports.findAssetById = exports.prepareAssetInfo = exports.toAssetWorth = exports.toAssetAmount = exports.deductLiquidationBonus = exports.addLiquidationBonus = exports.deductReserve = exports.addReserve = exports.isBadDebt = exports.isLiquidatable = exports.calculateMinCollateralByTransferredAmount = exports.calculateLiquidationAmounts = exports.BigMath = exports.calculateHealthParams = exports.predictHealthFactor = exports.calculateLiquidationData = exports.presentValue = exports.calculateMaximumWithdrawAmount = exports.getAvailableToBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.bigIntMax = exports.bigIntMin = exports.mulDiv = exports.mulFactor = void 0;
18
+ exports.getUserJettonWallet = exports.getTonConnectSender = exports.getLastSentBoc = exports.STTON_TESTNET = exports.JUSDC_TESTNET = exports.JUSDT_TESTNET = exports.TSTON_MAINNET = exports.STTON_MAINNET = exports.JUSDC_MAINNET = exports.JUSDT_MAINNET = exports.USDT_STORM_MAINNET = exports.TON_STORM_MAINNET = exports.TONUSDT_DEDUST_MAINNET = exports.USDT_MAINNET = exports.TON_MAINNET = exports.UNDEFINED_ASSET = exports.ASSET_ID = exports.MAINNET_LP_POOL_CONFIG = void 0;
19
19
  // Math
20
20
  var math_1 = require("./api/math");
21
21
  Object.defineProperty(exports, "mulFactor", { enumerable: true, get: function () { return math_1.mulFactor; } });
@@ -31,6 +31,23 @@ Object.defineProperty(exports, "calculateMaximumWithdrawAmount", { enumerable: t
31
31
  Object.defineProperty(exports, "presentValue", { enumerable: true, get: function () { return math_1.presentValue; } });
32
32
  Object.defineProperty(exports, "calculateLiquidationData", { enumerable: true, get: function () { return math_1.calculateLiquidationData; } });
33
33
  Object.defineProperty(exports, "predictHealthFactor", { enumerable: true, get: function () { return math_1.predictHealthFactor; } });
34
+ Object.defineProperty(exports, "calculateHealthParams", { enumerable: true, get: function () { return math_1.calculateHealthParams; } });
35
+ Object.defineProperty(exports, "BigMath", { enumerable: true, get: function () { return math_1.BigMath; } });
36
+ var liquidation_1 = require("./api/liquidation");
37
+ Object.defineProperty(exports, "calculateLiquidationAmounts", { enumerable: true, get: function () { return liquidation_1.calculateLiquidationAmounts; } });
38
+ Object.defineProperty(exports, "calculateMinCollateralByTransferredAmount", { enumerable: true, get: function () { return liquidation_1.calculateMinCollateralByTransferredAmount; } });
39
+ Object.defineProperty(exports, "isLiquidatable", { enumerable: true, get: function () { return liquidation_1.isLiquidatable; } });
40
+ Object.defineProperty(exports, "isBadDebt", { enumerable: true, get: function () { return liquidation_1.isBadDebt; } });
41
+ Object.defineProperty(exports, "addReserve", { enumerable: true, get: function () { return liquidation_1.addReserve; } });
42
+ Object.defineProperty(exports, "deductReserve", { enumerable: true, get: function () { return liquidation_1.deductReserve; } });
43
+ Object.defineProperty(exports, "addLiquidationBonus", { enumerable: true, get: function () { return liquidation_1.addLiquidationBonus; } });
44
+ Object.defineProperty(exports, "deductLiquidationBonus", { enumerable: true, get: function () { return liquidation_1.deductLiquidationBonus; } });
45
+ Object.defineProperty(exports, "toAssetAmount", { enumerable: true, get: function () { return liquidation_1.toAssetAmount; } });
46
+ Object.defineProperty(exports, "toAssetWorth", { enumerable: true, get: function () { return liquidation_1.toAssetWorth; } });
47
+ Object.defineProperty(exports, "prepareAssetInfo", { enumerable: true, get: function () { return liquidation_1.prepareAssetInfo; } });
48
+ Object.defineProperty(exports, "findAssetById", { enumerable: true, get: function () { return liquidation_1.findAssetById; } });
49
+ Object.defineProperty(exports, "selectGreatestAssets", { enumerable: true, get: function () { return liquidation_1.selectGreatestAssets; } });
50
+ Object.defineProperty(exports, "calculateAssetsValues", { enumerable: true, get: function () { return liquidation_1.calculateAssetsValues; } });
34
51
  // Parser
35
52
  var parser_1 = require("./api/parser");
36
53
  Object.defineProperty(exports, "createAssetData", { enumerable: true, get: function () { return parser_1.createAssetData; } });
@@ -66,6 +83,7 @@ Object.defineProperty(exports, "MAINNET_POOL_CONFIG", { enumerable: true, get: f
66
83
  Object.defineProperty(exports, "TESTNET_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.TESTNET_POOL_CONFIG; } });
67
84
  Object.defineProperty(exports, "MAINNET_LP_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.MAINNET_LP_POOL_CONFIG; } });
68
85
  var assets_1 = require("./constants/assets");
86
+ Object.defineProperty(exports, "ASSET_ID", { enumerable: true, get: function () { return assets_1.ASSET_ID; } });
69
87
  Object.defineProperty(exports, "UNDEFINED_ASSET", { enumerable: true, get: function () { return assets_1.UNDEFINED_ASSET; } });
70
88
  Object.defineProperty(exports, "TON_MAINNET", { enumerable: true, get: function () { return assets_1.TON_MAINNET; } });
71
89
  Object.defineProperty(exports, "USDT_MAINNET", { enumerable: true, get: function () { return assets_1.USDT_MAINNET; } });
@@ -9,6 +9,9 @@ export type MasterConstants = {
9
9
  ASSET_LIQUIDATION_THRESHOLD_SCALE: bigint;
10
10
  ASSET_LIQUIDATION_BONUS_SCALE: bigint;
11
11
  ASSET_ORIGINATION_FEE_SCALE: bigint;
12
+ ASSET_SRATE_SCALE: bigint;
13
+ ASSET_BRATE_SCALE: bigint;
14
+ COLLATERAL_WORTH_THRESHOLD: bigint;
12
15
  };
13
16
  export type PoolAssetsConfig = PoolAssetConfig[];
14
17
  export type PoolAssetConfig = {
@@ -77,7 +80,7 @@ export type AssetData = {
77
80
  balance: bigint;
78
81
  trackingSupplyIndex: bigint;
79
82
  trackingBorrowIndex: bigint;
80
- awaitedSupply?: bigint;
83
+ awaitedSupply: bigint;
81
84
  };
82
85
  export type AssetInterest = {
83
86
  supplyInterest: bigint;
@@ -61,6 +61,13 @@ export type UserRewards = {
61
61
  trackingIndex: bigint;
62
62
  trackingAccured: bigint;
63
63
  };
64
+ export type HealthParamsArgs = {
65
+ assetsData: ExtendedAssetsData;
66
+ assetsConfig: ExtendedAssetsConfig;
67
+ principals: Dictionary<bigint, bigint>;
68
+ prices: Dictionary<bigint, bigint>;
69
+ poolConfig: PoolConfig;
70
+ };
64
71
  export declare enum BalanceChangeType {
65
72
  Borrow = 0,
66
73
  Repay = 1,
@@ -1,2 +1,3 @@
1
1
  import { PoolAssetConfig } from "../types/Master";
2
2
  export declare function isTonAsset(asset: PoolAssetConfig): boolean;
3
+ export declare function isTonAssetId(assetId: bigint): boolean;
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isTonAsset = void 0;
3
+ exports.isTonAssetId = exports.isTonAsset = void 0;
4
+ const assets_1 = require("../constants/assets");
4
5
  function isTonAsset(asset) {
5
6
  return asset.name === 'TON';
6
7
  }
7
8
  exports.isTonAsset = isTonAsset;
9
+ function isTonAssetId(assetId) {
10
+ return assetId === assets_1.ASSET_ID.TON;
11
+ }
12
+ exports.isTonAssetId = isTonAssetId;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@evaafi/sdk",
3
- "version": "0.6.0",
4
- "description": "SDK for EVAA v6 contracts",
3
+ "version": "0.6.1-a",
4
+ "description": "The EVAA SDK is designed to easily integrate with the EVAA lending protocol on TON blockchain.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
7
7
  "dist",
@@ -20,6 +20,7 @@
20
20
  "devDependencies": {
21
21
  "@orbs-network/ton-access": "^2.3.3",
22
22
  "@ton/core": "0.56.0",
23
+ "@ton/crypto": "^3.3.0",
23
24
  "@tonconnect/sdk": "^3.0.5",
24
25
  "@types/jest": "^29.5.12",
25
26
  "@types/node": "^20.10.4",
@@ -0,0 +1,346 @@
1
+ import { Dictionary } from '@ton/core';
2
+ import {
3
+ AssetConfig,
4
+ AssetData,
5
+ ExtendedAssetsConfig,
6
+ ExtendedAssetsData,
7
+ MasterConstants,
8
+ PoolAssetConfig,
9
+ PoolConfig
10
+ } from '../types/Master';
11
+ import { BigMath, calculateHealthParams, presentValue } from './math';
12
+ import { BalanceType, UserBalance } from '../types/User';
13
+
14
+ export function findAssetById(assetId: bigint, poolConfig: PoolConfig): PoolAssetConfig | undefined {
15
+ return poolConfig.poolAssetsConfig.find(asset => asset.assetId === assetId);
16
+ }
17
+
18
+ export type AssetsValues = {
19
+ loanAssets: Dictionary<bigint, bigint>,
20
+ collateralAssets: Dictionary<bigint, bigint>
21
+ }
22
+
23
+ export type SelectedAssets = {
24
+ selectedLoanId: bigint,
25
+ selectedCollateralId: bigint,
26
+ selectedLoanValue?: bigint,
27
+ selectedCollateralValue?: bigint,
28
+ }
29
+
30
+ export function calculateAssetsValues(
31
+ principalsDict: Dictionary<bigint, bigint>,
32
+ pricesDict: Dictionary<bigint, bigint>,
33
+ assetsConfigDict: ExtendedAssetsConfig,
34
+ assetsDataDict: ExtendedAssetsData,
35
+ poolConfig: PoolConfig
36
+ ): AssetsValues {
37
+ const loanAssets = Dictionary.empty<bigint, bigint>();
38
+ const collateralAssets = Dictionary.empty<bigint, bigint>();
39
+
40
+ for (const asset of poolConfig.poolAssetsConfig) {
41
+ const assetId = asset.assetId;
42
+ if (!principalsDict.has(assetId)) {
43
+ continue;
44
+ }
45
+ const assetPrincipal: bigint = principalsDict.get(assetId)!;
46
+ if (!pricesDict.has(assetId)) {
47
+ console.warn(`No price for asset ${asset.name}`);
48
+ continue;
49
+ }
50
+ const assetPrice = pricesDict.get(assetId)!;
51
+ if (!assetsDataDict.has(assetId)) {
52
+ console.warn(`Dynamics for assetId ${assetId} is not defined, skipping`);
53
+ continue;
54
+ }
55
+ const assetData = assetsDataDict.get(assetId)!;
56
+
57
+ if (!assetsConfigDict.has(assetId)) {
58
+ console.warn(`Config for assetId ${assetId} is not defined, skipping`);
59
+ continue;
60
+ }
61
+ const assetConfig = assetsConfigDict.get(assetId)!;
62
+ const assetScale = 10n ** assetConfig.decimals;
63
+ const { sRate, bRate } = assetData;
64
+ const assetPresent = presentValue(sRate, bRate, assetPrincipal, poolConfig.masterConstants);
65
+ const assetValue = assetPresent.amount * assetPrice / assetScale;
66
+ if (assetPresent.type === BalanceType.borrow) {
67
+ loanAssets.set(assetId, assetValue);
68
+ } else {
69
+ collateralAssets.set(assetId, assetValue);
70
+ }
71
+ }
72
+
73
+ return { loanAssets, collateralAssets };
74
+ }
75
+
76
+ export function selectGreatestAssets(principalsDict: Dictionary<bigint, bigint>,
77
+ pricesDict: Dictionary<bigint, bigint>,
78
+ assetsConfigDict: ExtendedAssetsConfig,
79
+ assetsDataDict: ExtendedAssetsData,
80
+ poolConfig: PoolConfig): SelectedAssets {
81
+ let maxLoanId = 0n;
82
+ let maxLoanValue = 0n;
83
+ let maxCollateralId = 0n;
84
+ let maxCollateralValue = 0n;
85
+
86
+ const assetsValues = calculateAssetsValues(principalsDict, pricesDict, assetsConfigDict, assetsDataDict, poolConfig);
87
+
88
+ for (const [loanId, loanValue] of assetsValues.loanAssets) {
89
+ if (loanValue > maxLoanValue) {
90
+ maxLoanId = loanId;
91
+ maxLoanValue = loanValue;
92
+ }
93
+ }
94
+
95
+ for (const [collateralId, collateralValue] of assetsValues.collateralAssets) {
96
+ if (collateralValue > maxCollateralValue) {
97
+ maxCollateralValue = collateralValue;
98
+ maxCollateralId = collateralId;
99
+ }
100
+ }
101
+
102
+ return {
103
+ selectedLoanId: maxLoanId,
104
+ selectedLoanValue: maxLoanValue,
105
+ selectedCollateralId: maxCollateralId,
106
+ selectedCollateralValue: maxCollateralValue
107
+ };
108
+ }
109
+
110
+ /**
111
+ * This function shows how to calculate min collateral amount value.
112
+ * when liquidator has not enough of loan asset to cover the full loan.
113
+ * @param transferredAmount amount of loan asset liquidator want to transfer.
114
+ * @param maxLiquidationAmount max liquidation amount value calculated.
115
+ * @param maxCollateralReward max collateral reward amount calculated.
116
+ * @returns minCollateralAmount value for safe liquidation.
117
+ */
118
+ export function calculateMinCollateralByTransferredAmount(
119
+ transferredAmount: bigint, maxLiquidationAmount: bigint, maxCollateralReward: bigint
120
+ ) {
121
+ if (maxLiquidationAmount === 0n) {
122
+ return 0n;
123
+ }
124
+ return maxCollateralReward * transferredAmount / maxLiquidationAmount;
125
+ }
126
+
127
+ /**
128
+ * Calculates liquidation amount and corresponding collateral amount
129
+ * @param supplyAmount user total supply worth amount
130
+ * @param borrowAmount user total borrow worth amount
131
+ * @param masterConstants evaa master contract constants
132
+ * @param loanAsset loan asset pool config
133
+ * @param collateralAsset collateral asset pool config
134
+ * @param principalsDict user principals
135
+ * @param assetsDataDict assets data collection
136
+ * @param assetsConfigDict assets config collection
137
+ * @param pricesDict assets prices
138
+ * @returns maxLiquidationAmount max loan asset amount to transfer
139
+ * @returns maxCollateralRewardAmount max collateral reward amount, which can be obtained
140
+ */
141
+ export function calculateLiquidationAmounts(
142
+ loanAsset: PoolAssetConfig,
143
+ collateralAsset: PoolAssetConfig,
144
+ supplyAmount: bigint,
145
+ borrowAmount: bigint, // from calculate health params
146
+ principalsDict: Dictionary<bigint, bigint>,
147
+ pricesDict: Dictionary<bigint, bigint>,
148
+ assetsDataDict: ExtendedAssetsData,
149
+ assetsConfigDict: ExtendedAssetsConfig,
150
+ masterConstants: MasterConstants
151
+ ): {
152
+ maxLiquidationAmount: bigint, maxCollateralRewardAmount: bigint
153
+ } {
154
+ const loanInfo = prepareAssetInfo(loanAsset.assetId,
155
+ assetsConfigDict, assetsDataDict, pricesDict, principalsDict, masterConstants
156
+ );
157
+ const collateralInfo = prepareAssetInfo(collateralAsset.assetId,
158
+ assetsConfigDict, assetsDataDict, pricesDict, principalsDict, masterConstants
159
+ );
160
+
161
+ if (!loanInfo.ok || !collateralInfo.ok ||
162
+ loanInfo.present.type !== BalanceType.borrow ||
163
+ collateralInfo.present.type !== BalanceType.supply) {
164
+ return { maxLiquidationAmount: 0n, maxCollateralRewardAmount: 0n };
165
+ }
166
+
167
+ const liquidationBonusScale = masterConstants.ASSET_LIQUIDATION_BONUS_SCALE;
168
+ const collateralThreshold = masterConstants.COLLATERAL_WORTH_THRESHOLD; // basically 100$ worth (100*10^9)
169
+ const reserveFactorScale = masterConstants.ASSET_RESERVE_FACTOR_SCALE;
170
+ const reserveFactor = loanInfo.liquidationReserveFactor;
171
+ const liquidationBonus = collateralInfo.liquidationBonus;
172
+
173
+ let allowedCollateralValue = toAssetWorth(collateralInfo.balance, collateralInfo.scale, collateralInfo.price);
174
+
175
+ const _isBadDebt = isBadDebt(supplyAmount, borrowAmount, liquidationBonus, masterConstants);
176
+ if (!_isBadDebt) {
177
+ allowedCollateralValue = BigMath.min(allowedCollateralValue, BigMath.max(allowedCollateralValue / 2n, collateralThreshold));
178
+ }
179
+
180
+ const loanValue = toAssetWorth(loanInfo.balance, loanInfo.scale, loanInfo.price);
181
+ const baseLiquidationValue = BigMath.min(
182
+ // deductReserve(loanValue, reserveFactor, reserveFactorScale),
183
+ loanValue,
184
+ deductLiquidationBonus(allowedCollateralValue, liquidationBonus, liquidationBonusScale)
185
+ );
186
+
187
+ // calculate collateral amount
188
+ let collateralAmount = addLiquidationBonus(baseLiquidationValue, liquidationBonus, liquidationBonusScale);
189
+ collateralAmount = toAssetAmount(collateralAmount, collateralInfo.scale, collateralInfo.price);
190
+
191
+ // calculate loan amount
192
+ let liquidationAmount = addReserve(baseLiquidationValue, reserveFactor, reserveFactorScale);
193
+ liquidationAmount = toAssetAmount(liquidationAmount, loanInfo.scale, loanInfo.price);
194
+
195
+ return {
196
+ maxLiquidationAmount: liquidationAmount,
197
+ maxCollateralRewardAmount: collateralAmount
198
+ };
199
+ }
200
+
201
+ /**
202
+ * Check if the user is subject to liquidation
203
+ * @param args
204
+ */
205
+ export function isLiquidatable(args: {
206
+ assetsData: ExtendedAssetsData, assetsConfig: ExtendedAssetsConfig,
207
+ principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>,
208
+ poolConfig: PoolConfig
209
+ }): boolean {
210
+ const { isLiquidatable: res } = calculateHealthParams(args);
211
+ return res;
212
+ }
213
+
214
+ /**
215
+ * Determines if the provided pair of assets forms a bad debt.
216
+ * @param totalSupply total supply worth amount
217
+ * @param totalBorrow total borrow worth amount
218
+ * @param liquidationBonus collateral liquidation bonus value
219
+ * @param masterConstants pool constants
220
+ */
221
+ export function isBadDebt(totalSupply: bigint, totalBorrow: bigint,
222
+ liquidationBonus: bigint, masterConstants: MasterConstants
223
+ ) {
224
+ return totalSupply * masterConstants.ASSET_LIQUIDATION_BONUS_SCALE < totalBorrow * liquidationBonus;
225
+ }
226
+
227
+ /**
228
+ * Adds reserve to liquidation amount
229
+ * @param amount raw liquidation amount
230
+ * @param reserveFactor asset reserve factor
231
+ * @param factorScale asset reserve factor scale
232
+ * @returns liquidation amount with reserve
233
+ */
234
+ export function addReserve(amount: bigint, reserveFactor: bigint, factorScale: bigint): bigint {
235
+ return amount * factorScale / (factorScale - reserveFactor);
236
+ }
237
+
238
+ /**
239
+ * Deducts reserve from liquidation amount
240
+ * @param amount liquidation amount with reserve
241
+ * @param reserveFactor asset reserve factor
242
+ * @param reserveFactorScale asset reserve factor scale
243
+ * @returns liquidation amount without reserve
244
+ */
245
+ export function deductReserve(amount: bigint, reserveFactor: bigint, reserveFactorScale: bigint): bigint {
246
+ return amount * (reserveFactorScale - reserveFactor) / reserveFactorScale;
247
+ }
248
+
249
+ /**
250
+ * Converts worth value to specified asset amount
251
+ * @param worth worth value (decimals = 9)
252
+ * @param scale asset scale (10^asset_decimals)
253
+ * @param price asset price
254
+ */
255
+ export function toAssetAmount(worth: bigint, scale: bigint, price: bigint): bigint {
256
+ return worth * scale / price;
257
+ }
258
+
259
+ /**
260
+ * Converts calculates worth value of specified asset amount
261
+ * @param amount worth value (decimals = 9)
262
+ * @param scale asset scale (10^asset_decimals)
263
+ * @param price asset price
264
+ */
265
+ export function toAssetWorth(amount: bigint, scale: bigint, price: bigint): bigint {
266
+ return amount * price / scale;
267
+ }
268
+
269
+ /**
270
+ * Adds liquidation bonus to reward value.
271
+ * @param value reward asset value
272
+ * @param bonus liquidation bonus factor
273
+ * @param scale liquidation bonus scale
274
+ */
275
+ export function addLiquidationBonus(value: bigint, bonus: bigint, scale: bigint): bigint {
276
+ return value * bonus / scale;
277
+ }
278
+
279
+ /**
280
+ * Deducts liquidation bonus from reward value.
281
+ * @param value reward asset value
282
+ * @param bonus liquidation bonus factor
283
+ * @param scale liquidation bonus scale
284
+ */
285
+ export function deductLiquidationBonus(value: bigint, bonus: bigint, scale: bigint): bigint {
286
+ return value * scale / bonus;
287
+ }
288
+
289
+ export type SuccessType = { ok: true };
290
+ export type FailType = { ok: false };
291
+
292
+ export type PreparedAssetInfo = {
293
+ config: AssetConfig,
294
+ data: AssetData,
295
+ price: bigint,
296
+ principal: bigint,
297
+ scale: bigint,
298
+ liquidationReserveFactor: bigint,
299
+ liquidationBonus: bigint,
300
+ present: UserBalance,
301
+ balance: bigint,
302
+ dust: bigint,
303
+ };
304
+
305
+ export type PreparedAssetInfoResult = (PreparedAssetInfo & SuccessType) | FailType;
306
+
307
+ /**
308
+ * Prepares extended asset info
309
+ * @param assetId
310
+ * @param assetsConfigDict
311
+ * @param assetsDataDict
312
+ * @param pricesDict
313
+ * @param principalsDict
314
+ * @param masterConstants
315
+ */
316
+ export function prepareAssetInfo(assetId: bigint,
317
+ assetsConfigDict: ExtendedAssetsConfig,
318
+ assetsDataDict: ExtendedAssetsData,
319
+ pricesDict: Dictionary<bigint, bigint>,
320
+ principalsDict: Dictionary<bigint, bigint>,
321
+ masterConstants: MasterConstants
322
+ ): PreparedAssetInfoResult {
323
+ if (!assetsConfigDict.has(assetId) ||
324
+ !assetsDataDict.has(assetId) ||
325
+ !pricesDict.has(assetId) ||
326
+ !principalsDict.has(assetId)) {
327
+ return { ok: false };
328
+ }
329
+
330
+ const config = assetsConfigDict.get(assetId)!;
331
+ const data = assetsDataDict.get(assetId)!;
332
+ const base = {
333
+ ok: true,
334
+ config, data,
335
+ price: pricesDict.get(assetId)!,
336
+ principal: principalsDict.get(assetId)!,
337
+ scale: 10n ** config.decimals,
338
+ liquidationReserveFactor: config.liquidationReserveFactor,
339
+ liquidationBonus: config.liquidationBonus
340
+ };
341
+
342
+ const assetPresent = presentValue(data.sRate, data.bRate, base.principal, masterConstants);
343
+ const dustPresent = presentValue(data.sRate, data.bRate, config.dust, masterConstants);
344
+
345
+ return { ...base, present: assetPresent, balance: assetPresent.amount, dust: dustPresent.amount };
346
+ }