@evaafi/sdk 0.5.3 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,20 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getUserJettonWallet = exports.getTonConnectSender = exports.getLastSentBoc = exports.FEES = exports.OPCODES = exports.LENDING_CODE = exports.MASTER_CONSTANTS = exports.JETTON_MASTER_ADDRESSES = 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.calculateLiquidationData = exports.presentValue = exports.getAvailableToBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.bigIntMax = exports.bigIntMin = exports.mulDiv = exports.mulFactor = void 0;
17
+ 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.TESTNET_LP_POOL_CONFIG = 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.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;
4
18
  // Math
5
19
  var math_1 = require("./api/math");
6
20
  Object.defineProperty(exports, "mulFactor", { enumerable: true, get: function () { return math_1.mulFactor; } });
@@ -12,6 +26,7 @@ Object.defineProperty(exports, "calculateCurrentRates", { enumerable: true, get:
12
26
  Object.defineProperty(exports, "calculateAssetData", { enumerable: true, get: function () { return math_1.calculateAssetData; } });
13
27
  Object.defineProperty(exports, "calculateAssetInterest", { enumerable: true, get: function () { return math_1.calculateAssetInterest; } });
14
28
  Object.defineProperty(exports, "getAvailableToBorrow", { enumerable: true, get: function () { return math_1.getAvailableToBorrow; } });
29
+ Object.defineProperty(exports, "calculateMaximumWithdrawAmount", { enumerable: true, get: function () { return math_1.calculateMaximumWithdrawAmount; } });
15
30
  Object.defineProperty(exports, "presentValue", { enumerable: true, get: function () { return math_1.presentValue; } });
16
31
  Object.defineProperty(exports, "calculateLiquidationData", { enumerable: true, get: function () { return math_1.calculateLiquidationData; } });
17
32
  // Parser
@@ -35,16 +50,34 @@ var User_1 = require("./types/User");
35
50
  Object.defineProperty(exports, "BalanceType", { enumerable: true, get: function () { return User_1.BalanceType; } });
36
51
  Object.defineProperty(exports, "BalanceChangeType", { enumerable: true, get: function () { return User_1.BalanceChangeType; } });
37
52
  // Constants
38
- var constants_1 = require("./constants");
39
- Object.defineProperty(exports, "EVAA_MASTER_MAINNET", { enumerable: true, get: function () { return constants_1.EVAA_MASTER_MAINNET; } });
40
- Object.defineProperty(exports, "MAINNET_VERSION", { enumerable: true, get: function () { return constants_1.MAINNET_VERSION; } });
41
- Object.defineProperty(exports, "EVAA_MASTER_TESTNET", { enumerable: true, get: function () { return constants_1.EVAA_MASTER_TESTNET; } });
42
- Object.defineProperty(exports, "TESTNET_VERSION", { enumerable: true, get: function () { return constants_1.TESTNET_VERSION; } });
43
- Object.defineProperty(exports, "JETTON_MASTER_ADDRESSES", { enumerable: true, get: function () { return constants_1.JETTON_MASTER_ADDRESSES; } });
44
- Object.defineProperty(exports, "MASTER_CONSTANTS", { enumerable: true, get: function () { return constants_1.MASTER_CONSTANTS; } });
45
- Object.defineProperty(exports, "LENDING_CODE", { enumerable: true, get: function () { return constants_1.LENDING_CODE; } });
46
- Object.defineProperty(exports, "OPCODES", { enumerable: true, get: function () { return constants_1.OPCODES; } });
47
- Object.defineProperty(exports, "FEES", { enumerable: true, get: function () { return constants_1.FEES; } });
53
+ var general_1 = require("./constants/general");
54
+ Object.defineProperty(exports, "EVAA_MASTER_MAINNET", { enumerable: true, get: function () { return general_1.EVAA_MASTER_MAINNET; } });
55
+ Object.defineProperty(exports, "MAINNET_VERSION", { enumerable: true, get: function () { return general_1.MAINNET_VERSION; } });
56
+ Object.defineProperty(exports, "EVAA_MASTER_TESTNET", { enumerable: true, get: function () { return general_1.EVAA_MASTER_TESTNET; } });
57
+ Object.defineProperty(exports, "TESTNET_VERSION", { enumerable: true, get: function () { return general_1.TESTNET_VERSION; } });
58
+ Object.defineProperty(exports, "LENDING_CODE", { enumerable: true, get: function () { return general_1.LENDING_CODE; } });
59
+ Object.defineProperty(exports, "OPCODES", { enumerable: true, get: function () { return general_1.OPCODES; } });
60
+ Object.defineProperty(exports, "FEES", { enumerable: true, get: function () { return general_1.FEES; } });
61
+ Object.defineProperty(exports, "MASTER_CONSTANTS", { enumerable: true, get: function () { return general_1.MASTER_CONSTANTS; } });
62
+ var pools_1 = require("./constants/pools");
63
+ Object.defineProperty(exports, "MAINNET_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.MAINNET_POOL_CONFIG; } });
64
+ Object.defineProperty(exports, "TESTNET_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.TESTNET_POOL_CONFIG; } });
65
+ Object.defineProperty(exports, "MAINNET_LP_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.MAINNET_LP_POOL_CONFIG; } });
66
+ Object.defineProperty(exports, "TESTNET_LP_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.TESTNET_LP_POOL_CONFIG; } });
67
+ var assets_1 = require("./constants/assets");
68
+ Object.defineProperty(exports, "TON_MAINNET", { enumerable: true, get: function () { return assets_1.TON_MAINNET; } });
69
+ Object.defineProperty(exports, "USDT_MAINNET", { enumerable: true, get: function () { return assets_1.USDT_MAINNET; } });
70
+ Object.defineProperty(exports, "TONUSDT_DEDUST_MAINNET", { enumerable: true, get: function () { return assets_1.TONUSDT_DEDUST_MAINNET; } });
71
+ Object.defineProperty(exports, "TON_STORM_MAINNET", { enumerable: true, get: function () { return assets_1.TON_STORM_MAINNET; } });
72
+ Object.defineProperty(exports, "USDT_STORM_MAINNET", { enumerable: true, get: function () { return assets_1.USDT_STORM_MAINNET; } });
73
+ Object.defineProperty(exports, "JUSDT_MAINNET", { enumerable: true, get: function () { return assets_1.JUSDT_MAINNET; } });
74
+ Object.defineProperty(exports, "JUSDC_MAINNET", { enumerable: true, get: function () { return assets_1.JUSDC_MAINNET; } });
75
+ Object.defineProperty(exports, "STTON_MAINNET", { enumerable: true, get: function () { return assets_1.STTON_MAINNET; } });
76
+ Object.defineProperty(exports, "TSTON_MAINNET", { enumerable: true, get: function () { return assets_1.TSTON_MAINNET; } });
77
+ Object.defineProperty(exports, "JUSDT_TESTNET", { enumerable: true, get: function () { return assets_1.JUSDT_TESTNET; } });
78
+ Object.defineProperty(exports, "JUSDC_TESTNET", { enumerable: true, get: function () { return assets_1.JUSDC_TESTNET; } });
79
+ Object.defineProperty(exports, "STTON_TESTNET", { enumerable: true, get: function () { return assets_1.STTON_TESTNET; } });
80
+ __exportStar(require("./constants/assets"), exports);
48
81
  // Utils
49
82
  var tonConnectSender_1 = require("./utils/tonConnectSender");
50
83
  Object.defineProperty(exports, "getLastSentBoc", { enumerable: true, get: function () { return tonConnectSender_1.getLastSentBoc; } });
@@ -1,4 +1,32 @@
1
1
  import { Address, Cell, Dictionary } from '@ton/core';
2
+ export type MasterConstants = {
3
+ FACTOR_SCALE: bigint;
4
+ ASSET_COEFFICIENT_SCALE: bigint;
5
+ ASSET_PRICE_SCALE: bigint;
6
+ ASSET_RESERVE_FACTOR_SCALE: bigint;
7
+ ASSET_LIQUIDATION_RESERVE_FACTOR_SCALE: bigint;
8
+ ASSET_ORIGINATION_FEE_SCALE: bigint;
9
+ };
10
+ export type PoolAssetConfig = (PoolTonAssetConfig | PoolJettonAssetConfig) & {
11
+ name: string;
12
+ };
13
+ export type PoolAssetsConfig = PoolAssetConfig[];
14
+ export type PoolTonAssetConfig = {
15
+ assetId: bigint;
16
+ };
17
+ export type PoolJettonAssetConfig = {
18
+ assetId: bigint;
19
+ jettonMasterAddress: Address;
20
+ jettonWalletCode: Cell;
21
+ };
22
+ export type PoolConfig = {
23
+ masterAddress: Address;
24
+ masterVersion: number;
25
+ masterConstants: MasterConstants;
26
+ nftId: string;
27
+ poolAssetsConfig: PoolAssetsConfig;
28
+ lendingCode: Cell;
29
+ };
2
30
  export type UpgradeConfig = {
3
31
  masterCodeVersion: number;
4
32
  userCodeVersion: number;
@@ -52,12 +80,14 @@ export type AssetApy = {
52
80
  borrowApy: number;
53
81
  };
54
82
  export type ExtendedAssetData = AssetData & AssetInterest & AssetApy;
83
+ export type ExtendedAssetsData = Dictionary<bigint, ExtendedAssetData>;
84
+ export type ExtendedAssetsConfig = Dictionary<bigint, AssetConfig>;
55
85
  export type MasterData = {
56
86
  meta: string;
57
87
  upgradeConfig: UpgradeConfig;
58
88
  masterConfig: MasterConfig;
59
- assetsConfig: Dictionary<bigint, AssetConfig>;
60
- assetsData: Dictionary<bigint, ExtendedAssetData>;
89
+ assetsConfig: ExtendedAssetsConfig;
90
+ assetsData: ExtendedAssetsData;
61
91
  assetsReserves: Dictionary<bigint, bigint>;
62
92
  apy: {
63
93
  supply: Dictionary<bigint, number>;
@@ -1,5 +1,5 @@
1
1
  import { Address, Cell, Dictionary } from '@ton/core';
2
- import { AssetConfig, ExtendedAssetData } from './Master';
2
+ import { ExtendedAssetsConfig, ExtendedAssetsData, MasterConstants } from './Master';
3
3
  export declare enum BalanceType {
4
4
  supply = "supply",
5
5
  borrow = "borrow"
@@ -70,6 +70,7 @@ export type PredictHealthFactorArgs = {
70
70
  tokenSymbol: string;
71
71
  balances: Dictionary<bigint, bigint>;
72
72
  prices: Dictionary<bigint, bigint>;
73
- assetsData: Dictionary<bigint, ExtendedAssetData>;
74
- assetsConfig: Dictionary<bigint, AssetConfig>;
73
+ assetsData: ExtendedAssetsData;
74
+ assetsConfig: ExtendedAssetsConfig;
75
+ masterConstants: MasterConstants;
75
76
  };
@@ -1,2 +1,3 @@
1
1
  import { Address } from '@ton/core';
2
- export declare function getUserJettonWallet(ownerAddress: Address, assetID: bigint, network: 'mainnet' | 'testnet'): Address;
2
+ import { PoolAssetConfig, PoolJettonAssetConfig } from '../types/Master';
3
+ export declare function getUserJettonWallet(ownerAddress: Address, poolAssetConfig: PoolAssetConfig & PoolJettonAssetConfig): Address;
@@ -2,71 +2,55 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getUserJettonWallet = void 0;
4
4
  const core_1 = require("@ton/core");
5
- const constants_1 = require("../constants");
6
- function getUserJettonWallet(ownerAddress, assetID, network) {
7
- const builder = (0, core_1.beginCell)().storeCoins(0).storeAddress(ownerAddress);
8
- let jettonWalletCode;
9
- switch (assetID) {
10
- case constants_1.MAINNET_ASSETS_ID.jUSDT:
11
- if (network === 'mainnet') {
12
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDT_MAINNET);
13
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.jUSDT_MAINNET;
14
- }
15
- else {
16
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDT_TESTNET);
17
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.jUSDT_TESTNET;
18
- }
19
- break;
20
- case constants_1.MAINNET_ASSETS_ID.jUSDC:
21
- if (network === 'mainnet') {
22
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDC_MAINNET);
23
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.jUSDC_MAINNET;
24
- }
25
- else {
26
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDC_TESTNET);
27
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.jUSDC_TESTNET;
28
- }
29
- break;
30
- case constants_1.MAINNET_ASSETS_ID.stTON:
31
- if (network === 'mainnet') {
32
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.stTON_MAINNET);
33
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.stTON_MAINNET;
34
- }
35
- else {
36
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.stTON_TESTNET);
37
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.stTON_TESTNET;
38
- }
39
- break;
40
- case constants_1.MAINNET_ASSETS_ID.tsTON:
41
- if (network === 'mainnet') {
42
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.tsTON_MAINNET);
43
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.tsTON_MAINNET;
44
- }
45
- else {
46
- // builder.storeAddress(JETTON_MASTER_ADDRESSES.tsTON_TESTNET);
47
- // jettonWalletCode = JETTON_WALLETS_CODE.tsTON_TESTNET;
48
- throw new Error('tsTON is not supported on testnet');
49
- }
50
- break;
51
- case constants_1.MAINNET_ASSETS_ID.USDT:
52
- if (network === 'mainnet') {
53
- builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.USDT_MAINNET);
54
- jettonWalletCode = constants_1.JETTON_WALLETS_CODE.USDT_MAINNET;
55
- }
56
- else {
57
- // builder.storeAddress(JETTON_MASTER_ADDRESSES.USDT_TESTNET);
58
- // jettonWalletCode = JETTON_WALLETS_CODE.USDT_TESTNET;
59
- throw new Error('USDT is not supported on testnet');
60
- }
61
- break;
62
- default:
63
- throw new Error('Unsupported asset');
5
+ function getUserJettonWallet(ownerAddress, poolAssetConfig) {
6
+ const jettonMasterAddress = poolAssetConfig.jettonMasterAddress;
7
+ const jettonWalletCode = poolAssetConfig.jettonWalletCode;
8
+ if (poolAssetConfig.name === 'USDT') {
9
+ const lib_prep = (0, core_1.beginCell)().storeUint(2, 8).storeBuffer(jettonWalletCode.hash()).endCell();
10
+ const jwallet_code = new core_1.Cell({ exotic: true, bits: lib_prep.bits, refs: lib_prep.refs });
11
+ const jettonData = (0, core_1.beginCell)()
12
+ .storeUint(0, 4)
13
+ .storeCoins(0)
14
+ .storeAddress(ownerAddress)
15
+ .storeAddress(jettonMasterAddress)
16
+ .endCell();
17
+ const stateInit = (0, core_1.beginCell)()
18
+ .store((0, core_1.storeStateInit)({
19
+ code: jwallet_code,
20
+ data: jettonData
21
+ }))
22
+ .endCell();
23
+ return new core_1.Address(0, stateInit.hash());
64
24
  }
65
- const data = builder.storeRef(jettonWalletCode).endCell();
25
+ if (poolAssetConfig.name === 'tsTON') {
26
+ const lib_prep = (0, core_1.beginCell)().storeUint(2, 8).storeBuffer(jettonWalletCode.hash()).endCell();
27
+ const jwallet_code = new core_1.Cell({ exotic: true, bits: lib_prep.bits, refs: lib_prep.refs });
28
+ const jettonData = (0, core_1.beginCell)()
29
+ .storeCoins(0)
30
+ .storeAddress(ownerAddress)
31
+ .storeAddress(jettonMasterAddress)
32
+ .storeRef(jwallet_code)
33
+ .storeCoins(0)
34
+ .storeUint(0, 48)
35
+ .endCell();
36
+ const stateInit = (0, core_1.beginCell)()
37
+ .store((0, core_1.storeStateInit)({
38
+ code: jwallet_code,
39
+ data: jettonData
40
+ }))
41
+ .endCell();
42
+ return new core_1.Address(0, stateInit.hash());
43
+ }
44
+ const jettonData = (0, core_1.beginCell)()
45
+ .storeCoins(0)
46
+ .storeAddress(ownerAddress)
47
+ .storeAddress(jettonMasterAddress)
48
+ .storeRef(jettonWalletCode)
49
+ .endCell();
66
50
  const stateInit = (0, core_1.beginCell)()
67
51
  .store((0, core_1.storeStateInit)({
68
52
  code: jettonWalletCode,
69
- data: data,
53
+ data: jettonData
70
54
  }))
71
55
  .endCell();
72
56
  return new core_1.Address(0, stateInit.hash());
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@evaafi/sdk",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "SDK for EVAA contracts",
5
5
  "main": "dist/index.js",
6
+ "types": "src/index.ts",
6
7
  "files": [
7
8
  "dist",
8
9
  "src"
@@ -18,11 +19,14 @@
18
19
  "license": "MIT",
19
20
  "homepage": "https://github.com/evaafi/sdk#readme",
20
21
  "devDependencies": {
22
+ "@orbs-network/ton-access": "^2.3.3",
21
23
  "@ton/core": "0.56.0",
22
24
  "@tonconnect/sdk": "^3.0.0",
25
+ "@types/jest": "^29.5.12",
23
26
  "@types/node": "^20.10.4",
24
27
  "crypto-js": "^4.2.0",
25
28
  "prettier": "^3.2.4",
29
+ "ts-jest": "^29.2.4",
26
30
  "ts-node": "^10.9.1",
27
31
  "typescript": "^5.3.3"
28
32
  },
@@ -30,5 +34,9 @@
30
34
  "@ton/core": ">=0.56.0",
31
35
  "@tonconnect/sdk": ">=3.0.0",
32
36
  "crypto-js": ">=4.2.0"
37
+ },
38
+ "dependencies": {
39
+ "@ton/ton": "^14.0.0",
40
+ "dotenv": "^16.4.5"
33
41
  }
34
42
  }
package/src/api/math.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData } from '../types/Master';
2
- import { MASTER_CONSTANTS } from '../constants';
1
+ import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConstants } from '../types/Master';
3
2
  import { Dictionary } from '@ton/core';
4
3
  import { BalanceChangeType, BalanceType, LiquidationData, PredictHealthFactorArgs, UserBalance } from '../types/User';
5
4
  import { sha256Hash } from '../utils/sha256BigInt';
@@ -12,6 +11,11 @@ export function mulDiv(x: bigint, y: bigint, z: bigint): bigint {
12
11
  return (x * y) / z;
13
12
  }
14
13
 
14
+ export function mulDivC(x: bigint, y: bigint, z: bigint): bigint {
15
+ const mul = x * y;
16
+ return mul / z + (mul % z ? 1n : 0n);
17
+ }
18
+
15
19
  export function bigIntMax(...args: bigint[]): bigint {
16
20
  return args.reduce((m, e) => (e > m ? e : m));
17
21
  }
@@ -19,20 +23,20 @@ export function bigIntMin(...args: bigint[]): bigint {
19
23
  return args.reduce((m, e) => (e < m ? e : m));
20
24
  }
21
25
 
22
- export function calculatePresentValue(index: bigint, principalValue: bigint): bigint {
23
- return (principalValue * index) / MASTER_CONSTANTS.FACTOR_SCALE;
26
+ export function calculatePresentValue(index: bigint, principalValue: bigint, masterConstants: MasterConstants): bigint {
27
+ return (principalValue * index) / masterConstants.FACTOR_SCALE;
24
28
  }
25
29
 
26
- export function calculateCurrentRates(assetConfig: AssetConfig, assetData: AssetData) {
30
+ export function calculateCurrentRates(assetConfig: AssetConfig, assetData: AssetData, masterConstants: MasterConstants) {
27
31
  const now = BigInt(Math.floor(Date.now() / 1000));
28
32
  const timeElapsed = now - assetData.lastAccural;
29
- const { supplyInterest, borrowInterest } = calculateAssetInterest(assetConfig, assetData);
33
+ const { supplyInterest, borrowInterest } = calculateAssetInterest(assetConfig, assetData, masterConstants);
30
34
 
31
35
  if (timeElapsed > 0) {
32
36
  const updatedSRate =
33
- assetData.sRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.sRate, supplyInterest * timeElapsed);
37
+ assetData.sRate + mulFactor(masterConstants.FACTOR_SCALE, assetData.sRate, supplyInterest * timeElapsed);
34
38
  const updatedBRate =
35
- assetData.bRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.bRate, borrowInterest * timeElapsed);
39
+ assetData.bRate + mulFactor(masterConstants.FACTOR_SCALE, assetData.bRate, borrowInterest * timeElapsed);
36
40
  return {
37
41
  sRate: updatedSRate,
38
42
  bRate: updatedBRate,
@@ -52,9 +56,10 @@ export function calculateCurrentRates(assetConfig: AssetConfig, assetData: Asset
52
56
  }
53
57
 
54
58
  export function calculateAssetData(
55
- assetsConfigDict: Dictionary<bigint, AssetConfig>,
59
+ assetsConfigDict: ExtendedAssetsConfig,
56
60
  assetsDataDict: Dictionary<bigint, AssetData>,
57
61
  assetId: bigint,
62
+ masterConstants: MasterConstants
58
63
  ): ExtendedAssetData {
59
64
  const config = assetsConfigDict.get(assetId);
60
65
  const data = assetsDataDict.get(assetId);
@@ -63,7 +68,7 @@ export function calculateAssetData(
63
68
  throw new Error('Asset Data or Config is not accessible');
64
69
  }
65
70
 
66
- const { sRate, bRate, supplyInterest, borrowInterest, now } = calculateCurrentRates(config, data);
71
+ const { sRate, bRate, supplyInterest, borrowInterest, now } = calculateCurrentRates(config, data, masterConstants);
67
72
  data.sRate = sRate || 0n;
68
73
  data.bRate = bRate || 0n;
69
74
  data.lastAccural = now;
@@ -78,36 +83,36 @@ export function calculateAssetData(
78
83
  };
79
84
  }
80
85
 
81
- export function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData): AssetInterest {
82
- const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply);
83
- const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow);
86
+ export function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData, masterConstants: MasterConstants): AssetInterest {
87
+ const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply, masterConstants);
88
+ const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow, masterConstants);
84
89
  let utilization = 0n;
85
90
  let supplyInterest = 0n;
86
91
  let borrowInterest = 0n;
87
92
 
88
93
  if (totalSupply !== 0n) {
89
- utilization = (totalBorrow * MASTER_CONSTANTS.FACTOR_SCALE) / totalSupply;
94
+ utilization = (totalBorrow * masterConstants.FACTOR_SCALE) / totalSupply;
90
95
  }
91
96
 
92
97
  if (utilization <= assetConfig.targetUtilization) {
93
98
  borrowInterest =
94
99
  assetConfig.baseBorrowRate +
95
- mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, utilization);
100
+ mulFactor(masterConstants.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, utilization);
96
101
  } else {
97
102
  borrowInterest =
98
103
  assetConfig.baseBorrowRate +
99
- mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, assetConfig.targetUtilization) +
104
+ mulFactor(masterConstants.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, assetConfig.targetUtilization) +
100
105
  mulFactor(
101
- MASTER_CONSTANTS.FACTOR_SCALE,
106
+ masterConstants.FACTOR_SCALE,
102
107
  assetConfig.borrowRateSlopeHigh,
103
108
  utilization - assetConfig.targetUtilization,
104
109
  );
