@evaafi/sdk 0.6.2-a → 0.6.2-b

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/README.md CHANGED
@@ -3,5 +3,6 @@
3
3
  The EVAA SDK is designed to easily integrate with the EVAA lending protocol on TON blockchain.
4
4
 
5
5
  ## Documentation
6
+ You can find the Typedoc documentation [here](https://evaafi.github.io/sdk/).
6
7
 
7
- You can find the documentation in the [docs](./docs) folder.
8
+ Additional (older) documentation can also be found in the [docs](./docs) folder.
@@ -1,6 +1,6 @@
1
1
  import { AgregatedBalances, AssetConfig, AssetData, AssetInterest, ExtendedAssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConstants, PoolConfig } from '../types/Master';
2
2
  import { Dictionary } from '@ton/core';
3
- import { HealthParamsArgs, LiquidationData, PredictHealthFactorArgs, UserBalance } from '../types/User';
3
+ import { HealthParamsArgs, LiquidationData, PredictAPYArgs, PredictHealthFactorArgs, UserBalance } from '../types/User';
4
4
  export declare function mulFactor(decimal: bigint, a: bigint, b: bigint): bigint;
5
5
  export declare function mulDiv(x: bigint, y: bigint, z: bigint): bigint;
6
6
  export declare function mulDivC(x: bigint, y: bigint, z: bigint): bigint;
@@ -25,6 +25,7 @@ export declare function calculateCurrentRates(assetConfig: AssetConfig, assetDat
25
25
  };
26
26
  export declare function calculateAssetData(assetsConfigDict: ExtendedAssetsConfig, assetsDataDict: Dictionary<bigint, AssetData>, assetId: bigint, masterConstants: MasterConstants): ExtendedAssetData;
27
27
  export declare function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData, masterConstants: MasterConstants): AssetInterest;
28
+ export declare function calculateInterestWithSupplyBorrow(totalSupply: bigint, totalBorrow: bigint, assetConfig: AssetConfig, masterConstants: MasterConstants): AssetInterest;
28
29
  export declare function checkNotInDebtAtAll(principals: Dictionary<bigint, bigint>): boolean;
29
30
  export declare function getAgregatedBalances(assetsData: ExtendedAssetsData, assetsConfig: ExtendedAssetsConfig, principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>, masterConstants: MasterConstants): AgregatedBalances;
30
31
  export declare function calculateMaximumWithdrawAmount(assetsConfig: ExtendedAssetsConfig, assetsData: ExtendedAssetsData, principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>, masterConstants: MasterConstants, assetId: bigint): bigint;
@@ -59,3 +60,11 @@ export declare function calculateHealthParams(parameters: HealthParamsArgs): {
59
60
  */
60
61
  export declare function calculateLiquidationData(assetsConfig: ExtendedAssetsConfig, assetsData: ExtendedAssetsData, principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>, poolConfig: PoolConfig): LiquidationData;
61
62
  export declare function predictHealthFactor(args: PredictHealthFactorArgs): number;
63
+ /**
64
+ * Predicts how APY will change as a result of one of the actions Borrow, Supply, Withdraw or Repay.
65
+ *
66
+ * Used on the front-end.
67
+ *
68
+ * @returns Estimated APYs for Supply and Borrow
69
+ */
70
+ export declare function predictAPY(args: PredictAPYArgs): AssetInterest;
package/dist/api/math.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.predictHealthFactor = exports.calculateLiquidationData = exports.calculateHealthParams = exports.presentValue = exports.getAvailableToBorrow = exports.calculateMaximumWithdrawAmount = exports.getAgregatedBalances = exports.checkNotInDebtAtAll = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.BigMath = exports.bigIntMin = exports.bigIntMax = exports.bigAbs = exports.mulDivC = exports.mulDiv = exports.mulFactor = void 0;
3
+ exports.predictAPY = exports.predictHealthFactor = exports.calculateLiquidationData = exports.calculateHealthParams = exports.presentValue = exports.getAvailableToBorrow = exports.calculateMaximumWithdrawAmount = exports.getAgregatedBalances = exports.checkNotInDebtAtAll = exports.calculateInterestWithSupplyBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.BigMath = exports.bigIntMin = exports.bigIntMax = exports.bigAbs = exports.mulDivC = exports.mulDiv = exports.mulFactor = void 0;
4
4
  const User_1 = require("../types/User");
5
5
  const assets_1 = require("../constants/assets");
6
6
  const liquidation_1 = require("./liquidation");
@@ -81,6 +81,10 @@ exports.calculateAssetData = calculateAssetData;
81
81
  function calculateAssetInterest(assetConfig, assetData, masterConstants) {
82
82
  const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply, masterConstants);
83
83
  const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow, masterConstants);
