@evaafi/sdk 0.6.4 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/api/feeds.d.ts +30 -0
  2. package/dist/api/feeds.js +73 -0
  3. package/dist/api/liquidation.js +1 -1
  4. package/dist/api/math.js +1 -1
  5. package/dist/api/parser.d.ts +4 -2
  6. package/dist/api/parser.js +39 -18
  7. package/dist/api/parsers/AbstractOracleParser.d.ts +11 -0
  8. package/dist/api/parsers/AbstractOracleParser.js +9 -0
  9. package/dist/api/parsers/ClassicOracleParser.d.ts +10 -0
  10. package/dist/api/parsers/ClassicOracleParser.js +16 -0
  11. package/dist/api/parsers/PythOracleParser.d.ts +17 -0
  12. package/dist/api/parsers/PythOracleParser.js +22 -0
  13. package/dist/api/parsers/index.d.ts +3 -0
  14. package/dist/api/parsers/index.js +19 -0
  15. package/dist/api/prices.d.ts +6 -6
  16. package/dist/api/prices.js +37 -46
  17. package/dist/api/pyth.d.ts +16 -0
  18. package/dist/api/pyth.js +35 -0
  19. package/dist/constants/assets/assetId.d.ts +22 -0
  20. package/dist/constants/assets/assetId.js +29 -0
  21. package/dist/constants/assets/index.d.ts +3 -0
  22. package/dist/constants/assets/index.js +19 -0
  23. package/dist/constants/assets/mainnet.d.ts +19 -0
  24. package/dist/constants/assets/mainnet.js +114 -0
  25. package/dist/constants/assets/testnet.d.ts +14 -0
  26. package/dist/constants/assets/testnet.js +54 -0
  27. package/dist/constants/assets.d.ts +3 -0
  28. package/dist/constants/assets.js +14 -1
  29. package/dist/constants/general/index.d.ts +65 -0
  30. package/dist/constants/general/index.js +93 -0
  31. package/dist/constants/general/mainnet.d.ts +24 -0
  32. package/dist/constants/general/mainnet.js +53 -0
  33. package/dist/constants/general/testnet.d.ts +12 -0
  34. package/dist/constants/general/testnet.js +15 -0
  35. package/dist/constants/general.d.ts +4 -4
  36. package/dist/constants/general.js +6 -6
  37. package/dist/constants/index.d.ts +3 -0
  38. package/dist/constants/index.js +19 -0
  39. package/dist/constants/pools/index.d.ts +2 -0
  40. package/dist/constants/pools/index.js +18 -0
  41. package/dist/constants/pools/mainnet.d.ts +14 -0
  42. package/dist/constants/pools/mainnet.js +145 -0
  43. package/dist/constants/pools/testnet.d.ts +9 -0
  44. package/dist/constants/pools/testnet.js +57 -0
  45. package/dist/constants/pools.js +9 -9
  46. package/dist/contracts/AbstractMaster.d.ts +185 -0
  47. package/dist/contracts/AbstractMaster.js +179 -0
  48. package/dist/contracts/ClassicMaster.d.ts +34 -0
  49. package/dist/contracts/ClassicMaster.js +87 -0
  50. package/dist/contracts/PythMaster.d.ts +61 -0
  51. package/dist/contracts/PythMaster.js +179 -0
  52. package/dist/contracts/UserContract.d.ts +1 -7
  53. package/dist/contracts/UserContract.js +1 -19
  54. package/dist/contracts/index.d.ts +5 -0
  55. package/dist/contracts/index.js +21 -0
  56. package/dist/index.d.ts +14 -14
  57. package/dist/index.js +20 -60
  58. package/dist/prices/Oracle.interface.d.ts +9 -0
  59. package/dist/prices/Oracle.interface.js +2 -0
  60. package/dist/prices/Prices.d.ts +5 -3
  61. package/dist/prices/Prices.js +13 -3
  62. package/dist/prices/PricesCollector.d.ts +17 -7
  63. package/dist/prices/PricesCollector.js +67 -51
  64. package/dist/prices/PythCollector.d.ts +22 -0
  65. package/dist/prices/PythCollector.js +217 -0
  66. package/dist/prices/Types.d.ts +17 -2
  67. package/dist/prices/Types.js +8 -1
  68. package/dist/prices/index.d.ts +4 -3
  69. package/dist/prices/index.js +4 -3
  70. package/dist/prices/sources/Backend.d.ts +5 -4
  71. package/dist/prices/sources/Backend.js +16 -13
  72. package/dist/prices/sources/Icp.d.ts +2 -1
  73. package/dist/prices/sources/Icp.js +12 -9
  74. package/dist/prices/sources/PriceSource.d.ts +7 -6
  75. package/dist/prices/utils.d.ts +10 -9
  76. package/dist/prices/utils.js +32 -46
  77. package/dist/rewards/RewardMaster.d.ts +0 -1
  78. package/dist/rewards/RewardUser.d.ts +0 -1
  79. package/dist/types/Master.d.ts +10 -31
  80. package/dist/types/Master.js +3 -0
  81. package/dist/types/MasterRewards.d.ts +0 -1
  82. package/dist/types/UserRewards.d.ts +0 -1
  83. package/dist/utils/sha256BigInt.d.ts +0 -1
  84. package/dist/utils/userJettonWallet.js +0 -8
  85. package/dist/utils/utils.d.ts +8 -1
  86. package/dist/utils/utils.js +31 -2
  87. package/package.json +4 -3
  88. package/src/api/feeds.ts +90 -0
  89. package/src/api/liquidation.ts +1 -1
  90. package/src/api/math.ts +1 -1
  91. package/src/api/parser.ts +100 -38
  92. package/src/api/parsers/AbstractOracleParser.ts +16 -0
  93. package/src/api/parsers/ClassicOracleParser.ts +20 -0
  94. package/src/api/parsers/PythOracleParser.ts +34 -0
  95. package/src/api/parsers/index.ts +3 -0
  96. package/src/api/prices.ts +32 -41
  97. package/src/constants/assets/assetId.ts +30 -0
  98. package/src/constants/assets/index.ts +3 -0
  99. package/src/constants/{assets.ts → assets/mainnet.ts} +27 -94
  100. package/src/constants/assets/testnet.ts +74 -0
  101. package/src/constants/general/index.ts +91 -0
  102. package/src/constants/{general.ts → general/mainnet.ts} +48 -72
  103. package/src/constants/general/testnet.ts +25 -0
  104. package/src/constants/index.ts +3 -0
  105. package/src/constants/pools/index.ts +2 -0
  106. package/src/constants/pools/mainnet.ts +218 -0
  107. package/src/constants/pools/testnet.ts +75 -0
  108. package/src/contracts/AbstractMaster.ts +450 -0
  109. package/src/contracts/ClassicMaster.ts +149 -0
  110. package/src/contracts/PythMaster.ts +313 -0
  111. package/src/contracts/UserContract.ts +7 -28
  112. package/src/contracts/index.ts +7 -0
  113. package/src/index.ts +18 -85
  114. package/src/prices/Oracle.interface.ts +18 -0
  115. package/src/prices/Prices.ts +17 -4
  116. package/src/prices/PricesCollector.ts +91 -68
  117. package/src/prices/PythCollector.ts +294 -0
  118. package/src/prices/Types.ts +28 -6
  119. package/src/prices/index.ts +4 -3
  120. package/src/prices/sources/Backend.ts +21 -19
  121. package/src/prices/sources/Icp.ts +13 -10
  122. package/src/prices/sources/PriceSource.ts +6 -5
  123. package/src/prices/utils.ts +65 -68
  124. package/src/types/Master.ts +29 -52
  125. package/src/types/User.ts +15 -7
  126. package/src/utils/userJettonWallet.ts +0 -8
  127. package/src/utils/utils.ts +41 -2
  128. package/src/constants/pools.ts +0 -175
  129. package/src/contracts/MasterContract.ts +0 -410
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
2
  import { Address, Cell, Dictionary } from '@ton/core';