105
110
  }
106
111
 
107
112
  supplyInterest = mulDiv(
108
- mulDiv(borrowInterest, utilization, MASTER_CONSTANTS.FACTOR_SCALE),
109
- MASTER_CONSTANTS.ASSET_RESERVE_FACTOR_SCALE - assetConfig.reserveFactor,
110
- MASTER_CONSTANTS.ASSET_RESERVE_FACTOR_SCALE,
113
+ mulDiv(borrowInterest, utilization, masterConstants.FACTOR_SCALE),
114
+ masterConstants.ASSET_RESERVE_FACTOR_SCALE - assetConfig.reserveFactor,
115
+ masterConstants.ASSET_RESERVE_FACTOR_SCALE,
111
116
  );
112
117
 
113
118
  return {
@@ -116,11 +121,72 @@ export function calculateAssetInterest(assetConfig: AssetConfig, assetData: Asse
116
121
  };
117
122
  }
118
123
 
124
+ export function checkNotInDebtAtAll(principals: Dictionary<bigint, bigint>): boolean {
125
+ return principals.values().every(x => x >= 0n);
126
+ }
127
+
128
+ export function calculateMaximumWithdrawAmount(
129
+ assetsConfig: ExtendedAssetsConfig,
130
+ assetsData: ExtendedAssetsData,
131
+ principals: Dictionary<bigint, bigint>,
132
+ prices: Dictionary<bigint, bigint>,
133
+ masterConstants: MasterConstants,
134
+ assetId: bigint
135
+ ): bigint {
136
+ let withdrawAmountMax = 0n;
137
+
138
+ const assetConfig = assetsConfig.get(assetId) as AssetConfig;
139
+ const assetData = assetsData.get(assetId) as ExtendedAssetData;
140
+ const oldPrincipal = principals.get(assetId) as bigint;
141
+
142
+ if (oldPrincipal > assetConfig.dust) {
143
+ const oldPresentValue = presentValue(assetData.sRate, assetData.bRate, oldPrincipal, masterConstants);
144
+ if(checkNotInDebtAtAll(principals)) {
145
+ withdrawAmountMax = oldPresentValue.amount;
146
+ } else {
147
+ if (!prices.has(assetId)) {
148
+ return 0n;
149
+ }
150
+
151
+ const borrowable = getAvailableToBorrow(assetsConfig, assetsData, principals, prices, masterConstants);
152
+ const price = prices.get(assetId) as bigint;
153
+
154
+ let maxAmountToReclaim = 0n;
155
+ if (assetConfig.collateralFactor == 0n) {
156
+ maxAmountToReclaim = oldPresentValue.amount;
157
+ }
158
+ else if (price > 0) {
159
+ maxAmountToReclaim =
160
+ mulDiv(
161
+ mulDivC(borrowable, masterConstants.ASSET_COEFFICIENT_SCALE, assetConfig.collateralFactor),
162
+ 10n ** assetConfig.decimals, price
163
+ );
164
+ }
165
+
166
+ withdrawAmountMax = bigIntMin(
167
+ maxAmountToReclaim,
168
+ oldPresentValue.amount
169
+ );
170
+ }
171
+ } else {
172
+ if (!prices.has(assetId)) {
173
+ return 0n;
174
+ }
175
+
176
+ const price = prices.get(assetId) as bigint;
177
+
178
+ return getAvailableToBorrow(assetsConfig, assetsData, principals, prices, masterConstants) * (10n ** assetConfig.decimals) / price;
179
+ }
180
+
181
+ return withdrawAmountMax;
182
+ }
183
+
119
184
  export function getAvailableToBorrow(
120
- assetsConfig: Dictionary<bigint, AssetConfig>,
121
- assetsData: Dictionary<bigint, ExtendedAssetData>,
185
+ assetsConfig: ExtendedAssetsConfig,
186
+ assetsData: ExtendedAssetsData,
122
187
  principals: Dictionary<bigint, bigint>,
123
188
  prices: Dictionary<bigint, bigint>,
189
+ masterConstants: MasterConstants
124
190
  ): bigint {
125
191
  let borrowLimit = 0n;
126
192
  let borrowAmount = 0n;
@@ -132,27 +198,28 @@ export function getAvailableToBorrow(
132
198
  const principal = principals.get(assetID) as bigint;
133
199
 
134
200
  if (principal < 0) {
135
- borrowAmount += (calculatePresentValue(assetData.bRate, -principal) * price) / 10n ** assetConfig.decimals;
201
+ borrowAmount += (calculatePresentValue(assetData.bRate, -principal, masterConstants) * price) / 10n ** assetConfig.decimals;
136
202
  } else if (principal > 0) {
137
203
  borrowLimit +=
138
- (calculatePresentValue(assetData.sRate, principal) * price * assetConfig.collateralFactor) /
139
- 10n ** assetConfig.decimals /
140
- MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
204
+ mulDivC(
205
+ mulDivC(calculatePresentValue(assetData.sRate, principal, masterConstants), price, 10n ** assetConfig.decimals),
206
+ assetConfig.collateralFactor,
207
+ masterConstants.ASSET_COEFFICIENT_SCALE);
141
208
  }
142
209
  }
143
210
 
144
211
  return borrowLimit - borrowAmount;
145
212
  }
