@evaafi/sdk 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # EVAA SDK
2
-
3
- The EVAA SDK is designed to easily integrate with the EVAA lending protocol on TON blockchain.
4
-
5
- ## Documentation
6
-
1
+ # EVAA SDK
2
+
3
+ The EVAA SDK is designed to easily integrate with the EVAA lending protocol on TON blockchain.
4
+
5
+ ## Documentation
6
+
7
7
  You can find the documentation in the [docs](./docs) folder.
@@ -1,6 +1,6 @@
1
1
  import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData } from '../types/Master';
2
2
  import { Dictionary } from '@ton/core';
3
- import { LiquidationData, UserBalance } from '../types/User';
3
+ import { LiquidationData, 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 bigIntMax(...args: bigint[]): bigint;
@@ -18,3 +18,4 @@ export declare function calculateAssetInterest(assetConfig: AssetConfig, assetDa
18
18
  export declare function getAvailableToBorrow(assetsConfig: Dictionary<bigint, AssetConfig>, assetsData: Dictionary<bigint, ExtendedAssetData>, principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>): bigint;
19
19
  export declare function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint): UserBalance;
20
20
  export declare function calculateLiquidationData(assetsConfig: Dictionary<bigint, AssetConfig>, assetsData: Dictionary<bigint, ExtendedAssetData>, principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>): LiquidationData;
21
+ export declare function predictHealthFactor(args: PredictHealthFactorArgs): number;
package/dist/api/math.js CHANGED
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateLiquidationData = exports.presentValue = exports.getAvailableToBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.bigIntMin = exports.bigIntMax = exports.mulDiv = exports.mulFactor = void 0;
3
+ exports.predictHealthFactor = exports.calculateLiquidationData = exports.presentValue = exports.getAvailableToBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.bigIntMin = exports.bigIntMax = exports.mulDiv = exports.mulFactor = void 0;
4
4
  const constants_1 = require("../constants");
5
5
  const User_1 = require("../types/User");
6
+ const sha256BigInt_1 = require("../utils/sha256BigInt");
6
7
  function mulFactor(decimal, a, b) {
7
8
  return (a * b) / decimal;
8
9
  }
@@ -86,9 +87,7 @@ function calculateAssetInterest(assetConfig, assetData) {
86
87
  mulFactor(constants_1.MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, assetConfig.targetUtilization) +
87
88
  mulFactor(constants_1.MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeHigh, utilization - assetConfig.targetUtilization);
88
89
  }
89
- const reserveFactor = 20n;
90
- const reserveScale = 100n;
91
- supplyInterest = mulDiv(mulDiv(borrowInterest, utilization, constants_1.MASTER_CONSTANTS.FACTOR_SCALE), reserveScale - reserveFactor, reserveScale);
90
+ supplyInterest = mulDiv(mulDiv(borrowInterest, utilization, constants_1.MASTER_CONSTANTS.FACTOR_SCALE), constants_1.MASTER_CONSTANTS.ASSET_RESERVE_FACTOR_SCALE - assetConfig.reserveFactor, constants_1.MASTER_CONSTANTS.ASSET_RESERVE_FACTOR_SCALE);
92
91
  return {
93
92
  supplyInterest,
94
93
  borrowInterest,
@@ -171,7 +170,7 @@ function calculateLiquidationData(assetsConfig, assetsData, principals, prices)
171
170
  const values = [];
172
171
  const gCollateralAssetConfig = assetsConfig.get(gCollateralAsset);
173
172
  const gLoanAssetConfig = assetsConfig.get(gLoanAsset);
174
- const liquidationBonus = gLoanAssetConfig.liquidationBonus;
173
+ const liquidationBonus = gCollateralAssetConfig.liquidationBonus;
175
174
  const loanDecimal = 10n ** gLoanAssetConfig.decimals;
176
175
  values.push((bigIntMax(gCollateralValue / 2n, bigIntMin(gCollateralValue, 10000000000n)) *
177
176
  loanDecimal *
@@ -212,3 +211,34 @@ function calculateLiquidationData(assetsConfig, assetsData, principals, prices)
212
211
  };
213
212
  }
214
213
  exports.calculateLiquidationData = calculateLiquidationData;
214
+ function predictHealthFactor(args) {
215
+ const liquidationData = calculateLiquidationData(args.assetsConfig, args.assetsData, args.balances, args.prices);
216
+ const tokenHash = (0, sha256BigInt_1.sha256Hash)(args.tokenSymbol);
217
+ const assetConfig = args.assetsConfig.get(tokenHash);
218
+ const assetPrice = Number(args.prices.get(tokenHash));
219
+ let totalLimit = Number(liquidationData.totalLimit);
220
+ let totalBorrow = Number(liquidationData.totalDebt);
221
+ const currentAmount = args.amount;
222
+ const decimals = Number(assetConfig.decimals);
223
+ const currentBalance = assetPrice * Number(currentAmount) / Math.pow(10, decimals);
224
+ const changeType = args.balanceChangeType;
225
+ if (currentAmount != null && currentAmount != 0n) {
226
+ if (changeType == User_1.BalanceChangeType.Borrow) {
227
+ totalBorrow += currentBalance * (1 + Number(assetConfig.originationFee) / Number(constants_1.MASTER_CONSTANTS.ASSET_ORIGINATION_FEE_SCALE));
228
+ }
229
+ else if (changeType == User_1.BalanceChangeType.Repay) {
230
+ totalBorrow -= currentBalance;
231
+ }
232
+ else if (changeType == User_1.BalanceChangeType.Withdraw) {
233
+ totalLimit -= currentBalance * Number(assetConfig.liquidationThreshold) / Number(constants_1.MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE);
234
+ }
235
+ else if (changeType == User_1.BalanceChangeType.Supply) {
236
+ totalLimit += currentBalance * Number(assetConfig.liquidationThreshold) / Number(constants_1.MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE);
237
+ }
238
+ }
239
+ if (Number(totalLimit) == 0) {
240
+ return 1;
241
+ }
242
+ return Math.min(Math.max(1 - totalBorrow / totalLimit, 0), 1); // let's limit a result to zero below and one above
243
+ }
244
+ exports.predictHealthFactor = predictHealthFactor;
@@ -4,5 +4,5 @@ import { UserData, UserLiteData } from '../types/User';
4
4
  export declare function createAssetData(): DictionaryValue<AssetData>;
5
5
  export declare function createAssetConfig(): DictionaryValue<AssetConfig>;
6
6
  export declare function parseMasterData(masterDataBOC: string, testnet?: boolean): MasterData;
7
- export declare function parseUserLiteData(userDataBOC: string, assetsData: Dictionary<bigint, ExtendedAssetData>, assetsConfig: Dictionary<bigint, AssetConfig>, testnet?: boolean): UserLiteData;
8
- export declare function parseUserData(userLiteData: UserLiteData, assetsData: Dictionary<bigint, ExtendedAssetData>, assetsConfig: Dictionary<bigint, AssetConfig>, prices: Dictionary<bigint, bigint>, testnet?: boolean): UserData;
7
+ export declare function parseUserLiteData(userDataBOC: string, assetsData: Dictionary<bigint, ExtendedAssetData>, assetsConfig: Dictionary<bigint, AssetConfig>, testnet?: boolean, applyDust?: boolean): UserLiteData;
8
+ export declare function parseUserData(userLiteData: UserLiteData, assetsData: Dictionary<bigint, ExtendedAssetData>, assetsConfig: Dictionary<bigint, AssetConfig>, prices: Dictionary<bigint, bigint>, testnet?: boolean, applyDust?: boolean): UserData;
@@ -6,6 +6,20 @@ const constants_1 = require("../constants");
6
6
  const math_1 = require("./math");
7
7
  const helpers_1 = require("./helpers");
8
8
  const User_1 = require("../types/User");
9
+ // Will be in v6
10
+ /* export function createUserRewards(): DictionaryValue<UserRewards> {
11
+ return {
12
+ serialize: (src: any, buidler: any) => {
13
+ buidler.storeUint(src.trackingIndex, 64);
14
+ buidler.storeUint(src.trackingAccured, 64);
15
+ },
16
+ parse: (src: Slice) => {
17
+ const trackingIndex = BigInt(src.loadUint(64));
18
+ const trackingAccured = BigInt(src.loadUint(64));
19
+ return { trackingIndex, trackingAccured };
20
+ },
21
+ };
22
+ }*/
9
23
  function createAssetData() {
10
24
  return {
11
25
  serialize: (src, buidler) => {
@@ -15,6 +29,10 @@ function createAssetData() {
15
29
  buidler.storeUint(src.totalBorrow, 64);
16
30
  buidler.storeUint(src.lastAccural, 32);
17
31
  buidler.storeUint(src.balance, 64);
32
+ /* Will be in v6
33
+ buidler.storeUint(src.trackingSupplyIndex, 64);
34
+ buidler.storeUint(src.trackingBorrowIndex, 64);
35
+ buidler.storeUint(src.lastTrackingAccural, 32); */
18
36
  },
19
37
  parse: (src) => {
20
38
  const sRate = BigInt(src.loadInt(64));
@@ -23,6 +41,12 @@ function createAssetData() {
23
41
  const totalBorrow = BigInt(src.loadInt(64));
24
42
  const lastAccural = BigInt(src.loadInt(32));
25
43
  const balance = BigInt(src.loadInt(64));
44
+ /* Will be in v6
45
+ const trackingSupplyIndex = BigInt(src.loadUint(64));
46
+ const trackingBorrowIndex = BigInt(src.loadUint(64));
47
+ const lastTrackingAccural = BigInt(src.loadUint(32));
48
+
49
+ return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance, trackingSupplyIndex, trackingBorrowIndex, lastTrackingAccural}; }, */
26
50
  return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance };
27
51
  },
28
52
  };
@@ -44,7 +68,14 @@ function createAssetConfig() {
44
68
  refBuild.storeUint(src.supplyRateSlopeHigh, 64);
45
69
  refBuild.storeUint(src.targetUtilization, 64);
46
70
  refBuild.storeUint(src.originationFee, 64);
71
+ refBuild.storeUint(src.dust, 64);
47
72
  refBuild.storeUint(src.maxTotalSupply, 64);
73
+ refBuild.storeUint(src.reserveFactor, 16);
74
+ refBuild.storeUint(src.liquidationReserveFactor, 16);
75
+ /* Will be in v6
76
+ refBuild.storeUint(src.minPrincipalForRewards, 64);
77
+ refBuild.storeUint(src.baseTrackingSupplySpeed, 64);
78
+ refBuild.storeUint(src.baseTrackingBorrowSpeed, 64); */
48
79
  builder.storeRef(refBuild.endCell());
49
80
  },
50
81
  parse: (src) => {
@@ -63,6 +94,12 @@ function createAssetConfig() {
63
94
  const originationFee = ref.loadUintBig(64);
64
95
  const dust = ref.loadUintBig(64);
65
96
  const maxTotalSupply = ref.loadUintBig(64);
97
+ const reserveFactor = ref.loadUintBig(16);
98
+ const liquidationReserveFactor = ref.loadUintBig(16);
99
+ /* Will be in v6
100
+ const minPrincipalForRewards = ref.loadUintBig(64);
101
+ const baseTrackingSupplySpeed = ref.loadUintBig(64);
102
+ const baseTrackingBorrowSpeed = ref.loadUintBig(64); */
66
103
  return {
67
104
  oracle,
68
105
  decimals,
@@ -78,6 +115,12 @@ function createAssetConfig() {
78
115
  originationFee,
79
116
  dust,
80
117
  maxTotalSupply,
118
+ reserveFactor,
119
+ liquidationReserveFactor,
120
+ /* Will be in v6
121
+ minPrincipalForRewards,
122
+ baseTrackingSupplySpeed,
123
+ baseTrackingBorrowSpeed */
81
124
  };
82
125
  },
83
126
  };
@@ -140,7 +183,7 @@ function parseMasterData(masterDataBOC, testnet = false) {
140
183
  };
141
184
  }
142
185
  exports.parseMasterData = parseMasterData;
143
- function parseUserLiteData(userDataBOC, assetsData, assetsConfig, testnet = false) {
186
+ function parseUserLiteData(userDataBOC, assetsData, assetsConfig, testnet = false, applyDust = false) {
144
187
  const ASSETS_ID = testnet ? constants_1.TESTNET_ASSETS_ID : constants_1.MAINNET_ASSETS_ID;
145
188
  const userSlice = core_1.Cell.fromBase64(userDataBOC).beginParse();
146
189
  const codeVersion = userSlice.loadCoins();
@@ -152,12 +195,37 @@ function parseUserLiteData(userDataBOC, assetsData, assetsConfig, testnet = fals
152
195
  const trackingBorrowIndex = userSlice.loadUintBig(64);
153
196
  const dutchAuctionStart = userSlice.loadUint(32);
154
197
  const backupCell = (0, helpers_1.loadMyRef)(userSlice);
198
+ /* Will be in v6
199
+ let trackingSupplyIndex = 0n;
200
+ let trackingBorrowIndex = 0n;
201
+ let dutchAuctionStart = 0;
202
+ let backupCell = Cell.EMPTY;
203
+ let rewards = Dictionary.empty(Dictionary.Keys.BigUint(256), createUserRewards());
204
+ let backupCell1: Cell | null = null;
205
+ let backupCell2: Cell | null = null;
206
+ const bitsLeft = userSlice.remainingBits;
207
+ if (bitsLeft > 32) {
208
+ trackingSupplyIndex = userSlice.loadUintBig(64);
209
+ trackingBorrowIndex = userSlice.loadUintBig(64);
210
+ dutchAuctionStart = userSlice.loadUint(32);
211
+ backupCell = loadMyRef(userSlice);
212
+ } else {
213
+ rewards = userSlice.loadDict(Dictionary.Keys.BigUint(256), createUserRewards());
214
+ backupCell1 = userSlice.loadMaybeRef();
215
+ backupCell2 = userSlice.loadMaybeRef();
216
+ }
217
+ */
155
218
  userSlice.endParse();
156
219
  const userBalances = core_1.Dictionary.empty();
157
220
  for (const [_, assetID] of Object.entries(ASSETS_ID)) {
158
221
  const assetData = assetsData.get(assetID);
159
222
  const assetConfig = assetsConfig.get(assetID);
160
- const balance = (0, math_1.presentValue)(assetData.sRate, assetData.bRate, principalsDict.get(assetID) || 0n);
223
+ let principals = principalsDict.get(assetID) || 0n;
224
+ if (applyDust && (principals > -assetConfig.dust && principals < assetConfig.dust)) { // abs(principals) < dust
225
+ principals = 0n;
226
+ principalsDict.set(assetID, 0n);
227
+ }
228
+ const balance = (0, math_1.presentValue)(assetData.sRate, assetData.bRate, principals);
161
229
  userBalances.set(assetID, balance);
162
230
  }
163
231
  return {
@@ -172,10 +240,14 @@ function parseUserLiteData(userDataBOC, assetsData, assetsConfig, testnet = fals
172
240
  trackingBorrowIndex: trackingBorrowIndex,
173
241
  dutchAuctionStart: dutchAuctionStart,
174
242
  backupCell: backupCell,
243
+ /* Will be in v6
244
+ rewards: rewards,
245
+ backupCell1: backupCell1,
246
+ backupCell2: backupCell2, */
175
247
  };
176
248
  }
177
249
  exports.parseUserLiteData = parseUserLiteData;
178
- function parseUserData(userLiteData, assetsData, assetsConfig, prices, testnet = false) {
250
+ function parseUserData(userLiteData, assetsData, assetsConfig, prices, testnet = false, applyDust = false) {
179
251
  const ASSETS_ID = testnet ? constants_1.TESTNET_ASSETS_ID : constants_1.MAINNET_ASSETS_ID;
180
252
  const withdrawalLimits = core_1.Dictionary.empty();
181
253
  const borrowLimits = core_1.Dictionary.empty();
@@ -184,7 +256,12 @@ function parseUserData(userLiteData, assetsData, assetsConfig, prices, testnet =
184
256
  for (const [_, assetID] of Object.entries(ASSETS_ID)) {
185
257
  const assetData = assetsData.get(assetID);
186
258
  const assetConfig = assetsConfig.get(assetID);
187
- const balance = (0, math_1.presentValue)(assetData.sRate, assetData.bRate, userLiteData.principals.get(assetID) || 0n);
259
+ let principals = userLiteData.principals.get(assetID) || 0n;
260
+ if (applyDust && (principals > -assetConfig.dust && principals < assetConfig.dust)) { // abs(principals) < dust
261
+ principals = 0n;
262
+ userLiteData.principals.set(assetID, 0n);
263
+ }
264
+ const balance = (0, math_1.presentValue)(assetData.sRate, assetData.bRate, principals);
188
265
  userLiteData.balances.set(assetID, balance);
189
266
  }
190
267
  for (const [_, assetID] of Object.entries(ASSETS_ID)) {
@@ -209,9 +286,7 @@ function parseUserData(userLiteData, assetsData, assetsConfig, prices, testnet =
209
286
  prices.get(assetID) -
210
287
  5n, balance.amount), 0n));
211
288
  }
212
- else {
213
- borrowLimits.set(assetID, (0, math_1.bigIntMin)((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(assetID), assetData.balance));
214
- }
289
+ borrowLimits.set(assetID, (0, math_1.bigIntMin)((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(assetID), assetData.balance));
215
290
  }
216
291
  const limitUsed = borrowBalance + availableToBorrow;
217
292
  const limitUsedPercent = limitUsed === 0n
@@ -1,2 +1,2 @@
1
1
  import { PriceData } from '../types/Common';
2
- export declare function getPrices(): Promise<PriceData | undefined>;
2
+ export declare function getPrices(endpoint?: String): Promise<PriceData | undefined>;
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPrices = void 0;
4
4
  const core_1 = require("@ton/core");
5
5
  const constants_1 = require("../constants");
6
- async function getPrices() {
6
+ async function getPrices(endpoint = "api.stardust-mainnet.iotaledger.net") {
7
7
  try {
8
- let result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/indexer/v1/outputs/nft/' + constants_1.NFT_ID, {
8
+ let result = await fetch(`https://${endpoint}/api/indexer/v1/outputs/nft/${constants_1.NFT_ID}`, {
9
9
  headers: { accept: 'application/json' },
10
10
  });
11
11
  let outputId = (await result.json());
12
- result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/core/v2/outputs/' + outputId.items[0], {
12
+ result = await fetch(`https://${endpoint}/api/core/v2/outputs/${outputId.items[0]}`, {
13
13
  headers: { accept: 'application/json' },
14
14
  });
15
15
  let resData = (await result.json());
@@ -1,8 +1,8 @@
1
1
  import { Address, Cell } from '@ton/core';
2
2
  export declare const EVAA_MASTER_MAINNET: Address;
3
- export declare const MAINNET_VERSION = 4;
3
+ export declare const MAINNET_VERSION = 5;
4
4
  export declare const EVAA_MASTER_TESTNET: Address;
5
- export declare const TESTNET_VERSION = 4;
5
+ export declare const TESTNET_VERSION = 5;
6
6
  export declare const NFT_ID = "0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5";
7
7
  export declare const MAINNET_ASSETS_ID: {
8
8
  TON: bigint;
@@ -34,6 +34,9 @@ export declare const MASTER_CONSTANTS: {
34
34
  FACTOR_SCALE: bigint;
35
35
  ASSET_COEFFICIENT_SCALE: bigint;
36
36
  ASSET_PRICE_SCALE: bigint;
37
+ ASSET_RESERVE_FACTOR_SCALE: bigint;
38
+ ASSET_LIQUIDATION_RESERVE_FACTOR_SCALE: bigint;
39
+ ASSET_ORIGINATION_FEE_SCALE: bigint;
37
40
  };
38
41
  export declare const LENDING_CODE: Cell;
39
42
  export declare const JETTON_WALLETS_CODE: {
package/dist/constants.js CHANGED
@@ -4,9 +4,9 @@ exports.FEES = exports.OPCODES = exports.JETTON_WALLETS_CODE = exports.LENDING_C
4
4
  const core_1 = require("@ton/core");
5
5
  const sha256BigInt_1 = require("./utils/sha256BigInt");
6
6
  exports.EVAA_MASTER_MAINNET = core_1.Address.parse('EQC8rUZqR_pWV1BylWUlPNBzyiTYVoBEmQkMIQDZXICfnuRr');
7
- exports.MAINNET_VERSION = 4;
7
+ exports.MAINNET_VERSION = 5;
8
8
  exports.EVAA_MASTER_TESTNET = core_1.Address.parse('kQCj7qf3i2Cbf1GVtZCinla7lIvE7l3MBMsJMTfAja3BdoRP');
9
- exports.TESTNET_VERSION = 4;
9
+ exports.TESTNET_VERSION = 5;
10
10
  exports.NFT_ID = '0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5';
11
11
  exports.MAINNET_ASSETS_ID = {
12
12
  TON: (0, sha256BigInt_1.sha256Hash)('TON'),
@@ -40,6 +40,9 @@ exports.MASTER_CONSTANTS = {
40
40
  FACTOR_SCALE: BigInt(1e12),
41
41
  ASSET_COEFFICIENT_SCALE: 10000n,
42
42
  ASSET_PRICE_SCALE: BigInt(1e8),
43
+ ASSET_RESERVE_FACTOR_SCALE: 10000n,
44
+ ASSET_LIQUIDATION_RESERVE_FACTOR_SCALE: 10000n,
45
+ ASSET_ORIGINATION_FEE_SCALE: BigInt(1e9)
43
46
  };
44
47
  exports.LENDING_CODE = core_1.Cell.fromBoc(Buffer.from('b5ee9c72c1010e0100fd000d12182a555a6065717691969efd0114ff00f4a413f4bcf2c80b010202c8050202039f740403001ff2f8276a2687d2018fd201800f883b840051d38642c678b64e4400780e58fc10802faf07f80e59fa801e78b096664c02078067c07c100627a7978402014807060007a0ddb0c60201c709080013a0fd007a026900aa90400201200b0a0031b8e1002191960aa00b9e2ca007f4042796d225e8019203f6010201200d0c000bf7c147d2218400b9d10e86981fd201840b07f8138d809797976a2687d2029116382f970fd9178089910374daf81b619fd20182c7883b8701981684100627910eba56001797a6a6ba610fd8200e8768f76a9f6aa00cc2a32a8292878809bef2f1889f883bbcdeb86f01', 'hex'))[0];
45
48
  exports.JETTON_WALLETS_CODE = {
@@ -44,6 +44,9 @@ class Evaa {
44
44
  .storeUint(constants_1.OPCODES.SUPPLY, 32)
45
45
  .storeInt(parameters.includeUserCode ? -1 : 0, 2)
46
46
  .storeAddress(parameters.userAddress)
47
+ /* Will be in v6
48
+ .storeUint(parameters.amountToTransfer, 64)
49
+ .storeRef(parameters.payload) */
47
50
  .endCell())
48
51
  .endCell();
49
52
  }
@@ -54,6 +57,9 @@ class Evaa {
54
57
  .storeInt(parameters.includeUserCode ? -1 : 0, 2)
55
58
  .storeUint(parameters.amount, 64)
56
59
  .storeAddress(parameters.userAddress)
60
+ /* Will be in v6
61
+ .storeUint(parameters.amountToTransfer, 64)
62
+ .storeRef(parameters.payload) */
57
63
  .endCell();
58
64
  }
59
65
  }
@@ -69,6 +75,9 @@ class Evaa {
69
75
  .storeUint(parameters.amount, 64)
70
76
  .storeAddress(parameters.userAddress)
71
77
  .storeInt(parameters.includeUserCode ? -1 : 0, 2)
78
+ /* Will be in v6
79
+ .storeUint(parameters.amountToTransfer, 64)
80
+ .storeRef(parameters.payload) */
72
81
  .storeRef(parameters.priceData)
73
82
  .endCell();
74
83
  }
@@ -25,6 +25,8 @@ export type AssetConfig = {
25
25
  originationFee: bigint;
26
26
  dust: bigint;
27
27
  maxTotalSupply: bigint;
28
+ reserveFactor: bigint;
29
+ liquidationReserveFactor: bigint;
28
30
  };
29
31
  export type MasterConfig = {
30
32
  ifActive: number;
@@ -1,4 +1,5 @@
1
1
  import { Address, Cell, Dictionary } from '@ton/core';
2
+ import { AssetConfig, ExtendedAssetData } from './Master';
2
3
  export declare enum BalanceType {
3
4
  supply = "supply",
4
5
  borrow = "borrow"
@@ -53,3 +54,22 @@ export type UserDataInactive = {
53
54
  type: 'inactive';
54
55
  };
55
56
  export type UserData = UserDataActive | UserDataInactive;
57
+ export type UserRewards = {
58
+ trackingIndex: bigint;
59
+ trackingAccured: bigint;
60
+ };
61
+ export declare enum BalanceChangeType {
62
+ Borrow = 0,
63
+ Repay = 1,
64
+ Supply = 2,
65
+ Withdraw = 3
66
+ }
67
+ export type PredictHealthFactorArgs = {
68
+ balanceChangeType: BalanceChangeType;
69
+ amount: bigint;
70
+ tokenSymbol: string;
71
+ balances: Dictionary<bigint, bigint>;
72
+ prices: Dictionary<bigint, bigint>;
73
+ assetsData: Dictionary<bigint, ExtendedAssetData>;
74
+ assetsConfig: Dictionary<bigint, AssetConfig>;
75
+ };
@@ -1,8 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BalanceType = void 0;
3
+ exports.BalanceChangeType = exports.BalanceType = void 0;
4
4
  var BalanceType;
5
5
  (function (BalanceType) {
6
6
  BalanceType["supply"] = "supply";
7
7
  BalanceType["borrow"] = "borrow";
8
8
  })(BalanceType || (exports.BalanceType = BalanceType = {}));
9
+ var BalanceChangeType;
10
+ (function (BalanceChangeType) {
11
+ BalanceChangeType[BalanceChangeType["Borrow"] = 0] = "Borrow";
12
+ BalanceChangeType[BalanceChangeType["Repay"] = 1] = "Repay";
13
+ BalanceChangeType[BalanceChangeType["Supply"] = 2] = "Supply";
14
+ BalanceChangeType[BalanceChangeType["Withdraw"] = 3] = "Withdraw";
15
+ })(BalanceChangeType || (exports.BalanceChangeType = BalanceChangeType = {}));
package/package.json CHANGED
@@ -1,34 +1,34 @@
1
- {
2
- "name": "@evaafi/sdk",
3
- "version": "0.4.1",
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
- "@ton/core": "0.56.0",
22
- "@tonconnect/sdk": "^3.0.0",
23
- "@types/node": "^20.10.4",
24
- "crypto-js": "^4.2.0",
25
- "prettier": "^3.2.4",
26
- "ts-node": "^10.9.1",
27
- "typescript": "^5.3.3"
28
- },
29
- "peerDependencies": {
30
- "@ton/core": ">=0.56.0",
31
- "@tonconnect/sdk": ">=3.0.0",
32
- "crypto-js": ">=4.2.0"
33
- }
34
- }
1
+ {
2
+ "name": "@evaafi/sdk",
3
+ "version": "0.5.1",
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
+ "@ton/core": "0.56.0",
22
+ "@tonconnect/sdk": "^3.0.0",
23
+ "@types/node": "^20.10.4",
24
+ "crypto-js": "^4.2.0",
25
+ "prettier": "^3.2.4",
26
+ "ts-node": "^10.9.1",
27
+ "typescript": "^5.3.3"
28
+ },
29
+ "peerDependencies": {
30
+ "@ton/core": ">=0.56.0",
31
+ "@tonconnect/sdk": ">=3.0.0",
32
+ "crypto-js": ">=4.2.0"
33
+ }
34
+ }
package/src/api/math.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData } from '../types/Master';
2
2
  import { MASTER_CONSTANTS } from '../constants';
3
3
  import { Dictionary } from '@ton/core';
4
- import { BalanceType, LiquidationData, UserBalance } from '../types/User';
4
+ import { BalanceChangeType, BalanceType, LiquidationData, PredictHealthFactorArgs, UserBalance } from '../types/User';
5
+ import { sha256Hash } from '../utils/sha256BigInt';
5
6
 
6
7
  export function mulFactor(decimal: bigint, a: bigint, b: bigint): bigint {
7
8
  return (a * b) / decimal;
@@ -103,12 +104,10 @@ export function calculateAssetInterest(assetConfig: AssetConfig, assetData: Asse
103
104
  );
104
105
  }
105
106
 
106
- const reserveFactor = 20n;
107
- const reserveScale = 100n;
108
107
  supplyInterest = mulDiv(
109
108
  mulDiv(borrowInterest, utilization, MASTER_CONSTANTS.FACTOR_SCALE),
110
- reserveScale - reserveFactor,
111
- reserveScale,
109
+ MASTER_CONSTANTS.ASSET_RESERVE_FACTOR_SCALE - assetConfig.reserveFactor,
110
+ MASTER_CONSTANTS.ASSET_RESERVE_FACTOR_SCALE,
112
111
  );
113
112
 
114
113
  return {
@@ -205,7 +204,7 @@ export function calculateLiquidationData(
205
204
  const values: bigint[] = [];
206
205
  const gCollateralAssetConfig = assetsConfig.get(gCollateralAsset)!;
207
206
  const gLoanAssetConfig = assetsConfig.get(gLoanAsset)!;
208
- const liquidationBonus = gLoanAssetConfig.liquidationBonus;
207
+ const liquidationBonus = gCollateralAssetConfig.liquidationBonus;
209
208
  const loanDecimal = 10n ** gLoanAssetConfig.decimals;
210
209
  values.push(
211
210
  (bigIntMax(gCollateralValue / 2n, bigIntMin(gCollateralValue, 10_000_000_000n)) *
@@ -250,3 +249,38 @@ export function calculateLiquidationData(
250
249
  liquidable: false,
251
250
  };
252
251
  }
252
+
253
+ export function predictHealthFactor(args: PredictHealthFactorArgs): number {
254
+ const liquidationData = calculateLiquidationData(args.assetsConfig, args.assetsData, args.balances, args.prices);
255
+ const tokenHash = sha256Hash(args.tokenSymbol);
256
+
257
+ const assetConfig = args.assetsConfig.get(tokenHash)!;
258
+ const assetPrice = Number(args.prices.get(tokenHash)!);
259
+
260
+ let totalLimit = Number(liquidationData.totalLimit);
261
+ let totalBorrow = Number(liquidationData.totalDebt);
262
+
263
+ const currentAmount = args.amount;
264
+
265
+ const decimals = Number(assetConfig.decimals)
266
+
267
+ const currentBalance = assetPrice * Number(currentAmount) / Math.pow(10, decimals);
268
+ const changeType = args.balanceChangeType;
269
+
270
+ if (currentAmount != null && currentAmount != 0n) {
271
+ if (changeType == BalanceChangeType.Borrow) {
272
+ totalBorrow += currentBalance * (1 + Number(assetConfig.originationFee) / Number(MASTER_CONSTANTS.ASSET_ORIGINATION_FEE_SCALE));
273
+ } else if (changeType == BalanceChangeType.Repay) {
274
+ totalBorrow -= currentBalance;
275
+ } else if (changeType == BalanceChangeType.Withdraw) {
276
+ totalLimit -= currentBalance * Number(assetConfig.liquidationThreshold) / Number(MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE);
277
+ } else if (changeType == BalanceChangeType.Supply) {
278
+ totalLimit += currentBalance * Number(assetConfig.liquidationThreshold) / Number(MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE);
279
+ }
280
+ }
281
+ if (Number(totalLimit) == 0) {
282
+ return 1;
283
+ }
284
+
285
+ return Math.min(Math.max(1 - totalBorrow / totalLimit, 0), 1); // let's limit a result to zero below and one above
286
+ }
package/src/api/parser.ts CHANGED
@@ -11,7 +11,22 @@ import {
11
11
  presentValue,
12
12
  } from './math';
13
13
  import { loadMaybeMyRef, loadMyRef } from './helpers';
14
- import { BalanceType, UserBalance, UserData, UserLiteData } from '../types/User';
14
+ import { BalanceType, UserBalance, UserData, UserLiteData, UserRewards } from '../types/User';
15
+
16
+ // Will be in v6
17
+ /* export function createUserRewards(): DictionaryValue<UserRewards> {
18
+ return {
19
+ serialize: (src: any, buidler: any) => {
20
+ buidler.storeUint(src.trackingIndex, 64);
21
+ buidler.storeUint(src.trackingAccured, 64);
22
+ },
23
+ parse: (src: Slice) => {
24
+ const trackingIndex = BigInt(src.loadUint(64));
25
+ const trackingAccured = BigInt(src.loadUint(64));
26
+ return { trackingIndex, trackingAccured };
27
+ },
28
+ };
29
+ }*/
15
30
 
16
31
  export function createAssetData(): DictionaryValue<AssetData> {
17
32
  return {
@@ -22,6 +37,10 @@ export function createAssetData(): DictionaryValue<AssetData> {
22
37
  buidler.storeUint(src.totalBorrow, 64);
23
38
  buidler.storeUint(src.lastAccural, 32);
24
39
  buidler.storeUint(src.balance, 64);
40
+ /* Will be in v6
41
+ buidler.storeUint(src.trackingSupplyIndex, 64);
42
+ buidler.storeUint(src.trackingBorrowIndex, 64);
43
+ buidler.storeUint(src.lastTrackingAccural, 32); */
25
44
  },
26
45
  parse: (src: Slice) => {
27
46
  const sRate = BigInt(src.loadInt(64));
@@ -30,8 +49,13 @@ export function createAssetData(): DictionaryValue<AssetData> {
30
49
  const totalBorrow = BigInt(src.loadInt(64));
31
50
  const lastAccural = BigInt(src.loadInt(32));
32
51
  const balance = BigInt(src.loadInt(64));
33
- return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance };
34
- },
52
+ /* Will be in v6
53
+ const trackingSupplyIndex = BigInt(src.loadUint(64));
54
+ const trackingBorrowIndex = BigInt(src.loadUint(64));
55
+ const lastTrackingAccural = BigInt(src.loadUint(32));
56
+
57
+ return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance, trackingSupplyIndex, trackingBorrowIndex, lastTrackingAccural}; }, */
58
+ return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance}; },
35
59
  };
36
60
  }
37
61
 
@@ -51,7 +75,14 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
51
75
  refBuild.storeUint(src.supplyRateSlopeHigh, 64);
52
76
  refBuild.storeUint(src.targetUtilization, 64);
53
77
  refBuild.storeUint(src.originationFee, 64);
78
+ refBuild.storeUint(src.dust, 64);
54
79
  refBuild.storeUint(src.maxTotalSupply, 64);
80
+ refBuild.storeUint(src.reserveFactor, 16);
81
+ refBuild.storeUint(src.liquidationReserveFactor, 16);
82
+ /* Will be in v6
83
+ refBuild.storeUint(src.minPrincipalForRewards, 64);
84
+ refBuild.storeUint(src.baseTrackingSupplySpeed, 64);
85
+ refBuild.storeUint(src.baseTrackingBorrowSpeed, 64); */
55
86
  builder.storeRef(refBuild.endCell());
56
87
  },
57
88
  parse: (src: Slice) => {
@@ -70,6 +101,12 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
70
101
  const originationFee = ref.loadUintBig(64);
71
102
  const dust = ref.loadUintBig(64);
72
103
  const maxTotalSupply = ref.loadUintBig(64);
104
+ const reserveFactor = ref.loadUintBig(16);
105
+ const liquidationReserveFactor = ref.loadUintBig(16);
106
+ /* Will be in v6
107
+ const minPrincipalForRewards = ref.loadUintBig(64);
108
+ const baseTrackingSupplySpeed = ref.loadUintBig(64);
109
+ const baseTrackingBorrowSpeed = ref.loadUintBig(64); */
73
110
 
74
111
  return {
75
112
  oracle,
@@ -86,6 +123,12 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
86
123
  originationFee,
87
124
  dust,
88
125
  maxTotalSupply,
126
+ reserveFactor,
127
+ liquidationReserveFactor,
128
+ /* Will be in v6
129
+ minPrincipalForRewards,
130
+ baseTrackingSupplySpeed,
131
+ baseTrackingBorrowSpeed */
89
132
  };
90
133
  },
91
134
  };
@@ -162,6 +205,7 @@ export function parseUserLiteData(
162
205
  assetsData: Dictionary<bigint, ExtendedAssetData>,
163
206
  assetsConfig: Dictionary<bigint, AssetConfig>,
164
207
  testnet: boolean = false,
208
+ applyDust: boolean = false
165
209
  ): UserLiteData {
166
210
  const ASSETS_ID = testnet ? TESTNET_ASSETS_ID : MAINNET_ASSETS_ID;
167
211
  const userSlice = Cell.fromBase64(userDataBOC).beginParse();
@@ -175,6 +219,26 @@ export function parseUserLiteData(
175
219
  const trackingBorrowIndex = userSlice.loadUintBig(64);
176
220
  const dutchAuctionStart = userSlice.loadUint(32);
177
221
  const backupCell = loadMyRef(userSlice);
222
+ /* Will be in v6
223
+ let trackingSupplyIndex = 0n;
224
+ let trackingBorrowIndex = 0n;
225
+ let dutchAuctionStart = 0;
226
+ let backupCell = Cell.EMPTY;
227
+ let rewards = Dictionary.empty(Dictionary.Keys.BigUint(256), createUserRewards());
228
+ let backupCell1: Cell | null = null;
229
+ let backupCell2: Cell | null = null;
230
+ const bitsLeft = userSlice.remainingBits;
231
+ if (bitsLeft > 32) {
232
+ trackingSupplyIndex = userSlice.loadUintBig(64);
233
+ trackingBorrowIndex = userSlice.loadUintBig(64);
234
+ dutchAuctionStart = userSlice.loadUint(32);
235
+ backupCell = loadMyRef(userSlice);
236
+ } else {
237
+ rewards = userSlice.loadDict(Dictionary.Keys.BigUint(256), createUserRewards());
238
+ backupCell1 = userSlice.loadMaybeRef();
239
+ backupCell2 = userSlice.loadMaybeRef();
240
+ }
241
+ */
178
242
  userSlice.endParse();
179
243
 
180
244
  const userBalances = Dictionary.empty<bigint, UserBalance>();
@@ -182,7 +246,13 @@ export function parseUserLiteData(
182
246
  for (const [_, assetID] of Object.entries(ASSETS_ID)) {
183
247
  const assetData = assetsData.get(assetID) as ExtendedAssetData;
184
248
  const assetConfig = assetsConfig.get(assetID) as AssetConfig;
185
- const balance = presentValue(assetData.sRate, assetData.bRate, principalsDict.get(assetID) || 0n);
249
+ let principals = principalsDict.get(assetID) || 0n;
250
+
251
+ if (applyDust && (principals > -assetConfig.dust && principals < assetConfig.dust)) { // abs(principals) < dust
252
+ principals = 0n;
253
+ principalsDict.set(assetID, 0n);
254
+ }
255
+ const balance = presentValue(assetData.sRate, assetData.bRate, principals);
186
256
  userBalances.set(assetID, balance);
187
257
  }
188
258
 
@@ -198,6 +268,10 @@ export function parseUserLiteData(
198
268
  trackingBorrowIndex: trackingBorrowIndex,
199
269
  dutchAuctionStart: dutchAuctionStart,
200
270
  backupCell: backupCell,
271
+ /* Will be in v6
272
+ rewards: rewards,
273
+ backupCell1: backupCell1,
274
+ backupCell2: backupCell2, */
201
275
  };
202
276
  }
203
277
 
@@ -207,6 +281,7 @@ export function parseUserData(
207
281
  assetsConfig: Dictionary<bigint, AssetConfig>,
208
282
  prices: Dictionary<bigint, bigint>,
209
283
  testnet: boolean = false,
284
+ applyDust: boolean = false
210
285
  ): UserData {
211
286
  const ASSETS_ID = testnet ? TESTNET_ASSETS_ID : MAINNET_ASSETS_ID;
212
287
  const withdrawalLimits = Dictionary.empty<bigint, bigint>();
@@ -217,7 +292,14 @@ export function parseUserData(
217
292
  for (const [_, assetID] of Object.entries(ASSETS_ID)) {
218
293
  const assetData = assetsData.get(assetID) as ExtendedAssetData;
219
294
  const assetConfig = assetsConfig.get(assetID) as AssetConfig;
220
- const balance = presentValue(assetData.sRate, assetData.bRate, userLiteData.principals.get(assetID) || 0n);
295
+ let principals = userLiteData.principals.get(assetID) || 0n;
296
+
297
+ if (applyDust && (principals > -assetConfig.dust && principals < assetConfig.dust )) { // abs(principals) < dust
298
+ principals = 0n;
299
+ userLiteData.principals.set(assetID, 0n);
300
+ }
301
+
302
+ const balance = presentValue(assetData.sRate, assetData.bRate, principals);
221
303
  userLiteData.balances.set(assetID, balance);
222
304
  }
223
305
 
@@ -255,12 +337,11 @@ export function parseUserData(
255
337
  0n,
256
338
  ),
257
339
  );
258
- } else {
259
- borrowLimits.set(
260
- assetID,
261
- bigIntMin((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(assetID)!, assetData.balance),
262
- );
263
340
  }
341
+ borrowLimits.set(
342
+ assetID,
343
+ bigIntMin((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(assetID)!, assetData.balance),
344
+ );
264
345
  }
265
346
 
266
347
  const limitUsed = borrowBalance + availableToBorrow;
package/src/api/prices.ts CHANGED
@@ -1,70 +1,70 @@
1
- import { beginCell, Cell, Dictionary } from '@ton/core';
2
- import { NFT_ID } from '../constants';
3
- import { PriceData } from '../types/Common';
4
-
5
- type NftData = {
6
- ledgerIndex: number;
7
- pageSize: number;
8
- items: string[];
9
- };
10
-
11
- type OutputData = {
12
- metadata: {
13
- blockId: string;
14
- transactionId: string;
15
- outputIndex: number;
16
- isSpent: boolean;
17
- milestoneIndexSpent: number;
18
- milestoneTimestampSpent: number;
19
- transactionIdSpent: string;
20
- milestoneIndexBooked: number;
21
- milestoneTimestampBooked: number;
22
- ledgerIndex: number;
23
- };
24
- output: {
25
- type: number;
26
- amount: string;
27
- nftId: string;
28
- unlockConditions: {
29
- type: number;
30
- address: {
31
- type: number;
32
- pubKeyHash: string;
33
- };
34
- }[];
35
- features: {
36
- type: number;
37
- data: string;
38
- }[];
39
- };
40
- };
41
-
42
- export async function getPrices(): Promise<PriceData | undefined> {
43
- try {
44
- let result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/indexer/v1/outputs/nft/' + NFT_ID, {
45
- headers: { accept: 'application/json' },
46
- });
47
- let outputId = (await result.json()) as NftData;
48
-
49
- result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/core/v2/outputs/' + outputId.items[0], {
50
- headers: { accept: 'application/json' },
51
- });
52
-
53
- let resData = (await result.json()) as OutputData;
54
-
55
- const data = JSON.parse(
56
- decodeURIComponent(resData.output.features[0].data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')),
57
- );
58
-
59
- const pricesCell = Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
60
- const signature = Buffer.from(data['signature'], 'hex');
61
-
62
- return {
63
- dict: pricesCell.beginParse().loadDictDirect(Dictionary.Keys.BigUint(256), Dictionary.Values.BigUint(64)),
64
- dataCell: beginCell().storeRef(pricesCell).storeBuffer(signature).endCell(),
65
- };
66
- } catch (error) {
67
- console.error(error);
68
- return undefined;
69
- }
70
- }
1
+ import { beginCell, Cell, Dictionary } from '@ton/core';
2
+ import { NFT_ID } from '../constants';
3
+ import { PriceData } from '../types/Common';
4
+
5
+ type NftData = {
6
+ ledgerIndex: number;
7
+ pageSize: number;
8
+ items: string[];
9
+ };
10
+
11
+ type OutputData = {
12
+ metadata: {
13
+ blockId: string;
14
+ transactionId: string;
15
+ outputIndex: number;
16
+ isSpent: boolean;
17
+ milestoneIndexSpent: number;
18
+ milestoneTimestampSpent: number;
19
+ transactionIdSpent: string;
20
+ milestoneIndexBooked: number;
21
+ milestoneTimestampBooked: number;
22
+ ledgerIndex: number;
23
+ };
24
+ output: {
25
+ type: number;
26
+ amount: string;
27
+ nftId: string;
28
+ unlockConditions: {
29
+ type: number;
30
+ address: {
31
+ type: number;
32
+ pubKeyHash: string;
33
+ };
34
+ }[];
35
+ features: {
36
+ type: number;
37
+ data: string;
38
+ }[];
39
+ };
40
+ };
41
+
42
+ export async function getPrices(endpoint: String = "api.stardust-mainnet.iotaledger.net"): Promise<PriceData | undefined> {
43
+ try {
44
+ let result = await fetch(`https://${endpoint}/api/indexer/v1/outputs/nft/${NFT_ID}`, {
45
+ headers: { accept: 'application/json' },
46
+ });
47
+ let outputId = (await result.json()) as NftData;
48
+
49
+ result = await fetch(`https://${endpoint}/api/core/v2/outputs/${outputId.items[0]}`, {
50
+ headers: { accept: 'application/json' },
51
+ });
52
+
53
+ let resData = (await result.json()) as OutputData;
54
+
55
+ const data = JSON.parse(
56
+ decodeURIComponent(resData.output.features[0].data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')),
57
+ );
58
+
59
+ const pricesCell = Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
60
+ const signature = Buffer.from(data['signature'], 'hex');
61
+
62
+ return {
63
+ dict: pricesCell.beginParse().loadDictDirect(Dictionary.Keys.BigUint(256), Dictionary.Values.BigUint(64)),
64
+ dataCell: beginCell().storeRef(pricesCell).storeBuffer(signature).endCell(),
65
+ };
66
+ } catch (error) {
67
+ console.error(error);
68
+ return undefined;
69
+ }
70
+ }
package/src/constants.ts CHANGED
@@ -2,9 +2,9 @@ import { Address, Cell, toNano } from '@ton/core';
2
2
  import { sha256Hash } from './utils/sha256BigInt';
3
3
 
4
4
  export const EVAA_MASTER_MAINNET = Address.parse('EQC8rUZqR_pWV1BylWUlPNBzyiTYVoBEmQkMIQDZXICfnuRr');
5
- export const MAINNET_VERSION = 4;
5
+ export const MAINNET_VERSION = 5;
6
6
  export const EVAA_MASTER_TESTNET = Address.parse('kQCj7qf3i2Cbf1GVtZCinla7lIvE7l3MBMsJMTfAja3BdoRP');
7
- export const TESTNET_VERSION = 4;
7
+ export const TESTNET_VERSION = 5;
8
8
 
9
9
  export const NFT_ID = '0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5';
10
10
 
@@ -43,6 +43,9 @@ export const MASTER_CONSTANTS = {
43
43
  FACTOR_SCALE: BigInt(1e12),
44
44
  ASSET_COEFFICIENT_SCALE: 10000n,
45
45
  ASSET_PRICE_SCALE: BigInt(1e8),
46
+ ASSET_RESERVE_FACTOR_SCALE: 10000n,
47
+ ASSET_LIQUIDATION_RESERVE_FACTOR_SCALE: 10000n,
48
+ ASSET_ORIGINATION_FEE_SCALE: BigInt(1e9)
46
49
  };
47
50
 
48
51
  export const LENDING_CODE = Cell.fromBoc(
@@ -59,6 +59,9 @@ export type SupplyBaseParameters = {
59
59
  amount: bigint;
60
60
  userAddress: Address;
61
61
  assetID: bigint;
62
+ /* Will be in v6
63
+ amountToTransfer: bigint;
64
+ payload: Cell; */
62
65
  };
63
66
  /**
64
67
  * Parameters for the TON supply message
@@ -92,6 +95,9 @@ export type WithdrawParameters = {
92
95
  userAddress: Address;
93
96
  includeUserCode: boolean;
94
97
  priceData: Cell;
98
+ /* Will be in v6
99
+ amountToTransfer: bigint;
100
+ payload: Cell; */
95
101
  };
96
102
 
97
103
  /**
@@ -184,6 +190,9 @@ export class Evaa implements Contract {
184
190
  .storeUint(OPCODES.SUPPLY, 32)
185
191
  .storeInt(parameters.includeUserCode ? -1 : 0, 2)
186
192
  .storeAddress(parameters.userAddress)
193
+ /* Will be in v6
194
+ .storeUint(parameters.amountToTransfer, 64)
195
+ .storeRef(parameters.payload) */
187
196
  .endCell(),
188
197
  )
189
198
  .endCell();
@@ -194,6 +203,9 @@ export class Evaa implements Contract {
194
203
  .storeInt(parameters.includeUserCode ? -1 : 0, 2)
195
204
  .storeUint(parameters.amount, 64)
196
205
  .storeAddress(parameters.userAddress)
206
+ /* Will be in v6
207
+ .storeUint(parameters.amountToTransfer, 64)
208
+ .storeRef(parameters.payload) */
197
209
  .endCell();
198
210
  }
199
211
  }
@@ -210,6 +222,9 @@ export class Evaa implements Contract {
210
222
  .storeUint(parameters.amount, 64)
211
223
  .storeAddress(parameters.userAddress)
212
224
  .storeInt(parameters.includeUserCode ? -1 : 0, 2)
225
+ /* Will be in v6
226
+ .storeUint(parameters.amountToTransfer, 64)
227
+ .storeRef(parameters.payload) */
213
228
  .storeRef(parameters.priceData)
214
229
  .endCell();
215
230
  }
@@ -27,6 +27,12 @@ export type AssetConfig = {
27
27
  originationFee: bigint;
28
28
  dust: bigint;
29
29
  maxTotalSupply: bigint;
30
+ reserveFactor: bigint;
31
+ liquidationReserveFactor: bigint;
32
+ /* Will be in v6
33
+ minPrincipalForRewards: bigint;
34
+ baseTrackingSupplySpeed: bigint;
35
+ baseTrackingBorrowSpeed: bigint; */
30
36
  };
31
37
 
32
38
  export type MasterConfig = {
@@ -44,6 +50,10 @@ export type AssetData = {
44
50
  totalBorrow: bigint;
45
51
  lastAccural: bigint;
46
52
  balance: bigint;
53
+ /* Will be in v6
54
+ trackingSupplyIndex: bigint;
55
+ trackingBorrowIndex: bigint;
56
+ lastTrackingAccural: bigint; */
47
57
  };
48
58
 
49
59
  export type AssetInterest = {
package/src/types/User.ts CHANGED
@@ -1,66 +1,93 @@
1
- import { Address, Cell, Dictionary } from '@ton/core';
2
-
3
- export enum BalanceType {
4
- supply = 'supply',
5
- borrow = 'borrow',
6
- }
7
-
8
- export type UserBalance = {
9
- amount: bigint;
10
- type?: BalanceType;
11
- };
12
-
13
- export type UserLiqudationData = {
14
- greatestCollateralValue: bigint;
15
- greatestCollateralAsset: bigint;
16
- greatestLoanValue: bigint;
17
- greatestLoanAsset: bigint;
18
- totalDebt: bigint;
19
- totalLimit: bigint;
20
- };
21
-
22
- export type LiquidableData = UserLiqudationData & {
23
- liquidable: true;
24
- liquidationAmount: bigint;
25
- minCollateralAmount: bigint;
26
- };
27
-
28
- export type NonLiquidableData = UserLiqudationData & {
29
- liquidable: false;
30
- };
31
-
32
- export type LiquidationData = LiquidableData | NonLiquidableData;
33
-
34
- export type UserLiteData = {
35
- type: 'active';
36
- codeVersion: number;
37
- masterAddress: Address;
38
- ownerAddress: Address;
39
- principals: Dictionary<bigint, bigint>;
40
- state: number;
41
- balances: Dictionary<bigint, UserBalance>;
42
- trackingSupplyIndex: bigint;
43
- trackingBorrowIndex: bigint;
44
- dutchAuctionStart: number;
45
- backupCell: Cell;
46
- };
47
-
48
- export type UserDataActive = UserLiteData & {
49
- withdrawalLimits: Dictionary<bigint, bigint>;
50
- borrowLimits: Dictionary<bigint, bigint>;
51
- repayLimits?: Dictionary<bigint, bigint>;
52
- supplyBalance: bigint;
53
- borrowBalance: bigint;
54
- availableToBorrow: bigint;
55
- limitUsedPercent: number;
56
- limitUsed: bigint;
57
- healthFactor: number;
58
-
59
- liquidationData: LiquidationData;
60
- };
61
-
62
- export type UserDataInactive = {
63
- type: 'inactive';
64
- };
65
-
66
- export type UserData = UserDataActive | UserDataInactive;
1
+ import { Address, Cell, Dictionary } from '@ton/core';
2
+ import { AssetConfig, ExtendedAssetData } from './Master';
3
+
4
+ export enum BalanceType {
5
+ supply = 'supply',
6
+ borrow = 'borrow',
7
+ }
8
+
9
+ export type UserBalance = {
10
+ amount: bigint;
11
+ type?: BalanceType;
12
+ };
13
+
14
+ export type UserLiqudationData = {
15
+ greatestCollateralValue: bigint;
16
+ greatestCollateralAsset: bigint;
17
+ greatestLoanValue: bigint;
18
+ greatestLoanAsset: bigint;
19
+ totalDebt: bigint;
20
+ totalLimit: bigint;
21
+ };
22
+
23
+ export type LiquidableData = UserLiqudationData & {
24
+ liquidable: true;
25
+ liquidationAmount: bigint;
26
+ minCollateralAmount: bigint;
27
+ };
28
+
29
+ export type NonLiquidableData = UserLiqudationData & {
30
+ liquidable: false;
31
+ };
32
+
33
+ export type LiquidationData = LiquidableData | NonLiquidableData;
34
+
35
+ export type UserLiteData = {
36
+ type: 'active';
37
+ codeVersion: number;
38
+ masterAddress: Address;
39
+ ownerAddress: Address;
40
+ principals: Dictionary<bigint, bigint>;
41
+ state: number;
42
+ balances: Dictionary<bigint, UserBalance>;
43
+ trackingSupplyIndex: bigint;
44
+ trackingBorrowIndex: bigint;
45
+ dutchAuctionStart: number;
46
+ backupCell: Cell;
47
+ /* Will be in v6
48
+ rewards: Dictionary<bigint, UserRewards>;
49
+ backupCell1: Cell | null;
50
+ backupCell2: Cell | null; */
51
+ };
52
+
53
+ export type UserDataActive = UserLiteData & {
54
+ withdrawalLimits: Dictionary<bigint, bigint>;
55
+ borrowLimits: Dictionary<bigint, bigint>;
56
+ repayLimits?: Dictionary<bigint, bigint>;
57
+ supplyBalance: bigint;
58
+ borrowBalance: bigint;
59
+ availableToBorrow: bigint;
60
+ limitUsedPercent: number;
61
+ limitUsed: bigint;
62
+ healthFactor: number;
63
+
64
+ liquidationData: LiquidationData;
65
+ };
66
+
67
+ export type UserDataInactive = {
68
+ type: 'inactive';
69
+ };
70
+
71
+ export type UserData = UserDataActive | UserDataInactive;
72
+
73
+ export type UserRewards = {
74
+ trackingIndex: bigint;
75
+ trackingAccured: bigint;
76
+ };
77
+
78
+ export enum BalanceChangeType {
79
+ Borrow = 0,
80
+ Repay = 1,
81
+ Supply = 2,
82
+ Withdraw = 3
83
+ }
84
+
85
+ export type PredictHealthFactorArgs = {
86
+ balanceChangeType: BalanceChangeType;
87
+ amount: bigint; // always positive
88
+ tokenSymbol: string;
89
+ balances: Dictionary<bigint, bigint>;
90
+ prices: Dictionary<bigint, bigint>;
91
+ assetsData: Dictionary<bigint, ExtendedAssetData>;
92
+ assetsConfig: Dictionary<bigint, AssetConfig>;
93
+ };
@@ -1,37 +1,37 @@
1
- import { ITonConnect, SendTransactionResponse } from '@tonconnect/sdk';
2
- import { Address, beginCell, Sender, SenderArguments, storeStateInit } from '@ton/core';
3
-
4
- /*
5
- This is not the best solution to get the BOC of the sent external message, however the Sender
6
- interface does not support returning any value from send(), so at the moment you can get it from
7
- this global variable.
8
- */
9
- let lastSentBoc: SendTransactionResponse | undefined;
10
-
11
- export function getLastSentBoc() {
12
- return lastSentBoc;
13
- }
14
-
15
- export function getTonConnectSender(connector: ITonConnect): Sender {
16
- return {
17
- get address(): Address | undefined {
18
- return connector.account ? Address.parse(connector.account.address) : undefined;
19
- },
20
-
21
- async send(args: SenderArguments): Promise<void> {
22
- lastSentBoc = await connector.sendTransaction({
23
- validUntil: Date.now() + 2 * 60 * 1000, // 1 minutes
24
- messages: [
25
- {
26
- address: args.to.toString(),
27
- amount: args.value.toString(),
28
- payload: args.body?.toBoc().toString('base64'),
29
- stateInit: args.init
30
- ? beginCell().store(storeStateInit(args.init)).endCell().toBoc().toString('base64')
31
- : undefined,
32
- },
33
- ],
34
- });
35
- },
36
- };
37
- }
1
+ import { ITonConnect, SendTransactionResponse } from '@tonconnect/sdk';
2
+ import { Address, beginCell, Sender, SenderArguments, storeStateInit } from '@ton/core';
3
+
4
+ /*
5
+ This is not the best solution to get the BOC of the sent external message, however the Sender
6
+ interface does not support returning any value from send(), so at the moment you can get it from
7
+ this global variable.
8
+ */
9
+ let lastSentBoc: SendTransactionResponse | undefined;
10
+
11
+ export function getLastSentBoc() {
12
+ return lastSentBoc;
13
+ }
14
+
15
+ export function getTonConnectSender(connector: ITonConnect): Sender {
16
+ return {
17
+ get address(): Address | undefined {
18
+ return connector.account ? Address.parse(connector.account.address) : undefined;
19
+ },
20
+
21
+ async send(args: SenderArguments): Promise<void> {
22
+ lastSentBoc = await connector.sendTransaction({
23
+ validUntil: Date.now() + 2 * 60 * 1000, // 1 minutes
24
+ messages: [
25
+ {
26
+ address: args.to.toString(),
27
+ amount: args.value.toString(),
28
+ payload: args.body?.toBoc().toString('base64'),
29
+ stateInit: args.init
30
+ ? beginCell().store(storeStateInit(args.init)).endCell().toBoc().toString('base64')
31
+ : undefined,
32
+ },
33
+ ],
34
+ });
35
+ },
36
+ };
37
+ }