3
+ import { Oracle } from '../prices/Oracle.interface';
4
+ export { FeedMapItem, parseFeedsMapDict } from '../api/feeds';
4
5
  export type MasterConstants = {
5
6
  FACTOR_SCALE: bigint;
6
7
  ASSET_COEFFICIENT_SCALE: bigint;
@@ -25,10 +26,9 @@ export type PoolConfig = {
25
26
  masterAddress: Address;
26
27
  masterVersion: number;
27
28
  masterConstants: MasterConstants;
28
- oracles: OracleNFT[];
29
- minimalOracles: number;
30
29
  poolAssetsConfig: PoolAssetsConfig;
31
30
  lendingCode: Cell;
31
+ oracles: Oracle;
32
32
  };
33
33
  export type UpgradeConfig = {
34
34
  masterCodeVersion: number;
@@ -41,7 +41,7 @@ export type UpgradeConfig = {
41
41
  newUserCode: Cell | null;
42
42
  };
43
43
  export type AssetConfig = {
44
- oracle: bigint;
44
+ jwAddress: bigint;
45
45
  decimals: bigint;
46
46
  collateralFactor: bigint;
47
47
  liquidationThreshold: bigint;
@@ -60,17 +60,10 @@ export type AssetConfig = {
60
60
  minPrincipalForRewards: bigint;
61
61
  baseTrackingSupplySpeed: bigint;
62
62
  baseTrackingBorrowSpeed: bigint;
63
- };
64
- export type MasterConfig = {
65
- ifActive: number;
66
- admin: Address;
67
- oraclesInfo: OraclesInfo;
68
- tokenKeys: Cell | null;
69
- };
70
- export type OraclesInfo = {
71
- numOracles: number;
72
- threshold: number;
73
- oracles: Cell | null;
63
+ borrowCap: number | bigint;
64
+ heCategory: number;
65
+ heCollateralFactor: number;
66
+ heLiquidationThreshold: number;
74
67
  };
75
68
  export type AssetData = {
76
69
  sRate: bigint;
@@ -94,28 +87,14 @@ export type AssetApy = {
94
87
  export type ExtendedAssetData = AssetData & AssetInterest & AssetApy;
95
88
  export type ExtendedAssetsData = Dictionary<bigint, ExtendedAssetData>;
96
89
  export type ExtendedAssetsConfig = Dictionary<bigint, AssetConfig>;
97
- export type MasterData = {
98
- meta: string;
99
- upgradeConfig: UpgradeConfig;
100
- masterConfig: MasterConfig;
101
- assetsConfig: ExtendedAssetsConfig;
102
- assetsData: ExtendedAssetsData;
103
- assetsReserves: Dictionary<bigint, bigint>;
104
- apy: {
105
- supply: Dictionary<bigint, number>;
106
- borrow: Dictionary<bigint, number>;
107
- };
108
- };
109
90
  export type AgregatedBalances = {
110
91
  totalBorrow: bigint;
111
92
  totalSupply: bigint;
112
93
  };
113
- export type OracleNFT = {
114
- id: number;
94
+ export type ExtendedEvaaOracle = EvaaOracle & {
115
95
  address: string;
116
- pubkey: Buffer;
117
96
  };
118
- export type Oracle = {
97
+ export type EvaaOracle = {
119
98
  id: number;
120
99
  pubkey: Buffer;
121
100
  };
@@ -1,2 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseFeedsMapDict = void 0;
4
+ var feeds_1 = require("../api/feeds");
5
+ Object.defineProperty(exports, "parseFeedsMapDict", { enumerable: true, get: function () { return feeds_1.parseFeedsMapDict; } });
@@ -1,5 +1,4 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
2
  import { Address, Cell } from '@ton/ton';
4
3
  import { PoolAssetConfig } from './Master';
5
4
  export type EvaaRewardsConfig = {
@@ -1,5 +1,4 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
2
  import { Address, Cell } from '@ton/ton';
4
3
  import { PoolAssetConfig } from './Master';
5
4
  export type EvaaUserRewardsConfig = {
@@ -1,4 +1,3 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
2
  export declare function sha256Hash(input: string): bigint;
4
3
  export declare function bigIntToBuffer(value: bigint): Buffer;
@@ -5,14 +5,6 @@ const core_1 = require("@ton/core");
5
5
  const assets_1 = require("../constants/assets");
6
6
  function getUserJettonData(ownerAddress, assetName, jettonWalletCode, jettonMasterAddress) {
7
7
  switch (assetName) {
8
- case 'uTON':
9
- return (0, core_1.beginCell)()
10
- .storeCoins(0)
11
- .storeUint(0, 64)
12
- .storeAddress(ownerAddress)
13
- .storeAddress(jettonMasterAddress)
14
- .storeRef(jettonWalletCode)
15
- .endCell();
16
8
  case 'DOGS':
17
9
  case 'NOT':
18
10
  case 'USDT':
@@ -1,4 +1,11 @@
1
- import { PoolAssetConfig } from "../types/Master";
1
+ import { PoolAssetConfig } from '../types/Master';
2
2
  export declare function isTonAsset(asset: PoolAssetConfig): boolean;
3
3
  export declare function isTonAssetId(assetId: bigint): boolean;
4
4
  export declare function delay(ms: number): Promise<unknown>;
5
+ export interface FetchConfig {
6
+ retries: number;
7
+ timeout: number;
8
+ }
9
+ export declare const DefaultFetchConfig: FetchConfig;
10
+ export declare function proxyFetchRetries<T>(fetch: Promise<T>, config?: FetchConfig): Promise<T>;
11
+ export declare function isValidSubaccountId(subaccountId: number): boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.delay = exports.isTonAssetId = exports.isTonAsset = void 0;
3
+ exports.isValidSubaccountId = exports.proxyFetchRetries = exports.DefaultFetchConfig = exports.delay = exports.isTonAssetId = exports.isTonAsset = void 0;
4
4
  const assets_1 = require("../constants/assets");
5
5
  function isTonAsset(asset) {
6
6
  return asset.name === 'TON';
@@ -11,6 +11,35 @@ function isTonAssetId(assetId) {
11
11
  }
12
12
  exports.isTonAssetId = isTonAssetId;
13
13
  function delay(ms) {
14
- return new Promise(resolve => setTimeout(resolve, ms));
14
+ return new Promise((resolve) => setTimeout(resolve, ms));
15
15
  }
16
16
  exports.delay = delay;
17
+ exports.DefaultFetchConfig = {
18
+ retries: 3,
19
+ timeout: 1000,
20
+ };
21
+ async function proxyFetchRetries(fetch, config = exports.DefaultFetchConfig) {
22
+ let lastError = null;
23
+ for (let attempt = 0; attempt <= config.retries; attempt++) {
24
+ try {
25
+ const timeoutPromise = new Promise((_, reject) => {
26
+ setTimeout(() => reject(new Error('Request timeout')), config.timeout);
27
+ });
28
+ return await Promise.race([fetch, timeoutPromise]);
29
+ }
30
+ catch (error) {
31
+ lastError = error instanceof Error ? error : new Error(String(error));
32
+ if (attempt < config.retries) {
33
+ // Exponential backoff: wait 1s, 2s, 4s, etc.
34
+ const delay = Math.pow(2, attempt) * 1000;
35
+ await new Promise((resolve) => setTimeout(resolve, delay));
36
+ }
37
+ }
38
+ }
39
+ throw new Error(`Failed to fetch after ${config.retries + 1} attempts. Last error: ${lastError instanceof Error ? lastError.message : JSON.stringify(lastError, null, 2)}`);
40
+ }
41
+ exports.proxyFetchRetries = proxyFetchRetries;
42
+ function isValidSubaccountId(subaccountId) {
43
+ return (subaccountId << 16) >> 16 === subaccountId && subaccountId !== -0x8000;
44
+ }
45
+ exports.isValidSubaccountId = isValidSubaccountId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evaafi/sdk",
3
- "version": "0.6.4",
3
+ "version": "0.9.0",
4
4
  "description": "The EVAA SDK is designed to easily integrate with the EVAA lending protocol on TON blockchain.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -19,7 +19,6 @@
19
19
  "license": "MIT",
20
20
  "homepage": "https://github.com/evaafi/sdk#readme",
21
21
  "devDependencies": {
22
- "@orbs-network/ton-access": "^2.3.3",
23
22
  "@ton/core": "0.56.0",
24
23
  "@ton/crypto": "^3.3.0",
25
24
  "@tonconnect/sdk": "3.0.5",
@@ -38,8 +37,10 @@
38
37
  "crypto-js": ">=4.2.0"
39
38
  },
40
39
  "dependencies": {
40
+ "@pythnetwork/hermes-client": "^2.0.0",
41
+ "@pythnetwork/pyth-ton-js": "^0.1.2",
41
42
  "@ton/ton": "14.0.0",
42
43
  "dotenv": "16.4.5"
43
44
  },
44
- "packageManager": "yarn@4.9.1+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538"
45
+ "packageManager": "yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c"
45
46
  }
@@ -0,0 +1,90 @@
1
+ import { Dictionary } from '@ton/ton';
2
+ import { Buffer } from 'buffer';
3
+ import { ASSET_ID } from '../constants/assets';
4
+
5
+ export const PYTH_TON_PRICE_FEED_ID = '0x8963217838ab4cf5cadc172203c1f0b763fbaa45f346d8ee50ba994bbcac3026';
6
+ export const PYTH_USDT_PRICE_FEED_ID = '0x2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b';
7
+ export const PYTH_STTON_PRICE_FEED_ID = '0x9145e059026a4d5a46f3b96408f7e572e33b3257b9c2dbe8dba551c772762002';
8
+ export const PYTH_TSTON_PRICE_FEED_ID = '0x3d1784128eeab5961ec60648fe497d3901eebd211b7f51e4bb0db9f024977d25';
9
+ export const PYTH_USDC_PRICE_FEED_ID = '0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a';
10
+ export const PYTH_USDE_PRICE_FEED_ID = '0x6ec879b1e9963de5ee97e9c8710b742d6228252a5e2ca12d4ae81d7fe5ee8c5d';
11
+ export const PYTH_TSUSDE_PRICE_FEED_ID = '0xcbe184846426619a60f51056d26efecb0537ad3a73b1e965fe695d06a257cb19';
12
+
13
+ export function bigintToBuffer(value: bigint, size: number): Buffer {
14
+ if (value < 0n) {
15
+ throw new Error('Only non-negative bigint is supported');
16
+ }
17
+ // it's questionable whether it stores in LE or BE
18
+ // and what option will TVM use, now by default it's BE
19
+ const hex = value.toString(16);
20
+ const padded = hex.padStart(size * 2, '0');
21
+ return Buffer.from(padded, 'hex');
22
+ }
23
+
24
+ export const packConnectedFeeds = (evaa_id: bigint, reffered_id: bigint) => {
25
+ return Buffer.concat([bigintToBuffer(evaa_id, 32), bigintToBuffer(reffered_id, 32)]);
26
+ };
27
+
28
+ export const EVAA_TON_PRICE_FEED_ID = ASSET_ID.TON;
29
+ export const EVAA_NOT_PRICE_FEED_ID = ASSET_ID.NOT;
30
+ export const EVAA_DOGS_PRICE_FEED_ID = ASSET_ID.DOGS;
31
+ export const EVAA_USDT_PRICE_FEED_ID = ASSET_ID.USDT;
32
+ export const EVAA_STTON_PRICE_FEED_ID = ASSET_ID.stTON;
33
+ export const EVAA_TSTON_PRICE_FEED_ID = ASSET_ID.tsTON;
34
+ export const EVAA_JUSDC_PRICE_FEED_ID = ASSET_ID.jUSDC;
35
+ export const EVAA_JUSDT_PRICE_FEED_ID = ASSET_ID.jUSDT;
36
+ export const EVAA_USDE_PRICE_FEED_ID = ASSET_ID.USDe;
37
+ export const EVAA_TSUSDE_PRICE_FEED_ID = ASSET_ID.tsUSDe;
38
+
39
+ export const MAIN_POOL_FEEDS_MAP: Dictionary<bigint, Buffer> = (() => {
40
+ const map = Dictionary.empty<bigint, Buffer>();
41
+ map.set(BigInt(PYTH_TON_PRICE_FEED_ID), packConnectedFeeds(EVAA_TON_PRICE_FEED_ID, 0n));
42
+ map.set(BigInt(PYTH_USDT_PRICE_FEED_ID), packConnectedFeeds(EVAA_USDT_PRICE_FEED_ID, 0n));
43
+ map.set(
44
+ BigInt(PYTH_STTON_PRICE_FEED_ID),
45
+ packConnectedFeeds(EVAA_STTON_PRICE_FEED_ID, BigInt(PYTH_TON_PRICE_FEED_ID)),
46
+ );
47
+ map.set(
48
+ BigInt(PYTH_TSTON_PRICE_FEED_ID),
49
+ packConnectedFeeds(EVAA_TSTON_PRICE_FEED_ID, BigInt(PYTH_TON_PRICE_FEED_ID)),
50
+ );
51
+ map.set(BigInt(PYTH_USDC_PRICE_FEED_ID), packConnectedFeeds(EVAA_JUSDC_PRICE_FEED_ID, 0n));
52
+ map.set(BigInt(PYTH_USDT_PRICE_FEED_ID), packConnectedFeeds(EVAA_JUSDT_PRICE_FEED_ID, 0n));
53
+ map.set(BigInt(PYTH_USDE_PRICE_FEED_ID), packConnectedFeeds(EVAA_USDE_PRICE_FEED_ID, 0n));
54
+ map.set(BigInt(PYTH_TSUSDE_PRICE_FEED_ID), packConnectedFeeds(EVAA_TSUSDE_PRICE_FEED_ID, 0n));
55
+ return map;
56
+ })();
57
+
58
+ export type FeedMapItem = {
59
+ evaaId: bigint;
60
+ referredPythFeed: bigint;
61
+ };
62
+
63
+ export function parseFeedsMapDict(dict: Dictionary<bigint, Buffer>) {
64
+ const parsedData = new Map<bigint, FeedMapItem>();
65
+ for (const key of dict.keys()) {
66
+ const buffer = dict.get(key)!;
67
+
68
+ const hex1 = '0x' + buffer.toString('hex', 0, 32);
69
+ const hex2 = '0x' + buffer.toString('hex', 32);
70
+
71
+ const evaaId = BigInt(hex1);
72
+ const referredPythFeed = BigInt(hex2);
73
+
74
+ parsedData.set(key, { evaaId, referredPythFeed });
75
+ }
76
+
77
+ return parsedData;
78
+ }
79
+
80
+ export const TESTNET_ALLOWED_REF_TOKENS: Dictionary<bigint, bigint> = (() => {
81
+ const map = Dictionary.empty<bigint, bigint>();
82
+ map.set(BigInt(EVAA_JUSDT_PRICE_FEED_ID), BigInt(EVAA_USDT_PRICE_FEED_ID));
83
+ return map;
84
+ })();
85
+
86
+ export const TESTNET_FEEDS_MAP: Dictionary<bigint, Buffer> = (() => {
87
+ const map = Dictionary.empty<bigint, Buffer>();
88
+ map.set(BigInt(PYTH_TON_PRICE_FEED_ID), packConnectedFeeds(EVAA_TON_PRICE_FEED_ID, 0n));
89
+ return map;
90
+ })();
@@ -174,7 +174,7 @@ export function calculateLiquidationAmounts(
174
174
 
175
175
  const _isBadDebt = isBadDebt(supplyAmount, borrowAmount, liquidationBonus, masterConstants);
176
176
  if (!_isBadDebt) {
177
- allowedCollateralValue = BigMath.min(allowedCollateralValue, BigMath.max(allowedCollateralValue / 2n, collateralThreshold));
177
+ allowedCollateralValue = BigMath.min(allowedCollateralValue, BigMath.max(allowedCollateralValue / 3n, collateralThreshold));
178
178
  }
179
179
 
180
180
  const loanValue = toAssetWorth(loanInfo.balance, loanInfo.scale, loanInfo.price);
package/src/api/math.ts CHANGED
@@ -452,7 +452,7 @@ export function calculateLiquidationData(
452
452
  const liquidationBonus = collateralAssetConfig.liquidationBonus;
453
453
  const loanScale = 10n ** loanAssetConfig.decimals;
454
454
  values.push(
455
- (bigIntMax(collateralValue / 2n, bigIntMin(collateralValue, COLLATERAL_WORTH_THRESHOLD)) *
455
+ (bigIntMax(collateralValue / 3n, bigIntMin(collateralValue, COLLATERAL_WORTH_THRESHOLD)) *
456
456
  loanScale *
457
457
  poolConfig.masterConstants.ASSET_COEFFICIENT_SCALE) /
458
458
  liquidationBonus /
package/src/api/parser.ts CHANGED
@@ -1,5 +1,17 @@
1
1
  import { beginCell, Cell, Dictionary, DictionaryValue, Slice } from '@ton/core';
2
- import { AssetConfig, AssetData, ExtendedAssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConfig, MasterConstants, MasterData, PoolAssetsConfig, PoolConfig } from '../types/Master';
2
+ import { MasterConfig, MasterData, OracleInfo } from '../contracts/AbstractMaster';
3
+ import {
4
+ AssetConfig,
5
+ AssetData,
6
+ ExtendedAssetData,
7
+ ExtendedAssetsConfig,
8
+ ExtendedAssetsData,
9
+ MasterConstants,
10
+ PoolAssetsConfig,
11
+ PoolConfig,
12
+ } from '../types/Master';
13
+ import { BalanceType, UserBalance, UserData, UserLiteData, UserRewards } from '../types/User';
14
+ import { loadMaybeMyRef, loadMyRef } from './helpers';
3
15
  import {
4
16
  bigIntMax,
5
17
  bigIntMin,
@@ -11,16 +23,14 @@ import {
11
23
  getAvailableToBorrow,
12
24
  presentValue,
13
25
  } from './math';
14
- import { loadMaybeMyRef, loadMyRef } from './helpers';
15
- import { BalanceType, UserBalance, UserData, UserLiteData, UserRewards } from '../types/User';
16
- import { checkNotInDebtAtAll } from "../api/math";
26
+ import { OracleParser } from './parsers/AbstractOracleParser';
17
27
 
18
28
  export function createUserRewards(): DictionaryValue<UserRewards> {
19
29
  return {
20
30
  serialize: (src: any, buidler: any) => {
21
31
  buidler.storeUint(src.trackingIndex, 64);
22
32
  buidler.storeUint(src.trackingAccured, 64);
23
- },
33
+ },
24
34
  parse: (src: Slice) => {
25
35
  const trackingIndex = BigInt(src.loadUint(64));
26
36
  const trackingAccured = BigInt(src.loadUint(64));
@@ -51,9 +61,19 @@ export function createAssetData(): DictionaryValue<AssetData> {
51
61
  const balance = BigInt(src.loadUintBig(64));
52
62
  const trackingSupplyIndex = BigInt(src.loadUintBig(64));
53
63
  const trackingBorrowIndex = BigInt(src.loadUintBig(64));
54
- const awaitedSupply = BigInt(src.loadUintBig(64));
64
+ const awaitedSupply = BigInt(src.loadUintBig(64));
55
65
 
56
- return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance, trackingSupplyIndex, trackingBorrowIndex, awaitedSupply};
66
+ return {
67
+ sRate,
68
+ bRate,
69
+ totalSupply,
70
+ totalBorrow,
71
+ lastAccural,
72
+ balance,
73
+ trackingSupplyIndex,
74
+ trackingBorrowIndex,
75
+ awaitedSupply,
76
+ };
57
77
  },
58
78
  };
59
79
  }
@@ -61,7 +81,7 @@ export function createAssetData(): DictionaryValue<AssetData> {
61
81
  export function createAssetConfig(): DictionaryValue<AssetConfig> {
62
82
  return {
63
83
  serialize: (src: any, builder: any) => {
64
- builder.storeUint(src.oracle, 256);
84
+ builder.storeUint(src.jwAddress, 256);
65
85
  builder.storeUint(src.decimals, 8);
66
86
  const refBuild = beginCell();
67
87
  refBuild.storeUint(src.collateralFactor, 16);
@@ -81,10 +101,14 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
81
101
  refBuild.storeUint(src.minPrincipalForRewards, 64);
82
102
  refBuild.storeUint(src.baseTrackingSupplySpeed, 64);
83
103
  refBuild.storeUint(src.baseTrackingBorrowSpeed, 64);
104
+ refBuild.storeInt(src.borrowCap, 64);
105
+ refBuild.storeUint(src.heCategory, 8);
106
+ refBuild.storeUint(src.heCollateralFactor, 16);
107
+ refBuild.storeUint(src.heLiquidationThreshold, 16);
84
108
  builder.storeRef(refBuild.endCell());
85
109
  },
86
110
  parse: (src: Slice) => {
87
- const oracle = src.loadUintBig(256);
111
+ const jwAddress = src.loadUintBig(256);
88
112
  const decimals = BigInt(src.loadUint(8));
89
113
  const ref = src.loadRef().beginParse();
90
114
  const collateralFactor = ref.loadUintBig(16);
@@ -104,9 +128,13 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
104
128
  const minPrincipalForRewards = ref.loadUintBig(64);
105
129
  const baseTrackingSupplySpeed = ref.loadUintBig(64);
106
130
  const baseTrackingBorrowSpeed = ref.loadUintBig(64);
131
+ const borrowCap = ref.loadInt(64);
132
+ const heCategory = ref.loadUint(8);
133
+ const heCollateralFactor = ref.loadUint(16);
134
+ const heLiquidationThreshold = ref.loadUint(16);
107
135
 
108
136
  return {
109
- oracle,
137
+ jwAddress,
110
138
  decimals,
111
139
  collateralFactor,
112
140
  liquidationThreshold,
@@ -124,17 +152,25 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
124
152
  liquidationReserveFactor,
125
153
  minPrincipalForRewards,
126
154
  baseTrackingSupplySpeed,
127
- baseTrackingBorrowSpeed
155
+ baseTrackingBorrowSpeed,
156
+ borrowCap,
157
+ heCategory,
158
+ heCollateralFactor,
159
+ heLiquidationThreshold,
128
160
  };
129
161
  },
130
162
  };
131
163
  }
132
164
 
133
- export function parseMasterData(masterDataBOC: string, poolAssetsConfig: PoolAssetsConfig, masterConstants: MasterConstants): MasterData {
165
+ export function parseMasterData(
166
+ masterDataBOC: string,
167
+ poolAssetsConfig: PoolAssetsConfig,
168
+ masterConstants: MasterConstants,
169
+ oracleParser: OracleParser,
170
+ ): MasterData<MasterConfig<OracleInfo>> {
134
171
  const masterSlice = Cell.fromBase64(masterDataBOC).beginParse();
135
172
  const meta = masterSlice.loadRef().beginParse().loadStringTail();
136
173
  const upgradeConfigParser = masterSlice.loadRef().beginParse();
137
-
138
174
  const upgradeConfig = {
139
175
  masterCodeVersion: Number(upgradeConfigParser.loadCoins()),
140
176
  userCodeVersion: Number(upgradeConfigParser.loadCoins()),
@@ -146,31 +182,31 @@ export function parseMasterData(masterDataBOC: string, poolAssetsConfig: PoolAss
146
182
  newUserCode: loadMaybeMyRef(upgradeConfigParser),
147
183
  };
148
184
  // upgradeConfigParser.endParse(); todo fix with new testnet contract
149
-
150
185
  const masterConfigSlice = masterSlice.loadRef().beginParse();
186
+
151
187
  const assetsConfigDict = masterConfigSlice.loadDict(Dictionary.Keys.BigUint(256), createAssetConfig());
152
188
  const assetsDataDict = masterSlice.loadDict(Dictionary.Keys.BigUint(256), createAssetData());
153
-
154
189
  const assetsExtendedData = Dictionary.empty<bigint, ExtendedAssetData>();
155
190
  const assetsReserves = Dictionary.empty<bigint, bigint>();
156
191
  const apy = {
157
192
  supply: Dictionary.empty<bigint, number>(),
158
193
  borrow: Dictionary.empty<bigint, number>(),
159
194
  };
160
-
161
- for (const [tokenSymbol, asset] of Object.entries(poolAssetsConfig)) {
195
+
196
+ for (const [, asset] of Object.entries(poolAssetsConfig)) {
162
197
  const assetData = calculateAssetData(assetsConfigDict, assetsDataDict, asset.assetId, masterConstants);
163
198
  assetsExtendedData.set(asset.assetId, assetData);
164
199
  }
200
+
201
+ const ifActive = oracleParser.getIfActive(masterConfigSlice);
202
+ const oraclesInfo = oracleParser.parseOracleConfig(masterConfigSlice);
203
+
165
204
  const masterConfig = {
166
- ifActive: masterConfigSlice.loadInt(8),
205
+ ifActive,
167
206
  admin: masterConfigSlice.loadAddress(),
168
- oraclesInfo: {
169
- numOracles: masterConfigSlice.loadUint(16),
170
- threshold: masterConfigSlice.loadUint(16),
171
- oracles: loadMaybeMyRef(masterConfigSlice)
172
- },
207
+ oraclesInfo,
173
208
  tokenKeys: loadMaybeMyRef(masterConfigSlice),
209
+ supervisor: masterConfigSlice.loadMaybeAddress(),
174
210
  };
175
211
  masterConfigSlice.endParse();
176
212
 
@@ -179,11 +215,9 @@ export function parseMasterData(masterDataBOC: string, poolAssetsConfig: PoolAss
179
215
  const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply, masterConstants);
180
216
  const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow, masterConstants);
181
217
  assetsReserves.set(asset.assetId, assetData.balance - totalSupply + totalBorrow);
182
-
183
218
  apy.supply.set(asset.assetId, (1 + (Number(assetData.supplyInterest) / 1e12) * 24 * 3600) ** 365 - 1);
184
219
  apy.borrow.set(asset.assetId, (1 + (Number(assetData.borrowInterest) / 1e12) * 24 * 3600) ** 365 - 1);
185
220
  }
186
-
187
221
  return {
188
222
  meta: meta,
189
223
  upgradeConfig: upgradeConfig,
@@ -200,7 +234,7 @@ export function parseUserLiteData(
200
234
  assetsData: ExtendedAssetsData,
201
235
  assetsConfig: ExtendedAssetsConfig,
202
236
  poolConfig: PoolConfig,
203
- applyDust: boolean = false
237
+ applyDust: boolean = false,
204
238
  ): UserLiteData {
205
239
  const poolAssetsConfig = poolConfig.poolAssetsConfig;
206
240
  const masterConstants = poolConfig.masterConstants;
@@ -232,7 +266,7 @@ export function parseUserLiteData(
232
266
  backupCell1 = userSlice.loadMaybeRef();
233
267
  backupCell2 = userSlice.loadMaybeRef();
234
268
  }
235
-
269
+
236
270
  userSlice.endParse();
237
271
  const userBalances = Dictionary.empty<bigint, UserBalance>();
238
272
 
@@ -243,7 +277,7 @@ export function parseUserLiteData(
243
277
  let principal = realPrincipals.get(asset.assetId) || 0n;
244
278
  let balance = presentValue(assetData.sRate, assetData.bRate, principal, masterConstants);
245
279
 
246
- if (applyDust && (principal > 0 && (principal < assetConfig.dust))) {
280
+ if (applyDust && principal > 0 && principal < assetConfig.dust) {
247
281
  principal = 0n;
248
282
  balance = {
249
283
  amount: 0n,
@@ -270,7 +304,7 @@ export function parseUserLiteData(
270
304
  dutchAuctionStart: dutchAuctionStart,
271
305
  backupCell: backupCell,
272
306
  fullyParsed: false,
273
-
307
+
274
308
  rewards: rewards,
275
309
  backupCell1: backupCell1,
276
310
  backupCell2: backupCell2,
@@ -283,7 +317,7 @@ export function parseUserData(
283
317
  assetsConfig: ExtendedAssetsConfig,
284
318
  prices: Dictionary<bigint, bigint>,
285
319
  poolConfig: PoolConfig,
286
- applyDust: boolean = false
320
+ applyDust: boolean = false,
287
321
  ): UserData {
288
322
  userLiteData.fullyParsed = true;
289
323
  let havePrincipalWithoutPrice = false;
@@ -314,7 +348,7 @@ export function parseUserData(
314
348
  let principal = userLiteData.principals.get(asset.assetId) || 0n;
315
349
  const balance = presentValue(assetData.sRate, assetData.bRate, principal, masterConstants);
316
350
 
317
- if (applyDust && (principal > 0 && (principal < assetConfig.dust))) {
351
+ if (applyDust && principal > 0 && principal < assetConfig.dust) {
318
352
  principal = 0n;
319
353
  userLiteData.principals.set(asset.assetId, 0n);
320
354
  }
@@ -338,19 +372,35 @@ export function parseUserData(
338
372
  }
339
373
  }
340
374
 
341
- const availableToBorrow = getAvailableToBorrow(assetsConfig, assetsData, userLiteData.realPrincipals, prices, masterConstants);
375
+ const availableToBorrow = getAvailableToBorrow(
376
+ assetsConfig,
377
+ assetsData,
378
+ userLiteData.realPrincipals,
379
+ prices,
380
+ masterConstants,
381
+ );
342
382
 
343
383
  for (const [_, asset] of Object.entries(poolAssetsConfig)) {
344
384
  const balance = userLiteData.balances.get(asset.assetId) as UserBalance;
345
385
  const assetConfig = assetsConfig.get(asset.assetId) as AssetConfig;
346
386
  const assetData = assetsData.get(asset.assetId) as ExtendedAssetData;
347
-
387
+
348
388
  const assetLiquidityMinusReserves = getAssetLiquidityMinusReserves(assetData, masterConstants);
349
389
 
350
390
  if (balance.type === BalanceType.supply) {
351
391
  withdrawalLimits.set(
352
392
  asset.assetId,
353
- bigIntMin(calculateMaximumWithdrawAmount(assetsConfig, assetsData, userLiteData.realPrincipals, prices, masterConstants, asset.assetId), assetData.balance)
393
+ bigIntMin(
394
+ calculateMaximumWithdrawAmount(
395
+ assetsConfig,
396
+ assetsData,
397
+ userLiteData.realPrincipals,
398
+ prices,
399
+ masterConstants,
400
+ asset.assetId,
401
+ ),
402
+ assetData.balance,
403
+ ),
354
404
  );
355
405
  }
356
406
 
@@ -361,7 +411,13 @@ export function parseUserData(
361
411
 
362
412
  borrowLimits.set(
363
413
  asset.assetId,
364
- bigIntMax(0n, bigIntMin((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(asset.assetId)!, assetLiquidityMinusReserves)),
414
+ bigIntMax(
415
+ 0n,
416
+ bigIntMin(
417
+ (availableToBorrow * 10n ** assetConfig.decimals) / prices.get(asset.assetId)!,
418
+ assetLiquidityMinusReserves,
419
+ ),
420
+ ),
365
421
  );
366
422
  }
367
423
 
@@ -374,10 +430,16 @@ export function parseUserData(
374
430
  let healthFactor = 1;
375
431
  let liquidationData;
376
432
  if (!havePrincipalWithoutPrice) {
377
- liquidationData = calculateLiquidationData(assetsConfig, assetsData, userLiteData.realPrincipals, prices, poolConfig);
433
+ liquidationData = calculateLiquidationData(
434
+ assetsConfig,
435
+ assetsData,
436
+ userLiteData.realPrincipals,
437
+ prices,
438
+ poolConfig,
439
+ );
378
440
  if (liquidationData.totalLimit != 0n) {
379
441
  healthFactor = 1 - Number(liquidationData.totalDebt) / Number(liquidationData.totalLimit);
380
- }
442
+ }
381
443
  }
382
444
  return {
383
445
  ...userLiteData,
@@ -390,6 +452,6 @@ export function parseUserData(
390
452
  limitUsed: limitUsed,
391
453
  liquidationData: liquidationData,
392
454
  healthFactor: healthFactor,
393
- havePrincipalWithoutPrice: havePrincipalWithoutPrice
455
+ havePrincipalWithoutPrice: havePrincipalWithoutPrice,
394
456
  };
395
457
  }
@@ -0,0 +1,16 @@
1
+ import { Slice } from '@ton/core';
2
+ import { ClassicOracleInfo } from './ClassicOracleParser';
3
+ import { PythOracleInfo } from './PythOracleParser';
4
+
5
+ export interface OracleParser {
6
+ parseOracleConfig(masterConfigSlice: Slice): ClassicOracleInfo | PythOracleInfo;
7
+ getIfActive(masterConfigSlice: Slice): number;
8
+ }
9
+
10
+ export abstract class AbstractOracleParser implements OracleParser {
11
+ abstract parseOracleConfig(masterConfigSlice: Slice): ClassicOracleInfo | PythOracleInfo;
12
+
13
+ getIfActive(masterConfigSlice: Slice): number {
14
+ return masterConfigSlice.loadInt(8);
15
+ }
16
+ }
@@ -0,0 +1,20 @@
1
+ import { Cell, Slice } from '@ton/core';
2
+ import { loadMaybeMyRef } from '../helpers';
3
+ import { AbstractOracleParser } from './AbstractOracleParser';
4
+
5
+ export type ClassicOracleInfo = {
6
+ numOracles: number;
7
+ threshold: number;
8
+ oracles: Cell | null;
9
+ };
10
+
11
+ export class ClassicOracleParser extends AbstractOracleParser {
12
+ parseOracleConfig(masterConfigSlice: Slice): ClassicOracleInfo {
13
+ const oraclesSlice = masterConfigSlice.loadRef().beginParse();
14
+ return {
15
+ numOracles: oraclesSlice.loadUint(16),
16
+ threshold: oraclesSlice.loadUint(16),
17
+ oracles: loadMaybeMyRef(oraclesSlice),
18
+ };
19
+ }
20
+ }