@evaafi/sdk 0.9.5 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/math.d.ts +16 -3
- package/dist/api/math.js +356 -33
- package/dist/api/parser.js +34 -12
- package/dist/constants/assets/assetId.d.ts +2 -0
- package/dist/constants/assets/assetId.js +3 -0
- package/dist/constants/assets/mainnet.d.ts +2 -0
- package/dist/constants/assets/mainnet.js +13 -1
- package/dist/constants/general/mainnet.d.ts +2 -0
- package/dist/constants/general/mainnet.js +4 -1
- package/dist/constants/pools/mainnet.d.ts +2 -0
- package/dist/constants/pools/mainnet.js +45 -1
- package/dist/constants/pools/testnet.d.ts +3 -2
- package/dist/constants/pools/testnet.js +16 -1
- package/dist/oracles/collectors/ClassicCollector.js +13 -18
- package/dist/oracles/collectors/FakeCollector.d.ts +30 -0
- package/dist/oracles/collectors/FakeCollector.js +128 -0
- package/dist/oracles/collectors/index.d.ts +1 -0
- package/dist/oracles/collectors/index.js +1 -0
- package/dist/types/Master.d.ts +8 -2
- package/dist/types/User.d.ts +7 -3
- package/package.json +1 -1
- package/src/api/math.ts +504 -40
- package/src/api/parser.ts +57 -12
- package/src/constants/assets/assetId.ts +4 -0
- package/src/constants/assets/mainnet.ts +24 -0
- package/src/constants/general/mainnet.ts +4 -0
- package/src/constants/pools/mainnet.ts +53 -1
- package/src/constants/pools/testnet.ts +30 -5
- package/src/oracles/collectors/ClassicCollector.ts +10 -14
- package/src/oracles/collectors/FakeCollector.ts +153 -0
- package/src/oracles/collectors/index.ts +1 -0
- package/src/types/Master.ts +9 -2
- package/src/types/User.ts +7 -3
package/src/api/parser.ts
CHANGED
|
@@ -19,8 +19,11 @@ import {
|
|
|
19
19
|
calculateLiquidationData,
|
|
20
20
|
calculateMaximumWithdrawAmount,
|
|
21
21
|
calculatePresentValue,
|
|
22
|
+
determineHeCategory,
|
|
23
|
+
exceedsStandardBorrowLimit,
|
|
22
24
|
getAssetLiquidityMinusReserves,
|
|
23
25
|
getAvailableToBorrow,
|
|
26
|
+
getAvailableToBorrowWithEMode,
|
|
24
27
|
presentValue,
|
|
25
28
|
} from './math';
|
|
26
29
|
import { OracleParser } from './parsers/AbstractOracleParser';
|
|
@@ -130,8 +133,8 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
|
|
|
130
133
|
const baseTrackingBorrowSpeed = ref.loadUintBig(64);
|
|
131
134
|
const borrowCap = ref.loadInt(64);
|
|
132
135
|
const heCategory = ref.loadUint(8);
|
|
133
|
-
const heCollateralFactor = ref.
|
|
134
|
-
const heLiquidationThreshold = ref.
|
|
136
|
+
const heCollateralFactor = ref.loadUintBig(16);
|
|
137
|
+
const heLiquidationThreshold = ref.loadUintBig(16);
|
|
135
138
|
|
|
136
139
|
return {
|
|
137
140
|
jwAddress,
|
|
@@ -242,8 +245,8 @@ export function parseUserLiteData(
|
|
|
242
245
|
const userSlice = Cell.fromBase64(userDataBOC).beginParse();
|
|
243
246
|
|
|
244
247
|
const codeVersion = userSlice.loadCoins();
|
|
245
|
-
const masterAddress = userSlice.
|
|
246
|
-
const userAddress = userSlice.
|
|
248
|
+
const masterAddress = userSlice.loadAddressAny();
|
|
249
|
+
const userAddress = userSlice.loadAddressAny();
|
|
247
250
|
const realPrincipals = userSlice.loadDict(Dictionary.Keys.BigUint(256), Dictionary.Values.BigInt(64));
|
|
248
251
|
const principalsDict = Dictionary.empty(Dictionary.Keys.BigUint(256), Dictionary.Values.BigInt(64));
|
|
249
252
|
const userState = userSlice.loadInt(64);
|
|
@@ -256,18 +259,26 @@ export function parseUserLiteData(
|
|
|
256
259
|
let backupCell1: Cell | null = null;
|
|
257
260
|
let backupCell2: Cell | null = null;
|
|
258
261
|
const bitsLeft = userSlice.remainingBits;
|
|
259
|
-
|
|
262
|
+
const refsLeft = userSlice.remainingRefs;
|
|
263
|
+
if (bitsLeft === 0 && refsLeft === 0) {
|
|
264
|
+
// Init format: no extra data after state
|
|
265
|
+
} else if (bitsLeft >= 64 + 64 + 32 && refsLeft >= 1) {
|
|
266
|
+
// Old format with tracking indexes
|
|
260
267
|
trackingSupplyIndex = userSlice.loadUintBig(64);
|
|
261
268
|
trackingBorrowIndex = userSlice.loadUintBig(64);
|
|
262
269
|
dutchAuctionStart = userSlice.loadUint(32);
|
|
263
270
|
backupCell = loadMyRef(userSlice);
|
|
264
|
-
} else {
|
|
271
|
+
} else if (bitsLeft >= 3 && refsLeft >= 1) {
|
|
272
|
+
// New format with rewards dict + maybe_refs
|
|
265
273
|
rewards = userSlice.loadDict(Dictionary.Keys.BigUint(256), createUserRewards());
|
|
266
|
-
|
|
267
|
-
|
|
274
|
+
if (userSlice.remainingBits >= 2) {
|
|
275
|
+
backupCell1 = userSlice.loadMaybeRef();
|
|
276
|
+
backupCell2 = userSlice.loadMaybeRef();
|
|
277
|
+
}
|
|
268
278
|
}
|
|
269
279
|
|
|
270
|
-
|
|
280
|
+
// Skip remaining data if any (for forward compatibility)
|
|
281
|
+
// userSlice.endParse();
|
|
271
282
|
const userBalances = Dictionary.empty<bigint, UserBalance>();
|
|
272
283
|
|
|
273
284
|
for (const [_, asset] of Object.entries(poolAssetsConfig)) {
|
|
@@ -327,6 +338,7 @@ export function parseUserData(
|
|
|
327
338
|
|
|
328
339
|
const withdrawalLimits = Dictionary.empty<bigint, bigint>();
|
|
329
340
|
const borrowLimits = Dictionary.empty<bigint, bigint>();
|
|
341
|
+
const borrowLimitsWithEmode = Dictionary.empty<bigint, bigint>();
|
|
330
342
|
|
|
331
343
|
let supplyBalance = 0n;
|
|
332
344
|
let borrowBalance = 0n;
|
|
@@ -379,6 +391,19 @@ export function parseUserData(
|
|
|
379
391
|
prices,
|
|
380
392
|
masterConstants,
|
|
381
393
|
);
|
|
394
|
+
const { availableToBorrow: availableToBorrowWithEmode, heCategory: predictedHeCategory } =
|
|
395
|
+
getAvailableToBorrowWithEMode(
|
|
396
|
+
assetsConfig,
|
|
397
|
+
assetsData,
|
|
398
|
+
userLiteData.realPrincipals,
|
|
399
|
+
prices,
|
|
400
|
+
masterConstants,
|
|
401
|
+
poolConfig,
|
|
402
|
+
);
|
|
403
|
+
let activeHeCategory = determineHeCategory(assetsConfig, userLiteData.realPrincipals, poolConfig);
|
|
404
|
+
if (activeHeCategory > 0 && !exceedsStandardBorrowLimit(userLiteData.realPrincipals, assetsConfig, assetsData, prices, masterConstants)) {
|
|
405
|
+
activeHeCategory = -1;
|
|
406
|
+
}
|
|
382
407
|
|
|
383
408
|
for (const [_, asset] of Object.entries(poolAssetsConfig)) {
|
|
384
409
|
const balance = userLiteData.balances.get(asset.assetId) as UserBalance;
|
|
@@ -396,7 +421,7 @@ export function parseUserData(
|
|
|
396
421
|
assetsData,
|
|
397
422
|
userLiteData.realPrincipals,
|
|
398
423
|
prices,
|
|
399
|
-
|
|
424
|
+
poolConfig,
|
|
400
425
|
asset.assetId,
|
|
401
426
|
),
|
|
402
427
|
assetData.balance,
|
|
@@ -406,6 +431,7 @@ export function parseUserData(
|
|
|
406
431
|
|
|
407
432
|
if (!prices.has(asset.assetId)) {
|
|
408
433
|
borrowLimits.set(asset.assetId, 0n);
|
|
434
|
+
borrowLimitsWithEmode.set(asset.assetId, 0n);
|
|
409
435
|
continue;
|
|
410
436
|
}
|
|
411
437
|
|
|
@@ -419,13 +445,27 @@ export function parseUserData(
|
|
|
419
445
|
),
|
|
420
446
|
),
|
|
421
447
|
);
|
|
448
|
+
|
|
449
|
+
borrowLimitsWithEmode.set(
|
|
450
|
+
asset.assetId,
|
|
451
|
+
bigIntMax(
|
|
452
|
+
0n,
|
|
453
|
+
bigIntMin(
|
|
454
|
+
(availableToBorrowWithEmode * 10n ** assetConfig.decimals) / prices.get(asset.assetId)!,
|
|
455
|
+
assetLiquidityMinusReserves,
|
|
456
|
+
),
|
|
457
|
+
),
|
|
458
|
+
);
|
|
422
459
|
}
|
|
423
460
|
|
|
424
|
-
const limitUsed = borrowBalance +
|
|
461
|
+
const limitUsed = borrowBalance + availableToBorrowWithEmode;
|
|
425
462
|
const limitUsedPercent =
|
|
426
463
|
limitUsed === 0n
|
|
427
464
|
? 0
|
|
428
|
-
: Number(
|
|
465
|
+
: Number(
|
|
466
|
+
BigInt(1e9) -
|
|
467
|
+
(availableToBorrowWithEmode * BigInt(1e9)) / (borrowBalance + availableToBorrowWithEmode),
|
|
468
|
+
) / 1e7;
|
|
429
469
|
|
|
430
470
|
let healthFactor = 1;
|
|
431
471
|
let liquidationData;
|
|
@@ -441,17 +481,22 @@ export function parseUserData(
|
|
|
441
481
|
healthFactor = 1 - Number(liquidationData.totalDebt) / Number(liquidationData.totalLimit);
|
|
442
482
|
}
|
|
443
483
|
}
|
|
484
|
+
|
|
444
485
|
return {
|
|
445
486
|
...userLiteData,
|
|
446
487
|
withdrawalLimits: withdrawalLimits,
|
|
447
488
|
borrowLimits: borrowLimits,
|
|
489
|
+
borrowLimitsWithEmode: borrowLimitsWithEmode,
|
|
448
490
|
supplyBalance: supplyBalance,
|
|
449
491
|
borrowBalance: borrowBalance,
|
|
450
492
|
availableToBorrow: availableToBorrow,
|
|
493
|
+
availableToBorrowWithEmode: availableToBorrowWithEmode,
|
|
494
|
+
predictedHeCategory: predictedHeCategory,
|
|
451
495
|
limitUsedPercent: limitUsedPercent,
|
|
452
496
|
limitUsed: limitUsed,
|
|
453
497
|
liquidationData: liquidationData,
|
|
454
498
|
healthFactor: healthFactor,
|
|
455
499
|
havePrincipalWithoutPrice: havePrincipalWithoutPrice,
|
|
500
|
+
activeHeCategory: activeHeCategory,
|
|
456
501
|
};
|
|
457
502
|
}
|
|
@@ -30,6 +30,10 @@ export const ASSET_ID = {
|
|
|
30
30
|
PT_tsUSDe_01Sep2025: sha256Hash('PT_tsUSDe_01Sep2025'),
|
|
31
31
|
PT_tsUSDe_18Dec2025: sha256Hash('PT_tsUSDe_18Dec2025'),
|
|
32
32
|
|
|
33
|
+
// Mainnet test assets
|
|
34
|
+
TUSDT: sha256Hash('TUSDT'),
|
|
35
|
+
TUSDe: sha256Hash('TUSDe'),
|
|
36
|
+
|
|
33
37
|
// Testnet assets, faucet t.me/evaabuidl
|
|
34
38
|
EUSDT: sha256Hash('EUSDT'),
|
|
35
39
|
EUSDC: sha256Hash('EUSDC'),
|
|
@@ -216,3 +216,27 @@ export const EVAA_MAINNET: PoolAssetConfig = {
|
|
|
216
216
|
),
|
|
217
217
|
)[0],
|
|
218
218
|
};
|
|
219
|
+
|
|
220
|
+
export const TUSDT_MAINNET: PoolAssetConfig = {
|
|
221
|
+
name: 'TUSDT',
|
|
222
|
+
assetId: ASSET_ID.TUSDT,
|
|
223
|
+
jettonMasterAddress: Address.parse('EQCA1saJX4oYdG38m1__Of6ym2GnKSGVuccAy6UU-ESeXjvb'),
|
|
224
|
+
jettonWalletCode: Cell.fromBoc(
|
|
225
|
+
Buffer.from(
|
|
226
|
+
'b5ee9c7201021101000323000114ff00f4a413f4bcf2c80b0102016202030202cc0405001ba0f605da89a1f401f481f481a8610201d40607020120080900c30831c02497c138007434c0c05c6c2544d7c0fc03383e903e900c7e800c5c75c87e800c7e800c1cea6d0000b4c7e08403e29fa954882ea54c4d167c0278208405e3514654882ea58c511100fc02b80d60841657c1ef2ea4d67c02f817c12103fcbc2000113e910c1c2ebcb853600201200a0b0083d40106b90f6a2687d007d207d206a1802698fc1080bc6a28ca9105d41083deecbef09dd0958f97162e99f98fd001809d02811e428027d012c678b00e78b6664f6aa401f1503d33ffa00fa4021f001ed44d0fa00fa40fa40d4305136a1522ac705f2e2c128c2fff2e2c254344270542013541403c85004fa0258cf1601cf16ccc922c8cb0112f400f400cb00c920f9007074c8cb02ca07cbffc9d004fa40f40431fa0020d749c200f2e2c4778018c8cb055008cf1670fa0217cb6b13cc80c0201200d0e009e8210178d4519c8cb1f19cb3f5007fa0222cf165006cf1625fa025003cf16c95005cc2391729171e25008a813a08209c9c380a014bcf2e2c504c98040fb001023c85004fa0258cf1601cf16ccc9ed5402f73b51343e803e903e90350c0234cffe80145468017e903e9014d6f1c1551cdb5c150804d50500f214013e809633c58073c5b33248b232c044bd003d0032c0327e401c1d3232c0b281f2fff274140371c1472c7cb8b0c2be80146a2860822625a019ad822860822625a028062849e5c412440e0dd7c138c34975c2c0600f1000d73b51343e803e903e90350c01f4cffe803e900c145468549271c17cb8b049f0bffcb8b08160824c4b402805af3cb8b0e0841ef765f7b232c7c572cfd400fe8088b3c58073c5b25c60063232c14933c59c3e80b2dab33260103ec01004f214013e809633c58073c5b3327b552000705279a018a182107362d09cc8cb1f5230cb3f58fa025007cf165007cf16c9718010c8cb0524cf165006fa0215cb6a14ccc971fb0010241023007cc30023c200b08e218210d53276db708010c8cb055008cf165004fa0216cb6a12cb1f12cb3fc972fb0093356c21e203c85004fa0258cf1601cf16ccc9ed54',
|
|
227
|
+
'hex',
|
|
228
|
+
),
|
|
229
|
+
)[0],
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export const TUSDE_MAINNET: PoolAssetConfig = {
|
|
233
|
+
name: 'TUSDe',
|
|
234
|
+
assetId: ASSET_ID.TUSDe,
|
|
235
|
+
jettonMasterAddress: Address.parse('EQC2cewpgyIzP9o1gTSGsQceuY1nt3bjpilek7ARKyhWtQKk'),
|
|
236
|
+
jettonWalletCode: Cell.fromBoc(
|
|
237
|
+
Buffer.from(
|
|
238
|
+
'b5ee9c7201021101000323000114ff00f4a413f4bcf2c80b0102016202030202cc0405001ba0f605da89a1f401f481f481a8610201d40607020120080900c30831c02497c138007434c0c05c6c2544d7c0fc03383e903e900c7e800c5c75c87e800c7e800c1cea6d0000b4c7e08403e29fa954882ea54c4d167c0278208405e3514654882ea58c511100fc02b80d60841657c1ef2ea4d67c02f817c12103fcbc2000113e910c1c2ebcb853600201200a0b0083d40106b90f6a2687d007d207d206a1802698fc1080bc6a28ca9105d41083deecbef09dd0958f97162e99f98fd001809d02811e428027d012c678b00e78b6664f6aa401f1503d33ffa00fa4021f001ed44d0fa00fa40fa40d4305136a1522ac705f2e2c128c2fff2e2c254344270542013541403c85004fa0258cf1601cf16ccc922c8cb0112f400f400cb00c920f9007074c8cb02ca07cbffc9d004fa40f40431fa0020d749c200f2e2c4778018c8cb055008cf1670fa0217cb6b13cc80c0201200d0e009e8210178d4519c8cb1f19cb3f5007fa0222cf165006cf1625fa025003cf16c95005cc2391729171e25008a813a08209c9c380a014bcf2e2c504c98040fb001023c85004fa0258cf1601cf16ccc9ed5402f73b51343e803e903e90350c0234cffe80145468017e903e9014d6f1c1551cdb5c150804d50500f214013e809633c58073c5b33248b232c044bd003d0032c0327e401c1d3232c0b281f2fff274140371c1472c7cb8b0c2be80146a2860822625a019ad822860822625a028062849e5c412440e0dd7c138c34975c2c0600f1000d73b51343e803e903e90350c01f4cffe803e900c145468549271c17cb8b049f0bffcb8b08160824c4b402805af3cb8b0e0841ef765f7b232c7c572cfd400fe8088b3c58073c5b25c60063232c14933c59c3e80b2dab33260103ec01004f214013e809633c58073c5b3327b552000705279a018a182107362d09cc8cb1f5230cb3f58fa025007cf165007cf16c9718010c8cb0524cf165006fa0215cb6a14ccc971fb0010241023007cc30023c200b08e218210d53276db708010c8cb055008cf165004fa0216cb6a12cb1f12cb3fc972fb0093356c21e203c85004fa0258cf1601cf16ccc9ed54',
|
|
239
|
+
'hex',
|
|
240
|
+
),
|
|
241
|
+
)[0],
|
|
242
|
+
};
|
|
@@ -9,6 +9,10 @@ export const MAINNET_VERSION = 10;
|
|
|
9
9
|
export const EVAA_LP_MAINNET = Address.parse('EQBIlZX2URWkXCSg3QF2MJZU-wC5XkBoLww-hdWk2G37Jc6N');
|
|
10
10
|
export const EVAA_LP_MAINNET_VERSION = 6;
|
|
11
11
|
|
|
12
|
+
/* LP POOL COPY */
|
|
13
|
+
export const EVAA_LP_COPY_MAINNET = Address.parse('EQA8H9nNHly7yJ32UmUDzH97Je2l8bAI6P74yKIIwPwKKXrz');
|
|
14
|
+
export const EVAA_LP_COPY_MAINNET_VERSION = 0;
|
|
15
|
+
|
|
12
16
|
/* ALTS POOL */
|
|
13
17
|
export const EVAA_ALTS_MAINNET = Address.parse('EQANURVS3fhBO9bivig34iyJQi97FhMbpivo1aUEAS2GYSu-');
|
|
14
18
|
export const EVAA_ALTS_MAINNET_VERSION = 4;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HexString } from '@pythnetwork/hermes-client';
|
|
2
2
|
import { Address, Dictionary } from '@ton/core';
|
|
3
3
|
import { FEED_ID, FeedMapItem } from '../../api/feeds';
|
|
4
|
-
import { ClassicCollector, DefaultPythPriceSourcesConfig, PythCollector } from '../../oracles';
|
|
4
|
+
import { ClassicCollector, DefaultPythPriceSourcesConfig, FakeCollector, PythCollector } from '../../oracles';
|
|
5
5
|
import { PoolConfig } from '../../types/Master';
|
|
6
6
|
import { EvaaRewardsConfig } from '../../types/MasterRewards';
|
|
7
7
|
import {
|
|
@@ -24,11 +24,15 @@ import {
|
|
|
24
24
|
USDE_MAINNET,
|
|
25
25
|
USDT_MAINNET,
|
|
26
26
|
USDT_STORM_MAINNET,
|
|
27
|
+
TUSDE_MAINNET,
|
|
28
|
+
TUSDT_MAINNET,
|
|
27
29
|
} from '../assets';
|
|
28
30
|
import {
|
|
29
31
|
EVAA_ALTS_MAINNET,
|
|
30
32
|
EVAA_ALTS_MAINNET_VERSION,
|
|
31
33
|
EVAA_EVAA_REWARDS_MASTER_MAINNET,
|
|
34
|
+
EVAA_LP_COPY_MAINNET,
|
|
35
|
+
EVAA_LP_COPY_MAINNET_VERSION,
|
|
32
36
|
EVAA_LP_MAINNET,
|
|
33
37
|
EVAA_LP_MAINNET_VERSION,
|
|
34
38
|
EVAA_MASTER_MAINNET,
|
|
@@ -105,6 +109,10 @@ export const MAINNET_POOL_CONFIG: PoolConfig = {
|
|
|
105
109
|
},
|
|
106
110
|
}),
|
|
107
111
|
poolAssetsConfig: MAINNET_POOL_ASSETS_CONFIG,
|
|
112
|
+
poolAssetsHEConfig: [
|
|
113
|
+
{ title: 'ton', assets: [TON_MAINNET, TSTON_MAINNET], heCategory: 1 },
|
|
114
|
+
{ title: 'stable', assets: [USDT_MAINNET, USDE_MAINNET, TSUSDE_MAINNET], heCategory: 2 },
|
|
115
|
+
],
|
|
108
116
|
lendingCode: LENDING_CODE,
|
|
109
117
|
};
|
|
110
118
|
|
|
@@ -118,6 +126,7 @@ export const MAINNET_STABLE_POOL_CONFIG: PoolConfig = {
|
|
|
118
126
|
evaaOracles: ORACLES_MAINNET,
|
|
119
127
|
}),
|
|
120
128
|
poolAssetsConfig: MAINNET_STABLE_POOL_ASSETS_CONFIG,
|
|
129
|
+
poolAssetsHEConfig: [],
|
|
121
130
|
lendingCode: LENDING_CODE,
|
|
122
131
|
};
|
|
123
132
|
|
|
@@ -131,6 +140,27 @@ export const MAINNET_LP_POOL_CONFIG: PoolConfig = {
|
|
|
131
140
|
evaaOracles: ORACLES_LP,
|
|
132
141
|
}),
|
|
133
142
|
poolAssetsConfig: MAINNET_LP_POOL_ASSETS_CONFIG,
|
|
143
|
+
poolAssetsHEConfig: [
|
|
144
|
+
{ title: 'ton', assets: [TON_MAINNET, TON_STORM_MAINNET], heCategory: 1 },
|
|
145
|
+
{ title: 'stable', assets: [USDT_MAINNET, USDT_STORM_MAINNET], heCategory: 2 },
|
|
146
|
+
],
|
|
147
|
+
lendingCode: LENDING_CODE,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const MAINNET_LP_POOL_COPY_CONFIG: PoolConfig = {
|
|
151
|
+
masterAddress: EVAA_LP_COPY_MAINNET,
|
|
152
|
+
masterVersion: EVAA_LP_COPY_MAINNET_VERSION,
|
|
153
|
+
masterConstants: MASTER_CONSTANTS,
|
|
154
|
+
collector: new ClassicCollector({
|
|
155
|
+
poolAssetsConfig: MAINNET_LP_POOL_ASSETS_CONFIG,
|
|
156
|
+
minimalOracles: 3,
|
|
157
|
+
evaaOracles: ORACLES_LP,
|
|
158
|
+
}),
|
|
159
|
+
poolAssetsConfig: MAINNET_LP_POOL_ASSETS_CONFIG,
|
|
160
|
+
poolAssetsHEConfig: [
|
|
161
|
+
{ title: 'ton', assets: [TON_MAINNET, TON_STORM_MAINNET], heCategory: 1 },
|
|
162
|
+
{ title: 'stable', assets: [USDT_MAINNET, USDT_STORM_MAINNET], heCategory: 2 },
|
|
163
|
+
],
|
|
134
164
|
lendingCode: LENDING_CODE,
|
|
135
165
|
};
|
|
136
166
|
|
|
@@ -144,6 +174,7 @@ export const MAINNET_ALTS_POOL_CONFIG: PoolConfig = {
|
|
|
144
174
|
evaaOracles: ORACLES_ALTS,
|
|
145
175
|
}),
|
|
146
176
|
poolAssetsConfig: MAINNET_ALTS_POOL_ASSETS_CONFIG,
|
|
177
|
+
poolAssetsHEConfig: [],
|
|
147
178
|
lendingCode: LENDING_CODE,
|
|
148
179
|
};
|
|
149
180
|
|
|
@@ -166,6 +197,7 @@ export const MAINNET_PYTH_V8_TOB_POOL_CONFIG: PoolConfig = {
|
|
|
166
197
|
},
|
|
167
198
|
}),
|
|
168
199
|
poolAssetsConfig: MAINNET_PYTH_V8_TOB_POOL_ASSETS_CONFIG,
|
|
200
|
+
poolAssetsHEConfig: [],
|
|
169
201
|
lendingCode: LENDING_CODE,
|
|
170
202
|
};
|
|
171
203
|
|
|
@@ -181,6 +213,7 @@ export const MAINNET_V8_TOB_POOL_CONFIG: PoolConfig = {
|
|
|
181
213
|
evaaOracles: ORACLES_MAINNET,
|
|
182
214
|
}),
|
|
183
215
|
poolAssetsConfig: MAINNET_V8_TOB_POOL_ASSETS_CONFIG,
|
|
216
|
+
poolAssetsHEConfig: [],
|
|
184
217
|
lendingCode: LENDING_CODE,
|
|
185
218
|
};
|
|
186
219
|
|
|
@@ -214,6 +247,25 @@ export const MAINNET_MASTER_EVAA_REWARD_CONFIG: EvaaRewardsConfig = {
|
|
|
214
247
|
publicKey: Buffer.from('b8eb0e312a9aa6394edceef21573f2d45e7d7a616a924e33190bd52fa31c8bb1', 'hex'), // adminAddress publicKey
|
|
215
248
|
};
|
|
216
249
|
|
|
250
|
+
export const MAINNET_CLASSIC_HE_POOL_CONFIG: PoolConfig = {
|
|
251
|
+
masterAddress: Address.parse('EQAI_O_VqUhqFQ-AW969xl1eXOi4euSWl1puxEroekJ5xpOt'),
|
|
252
|
+
masterVersion: 0,
|
|
253
|
+
masterConstants: MASTER_CONSTANTS,
|
|
254
|
+
collector: new FakeCollector(
|
|
255
|
+
Dictionary.empty<bigint, bigint>()
|
|
256
|
+
.set(ASSET_ID.TON, 1_300_000_000n)
|
|
257
|
+
.set(ASSET_ID.tsTON, 1_500_000_000n)
|
|
258
|
+
.set(ASSET_ID.TUSDT, 1_000_000_000n)
|
|
259
|
+
.set(ASSET_ID.TUSDe, 1_000_000_000n),
|
|
260
|
+
),
|
|
261
|
+
poolAssetsConfig: [TON_MAINNET, TSTON_MAINNET, TUSDE_MAINNET, TUSDT_MAINNET],
|
|
262
|
+
poolAssetsHEConfig: [
|
|
263
|
+
{ title: 'ton', assets: [TON_MAINNET, TSTON_MAINNET], heCategory: 1 },
|
|
264
|
+
{ title: 'stable', assets: [TUSDT_MAINNET, TUSDE_MAINNET], heCategory: 2 },
|
|
265
|
+
],
|
|
266
|
+
lendingCode: LENDING_CODE,
|
|
267
|
+
};
|
|
268
|
+
|
|
217
269
|
export const ALL_MAINNET_POOLS: PoolConfig[] = [
|
|
218
270
|
MAINNET_POOL_CONFIG,
|
|
219
271
|
MAINNET_LP_POOL_CONFIG,
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { HexString } from '@pythnetwork/hermes-client';
|
|
1
|
+
import type { HexString } from '@pythnetwork/hermes-client';
|
|
2
|
+
import type { PoolConfig } from '../../types/Master';
|
|
3
|
+
import type { EvaaRewardsConfig } from '../../types/MasterRewards';
|
|
2
4
|
import { Address, Dictionary } from '@ton/core';
|
|
3
|
-
import { FEED_ID, FeedMapItem } from '../../api/feeds';
|
|
5
|
+
import { FEED_ID, type FeedMapItem } from '../../api/feeds';
|
|
4
6
|
import { ClassicCollector, DefaultPythPriceSourcesConfig, PythCollector } from '../../oracles';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
import {
|
|
8
|
+
ASSET_ID,
|
|
9
|
+
EUSDT_TESTNET,
|
|
10
|
+
JUSDC_TESTNET,
|
|
11
|
+
TON_MAINNET,
|
|
12
|
+
TON_TESTNET,
|
|
13
|
+
TSTON_MAINNET,
|
|
14
|
+
USDE_MAINNET,
|
|
15
|
+
USDT_MAINNET,
|
|
16
|
+
} from '../assets';
|
|
8
17
|
import {
|
|
9
18
|
EVAA_MASTER_TESTNET_CLASSIC_TOB_AUDITED,
|
|
10
19
|
EVAA_MASTER_TESTNET_PYTH_TOB_AUDITED,
|
|
@@ -45,6 +54,7 @@ export const TESTNET_PYTH_POOL_CONFIG_TOB_AUDITED: PoolConfig = {
|
|
|
45
54
|
pythConfig: DefaultPythPriceSourcesConfig,
|
|
46
55
|
}),
|
|
47
56
|
poolAssetsConfig: TESTNET_POOL_ASSETS_CONFIG_TOB_AUDITED,
|
|
57
|
+
poolAssetsHEConfig: [],
|
|
48
58
|
lendingCode: LENDING_CODE,
|
|
49
59
|
};
|
|
50
60
|
|
|
@@ -59,6 +69,21 @@ export const TESTNET_CLASSIC_POOL_CONFIG_TOB_AUDITED: PoolConfig = {
|
|
|
59
69
|
}),
|
|
60
70
|
lendingCode: LENDING_CODE,
|
|
61
71
|
poolAssetsConfig: TESTNET_POOL_ASSETS_CONFIG,
|
|
72
|
+
poolAssetsHEConfig: [],
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const TESTNET_CLASSIC_HE_POOL_CONFIG: PoolConfig = {
|
|
76
|
+
masterAddress: Address.parse('EQBykKj3k97Mx_EEGwzmnqFLteFRAt0BIg-ig96ifNkdV3Wn'),
|
|
77
|
+
masterVersion: 0,
|
|
78
|
+
masterConstants: MASTER_CONSTANTS,
|
|
79
|
+
collector: new ClassicCollector({
|
|
80
|
+
poolAssetsConfig: [TON_MAINNET, TSTON_MAINNET, USDT_MAINNET, USDE_MAINNET],
|
|
81
|
+
minimalOracles: 1,
|
|
82
|
+
evaaOracles: ORACLES_TESTNET,
|
|
83
|
+
}),
|
|
84
|
+
lendingCode: LENDING_CODE,
|
|
85
|
+
poolAssetsConfig: [TON_MAINNET, TSTON_MAINNET, USDT_MAINNET, USDE_MAINNET],
|
|
86
|
+
poolAssetsHEConfig: [],
|
|
62
87
|
};
|
|
63
88
|
|
|
64
89
|
export const TESTNET_MASTER_REWARD_CONFIG: EvaaRewardsConfig = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Dictionary } from '@ton/core';
|
|
2
2
|
import { checkNotInDebtAtAll } from '../../api/math';
|
|
3
3
|
import { ExtendedEvaaOracle, PoolAssetConfig } from '../../types/Master';
|
|
4
|
-
import { FetchConfig
|
|
4
|
+
import { FetchConfig } from '../../utils/utils';
|
|
5
5
|
import { ClassicPrices, ClassicPricesMode, ClassicPricesOffset } from '../prices/ClassicPrices';
|
|
6
6
|
import { PriceSource } from '../sources';
|
|
7
7
|
import { DefaultPriceSourcesConfig, PriceSourcesConfig, RawPriceData } from '../Types';
|
|
@@ -181,20 +181,16 @@ export class ClassicCollector extends AbstractCollector {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
async #collectPrices(fetchConfig?: FetchConfig): Promise<boolean> {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
this.#
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
184
|
+
try {
|
|
185
|
+
this.#prices = await Promise.any(
|
|
186
|
+
this.#priceSources.map((source) =>
|
|
187
|
+
collectAndFilterPrices(source, this.#minimalOracles, fetchConfig),
|
|
188
|
+
),
|
|
189
|
+
);
|
|
190
|
+
return true;
|
|
191
|
+
} catch {
|
|
192
|
+
return false;
|
|
195
193
|
}
|
|
196
|
-
|
|
197
|
-
return false;
|
|
198
194
|
}
|
|
199
195
|
|
|
200
196
|
async #collectPricesWithValidation(fetchConfig?: FetchConfig): Promise<void> {
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { beginCell, Cell, Dictionary } from '@ton/core';
|
|
2
|
+
import { ClassicPrices, ClassicPricesMode } from '../prices/ClassicPrices';
|
|
3
|
+
import { PoolAssetConfig } from '../../types/Master';
|
|
4
|
+
import { FetchConfig } from '../../utils/utils';
|
|
5
|
+
import { AbstractCollector } from './AbstractCollector';
|
|
6
|
+
import { packAssetsData, packPrices, packOraclesData } from '../utils';
|
|
7
|
+
import { keyPairFromSeed, sign } from '@ton/crypto';
|
|
8
|
+
|
|
9
|
+
function createFakeOracle(id: number, seed: Buffer) {
|
|
10
|
+
const keypair = keyPairFromSeed(seed);
|
|
11
|
+
return {
|
|
12
|
+
id,
|
|
13
|
+
pubkey: keypair.publicKey,
|
|
14
|
+
secret: keypair.secretKey,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const fakeOracles = [
|
|
19
|
+
createFakeOracle(0, Buffer.alloc(32, 0)),
|
|
20
|
+
createFakeOracle(1, Buffer.alloc(32, 1)),
|
|
21
|
+
createFakeOracle(2, Buffer.alloc(32, 2)),
|
|
22
|
+
createFakeOracle(3, Buffer.alloc(32, 3)),
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
function packPricesData(timestamp: number, prices: Dictionary<bigint, bigint>): Cell {
|
|
26
|
+
return beginCell()
|
|
27
|
+
.storeUint(timestamp, 32)
|
|
28
|
+
.storeDict(prices, Dictionary.Keys.BigUint(256), Dictionary.Values.BigVarUint(4))
|
|
29
|
+
.endCell();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function signPricesData(
|
|
33
|
+
oracle: { secret: Buffer },
|
|
34
|
+
data: { timestamp: number; prices: Dictionary<bigint, bigint> },
|
|
35
|
+
): Buffer {
|
|
36
|
+
const packedData = packPricesData(data.timestamp, data.prices);
|
|
37
|
+
return sign(packedData.hash(), oracle.secret);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function withSerializers(src: Dictionary<bigint, bigint>): Dictionary<bigint, bigint> {
|
|
41
|
+
const dict = Dictionary.empty(Dictionary.Keys.BigUint(256), Dictionary.Values.BigVarUint(4));
|
|
42
|
+
for (const key of src.keys()) {
|
|
43
|
+
dict.set(key, src.get(key)!);
|
|
44
|
+
}
|
|
45
|
+
return dict;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function buildPricesCell(
|
|
49
|
+
pricesDict: Dictionary<bigint, bigint>,
|
|
50
|
+
assetIds: bigint[],
|
|
51
|
+
timestamp: number,
|
|
52
|
+
): { dict: Dictionary<bigint, bigint>; dataCell: Cell } {
|
|
53
|
+
const serializedPrices = withSerializers(pricesDict);
|
|
54
|
+
const oraclesData = fakeOracles.map((oracle) => {
|
|
55
|
+
const data = { timestamp, prices: serializedPrices };
|
|
56
|
+
const signature = signPricesData(oracle, data);
|
|
57
|
+
return {
|
|
58
|
+
oracle: { id: oracle.id, pubkey: oracle.pubkey },
|
|
59
|
+
data,
|
|
60
|
+
signature,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const medianData = assetIds.map((assetId) => ({
|
|
65
|
+
assetId,
|
|
66
|
+
medianPrice: pricesDict.get(assetId)!,
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
const assetsDataCell = packAssetsData(medianData);
|
|
70
|
+
const oraclesDataCell = packOraclesData(oraclesData, assetIds);
|
|
71
|
+
const dataCell = packPrices(assetsDataCell, oraclesDataCell);
|
|
72
|
+
|
|
73
|
+
const dict = Dictionary.empty<bigint, bigint>();
|
|
74
|
+
for (const { assetId, medianPrice } of medianData) {
|
|
75
|
+
dict.set(assetId, medianPrice);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return { dict, dataCell };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* FakeCollector for testing smart contracts.
|
|
83
|
+
*
|
|
84
|
+
* Accepts a Dictionary<bigint, bigint> mapping assetId to price
|
|
85
|
+
* (in ASSET_PRICE_SCALE, i.e. USD price * 1e9) and produces valid
|
|
86
|
+
* ClassicPrices without any network calls.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const prices = Dictionary.empty<bigint, bigint>();
|
|
91
|
+
* prices.set(TON_ASSET_ID, 5_000_000_000n); // $5.00
|
|
92
|
+
* prices.set(USDT_ASSET_ID, 1_000_000_000n); // $1.00
|
|
93
|
+
*
|
|
94
|
+
* const collector = new FakeCollector(prices);
|
|
95
|
+
* const classicPrices = await collector.getPrices();
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export class FakeCollector extends AbstractCollector {
|
|
99
|
+
readonly #pricesDict: Dictionary<bigint, bigint>;
|
|
100
|
+
|
|
101
|
+
constructor(prices: Dictionary<bigint, bigint>) {
|
|
102
|
+
super();
|
|
103
|
+
this.#pricesDict = prices;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async getPricesForLiquidate(
|
|
107
|
+
_realPrincipals: Dictionary<bigint, bigint>,
|
|
108
|
+
_fetchConfig?: FetchConfig,
|
|
109
|
+
): Promise<ClassicPrices> {
|
|
110
|
+
return this.#buildClassicPrices(ClassicPricesMode.SPOT);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async getPricesForWithdraw(
|
|
114
|
+
realPrincipals: Dictionary<bigint, bigint>,
|
|
115
|
+
withdrawAsset: PoolAssetConfig,
|
|
116
|
+
collateralToDebt = false,
|
|
117
|
+
fetchConfig?: FetchConfig,
|
|
118
|
+
): Promise<ClassicPrices> {
|
|
119
|
+
return await this.getPrices();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async getPricesForSupplyWithdraw(
|
|
123
|
+
_realPrincipals: Dictionary<bigint, bigint>,
|
|
124
|
+
_supplyAsset: PoolAssetConfig | undefined,
|
|
125
|
+
_withdrawAsset: PoolAssetConfig | undefined,
|
|
126
|
+
_collateralToDebt: boolean,
|
|
127
|
+
_fetchConfig?: FetchConfig,
|
|
128
|
+
): Promise<ClassicPrices> {
|
|
129
|
+
return this.#buildClassicPrices(ClassicPricesMode.TWAP);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async getPrices(_assets?: PoolAssetConfig[], _fetchConfig?: FetchConfig): Promise<ClassicPrices> {
|
|
133
|
+
return this.#buildClassicPrices();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#buildClassicPrices(mode?: ClassicPricesMode): ClassicPrices {
|
|
137
|
+
const keys = this.#pricesDict.keys();
|
|
138
|
+
if (keys.length === 0) {
|
|
139
|
+
return ClassicPrices.createEmptyPrices();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
143
|
+
const { dict, dataCell } = buildPricesCell(this.#pricesDict, keys, timestamp);
|
|
144
|
+
|
|
145
|
+
return new ClassicPrices({
|
|
146
|
+
mode,
|
|
147
|
+
dict,
|
|
148
|
+
dataCell,
|
|
149
|
+
minPublishTime: undefined,
|
|
150
|
+
maxPublishTime: undefined,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
package/src/types/Master.ts
CHANGED
|
@@ -23,11 +23,18 @@ export type PoolAssetConfig = {
|
|
|
23
23
|
jettonWalletCode: Cell;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
export type PoolAssetHEConfig = {
|
|
27
|
+
title: string;
|
|
28
|
+
assets: PoolAssetConfig[];
|
|
29
|
+
heCategory: number;
|
|
30
|
+
};
|
|
31
|
+
|
|
26
32
|
export type PoolConfig = {
|
|
27
33
|
masterAddress: Address;
|
|
28
34
|
masterVersion: number;
|
|
29
35
|
masterConstants: MasterConstants;
|
|
30
36
|
poolAssetsConfig: PoolAssetConfig[];
|
|
37
|
+
poolAssetsHEConfig: PoolAssetHEConfig[];
|
|
31
38
|
lendingCode: Cell;
|
|
32
39
|
collector: AbstractCollector;
|
|
33
40
|
};
|
|
@@ -66,8 +73,8 @@ export type AssetConfig = {
|
|
|
66
73
|
baseTrackingBorrowSpeed: bigint;
|
|
67
74
|
borrowCap: number | bigint;
|
|
68
75
|
heCategory: number;
|
|
69
|
-
heCollateralFactor:
|
|
70
|
-
heLiquidationThreshold:
|
|
76
|
+
heCollateralFactor: bigint;
|
|
77
|
+
heLiquidationThreshold: bigint;
|
|
71
78
|
};
|
|
72
79
|
|
|
73
80
|
export type AssetData = {
|
package/src/types/User.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address, Cell, Dictionary } from '@ton/core';
|
|
1
|
+
import { Address, Cell, Dictionary, ExternalAddress } from '@ton/core';
|
|
2
2
|
import {
|
|
3
3
|
AssetConfig,
|
|
4
4
|
AssetData,
|
|
@@ -43,8 +43,8 @@ export type LiquidationData = LiquidableData | NonLiquidableData;
|
|
|
43
43
|
export type UserLiteData = {
|
|
44
44
|
type: 'active';
|
|
45
45
|
codeVersion: number;
|
|
46
|
-
masterAddress: Address;
|
|
47
|
-
ownerAddress: Address;
|
|
46
|
+
masterAddress: Address | ExternalAddress | null;
|
|
47
|
+
ownerAddress: Address | ExternalAddress | null;
|
|
48
48
|
principals: Dictionary<bigint, bigint>;
|
|
49
49
|
realPrincipals: Dictionary<bigint, bigint>; // principals before applying dusts
|
|
50
50
|
state: number;
|
|
@@ -62,15 +62,19 @@ export type UserLiteData = {
|
|
|
62
62
|
export type UserDataActive = UserLiteData & {
|
|
63
63
|
withdrawalLimits: Dictionary<bigint, bigint>;
|
|
64
64
|
borrowLimits: Dictionary<bigint, bigint>;
|
|
65
|
+
borrowLimitsWithEmode: Dictionary<bigint, bigint>;
|
|
65
66
|
repayLimits?: Dictionary<bigint, bigint>;
|
|
66
67
|
supplyBalance: bigint;
|
|
67
68
|
borrowBalance: bigint;
|
|
68
69
|
availableToBorrow: bigint;
|
|
70
|
+
availableToBorrowWithEmode: bigint;
|
|
69
71
|
limitUsedPercent: number;
|
|
70
72
|
limitUsed: bigint;
|
|
71
73
|
healthFactor: number;
|
|
72
74
|
liquidationData: LiquidationData;
|
|
73
75
|
havePrincipalWithoutPrice: boolean;
|
|
76
|
+
predictedHeCategory: number;
|
|
77
|
+
activeHeCategory: number;
|
|
74
78
|
};
|
|
75
79
|
|
|
76
80
|
export type UserDataInactive = {
|