@evaafi/sdk 0.2.0

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.
Files changed (50) hide show
  1. package/README.md +7 -0
  2. package/dist/api/helpers.d.ts +8 -0
  3. package/dist/api/helpers.js +33 -0
  4. package/dist/api/math.d.ts +20 -0
  5. package/dist/api/math.js +214 -0
  6. package/dist/api/parser.d.ts +8 -0
  7. package/dist/api/parser.js +227 -0
  8. package/dist/api/prices.d.ts +9 -0
  9. package/dist/api/prices.js +104 -0
  10. package/dist/constants.d.ts +38 -0
  11. package/dist/constants.js +42 -0
  12. package/dist/contracts/JettonWallet.d.ts +7 -0
  13. package/dist/contracts/JettonWallet.js +20 -0
  14. package/dist/contracts/MasterContract.d.ts +166 -0
  15. package/dist/contracts/MasterContract.js +217 -0
  16. package/dist/contracts/UserContract.d.ts +49 -0
  17. package/dist/contracts/UserContract.js +99 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.js +53 -0
  20. package/dist/types/Common.d.ts +5 -0
  21. package/dist/types/Common.js +2 -0
  22. package/dist/types/Master.d.ts +63 -0
  23. package/dist/types/Master.js +2 -0
  24. package/dist/types/Redstone.d.ts +15 -0
  25. package/dist/types/Redstone.js +2 -0
  26. package/dist/types/User.d.ts +55 -0
  27. package/dist/types/User.js +8 -0
  28. package/dist/utils/sha256BigInt.d.ts +1 -0
  29. package/dist/utils/sha256BigInt.js +13 -0
  30. package/dist/utils/tonConnectSender.d.ts +4 -0
  31. package/dist/utils/tonConnectSender.js +37 -0
  32. package/dist/utils/userJettonWallet.d.ts +2 -0
  33. package/dist/utils/userJettonWallet.js +37 -0
  34. package/package.json +38 -0
  35. package/src/api/helpers.ts +32 -0
  36. package/src/api/math.ts +252 -0
  37. package/src/api/parser.ts +277 -0
  38. package/src/api/prices.ts +127 -0
  39. package/src/constants.ts +53 -0
  40. package/src/contracts/JettonWallet.ts +20 -0
  41. package/src/contracts/MasterContract.ts +387 -0
  42. package/src/contracts/UserContract.ts +125 -0
  43. package/src/index.ts +78 -0
  44. package/src/types/Common.ts +6 -0
  45. package/src/types/Master.ts +70 -0
  46. package/src/types/Redstone.ts +15 -0
  47. package/src/types/User.ts +66 -0
  48. package/src/utils/sha256BigInt.ts +7 -0
  49. package/src/utils/tonConnectSender.ts +37 -0
  50. package/src/utils/userJettonWallet.ts +34 -0