146
213
 
147
- export function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint): UserBalance {
214
+ export function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint, masterConstants: MasterConstants): UserBalance {
148
215
  if (principalValue > 0) {
149
216
  return {
150
- amount: calculatePresentValue(sRate, principalValue),
217
+ amount: calculatePresentValue(sRate, principalValue, masterConstants),
151
218
  type: BalanceType.supply,
152
219
  };
153
220
  } else if (principalValue < 0) {
154
221
  return {
155
- amount: calculatePresentValue(bRate, -principalValue),
222
+ amount: calculatePresentValue(bRate, -principalValue, masterConstants),
156
223
  type: BalanceType.borrow,
157
224
  };
158
225
  } else {
@@ -164,10 +231,11 @@ export function presentValue(sRate: bigint, bRate: bigint, principalValue: bigin
164
231
  }
165
232
 
166
233
  export function calculateLiquidationData(
167
- assetsConfig: Dictionary<bigint, AssetConfig>,
168
- assetsData: Dictionary<bigint, ExtendedAssetData>,
234
+ assetsConfig: ExtendedAssetsConfig,
235
+ assetsData: ExtendedAssetsData,
169
236
  principals: Dictionary<bigint, bigint>,
170
237
  prices: Dictionary<bigint, bigint>,
238
+ masterConstants: MasterConstants,
171
239
  ): LiquidationData {
172
240
  let gCollateralValue = 0n;
173
241
  let gCollateralAsset = 0n;
@@ -184,7 +252,7 @@ export function calculateLiquidationData(
184
252
  principal > 0 ? (principal * assetData.sRate) / BigInt(1e12) : (principal * assetData.bRate) / BigInt(1e12);
185
253
  if (balance > 0) {
186
254
  const assetWorth = (balance * prices.get(key)!) / 10n ** assetConfig.decimals;
187
- totalLimit += (assetWorth * assetConfig.liquidationThreshold) / MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
255
+ totalLimit += (assetWorth * assetConfig.liquidationThreshold) / masterConstants.ASSET_COEFFICIENT_SCALE;
188
256
  if (assetWorth > gCollateralValue) {
189
257
  gCollateralValue = assetWorth;
190
258
  gCollateralAsset = key;
@@ -209,7 +277,7 @@ export function calculateLiquidationData(
209
277
  values.push(
210
278
  (bigIntMax(gCollateralValue / 2n, bigIntMin(gCollateralValue, 10_000_000_000n)) *
211
279
  loanDecimal *
212
- MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE) /
280
+ masterConstants.ASSET_COEFFICIENT_SCALE) /
213
281
  liquidationBonus /
214
282
  gLoanAssetPrice,
215
283
  );
@@ -251,7 +319,7 @@ export function calculateLiquidationData(
251
319
  }
252
320
 
253
321
  export function predictHealthFactor(args: PredictHealthFactorArgs): number {
254
- const liquidationData = calculateLiquidationData(args.assetsConfig, args.assetsData, args.balances, args.prices);
322
+ const liquidationData = calculateLiquidationData(args.assetsConfig, args.assetsData, args.balances, args.prices, args.masterConstants);
255
323
  const tokenHash = sha256Hash(args.tokenSymbol);
256
324
 
257
325
  const assetConfig = args.assetsConfig.get(tokenHash)!;
@@ -267,16 +335,15 @@ export function predictHealthFactor(args: PredictHealthFactorArgs): number {
267
335
  const currentBalance = assetPrice * Number(currentAmount) / Math.pow(10, decimals);
268
336
  const changeType = args.balanceChangeType;
269
337
 
270
- if (currentAmount != null && !Number.isNaN(currentAmount) &&
271
- Number.isFinite(currentAmount) && currentAmount != 0n) {
338
+ if (currentAmount != null && currentAmount != 0n) {
272
339
  if (changeType == BalanceChangeType.Borrow) {
273
- totalBorrow += currentBalance * (1 + Number(assetConfig.originationFee) / Number(MASTER_CONSTANTS.ASSET_ORIGINATION_FEE_SCALE));
340
+ totalBorrow += currentBalance * (1 + Number(assetConfig.originationFee) / Number(args.masterConstants.ASSET_ORIGINATION_FEE_SCALE));
274
341
  } else if (changeType == BalanceChangeType.Repay) {
275
342
  totalBorrow -= currentBalance;
276
343
  } else if (changeType == BalanceChangeType.Withdraw) {
277
- totalLimit -= currentBalance * Number(assetConfig.liquidationThreshold) / Number(MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE);
344
+ totalLimit -= currentBalance * Number(assetConfig.liquidationThreshold) / Number(args.masterConstants.ASSET_COEFFICIENT_SCALE);
278
345
  } else if (changeType == BalanceChangeType.Supply) {
279
- totalLimit += currentBalance * Number(assetConfig.liquidationThreshold) / Number(MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE);
346
+ totalLimit += currentBalance * Number(assetConfig.liquidationThreshold) / Number(args.masterConstants.ASSET_COEFFICIENT_SCALE);
280
347
  }
281
348
  }
282
349
  if (Number(totalLimit) == 0) {