@evaafi/sdk 0.9.5 → 0.9.6
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 +39 -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 +47 -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,7 @@ export const MAINNET_POOL_CONFIG: PoolConfig = {
|
|
|
105
109
|
},
|
|
106
110
|
}),
|
|
107
111
|
poolAssetsConfig: MAINNET_POOL_ASSETS_CONFIG,
|
|
112
|
+
poolAssetsHEConfig: [],
|
|
108
113
|
lendingCode: LENDING_CODE,
|
|
109
114
|
};
|
|
110
115
|
|
|
@@ -118,6 +123,7 @@ export const MAINNET_STABLE_POOL_CONFIG: PoolConfig = {
|
|
|
118
123
|
evaaOracles: ORACLES_MAINNET,
|
|
119
124
|
}),
|
|
120
125
|
poolAssetsConfig: MAINNET_STABLE_POOL_ASSETS_CONFIG,
|
|
126
|
+
poolAssetsHEConfig: [],
|
|
121
127
|
lendingCode: LENDING_CODE,
|
|
122
128
|
};
|
|
123
129
|
|
|
@@ -131,6 +137,24 @@ export const MAINNET_LP_POOL_CONFIG: PoolConfig = {
|
|
|
131
137
|
evaaOracles: ORACLES_LP,
|
|
132
138
|
}),
|
|
133
139
|
poolAssetsConfig: MAINNET_LP_POOL_ASSETS_CONFIG,
|
|
140
|
+
poolAssetsHEConfig: [],
|
|
141
|
+
lendingCode: LENDING_CODE,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const MAINNET_LP_POOL_COPY_CONFIG: PoolConfig = {
|
|
145
|
+
masterAddress: EVAA_LP_COPY_MAINNET,
|
|
146
|
+
masterVersion: EVAA_LP_COPY_MAINNET_VERSION,
|
|
147
|
+
masterConstants: MASTER_CONSTANTS,
|
|
148
|
+
collector: new ClassicCollector({
|
|
149
|
+
poolAssetsConfig: MAINNET_LP_POOL_ASSETS_CONFIG,
|
|
150
|
+
minimalOracles: 3,
|
|
151
|
+
evaaOracles: ORACLES_LP,
|
|
152
|
+
}),
|
|
153
|
+
poolAssetsConfig: MAINNET_LP_POOL_ASSETS_CONFIG,
|
|
154
|
+
poolAssetsHEConfig: [
|
|
155
|
+
{ title: 'ton', assets: [TON_MAINNET, TON_STORM_MAINNET], heCategory: 1 },
|
|
156
|
+
{ title: 'stable', assets: [USDT_MAINNET, USDT_STORM_MAINNET], heCategory: 2 },
|
|
157
|
+
],
|
|
134
158
|
lendingCode: LENDING_CODE,
|
|
135
159
|
};
|
|
136
160
|
|
|
@@ -144,6 +168,7 @@ export const MAINNET_ALTS_POOL_CONFIG: PoolConfig = {
|
|
|
144
168
|
evaaOracles: ORACLES_ALTS,
|
|
145
169
|
}),
|
|
146
170
|
poolAssetsConfig: MAINNET_ALTS_POOL_ASSETS_CONFIG,
|
|
171
|
+
poolAssetsHEConfig: [],
|
|
147
172
|
lendingCode: LENDING_CODE,
|
|
148
173
|
};
|
|
149
174
|
|
|
@@ -166,6 +191,7 @@ export const MAINNET_PYTH_V8_TOB_POOL_CONFIG: PoolConfig = {
|
|
|
166
191
|
},
|
|
167
192
|
}),
|
|
168
193
|
poolAssetsConfig: MAINNET_PYTH_V8_TOB_POOL_ASSETS_CONFIG,
|
|
194
|
+
poolAssetsHEConfig: [],
|
|
169
195
|
lendingCode: LENDING_CODE,
|
|
170
196
|
};
|
|
171
197
|
|
|
@@ -181,6 +207,7 @@ export const MAINNET_V8_TOB_POOL_CONFIG: PoolConfig = {
|
|
|
181
207
|
evaaOracles: ORACLES_MAINNET,
|
|
182
208
|
}),
|
|
183
209
|
poolAssetsConfig: MAINNET_V8_TOB_POOL_ASSETS_CONFIG,
|
|
210
|
+
poolAssetsHEConfig: [],
|
|
184
211
|
lendingCode: LENDING_CODE,
|
|
185
212
|
};
|
|
186
213
|
|
|
@@ -214,6 +241,25 @@ export const MAINNET_MASTER_EVAA_REWARD_CONFIG: EvaaRewardsConfig = {
|
|
|
214
241
|
publicKey: Buffer.from('b8eb0e312a9aa6394edceef21573f2d45e7d7a616a924e33190bd52fa31c8bb1', 'hex'), // adminAddress publicKey
|
|
215
242
|
};
|
|
216
243
|
|
|
244
|
+
export const MAINNET_CLASSIC_HE_POOL_CONFIG: PoolConfig = {
|
|
245
|
+
masterAddress: Address.parse('EQAI_O_VqUhqFQ-AW969xl1eXOi4euSWl1puxEroekJ5xpOt'),
|
|
246
|
+
masterVersion: 0,
|
|
247
|
+
masterConstants: MASTER_CONSTANTS,
|
|
248
|
+
collector: new FakeCollector(
|
|
249
|
+
Dictionary.empty<bigint, bigint>()
|
|
250
|
+
.set(ASSET_ID.TON, 1_300_000_000n)
|
|
251
|
+
.set(ASSET_ID.tsTON, 1_500_000_000n)
|
|
252
|
+
.set(ASSET_ID.TUSDT, 1_000_000_000n)
|
|
253
|
+
.set(ASSET_ID.TUSDe, 1_000_000_000n),
|
|
254
|
+
),
|
|
255
|
+
poolAssetsConfig: [TON_MAINNET, TSTON_MAINNET, TUSDE_MAINNET, TUSDT_MAINNET],
|
|
256
|
+
poolAssetsHEConfig: [
|
|
257
|
+
{ title: 'ton', assets: [TON_MAINNET, TSTON_MAINNET], heCategory: 1 },
|
|
258
|
+
{ title: 'stable', assets: [TUSDT_MAINNET, TUSDE_MAINNET], heCategory: 2 },
|
|
259
|
+
],
|
|
260
|
+
lendingCode: LENDING_CODE,
|
|
261
|
+
};
|
|
262
|
+
|
|
217
263
|
export const ALL_MAINNET_POOLS: PoolConfig[] = [
|
|
218
264
|
MAINNET_POOL_CONFIG,
|
|
219
265
|
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 = {
|