@@ -0,0 +1,5 @@
1
+ import { Cell, Dictionary } from '@ton/core';
2
+ export type PriceData = {
3
+ dict: Dictionary<bigint, bigint>;
4
+ dataCell: Cell;
5
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,63 @@
1
+ /// <reference types="node" />
2
+ import { Address, Cell, Dictionary } from '@ton/core';
3
+ export type UpgradeConfig = {
4
+ masterCodeVersion: number;
5
+ userCodeVersion: number;
6
+ timeout: number;
7
+ updateTime: number;
8
+ freezeTime: number;
9
+ userCode: Cell;
10
+ blankCode: Cell;
11
+ newMasterCode: Cell | null;
12
+ newUserCode: Cell | null;
13
+ };
14
+ export type AssetConfig = {
15
+ oracle: bigint;
16
+ decimals: bigint;
17
+ collateralFactor: bigint;
18
+ liquidationThreshold: bigint;
19
+ liquidationBonus: bigint;
20
+ baseBorrowRate: bigint;
21
+ borrowRateSlopeLow: bigint;
22
+ borrowRateSlopeHigh: bigint;
23
+ supplyRateSlopeLow: bigint;
24
+ supplyRateSlopeHigh: bigint;
25
+ targetUtilization: bigint;
26
+ originationFee: bigint;
27
+ };
28
+ export type MasterConfig = {
29
+ ifActive: number;
30
+ admin: Address;
31
+ adminPK: Buffer;
32
+ tokenKeys: Cell | null;
33
+ walletToMaster: Cell | null;
34
+ };
35
+ export type AssetData = {
36
+ sRate: bigint;
37
+ bRate: bigint;
38
+ totalSupply: bigint;
39
+ totalBorrow: bigint;
40
+ lastAccural: bigint;
41
+ balance: bigint;
42
+ };
43
+ export type AssetInterest = {
44
+ supplyInterest: bigint;
45
+ borrowInterest: bigint;
46
+ };
47
+ export type AssetApy = {
48
+ supplyApy: number;
49
+ borrowApy: number;
50
+ };
51
+ export type ExtendedAssetData = AssetData & AssetInterest & AssetApy;
52
+ export type MasterData = {
53
+ meta: string;
54
+ upgradeConfig: UpgradeConfig;
55
+ masterConfig: MasterConfig;
56
+ assetsConfig: Dictionary<bigint, AssetConfig>;
57
+ assetsData: Dictionary<bigint, ExtendedAssetData>;
58
+ assetsReserves: Dictionary<bigint, bigint>;
59
+ apy: {
60
+ supply: Dictionary<bigint, number>;
61
+ borrow: Dictionary<bigint, number>;
62
+ };
63
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,15 @@
1
+ export type CoinData = {
2
+ id: string;
3
+ symbol: string;
4
+ provider: string;
5
+ value: number;
6
+ liteEvmSignature: string;
7
+ permawebTx: string;
8
+ version: string;
9
+ source: {
10
+ coingecko: number;
11
+ };
12
+ timestamp: number;
13
+ minutes: number;
14
+ providerPublicKey: string;
15
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,55 @@
1
+ import { Address, Cell, Dictionary } from '@ton/core';
2
+ export declare enum BalanceType {
3
+ supply = "supply",
4
+ borrow = "borrow"
5
+ }
6
+ export type UserBalance = {
7
+ amount: bigint;
8
+ type?: BalanceType;
9
+ };
10
+ export type UserLiqudationData = {
11
+ greatestCollateralValue: bigint;
12
+ greatestCollateralAsset: bigint;
13
+ greatestLoanValue: bigint;
14
+ greatestLoanAsset: bigint;
15
+ totalDebt: bigint;
16
+ totalLimit: bigint;
17
+ };
18
+ export type LiquidableData = UserLiqudationData & {
19
+ liquidable: true;
20
+ liquidationAmount: bigint;
21
+ minCollateralAmount: bigint;
22
+ };
23
+ export type NonLiquidableData = UserLiqudationData & {
24
+ liquidable: false;
25
+ };
26
+ export type LiquidationData = LiquidableData | NonLiquidableData;
27
+ export type UserLiteData = {
28
+ type: 'active';
29
+ codeVersion: number;
30
+ masterAddress: Address;
31
+ ownerAddress: Address;
32
+ principals: Dictionary<bigint, bigint>;
33
+ state: number;
34
+ balances: Dictionary<bigint, UserBalance>;
35
+ trackingSupplyIndex: bigint;
36
+ trackingBorrowIndex: bigint;
37
+ dutchAuctionStart: number;
38
+ backupCell: Cell;
39
+ };
40
+ export type UserDataActive = UserLiteData & {
41
+ withdrawalLimits: Dictionary<bigint, bigint>;
42
+ borrowLimits: Dictionary<bigint, bigint>;
43
+ repayLimits?: Dictionary<bigint, bigint>;
44
+ supplyBalance: bigint;
45
+ borrowBalance: bigint;
46
+ availableToBorrow: bigint;
47
+ limitUsedPercent: number;
48
+ limitUsed: bigint;
49
+ healthFactor: number;
50
+ liquidationData: LiquidationData;
51
+ };
52
+ export type UserDataInactive = {
53
+ type: 'inactive';
54
+ };
55
+ export type UserData = UserDataActive | UserDataInactive;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BalanceType = void 0;
4
+ var BalanceType;
5
+ (function (BalanceType) {
6
+ BalanceType["supply"] = "supply";
7
+ BalanceType["borrow"] = "borrow";
8
+ })(BalanceType || (exports.BalanceType = BalanceType = {}));
@@ -0,0 +1 @@
1
+ export declare function sha256Hash(input: string): bigint;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.sha256Hash = void 0;
7
+ const sha256_1 = __importDefault(require("crypto-js/sha256"));
8
+ function sha256Hash(input) {
9
+ const hash = (0, sha256_1.default)(input);
10
+ const hashHex = hash.toString();
11
+ return BigInt('0x' + hashHex);
12
+ }
13
+ exports.sha256Hash = sha256Hash;
@@ -0,0 +1,4 @@
1
+ import { ITonConnect, SendTransactionResponse } from '@tonconnect/sdk';
2
+ import { Sender } from '@ton/core';
3
+ export declare function getLastSentBoc(): SendTransactionResponse | undefined;
4
+ export declare function getTonConnectSender(connector: ITonConnect): Sender;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTonConnectSender = exports.getLastSentBoc = void 0;
4
+ const core_1 = require("@ton/core");
5
+ /*
6
+ This is not the best solution to get the BOC of the sent external message, however the Sender
7
+ interface does not support returning any value from send(), so at the moment you can get it from
8
+ this global variable.
9
+ */
10
+ let lastSentBoc;
11
+ function getLastSentBoc() {
12
+ return lastSentBoc;
13
+ }
14
+ exports.getLastSentBoc = getLastSentBoc;
15
+ function getTonConnectSender(connector) {
16
+ return {
17
+ get address() {
18
+ return connector.account ? core_1.Address.parse(connector.account.address) : undefined;
19
+ },
20
+ async send(args) {
21
+ lastSentBoc = await connector.sendTransaction({
22
+ validUntil: Date.now() + 2 * 60 * 1000, // 1 minutes
23
+ messages: [
24
+ {
25
+ address: args.to.toString(),
26
+ amount: args.value.toString(),
27
+ payload: args.body?.toBoc().toString('base64'),
28
+ stateInit: args.init
29
+ ? (0, core_1.beginCell)().store((0, core_1.storeStateInit)(args.init)).endCell().toBoc().toString('base64')
30
+ : undefined,
31
+ },
32
+ ],
33
+ });
34
+ },
35
+ };
36
+ }
37
+ exports.getTonConnectSender = getTonConnectSender;
@@ -0,0 +1,2 @@
1
+ import { Address } from '@ton/core';
2
+ export declare function getUserJettonWallet(ownerAddress: Address, assetID: bigint, network: 'mainnet' | 'testnet'): Address;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getUserJettonWallet = void 0;
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
+ switch (assetID) {
9
+ case constants_1.ASSET_ID.jUSDT:
10
+ if (network === 'mainnet') {
11
+ builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDT_MAINNET);
12
+ }
13
+ else {
14
+ builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDT_TESTNET);
15
+ }
16
+ break;
17
+ case constants_1.ASSET_ID.jUSDC:
18
+ if (network === 'mainnet') {
19
+ builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDC_MAINNET);
20
+ }
21
+ else {
22
+ builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDC_TESTNET);
23
+ }
24
+ break;
25
+ default:
26
+ throw new Error('Unsupported asset');
27
+ }
28
+ const data = builder.storeRef(constants_1.JETTON_WALLET_CODE).endCell();
29
+ const stateInit = (0, core_1.beginCell)()
30
+ .store((0, core_1.storeStateInit)({
31
+ code: constants_1.JETTON_WALLET_CODE,
32
+ data: data,
33
+ }))
34
+ .endCell();
35
+ return new core_1.Address(0, stateInit.hash());
36
+ }
37
+ exports.getUserJettonWallet = getUserJettonWallet;
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@evaafi/sdk",
3
+ "version": "0.2.0",
4
+ "description": "SDK for EVAA contracts",
5
+ "main": "dist/index.js",
6
+ "files": [
7
+ "dist",
8
+ "src"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc --declaration"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/evaafi/sdk.git"
16
+ },
17
+ "author": "EVAA Finance",
18
+ "license": "MIT",
19
+ "homepage": "https://github.com/evaafi/sdk#readme",
20
+ "devDependencies": {
21
+ "@types/node": "^20.10.4",
22
+ "prettier": "^3.2.4",
23
+ "ts-node": "^10.9.1",
24
+ "typescript": "^5.3.3",
25
+ "@ton/core": "0.56.0",
26
+ "@tonconnect/sdk": "^3.0.0",
27
+ "crypto-js": "^4.2.0",
28
+ "ethereumjs-util": "7.0.10",
29
+ "ethers": "5.6.9"
30
+ },
31
+ "peerDependencies": {
32
+ "@ton/core": ">=0.56.0",
33
+ "@tonconnect/sdk": ">=3.0.0",
34
+ "crypto-js": ">=4.2.0",
35
+ "ethereumjs-util": "7.0.10",
36
+ "ethers": "5.6.9"
37
+ }
38
+ }
@@ -0,0 +1,32 @@
1
+ import { Cell, Slice } from '@ton/core';
2
+
3
+ class MyCell extends Cell {
4
+ toString() {
5
+ return this.hashBigInt().toString();
6
+ }
7
+
8
+ hashBigInt() {
9
+ return BigInt('0x' + this.hash().toString('hex'));
10
+ }
11
+ }
12
+
13
+ export function loadMyRef(slice: Slice): MyCell {
14
+ const cell = slice.loadRef();
15
+ return new MyCell({
16
+ exotic: cell.isExotic,
17
+ bits: cell.bits,
18
+ refs: cell.refs,
19
+ });
20
+ }
21
+
22
+ export function loadMaybeMyRef(slice: Slice): Cell | null {
23
+ const cell = slice.loadMaybeRef();
24
+ if (cell === null) {
25
+ return null;
26
+ }
27
+ return new MyCell({
28
+ exotic: cell.isExotic,
29
+ bits: cell.bits,
30
+ refs: cell.refs,
31
+ });
32
+ }
@@ -0,0 +1,252 @@
1
+ import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData } from '../types/Master';
2
+ import { MASTER_CONSTANTS } from '../constants';
3
+ import { Dictionary } from '@ton/core';
4
+ import { BalanceType, LiquidationData, UserBalance } from '../types/User';
5
+
6
+ export function mulFactor(decimal: bigint, a: bigint, b: bigint): bigint {
7
+ return (a * b) / decimal;
8
+ }
9
+
10
+ export function mulDiv(x: bigint, y: bigint, z: bigint): bigint {
11
+ return (x * y) / z;
12
+ }
13
+
14
+ export function bigIntMax(...args: bigint[]): bigint {
15
+ return args.reduce((m, e) => (e > m ? e : m));
16
+ }
17
+ export function bigIntMin(...args: bigint[]): bigint {
18
+ return args.reduce((m, e) => (e < m ? e : m));
19
+ }
20
+
21
+ export function calculatePresentValue(index: bigint, principalValue: bigint): bigint {
22
+ return (principalValue * index) / MASTER_CONSTANTS.FACTOR_SCALE;
23
+ }
24
+
25
+ export function calculateCurrentRates(assetConfig: AssetConfig, assetData: AssetData) {
26
+ const now = BigInt(Math.floor(Date.now() / 1000));
27
+ const timeElapsed = now - assetData.lastAccural;
28
+ const { supplyInterest, borrowInterest } = calculateAssetInterest(assetConfig, assetData);
29
+
30
+ if (timeElapsed > 0) {
31
+ const updatedSRate =
32
+ assetData.sRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.sRate, supplyInterest * timeElapsed);
33
+ const updatedBRate =
34
+ assetData.bRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.bRate, borrowInterest * timeElapsed);
35
+ return {
36
+ sRate: updatedSRate,
37
+ bRate: updatedBRate,
38
+ supplyInterest,
39
+ borrowInterest,
40
+ now,
41
+ };
42
+ }
43
+
44
+ return {
45
+ sRate: assetData.sRate,
46
+ bRate: assetData.bRate,
47
+ supplyInterest,
48
+ borrowInterest,
49
+ now,
50
+ };
51
+ }
52
+
53
+ export function calculateAssetData(
54
+ assetsConfigDict: Dictionary<bigint, AssetConfig>,
55
+ assetsDataDict: Dictionary<bigint, AssetData>,
56
+ assetId: bigint,
57
+ ): ExtendedAssetData {
58
+ const config = assetsConfigDict.get(assetId); // maybe it's a huge mistake could be
59
+ const data = assetsDataDict.get(assetId);
60
+
61
+ if (!data || !config) {
62
+ throw new Error('Asset Data or Config is not accessible');
63
+ }
64
+
65
+ const { sRate, bRate, supplyInterest, borrowInterest, now } = calculateCurrentRates(config, data);
66
+ data.sRate = sRate || 0n;
67
+ data.bRate = bRate || 0n;
68
+ data.lastAccural = now;
69
+
70
+ const supplyApy = (1 + (Number(supplyInterest) / 1e12) * 24 * 3600) ** 365 - 1;
71
+ const borrowApy = (1 + (Number(borrowInterest) / 1e12) * 24 * 3600) ** 365 - 1;
72
+
73
+ return {
74
+ ...data,
75
+ ...{ supplyInterest, borrowInterest },
76
+ ...{ supplyApy, borrowApy },
77
+ };
78
+ }
79
+
80
+ export function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData): AssetInterest {
81
+ const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply);
82
+ const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow);
83
+ let utilization = 0n;
84
+ let supplyInterest = 0n;
85
+ let borrowInterest = 0n;
86
+
87
+ if (totalSupply !== 0n) {
88
+ utilization = (totalBorrow * MASTER_CONSTANTS.FACTOR_SCALE) / totalSupply;
89
+ }
90
+
91
+ if (utilization <= assetConfig.targetUtilization) {
92
+ borrowInterest =
93
+ assetConfig.baseBorrowRate +
94
+ mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, utilization);
95
+ } else {
96
+ borrowInterest =
97
+ assetConfig.baseBorrowRate +
98
+ mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, assetConfig.targetUtilization) +
99
+ mulFactor(
100
+ MASTER_CONSTANTS.FACTOR_SCALE,
101
+ assetConfig.borrowRateSlopeHigh,
102
+ utilization - assetConfig.targetUtilization,
103
+ );
104
+ }
105
+
106
+ const reserveFactor = 10n;
107
+ const reserveScale = 100n;
108
+ supplyInterest = mulDiv(
109
+ mulDiv(borrowInterest, utilization, MASTER_CONSTANTS.FACTOR_SCALE),
110
+ reserveScale - reserveFactor,
111
+ reserveScale,
112
+ );
113
+
114
+ return {
115
+ supplyInterest,
116
+ borrowInterest,
117
+ };
118
+ }
119
+
120
+ export function getAvailableToBorrow(
121
+ assetsConfig: Dictionary<bigint, AssetConfig>,
122
+ assetsData: Dictionary<bigint, ExtendedAssetData>,
123
+ principals: Dictionary<bigint, bigint>,
124
+ prices: Dictionary<bigint, bigint>,
125
+ ): bigint {
126
+ let borrowLimit = 0n;
127
+ let borrowAmount = 0n;
128
+
129
+ for (const assetID of principals.keys()) {
130
+ const assetConfig = assetsConfig.get(assetID) as AssetConfig;
131
+ const assetData = assetsData.get(assetID) as ExtendedAssetData;
132
+ const price = prices.get(assetID) as bigint;
133
+ const principal = principals.get(assetID) as bigint;
134
+
135
+ if (principal < 0) {
136
+ borrowAmount += (calculatePresentValue(assetData.bRate, -principal) * price) / 10n ** assetConfig.decimals;
137
+ } else if (principal > 0) {
138
+ borrowLimit +=
139
+ (calculatePresentValue(assetData.sRate, principal) * price * assetConfig.collateralFactor) /
140
+ 10n ** assetConfig.decimals /
141
+ MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
142
+ }
143
+ }
144
+
145
+ return borrowLimit - borrowAmount;
146
+ }
147
+
148
+ export function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint): UserBalance {
149
+ if (principalValue > 0) {
150
+ return {
151
+ amount: calculatePresentValue(sRate, principalValue),
152
+ type: BalanceType.supply,
153
+ };
154
+ } else if (principalValue < 0) {
155
+ return {
156
+ amount: calculatePresentValue(bRate, -principalValue),
157
+ type: BalanceType.borrow,
158
+ };
159
+ } else {
160
+ return {
161
+ amount: 0n,
162
+ type: undefined,
163
+ };
164
+ }
165
+ }
166
+
167
+ export function calculateLiquidationData(
168
+ assetsConfig: Dictionary<bigint, AssetConfig>,
169
+ assetsData: Dictionary<bigint, ExtendedAssetData>,
170
+ principals: Dictionary<bigint, bigint>,
171
+ prices: Dictionary<bigint, bigint>,
172
+ ): LiquidationData {
173
+ let gCollateralValue = 0n;
174
+ let gCollateralAsset = 0n;
175
+ let gLoanValue = 0n;
176
+ let gLoanAsset = 0n;
177
+ let totalDebt = 0n;
178
+ let totalLimit = 0n;
179
+
180
+ for (const key of principals.keys()) {
181
+ const principal = principals.get(key)!;
182
+ const assetConfig = assetsConfig.get(key)!;
183
+ const assetData = assetsData.get(key)!;
184
+ const balance =
185
+ principal > 0 ? (principal * assetData.sRate) / BigInt(1e12) : (principal * assetData.bRate) / BigInt(1e12);
186
+ if (balance > 0) {
187
+ const assetWorth = (balance * prices.get(key)!) / 10n ** assetConfig.decimals;
188
+ totalLimit += (assetWorth * assetConfig.liquidationThreshold) / MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
189
+ if (assetWorth > gCollateralValue) {
190
+ gCollateralValue = assetWorth;
191
+ gCollateralAsset = key;
192
+ }
193
+ } else if (balance < 0) {
194
+ const assetWorth = (-balance * prices.get(key)!) / 10n ** assetConfig.decimals;
195
+ totalDebt += assetWorth;
196
+ if (assetWorth > gLoanValue) {
197
+ gLoanValue = assetWorth;
198
+ gLoanAsset = key;
199
+ }
200
+ }
201
+ }
202
+
203
+ if (totalLimit < totalDebt) {
204
+ const gLoanAssetPrice = prices.get(gLoanAsset)!;
205
+ const values: bigint[] = [];
206
+ const gCollateralAssetConfig = assetsConfig.get(gCollateralAsset)!;
207
+ const gLoanAssetConfig = assetsConfig.get(gLoanAsset)!;
208
+ const liquidationBonus = gLoanAssetConfig.liquidationBonus;
209
+ const loanDecimal = 10n ** gLoanAssetConfig.decimals;
210
+ values.push(
211
+ (bigIntMax(gCollateralValue / 2n, bigIntMin(gCollateralValue, 10_000_000_000n)) *
212
+ loanDecimal *
213
+ MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE) /
214
+ liquidationBonus /
215
+ gLoanAssetPrice,
216
+ );
217
+ values.push((gLoanValue * loanDecimal) / gLoanAssetPrice);
218
+
219
+ const liquidationAmount = (bigIntMin(...values) as bigint) - 5n;
220
+ const gCollateralAssetPrice: bigint = prices.get(gCollateralAsset)!;
221
+ const collateralDecimal = 10n ** gCollateralAssetConfig.decimals;
222
+ let minCollateralAmount =
223
+ (((liquidationAmount * gLoanAssetPrice * liquidationBonus) / 10000n) * collateralDecimal) /
224
+ gCollateralAssetPrice /
225
+ loanDecimal -
226
+ 10n;
227
+ minCollateralAmount = (minCollateralAmount * 97n) / 100n;
228
+ if (minCollateralAmount / collateralDecimal >= 1n) {
229
+ return {
230
+ greatestCollateralAsset: gCollateralAsset,
231
+ greatestCollateralValue: gCollateralValue,
232
+ greatestLoanAsset: gLoanAsset,
233
+ greatestLoanValue: gLoanValue,
234
+ totalDebt,
235
+ totalLimit,
236
+ liquidable: true,
237
+ liquidationAmount,
238
+ minCollateralAmount,
239
+ };
240
+ }
241
+ }
242
+
243
+ return {
244
+ greatestCollateralAsset: gCollateralAsset,
245
+ greatestCollateralValue: gCollateralValue,
246
+ greatestLoanAsset: gLoanAsset,
247
+ greatestLoanValue: gLoanValue,
248
+ totalDebt,
249
+ totalLimit,
250
+ liquidable: false,
251
+ };
252
+ }