84
+ return calculateInterestWithSupplyBorrow(totalSupply, totalBorrow, assetConfig, masterConstants);
85
+ }
86
+ exports.calculateAssetInterest = calculateAssetInterest;
87
+ function calculateInterestWithSupplyBorrow(totalSupply, totalBorrow, assetConfig, masterConstants) {
84
88
  let utilization = 0n;
85
89
  let supplyInterest = 0n;
86
90
  let borrowInterest = 0n;
@@ -104,7 +108,7 @@ function calculateAssetInterest(assetConfig, assetData, masterConstants) {
104
108
  borrowInterest
105
109
  };
106
110
  }
107
- exports.calculateAssetInterest = calculateAssetInterest;
111
+ exports.calculateInterestWithSupplyBorrow = calculateInterestWithSupplyBorrow;
108
112
  function checkNotInDebtAtAll(principals) {
109
113
  return principals.values().every(x => x >= 0n);
110
114
  }
@@ -173,10 +177,16 @@ function getAvailableToBorrow(assetsConfig, assetsData, principals, prices, mast
173
177
  let borrowLimit = 0n;
174
178
  let borrowAmount = 0n;
175
179
  for (const assetID of principals.keys()) {
180
+ const principal = principals.get(assetID);
181
+ if (principal == 0n) {
182
+ continue;
183
+ }
184
+ if (!prices.has(assetID)) {
185
+ return 0n;
186
+ }
176
187
  const assetConfig = assetsConfig.get(assetID);
177
188
  const assetData = assetsData.get(assetID);
178
189
  const price = prices.get(assetID);
179
- const principal = principals.get(assetID);
180
190
  if (principal < 0n) {
181
191
  borrowAmount += mulDiv(calculatePresentValue(assetData.bRate, -principal, masterConstants), price, 10n ** assetConfig.decimals);
182
192
  }
@@ -359,7 +369,6 @@ function predictHealthFactor(args) {
359
369
  const assetId = args.asset.assetId;
360
370
  const assetConfig = args.assetsConfig.get(assetId);
361
371
  const assetPrice = Number(args.prices.get(assetId));
362
- const assetData = args.assetsData.get(assetId);
363
372
  let totalLimit = Number(healthParams.totalLimit);
364
373
  let totalBorrow = Number(healthParams.totalDebt);
365
374
  const currentAmount = args.amount;
@@ -386,3 +395,35 @@ function predictHealthFactor(args) {
386
395
  return Math.min(Math.max(1 - totalBorrow / totalLimit, 0), 1); // let's limit a result to zero below and one above
387
396
  }
388
397
  exports.predictHealthFactor = predictHealthFactor;
398
+ /**
399
+ * Predicts how APY will change as a result of one of the actions Borrow, Supply, Withdraw or Repay.
400
+ *
401
+ * Used on the front-end.
402
+ *
403
+ * @returns Estimated APYs for Supply and Borrow
404
+ */
405
+ function predictAPY(args) {
406
+ const assetConfig = args.assetConfig;
407
+ const assetData = args.assetData;
408
+ const masterConstants = args.masterConstants;
409
+ let totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply, masterConstants);
410
+ let totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow, masterConstants);
411
+ const currentAmount = args.amount;
412
+ const changeType = args.balanceChangeType;
413
+ if (currentAmount != null && currentAmount != 0n) {
414
+ if (changeType == User_1.BalanceChangeType.Borrow) {
415
+ totalBorrow += currentAmount;
416
+ }
417
+ else if (changeType == User_1.BalanceChangeType.Repay) {
418
+ totalBorrow -= currentAmount;
419
+ }
420
+ else if (changeType == User_1.BalanceChangeType.Withdraw) {
421
+ totalSupply -= currentAmount;
422
+ }
423
+ else if (changeType == User_1.BalanceChangeType.Supply) {
424
+ totalSupply += currentAmount;
425
+ }
426
+ }
427
+ return calculateInterestWithSupplyBorrow(totalSupply, totalBorrow, assetConfig, masterConstants);
428
+ }
429
+ exports.predictAPY = predictAPY;
@@ -24,8 +24,8 @@ function createAssetData() {
24
24
  serialize: (src, buidler) => {
25
25
  buidler.storeUint(src.sRate, 64);
26
26
  buidler.storeUint(src.bRate, 64);
27
- buidler.storeUint(src.totalSupply, 64);
28
- buidler.storeUint(src.totalBorrow, 64);
27
+ buidler.storeInt(src.totalSupply, 64);
28
+ buidler.storeInt(src.totalBorrow, 64);
29
29
  buidler.storeUint(src.lastAccural, 32);
30
30
  buidler.storeUint(src.balance, 64);
31
31
  buidler.storeUint(src.trackingSupplyIndex, 64);
@@ -33,15 +33,15 @@ function createAssetData() {
33
33
  buidler.storeUint(src.awaitedSupply, 64);
34
34
  },
35
35
  parse: (src) => {
36
- const sRate = BigInt(src.loadInt(64));
37
- const bRate = BigInt(src.loadInt(64));
38
- const totalSupply = BigInt(src.loadInt(64));
39
- const totalBorrow = BigInt(src.loadInt(64));
40
- const lastAccural = BigInt(src.loadInt(32));
41
- const balance = BigInt(src.loadInt(64));
42
- const trackingSupplyIndex = BigInt(src.loadUint(64));
43
- const trackingBorrowIndex = BigInt(src.loadUint(64));
44
- const awaitedSupply = BigInt(src.loadUint(64));
36
+ const sRate = BigInt(src.loadUintBig(64));
37
+ const bRate = BigInt(src.loadUintBig(64));
38
+ const totalSupply = BigInt(src.loadIntBig(64));
39
+ const totalBorrow = BigInt(src.loadIntBig(64));
40
+ const lastAccural = BigInt(src.loadUintBig(32));
41
+ const balance = BigInt(src.loadUintBig(64));
42
+ const trackingSupplyIndex = BigInt(src.loadUintBig(64));
43
+ const trackingBorrowIndex = BigInt(src.loadUintBig(64));
44
+ const awaitedSupply = BigInt(src.loadUintBig(64));
45
45
  return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance, trackingSupplyIndex, trackingBorrowIndex, awaitedSupply };
46
46
  },
47
47
  };
@@ -238,6 +238,7 @@ function parseUserLiteData(userDataBOC, assetsData, assetsConfig, poolConfig, ap
238
238
  trackingBorrowIndex: trackingBorrowIndex,
239
239
  dutchAuctionStart: dutchAuctionStart,
240
240
  backupCell: backupCell,
241
+ fullyParsed: false,
241
242
  rewards: rewards,
242
243
  backupCell1: backupCell1,
243
244
  backupCell2: backupCell2,
@@ -245,12 +246,22 @@ function parseUserLiteData(userDataBOC, assetsData, assetsConfig, poolConfig, ap
245
246
  }
246
247
  exports.parseUserLiteData = parseUserLiteData;
247
248
  function parseUserData(userLiteData, assetsData, assetsConfig, prices, poolConfig, applyDust = false) {
249
+ userLiteData.fullyParsed = true;
250
+ let havePrincipalWithoutPrice = false;
248
251
  const poolAssetsConfig = poolConfig.poolAssetsConfig;
249
252
  const masterConstants = poolConfig.masterConstants;
250
253
  const withdrawalLimits = core_1.Dictionary.empty();
251
254
  const borrowLimits = core_1.Dictionary.empty();
252
255
  let supplyBalance = 0n;
253
256
  let borrowBalance = 0n;
257
+ for (const [assetId, principal] of userLiteData.realPrincipals) {
258
+ if (!prices.has(assetId)) {
259
+ userLiteData.fullyParsed = false;
260
+ if (principal != 0n) {
261
+ havePrincipalWithoutPrice = true;
262
+ }
263
+ }
264
+ }
254
265
  for (const [_, asset] of Object.entries(poolAssetsConfig)) {
255
266
  const assetData = assetsData.get(asset.assetId);
256
267
  const assetConfig = assetsConfig.get(asset.assetId);
@@ -263,6 +274,9 @@ function parseUserData(userLiteData, assetsData, assetsConfig, prices, poolConfi
263
274
  userLiteData.balances.set(asset.assetId, balance);
264
275
  }
265
276
  for (const [_, asset] of Object.entries(poolAssetsConfig)) {
277
+ if (!prices.has(asset.assetId)) {
278
+ continue;
279
+ }
266
280
  const assetConfig = assetsConfig.get(asset.assetId);
267
281
  const balance = userLiteData.balances.get(asset.assetId);
268
282
  if (balance.type === User_1.BalanceType.supply) {
@@ -272,13 +286,17 @@ function parseUserData(userLiteData, assetsData, assetsConfig, prices, poolConfi
272
286
  borrowBalance += (balance.amount * prices.get(asset.assetId)) / 10n ** assetConfig.decimals;
273
287
  }
274
288
  }
275
- const availableToBorrow = (0, math_1.getAvailableToBorrow)(assetsConfig, assetsData, userLiteData.principals, prices, masterConstants);
289
+ const availableToBorrow = (0, math_1.getAvailableToBorrow)(assetsConfig, assetsData, userLiteData.realPrincipals, prices, masterConstants);
276
290
  for (const [_, asset] of Object.entries(poolAssetsConfig)) {
291
+ const balance = userLiteData.balances.get(asset.assetId);
277
292
  const assetConfig = assetsConfig.get(asset.assetId);
278
293
  const assetData = assetsData.get(asset.assetId);
279
- const balance = userLiteData.balances.get(asset.assetId);
280
294
  if (balance.type === User_1.BalanceType.supply) {
281
- withdrawalLimits.set(asset.assetId, (0, math_1.bigIntMin)((0, math_1.calculateMaximumWithdrawAmount)(assetsConfig, assetsData, userLiteData.principals, prices, masterConstants, asset.assetId), assetData.balance));
295
+ withdrawalLimits.set(asset.assetId, (0, math_1.bigIntMin)((0, math_1.calculateMaximumWithdrawAmount)(assetsConfig, assetsData, userLiteData.realPrincipals, prices, masterConstants, asset.assetId), assetData.balance));
296
+ }
297
+ if (!prices.has(asset.assetId)) {
298
+ borrowLimits.set(asset.assetId, 0n);
299
+ continue;
282
300
  }
283
301
  borrowLimits.set(asset.assetId, (0, math_1.bigIntMax)(0n, (0, math_1.bigIntMin)((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(asset.assetId), assetData.balance, assetData.totalSupply - assetData.totalBorrow)));
284
302
  }
@@ -286,10 +304,13 @@ function parseUserData(userLiteData, assetsData, assetsConfig, prices, poolConfi
286
304
  const limitUsedPercent = limitUsed === 0n
287
305
  ? 0
288
306
  : Number(BigInt(1e9) - (availableToBorrow * BigInt(1e9)) / (borrowBalance + availableToBorrow)) / 1e7;
289
- const liquidationData = (0, math_1.calculateLiquidationData)(assetsConfig, assetsData, userLiteData.principals, prices, poolConfig);
290
307
  let healthFactor = 1;
291
- if (liquidationData.totalLimit != 0n) {
292
- healthFactor = 1 - Number(liquidationData.totalDebt) / Number(liquidationData.totalLimit);
308
+ let liquidationData;
309
+ if (!havePrincipalWithoutPrice) {
310
+ liquidationData = (0, math_1.calculateLiquidationData)(assetsConfig, assetsData, userLiteData.realPrincipals, prices, poolConfig);
311
+ if (liquidationData.totalLimit != 0n) {
312
+ healthFactor = 1 - Number(liquidationData.totalDebt) / Number(liquidationData.totalLimit);
313
+ }
293
314
  }
294
315
  return {
295
316
  ...userLiteData,
@@ -302,6 +323,7 @@ function parseUserData(userLiteData, assetsData, assetsConfig, prices, poolConfi
302
323
  limitUsed: limitUsed,
303
324
  liquidationData: liquidationData,
304
325
  healthFactor: healthFactor,
326
+ havePrincipalWithoutPrice: havePrincipalWithoutPrice
305
327
  };
306
328
  }
307
329
  exports.parseUserData = parseUserData;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { mulFactor, mulDiv, bigIntMin, bigIntMax, calculatePresentValue, calculateCurrentRates, calculateAssetData, calculateAssetInterest, getAvailableToBorrow, calculateMaximumWithdrawAmount, presentValue, calculateLiquidationData, predictHealthFactor, calculateHealthParams, BigMath, } from './api/math';
1
+ export { mulFactor, mulDiv, bigIntMin, bigIntMax, calculatePresentValue, calculateCurrentRates, calculateAssetData, calculateAssetInterest, getAvailableToBorrow, calculateMaximumWithdrawAmount, presentValue, calculateLiquidationData, predictHealthFactor, calculateHealthParams, calculateInterestWithSupplyBorrow, predictAPY, BigMath, } from './api/math';
2
2
  export { calculateLiquidationAmounts, calculateMinCollateralByTransferredAmount, isLiquidatable, isBadDebt, addReserve, deductReserve, addLiquidationBonus, deductLiquidationBonus, toAssetAmount, toAssetWorth, PreparedAssetInfo, PreparedAssetInfoResult, prepareAssetInfo, findAssetById, selectGreatestAssets, calculateAssetsValues, AssetsValues, SelectedAssets, } from './api/liquidation';
3
3
  export { createAssetData, createAssetConfig, parseMasterData, parseUserData, parseUserLiteData } from './api/parser';
4
4
  export { getPrices } from './api/prices';
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.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.NOT_MAINNET = exports.UTON_MAINNET = exports.CATI_MAINNET = exports.DOGS_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_ALTS_POOL_CONFIG = exports.MAINNET_LP_POOL_CONFIG = void 0;
17
+ 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.predictAPY = exports.calculateInterestWithSupplyBorrow = 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.NOT_MAINNET = exports.UTON_MAINNET = exports.CATI_MAINNET = exports.DOGS_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_ALTS_POOL_CONFIG = exports.MAINNET_LP_POOL_CONFIG = exports.TESTNET_POOL_CONFIG = exports.MAINNET_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; } });
@@ -32,6 +32,8 @@ Object.defineProperty(exports, "presentValue", { enumerable: true, get: function
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
34
  Object.defineProperty(exports, "calculateHealthParams", { enumerable: true, get: function () { return math_1.calculateHealthParams; } });
35
+ Object.defineProperty(exports, "calculateInterestWithSupplyBorrow", { enumerable: true, get: function () { return math_1.calculateInterestWithSupplyBorrow; } });
36
+ Object.defineProperty(exports, "predictAPY", { enumerable: true, get: function () { return math_1.predictAPY; } });
35
37
  Object.defineProperty(exports, "BigMath", { enumerable: true, get: function () { return math_1.BigMath; } });
36
38
  var liquidation_1 = require("./api/liquidation");
37
39
  Object.defineProperty(exports, "calculateLiquidationAmounts", { enumerable: true, get: function () { return liquidation_1.calculateLiquidationAmounts; } });
@@ -119,5 +119,5 @@ _PricesCollector_prices = new WeakMap(), _PricesCollector_poolConfig = new WeakM
119
119
  __classPrivateFieldSet(this, _PricesCollector_prices, __classPrivateFieldGet(this, _PricesCollector_prices, "f").filter((0, utils_1.verifyPricesTimestamp)()), "f");
120
120
  return __classPrivateFieldGet(this, _PricesCollector_prices, "f").length;
121
121
  }, _PricesCollector_filterEmptyPrincipalsAndAssets = function _PricesCollector_filterEmptyPrincipalsAndAssets(principals) {
122
- return principals.keys().filter(x => principals.get(x) > 0n).map(x => __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").poolAssetsConfig.find(asset => asset.assetId == x));
122
+ return principals.keys().filter(x => principals.get(x) != 0n).map(x => __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").poolAssetsConfig.find(asset => asset.assetId == x));
123
123
  };
@@ -1,5 +1,5 @@
1
1
  import { Address, Cell, Dictionary } from '@ton/core';
2
- import { ExtendedAssetsConfig, ExtendedAssetsData, PoolAssetConfig, PoolConfig } from './Master';
2
+ import { AssetConfig, AssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConstants, PoolAssetConfig, PoolConfig } from './Master';
3
3
  export declare enum BalanceType {
4
4
  supply = "supply",
5
5
  borrow = "borrow"
@@ -41,6 +41,7 @@ export type UserLiteData = {
41
41
  rewards: Dictionary<bigint, UserRewards>;
42
42
  backupCell1: Cell | null;
43
43
  backupCell2: Cell | null;
44
+ fullyParsed: boolean;
44
45
  };
45
46
  export type UserDataActive = UserLiteData & {
46
47
  withdrawalLimits: Dictionary<bigint, bigint>;
@@ -53,6 +54,7 @@ export type UserDataActive = UserLiteData & {
53
54
  limitUsed: bigint;
54
55
  healthFactor: number;
55
56
  liquidationData: LiquidationData;
57
+ havePrincipalWithoutPrice: boolean;
56
58
  };
57
59
  export type UserDataInactive = {
58
60
  type: 'inactive';
@@ -85,3 +87,10 @@ export type PredictHealthFactorArgs = {
85
87
  assetsConfig: ExtendedAssetsConfig;
86
88
  poolConfig: PoolConfig;
87
89
  };
90
+ export type PredictAPYArgs = {
91
+ balanceChangeType: BalanceChangeType;
92
+ amount: bigint;
93
+ assetData: AssetData;
94
+ assetConfig: AssetConfig;
95
+ masterConstants: MasterConstants;
96
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evaafi/sdk",
3
- "version": "0.6.2-a",
3
+ "version": "0.6.2-b",
4
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": [
@@ -21,16 +21,16 @@
21
21
  "devDependencies": {
22
22
  "@orbs-network/ton-access": "^2.3.3",
23
23
  "@ton/core": "0.56.0",
24
- "@ton/crypto": "^3.3.0",
25
- "@tonconnect/sdk": "^3.0.5",
24
+ "@ton/crypto": "3.3.0",
25
+ "@tonconnect/sdk": "3.0.5",
26
26
  "@types/jest": "^29.5.12",
27
27
  "@types/node": "^20.10.4",
28
- "crypto-js": "^4.2.0",
29
- "prettier": "^3.2.4",
28
+ "crypto-js": "4.2.0",
29
+ "prettier": "3.2.4",
30
30
  "ts-jest": "^29.2.4",
31
31
  "ts-node": "^10.9.1",
32
- "typedoc": "^0.27.4",
33
- "typescript": "^5.3.3"
32
+ "typedoc": "0.27.4",
33
+ "typescript": "5.3.3"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "@ton/core": ">=0.56.0",
@@ -38,7 +38,7 @@
38
38
  "crypto-js": ">=4.2.0"
39
39
  },
40
40
  "dependencies": {
41
- "@ton/ton": "^14.0.0",
42
- "dotenv": "^16.4.5"
41
+ "@ton/ton": "14.0.0",
42
+ "dotenv": "16.4.5"
43
43
  }
44
44
  }
package/src/api/math.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  BalanceType,
16
16
  HealthParamsArgs,
17
17
  LiquidationData,
18
+ PredictAPYArgs,
18
19
  PredictHealthFactorArgs,
19
20
  UserBalance
20
21
  } from '../types/User';
@@ -109,9 +110,28 @@ export function calculateAssetData(
109
110
  };
110
111
  }
111
112
 
112
- export function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData, masterConstants: MasterConstants): AssetInterest {
113
+ export function calculateAssetInterest(
114
+ assetConfig: AssetConfig,
115
+ assetData: AssetData,
116
+ masterConstants: MasterConstants
117
+ ): AssetInterest {
113
118
  const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply, masterConstants);
114
119
  const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow, masterConstants);
120
+
121
+ return calculateInterestWithSupplyBorrow(
122
+ totalSupply,
123
+ totalBorrow,
124
+ assetConfig,
125
+ masterConstants
126
+ );
127
+ }
128
+
129
+ export function calculateInterestWithSupplyBorrow(
130
+ totalSupply: bigint,
131
+ totalBorrow: bigint,
132
+ assetConfig: AssetConfig,
133
+ masterConstants: MasterConstants
134
+ ): AssetInterest {
115
135
  let utilization = 0n;
116
136
  let supplyInterest = 0n;
117
137
  let borrowInterest = 0n;
@@ -147,6 +167,7 @@ export function calculateAssetInterest(assetConfig: AssetConfig, assetData: Asse
147
167
  };
148
168
  }
149
169
 
170
+
150
171
  export function checkNotInDebtAtAll(principals: Dictionary<bigint, bigint>): boolean {
151
172
  return principals.values().every(x => x >= 0n);
152
173
  }
@@ -250,10 +271,19 @@ export function getAvailableToBorrow(
250
271
  let borrowAmount = 0n;
251
272
 
252
273
  for (const assetID of principals.keys()) {
274
+ const principal = principals.get(assetID) as bigint;
275
+
276
+ if (principal == 0n) {
277
+ continue;
278
+ }
279
+
280
+ if (!prices.has(assetID)) {
281
+ return 0n;
282
+ }
283
+
253
284
  const assetConfig = assetsConfig.get(assetID) as AssetConfig;
254
285
  const assetData = assetsData.get(assetID) as ExtendedAssetData;
255
286
  const price = prices.get(assetID) as bigint;
256
- const principal = principals.get(assetID) as bigint;
257
287
 
258
288
  if (principal < 0n) {
259
289
  borrowAmount += mulDiv(calculatePresentValue(assetData.bRate, -principal, masterConstants), price, 10n ** assetConfig.decimals);
@@ -464,7 +494,6 @@ export function predictHealthFactor(args: PredictHealthFactorArgs): number {
464
494
 
465
495
  const assetConfig = args.assetsConfig.get(assetId)!;
466
496
  const assetPrice = Number(args.prices.get(assetId)!);
467
- const assetData = args.assetsData.get(assetId)!;
468
497
 
469
498
  let totalLimit = Number(healthParams.totalLimit);
470
499
  let totalBorrow = Number(healthParams.totalDebt);
@@ -493,3 +522,36 @@ const assetData = args.assetsData.get(assetId)!;
493
522
 
494
523
  return Math.min(Math.max(1 - totalBorrow / totalLimit, 0), 1); // let's limit a result to zero below and one above
495
524
  }
525
+
526
+ /**
527
+ * Predicts how APY will change as a result of one of the actions Borrow, Supply, Withdraw or Repay.
528
+ *
529
+ * Used on the front-end.
530
+ *
531
+ * @returns Estimated APYs for Supply and Borrow
532
+ */
533
+ export function predictAPY(args: PredictAPYArgs): AssetInterest {
534
+ const assetConfig = args.assetConfig;
535
+ const assetData = args.assetData;
536
+ const masterConstants = args.masterConstants;
537
+
538
+ let totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply, masterConstants);
539
+ let totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow, masterConstants);
540
+
541
+ const currentAmount = args.amount;
542
+ const changeType = args.balanceChangeType;
543
+
544
+ if (currentAmount != null && currentAmount != 0n) {
545
+ if (changeType == BalanceChangeType.Borrow) {
546
+ totalBorrow += currentAmount;
547
+ } else if (changeType == BalanceChangeType.Repay) {
548
+ totalBorrow -= currentAmount;
549
+ } else if (changeType == BalanceChangeType.Withdraw) {
550
+ totalSupply -= currentAmount;
551
+ } else if (changeType == BalanceChangeType.Supply) {
552
+ totalSupply += currentAmount;
553
+ }
554
+ }
555
+
556
+ return calculateInterestWithSupplyBorrow(totalSupply, totalBorrow, assetConfig, masterConstants);
557
+ }
package/src/api/parser.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  } from './math';
13
13
  import { loadMaybeMyRef, loadMyRef } from './helpers';
14
14
  import { BalanceType, UserBalance, UserData, UserLiteData, UserRewards } from '../types/User';
15
+ import { checkNotInDebtAtAll } from "../api/math";
15
16
 
16
17
  export function createUserRewards(): DictionaryValue<UserRewards> {
17
18
  return {
@@ -32,8 +33,8 @@ export function createAssetData(): DictionaryValue<AssetData> {
32
33
  serialize: (src: any, buidler: any) => {
33
34
  buidler.storeUint(src.sRate, 64);
34
35
  buidler.storeUint(src.bRate, 64);
35
- buidler.storeUint(src.totalSupply, 64);
36
- buidler.storeUint(src.totalBorrow, 64);
36
+ buidler.storeInt(src.totalSupply, 64);
37
+ buidler.storeInt(src.totalBorrow, 64);
37
38
  buidler.storeUint(src.lastAccural, 32);
38
39
  buidler.storeUint(src.balance, 64);
39
40
  buidler.storeUint(src.trackingSupplyIndex, 64);
@@ -41,15 +42,15 @@ export function createAssetData(): DictionaryValue<AssetData> {
41
42
  buidler.storeUint(src.awaitedSupply, 64);
42
43
  },
43
44
  parse: (src: Slice) => {
44
- const sRate = BigInt(src.loadInt(64));
45
- const bRate = BigInt(src.loadInt(64));
46
- const totalSupply = BigInt(src.loadInt(64));
47
- const totalBorrow = BigInt(src.loadInt(64));
48
- const lastAccural = BigInt(src.loadInt(32));
49
- const balance = BigInt(src.loadInt(64));
50
- const trackingSupplyIndex = BigInt(src.loadUint(64));
51
- const trackingBorrowIndex = BigInt(src.loadUint(64));
52
- const awaitedSupply = BigInt(src.loadUint(64));
45
+ const sRate = BigInt(src.loadUintBig(64));
46
+ const bRate = BigInt(src.loadUintBig(64));
47
+ const totalSupply = BigInt(src.loadIntBig(64));
48
+ const totalBorrow = BigInt(src.loadIntBig(64));
49
+ const lastAccural = BigInt(src.loadUintBig(32));
50
+ const balance = BigInt(src.loadUintBig(64));
51
+ const trackingSupplyIndex = BigInt(src.loadUintBig(64));
52
+ const trackingBorrowIndex = BigInt(src.loadUintBig(64));
53
+ const awaitedSupply = BigInt(src.loadUintBig(64));
53
54
 
54
55
  return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance, trackingSupplyIndex, trackingBorrowIndex, awaitedSupply};
55
56
  },
@@ -267,6 +268,7 @@ export function parseUserLiteData(
267
268
  trackingBorrowIndex: trackingBorrowIndex,
268
269
  dutchAuctionStart: dutchAuctionStart,
269
270
  backupCell: backupCell,
271
+ fullyParsed: false,
270
272
 
271
273
  rewards: rewards,
272
274
  backupCell1: backupCell1,
@@ -282,6 +284,9 @@ export function parseUserData(
282
284
  poolConfig: PoolConfig,
283
285
  applyDust: boolean = false
284
286
  ): UserData {
287
+ userLiteData.fullyParsed = true;
288
+ let havePrincipalWithoutPrice = false;
289
+
285
290
  const poolAssetsConfig = poolConfig.poolAssetsConfig;
286
291
  const masterConstants = poolConfig.masterConstants;
287
292
 
@@ -291,6 +296,16 @@ export function parseUserData(
291
296
  let supplyBalance = 0n;
292
297
  let borrowBalance = 0n;
293
298
 
299
+ for (const [assetId, principal] of userLiteData.realPrincipals) {
300
+ if (!prices.has(assetId)) {
301
+ userLiteData.fullyParsed = false;
302
+
303
+ if (principal != 0n) {
304
+ havePrincipalWithoutPrice = true;
305
+ }
306
+ }
307
+ }
308
+
294
309
  for (const [_, asset] of Object.entries(poolAssetsConfig)) {
295
310
  const assetData = assetsData.get(asset.assetId) as ExtendedAssetData;
296
311
  const assetConfig = assetsConfig.get(asset.assetId) as AssetConfig;
@@ -307,6 +322,10 @@ export function parseUserData(
307
322
  }
308
323
 
309
324
  for (const [_, asset] of Object.entries(poolAssetsConfig)) {
325
+ if (!prices.has(asset.assetId)) {
326
+ continue;
327
+ }
328
+
310
329
  const assetConfig = assetsConfig.get(asset.assetId) as AssetConfig;
311
330
  const balance = userLiteData.balances.get(asset.assetId) as UserBalance;
312
331
 
@@ -318,19 +337,25 @@ export function parseUserData(
318
337
  }
319
338
  }
320
339
 
321
- const availableToBorrow = getAvailableToBorrow(assetsConfig, assetsData, userLiteData.principals, prices, masterConstants);
340
+ const availableToBorrow = getAvailableToBorrow(assetsConfig, assetsData, userLiteData.realPrincipals, prices, masterConstants);
341
+
322
342
  for (const [_, asset] of Object.entries(poolAssetsConfig)) {
343
+ const balance = userLiteData.balances.get(asset.assetId) as UserBalance;
323
344
  const assetConfig = assetsConfig.get(asset.assetId) as AssetConfig;
324
345
  const assetData = assetsData.get(asset.assetId) as ExtendedAssetData;
325
- const balance = userLiteData.balances.get(asset.assetId) as UserBalance;
326
346
 
327
347
  if (balance.type === BalanceType.supply) {
328
348
  withdrawalLimits.set(
329
349
  asset.assetId,
330
- bigIntMin(calculateMaximumWithdrawAmount(assetsConfig, assetsData, userLiteData.principals, prices, masterConstants, asset.assetId), assetData.balance)
350
+ bigIntMin(calculateMaximumWithdrawAmount(assetsConfig, assetsData, userLiteData.realPrincipals, prices, masterConstants, asset.assetId), assetData.balance)
331
351
  );
332
352
  }
333
353
 
354
+ if (!prices.has(asset.assetId)) {
355
+ borrowLimits.set(asset.assetId, 0n);
356
+ continue;
357
+ }
358
+
334
359
  borrowLimits.set(
335
360
  asset.assetId,
336
361
  bigIntMax(0n, bigIntMin((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(asset.assetId)!, assetData.balance, assetData.totalSupply - assetData.totalBorrow)),
@@ -343,12 +368,14 @@ export function parseUserData(
343
368
  ? 0
344
369
  : Number(BigInt(1e9) - (availableToBorrow * BigInt(1e9)) / (borrowBalance + availableToBorrow)) / 1e7;
345
370
 
346
- const liquidationData = calculateLiquidationData(assetsConfig, assetsData, userLiteData.principals, prices, poolConfig);
347
371
  let healthFactor = 1;
348
- if (liquidationData.totalLimit != 0n) {
349
- healthFactor = 1 - Number(liquidationData.totalDebt) / Number(liquidationData.totalLimit);
350
- }
351
-
372
+ let liquidationData;
373
+ if (!havePrincipalWithoutPrice) {
374
+ liquidationData = calculateLiquidationData(assetsConfig, assetsData, userLiteData.realPrincipals, prices, poolConfig);
375
+ if (liquidationData.totalLimit != 0n) {
376
+ healthFactor = 1 - Number(liquidationData.totalDebt) / Number(liquidationData.totalLimit);
377
+ }
378
+ }
352
379
  return {
353
380
  ...userLiteData,
354
381
  withdrawalLimits: withdrawalLimits,
@@ -360,5 +387,6 @@ export function parseUserData(
360
387
  limitUsed: limitUsed,
361
388
  liquidationData: liquidationData,
362
389
  healthFactor: healthFactor,
390
+ havePrincipalWithoutPrice: havePrincipalWithoutPrice
363
391
  };
364
392
  }
package/src/index.ts CHANGED
@@ -14,6 +14,8 @@ export {
14
14
  calculateLiquidationData,
15
15
  predictHealthFactor,
16
16
  calculateHealthParams,
17
+ calculateInterestWithSupplyBorrow,
18
+ predictAPY,
17
19
  BigMath,
18
20
  } from './api/math';
19
21
 
@@ -134,6 +134,6 @@ export class PricesCollector {
134
134
  }
135
135
 
136
136
  #filterEmptyPrincipalsAndAssets(principals: Dictionary<bigint, bigint>) {
137
- return principals.keys().filter(x => principals.get(x)! > 0n).map(x => this.#poolConfig.poolAssetsConfig.find(asset => asset.assetId == x));
137
+ return principals.keys().filter(x => principals.get(x)! != 0n).map(x => this.#poolConfig.poolAssetsConfig.find(asset => asset.assetId == x));
138
138
  }
139
139
  }
package/src/types/User.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Address, BitBuilder, Cell, Dictionary } from '@ton/core';
2
- import { AssetConfig, ExtendedAssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConfig, MasterConstants, PoolAssetConfig, PoolConfig } from './Master';
2
+ import { AssetConfig, AssetData, ExtendedAssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConfig, MasterConstants, PoolAssetConfig, PoolConfig } from './Master';
3
3
 
4
4
  export enum BalanceType {
5
5
  supply = 'supply',
@@ -48,6 +48,7 @@ export type UserLiteData = {
48
48
  rewards: Dictionary<bigint, UserRewards>;
49
49
  backupCell1: Cell | null;
50
50
  backupCell2: Cell | null;
51
+ fullyParsed: boolean;
51
52
  };
52
53
 
53
54
  export type UserDataActive = UserLiteData & {
@@ -61,6 +62,7 @@ export type UserDataActive = UserLiteData & {
61
62
  limitUsed: bigint;
62
63
  healthFactor: number;
63
64
  liquidationData: LiquidationData;
65
+ havePrincipalWithoutPrice: boolean;
64
66
  };
65
67
 
66
68
  export type UserDataInactive = {
@@ -99,3 +101,11 @@ export type PredictHealthFactorArgs = {
99
101
  assetsConfig: ExtendedAssetsConfig;
100
102
  poolConfig: PoolConfig;
101
103
  };
104
+
105
+ export type PredictAPYArgs = {
106
+ balanceChangeType: BalanceChangeType;
107
+ amount: bigint; // always positive
108
+ assetData: AssetData;
109
+ assetConfig: AssetConfig;
110
+ masterConstants: MasterConstants;
111
+ };