@gearbox-protocol/sdk 3.0.0-vfourabi.1 → 3.0.0-vfourabi.3

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 (275) hide show
  1. package/.eslintignore +3 -0
  2. package/.github/workflows/lint_pr.yml +18 -0
  3. package/.github/workflows/pr.yml +39 -0
  4. package/.github/workflows/release.yml +47 -0
  5. package/.gitignore +19 -0
  6. package/.husky/commit-msg +1 -0
  7. package/.husky/pre-commit +1 -0
  8. package/.nvmrc +1 -0
  9. package/.releaserc.json +34 -0
  10. package/.vscode/extensions.json +7 -0
  11. package/.vscode/settings.json +16 -0
  12. package/.yarn/install-state.gz +0 -0
  13. package/.yarnrc.yml +1 -0
  14. package/ContributionAgreement +72 -0
  15. package/dist/cjs/abi/iZapper.cjs +85 -0
  16. package/dist/cjs/abi/iZapper.d.ts +123 -0
  17. package/dist/cjs/sdk/index.cjs +19830 -19764
  18. package/dist/cjs/sdk/index.d.ts +3746 -3061
  19. package/dist/esm/abi/iZapper.d.mts +123 -0
  20. package/dist/esm/abi/iZapper.mjs +83 -0
  21. package/dist/esm/sdk/index.d.mts +3746 -3061
  22. package/dist/esm/sdk/index.mjs +19807 -19765
  23. package/jest.config.js +7 -0
  24. package/package.json +32 -2
  25. package/scripts/example.ts +30 -0
  26. package/src/abi/compressors.ts +3962 -0
  27. package/src/abi/errors.ts +196 -0
  28. package/src/abi/iERC20.ts +122 -0
  29. package/src/abi/iPausable.ts +35 -0
  30. package/src/abi/iPriceFeedStore.ts +227 -0
  31. package/src/abi/iUpdatablePriceFeed.ts +16 -0
  32. package/src/abi/iVersion.ts +28 -0
  33. package/src/abi/iZapper.ts +84 -0
  34. package/src/abi/routerV300.ts +378 -0
  35. package/src/abi/v300.ts +4151 -0
  36. package/src/abi/v310.ts +5179 -0
  37. package/src/adapters/AbstractAdapter.ts +28 -0
  38. package/src/adapters/BalancerV2VaultAdapterContract.ts +19 -0
  39. package/src/adapters/BalancerV3RouterAdapterContract.ts +19 -0
  40. package/src/adapters/CamelotV3AdapterContract.ts +20 -0
  41. package/src/adapters/ConvexV1BaseRewardPoolAdapterContract.ts +20 -0
  42. package/src/adapters/ConvexV1BoosterAdapterContract.ts +20 -0
  43. package/src/adapters/Curve2AssetsAdapterContract.ts +20 -0
  44. package/src/adapters/Curve3AssetsAdapterContract.ts +20 -0
  45. package/src/adapters/Curve4AssetsAdapterContract.ts +20 -0
  46. package/src/adapters/CurveV1AdapterStETHContract.ts +20 -0
  47. package/src/adapters/CurveV1StableNGAdapterContract.ts +20 -0
  48. package/src/adapters/DaiUsdsAdapterContract.ts +21 -0
  49. package/src/adapters/ERC4626AdapterContract.ts +20 -0
  50. package/src/adapters/MellowERC4626VaultAdapterContract.ts +20 -0
  51. package/src/adapters/MellowVaultAdapterContract.ts +20 -0
  52. package/src/adapters/PendleRouterAdapterContract.ts +21 -0
  53. package/src/adapters/StakingRewardsAdapterContract.ts +21 -0
  54. package/src/adapters/UniswapV2AdapterContract.ts +20 -0
  55. package/src/adapters/UniswapV3AdapterContract.ts +170 -0
  56. package/src/adapters/VelodromeV2AdapterContract.ts +20 -0
  57. package/src/adapters/WstETHV1AdapterContract.ts +20 -0
  58. package/src/adapters/YearnV2AdapterContract.ts +20 -0
  59. package/src/adapters/abi/adapters.ts +4325 -0
  60. package/src/adapters/abi/iBalancerV3RouterAdapter.ts +126 -0
  61. package/src/adapters/abi/index.ts +2 -0
  62. package/src/adapters/index.ts +2 -0
  63. package/src/adapters/plugin.ts +90 -0
  64. package/src/adapters/types.ts +62 -0
  65. package/src/dev/AccountOpener.ts +611 -0
  66. package/src/dev/PriceFeedStore.ts +95 -0
  67. package/src/dev/SDKExample.ts +167 -0
  68. package/src/dev/abi.ts +14 -0
  69. package/src/dev/calcLiquidatableLTs.ts +77 -0
  70. package/src/dev/createAnvilClient.ts +155 -0
  71. package/src/dev/index.ts +7 -0
  72. package/src/dev/setLTZero.ts +127 -0
  73. package/src/dev/setLTs.ts +68 -0
  74. package/src/sdk/GearboxSDK.ts +488 -0
  75. package/src/sdk/abi/index.ts +1 -0
  76. package/src/sdk/abi/oracles.ts +4614 -0
  77. package/src/sdk/accounts/CreditAccountsService.ts +1123 -0
  78. package/src/sdk/accounts/index.ts +1 -0
  79. package/src/sdk/base/AddressLabeller.ts +35 -0
  80. package/src/sdk/base/BaseContract.ts +237 -0
  81. package/src/sdk/base/IAddressLabeller.ts +13 -0
  82. package/src/sdk/base/PlaceholderContract.ts +12 -0
  83. package/src/sdk/base/SDKConstruct.ts +35 -0
  84. package/src/sdk/base/TokensMeta.ts +45 -0
  85. package/src/sdk/base/index.ts +6 -0
  86. package/src/sdk/base/types.ts +102 -0
  87. package/src/sdk/bots/BotsService.ts +92 -0
  88. package/src/sdk/bots/index.ts +2 -0
  89. package/src/sdk/bots/utils.ts +19 -0
  90. package/src/sdk/chain/Provider.ts +99 -0
  91. package/src/sdk/chain/chains.ts +41 -0
  92. package/src/sdk/chain/detectChain.ts +21 -0
  93. package/src/sdk/chain/index.ts +3 -0
  94. package/src/sdk/constants/address-provider.ts +47 -0
  95. package/src/sdk/constants/addresses.ts +82 -0
  96. package/src/sdk/constants/bot-permissions.ts +36 -0
  97. package/src/sdk/constants/index.ts +6 -0
  98. package/src/sdk/constants/math.ts +23 -0
  99. package/src/sdk/constants/networks.ts +38 -0
  100. package/src/sdk/constants/periphery.ts +7 -0
  101. package/src/sdk/core/BotListV3Contract.ts +103 -0
  102. package/src/sdk/core/GearStakingV3Contract.ts +84 -0
  103. package/src/sdk/core/address-provider/AbstractAddressProviderContract.ts +101 -0
  104. package/src/sdk/core/address-provider/AddressProviderV3Contract.ts +105 -0
  105. package/src/sdk/core/address-provider/AddressProviderV3_1Contract.ts +92 -0
  106. package/src/sdk/core/address-provider/getAddressProvider.ts +45 -0
  107. package/src/sdk/core/address-provider/index.ts +4 -0
  108. package/src/sdk/core/address-provider/types.ts +17 -0
  109. package/src/sdk/core/index.ts +3 -0
  110. package/src/sdk/gauges/GaugeStakingService.ts +100 -0
  111. package/src/sdk/gauges/index.ts +2 -0
  112. package/src/sdk/gauges/utils.ts +25 -0
  113. package/src/sdk/index.ts +17 -0
  114. package/src/sdk/market/MarketConfiguratorContract.ts +78 -0
  115. package/src/sdk/market/MarketRegister.ts +330 -0
  116. package/src/sdk/market/MarketSuite.ts +83 -0
  117. package/src/sdk/market/adapters/PlaceholderAdapterContracts.ts +18 -0
  118. package/src/sdk/market/adapters/factory.ts +34 -0
  119. package/src/sdk/market/adapters/index.ts +3 -0
  120. package/src/sdk/market/adapters/types.ts +7 -0
  121. package/src/sdk/market/credit/CreditConfiguratorV300Contract.ts +164 -0
  122. package/src/sdk/market/credit/CreditConfiguratorV310Contract.ts +139 -0
  123. package/src/sdk/market/credit/CreditFacadeV300Contract.ts +206 -0
  124. package/src/sdk/market/credit/CreditFacadeV310Contract.ts +190 -0
  125. package/src/sdk/market/credit/CreditManagerV300Contract.ts +122 -0
  126. package/src/sdk/market/credit/CreditManagerV310Contract.ts +122 -0
  127. package/src/sdk/market/credit/CreditSuite.ts +65 -0
  128. package/src/sdk/market/credit/createCreditConfigurator.ts +18 -0
  129. package/src/sdk/market/credit/createCreditFacade.ts +18 -0
  130. package/src/sdk/market/credit/createCreditManager.ts +18 -0
  131. package/src/sdk/market/credit/index.ts +8 -0
  132. package/src/sdk/market/credit/types.ts +42 -0
  133. package/src/sdk/market/index.ts +7 -0
  134. package/src/sdk/market/oracle/PriceOracleBaseContract.ts +376 -0
  135. package/src/sdk/market/oracle/PriceOracleV300Contract.ts +71 -0
  136. package/src/sdk/market/oracle/PriceOracleV310Contract.ts +43 -0
  137. package/src/sdk/market/oracle/createPriceOracle.ts +22 -0
  138. package/src/sdk/market/oracle/index.ts +4 -0
  139. package/src/sdk/market/oracle/types.ts +48 -0
  140. package/src/sdk/market/pool/GaugeContract.ts +120 -0
  141. package/src/sdk/market/pool/LinearInterestRateModelContract.ts +75 -0
  142. package/src/sdk/market/pool/PoolQuotaKeeperV300Contract.ts +89 -0
  143. package/src/sdk/market/pool/PoolQuotaKeeperV310Contract.ts +89 -0
  144. package/src/sdk/market/pool/PoolSuite.ts +76 -0
  145. package/src/sdk/market/pool/PoolV300Contract.ts +144 -0
  146. package/src/sdk/market/pool/PoolV310Contract.ts +144 -0
  147. package/src/sdk/market/pool/TumblerContract.ts +73 -0
  148. package/src/sdk/market/pool/createInterestRateModel.ts +33 -0
  149. package/src/sdk/market/pool/createPool.ts +19 -0
  150. package/src/sdk/market/pool/createPoolQuotaKeeper.ts +20 -0
  151. package/src/sdk/market/pool/createRateKeeper.ts +25 -0
  152. package/src/sdk/market/pool/index.ts +6 -0
  153. package/src/sdk/market/pool/types.ts +28 -0
  154. package/src/sdk/market/pricefeeds/AbstractLPPriceFeed.ts +71 -0
  155. package/src/sdk/market/pricefeeds/AbstractPriceFeed.ts +137 -0
  156. package/src/sdk/market/pricefeeds/BalancerStablePriceFeed.ts +24 -0
  157. package/src/sdk/market/pricefeeds/BalancerWeightedPriceFeed.ts +70 -0
  158. package/src/sdk/market/pricefeeds/BoundedPriceFeed.ts +34 -0
  159. package/src/sdk/market/pricefeeds/ChainlinkPriceFeed.ts +16 -0
  160. package/src/sdk/market/pricefeeds/CompositePriceFeed.ts +25 -0
  161. package/src/sdk/market/pricefeeds/CurveCryptoPriceFeed.ts +24 -0
  162. package/src/sdk/market/pricefeeds/CurveStablePriceFeed.ts +24 -0
  163. package/src/sdk/market/pricefeeds/CurveUSDPriceFeed.ts +24 -0
  164. package/src/sdk/market/pricefeeds/Erc4626PriceFeed.ts +36 -0
  165. package/src/sdk/market/pricefeeds/MellowLRTPriceFeed.ts +26 -0
  166. package/src/sdk/market/pricefeeds/PendleTWAPPTPriceFeed.ts +44 -0
  167. package/src/sdk/market/pricefeeds/PriceFeedRef.ts +34 -0
  168. package/src/sdk/market/pricefeeds/PriceFeedsRegister.ts +293 -0
  169. package/src/sdk/market/pricefeeds/RedstonePriceFeed.ts +65 -0
  170. package/src/sdk/market/pricefeeds/RedstoneUpdater.ts +304 -0
  171. package/src/sdk/market/pricefeeds/WstETHPriceFeed.ts +24 -0
  172. package/src/sdk/market/pricefeeds/YearnPriceFeed.ts +24 -0
  173. package/src/sdk/market/pricefeeds/ZeroPriceFeed.ts +17 -0
  174. package/src/sdk/market/pricefeeds/index.ts +20 -0
  175. package/src/sdk/market/pricefeeds/types.ts +82 -0
  176. package/src/sdk/market/pricefeeds/utils.ts +24 -0
  177. package/src/sdk/plugins/index.ts +10 -0
  178. package/src/sdk/router/PathOptionFactory.ts +147 -0
  179. package/src/sdk/router/RouterV3Contract.ts +558 -0
  180. package/src/sdk/router/index.ts +2 -0
  181. package/src/sdk/router/types.ts +48 -0
  182. package/src/sdk/sdk-gov-legacy/contracts/adapters.ts +39 -0
  183. package/src/sdk/sdk-gov-legacy/contracts/contracts.ts +647 -0
  184. package/src/sdk/sdk-gov-legacy/contracts/index.ts +2 -0
  185. package/src/sdk/sdk-gov-legacy/core/constants.ts +11 -0
  186. package/src/sdk/sdk-gov-legacy/index.ts +4 -0
  187. package/src/sdk/sdk-gov-legacy/oracles/PriceFeedType.ts +24 -0
  188. package/src/sdk/sdk-gov-legacy/oracles/index.ts +1 -0
  189. package/src/sdk/sdk-gov-legacy/tokens/aave.ts +101 -0
  190. package/src/sdk/sdk-gov-legacy/tokens/aura.ts +284 -0
  191. package/src/sdk/sdk-gov-legacy/tokens/balancer.ts +421 -0
  192. package/src/sdk/sdk-gov-legacy/tokens/compound.ts +79 -0
  193. package/src/sdk/sdk-gov-legacy/tokens/convex.ts +561 -0
  194. package/src/sdk/sdk-gov-legacy/tokens/curveLP.ts +480 -0
  195. package/src/sdk/sdk-gov-legacy/tokens/decimals.ts +301 -0
  196. package/src/sdk/sdk-gov-legacy/tokens/erc4626.ts +75 -0
  197. package/src/sdk/sdk-gov-legacy/tokens/gear.ts +273 -0
  198. package/src/sdk/sdk-gov-legacy/tokens/index.ts +18 -0
  199. package/src/sdk/sdk-gov-legacy/tokens/normal.ts +613 -0
  200. package/src/sdk/sdk-gov-legacy/tokens/quoted.ts +10 -0
  201. package/src/sdk/sdk-gov-legacy/tokens/stakingRewards.ts +41 -0
  202. package/src/sdk/sdk-gov-legacy/tokens/token.ts +2354 -0
  203. package/src/sdk/sdk-gov-legacy/tokens/tokenData.ts +44 -0
  204. package/src/sdk/sdk-gov-legacy/tokens/tokenType.ts +33 -0
  205. package/src/sdk/sdk-gov-legacy/tokens/wrapped.ts +28 -0
  206. package/src/sdk/sdk-gov-legacy/tokens/yearn.ts +122 -0
  207. package/src/sdk/sdk-gov-legacy/tokens/zircuit.ts +44 -0
  208. package/src/sdk/sdk-legacy/apy/index.ts +149 -0
  209. package/src/sdk/sdk-legacy/core/assets.ts +200 -0
  210. package/src/sdk/sdk-legacy/core/creditAccount.spec.ts +1966 -0
  211. package/src/sdk/sdk-legacy/core/creditAccount.ts +816 -0
  212. package/src/sdk/sdk-legacy/core/creditManager.ts +316 -0
  213. package/src/sdk/sdk-legacy/core/creditSession.ts +352 -0
  214. package/src/sdk/sdk-legacy/core/endpoint.ts +131 -0
  215. package/src/sdk/sdk-legacy/core/eventOrTx.ts +101 -0
  216. package/src/sdk/sdk-legacy/core/pool.ts +439 -0
  217. package/src/sdk/sdk-legacy/core/strategy.ts +82 -0
  218. package/src/sdk/sdk-legacy/core/transactions.ts +865 -0
  219. package/src/sdk/sdk-legacy/gearboxRewards/api.ts +704 -0
  220. package/src/sdk/sdk-legacy/gearboxRewards/apy.ts +267 -0
  221. package/src/sdk/sdk-legacy/gearboxRewards/extraAPY.ts +165 -0
  222. package/src/sdk/sdk-legacy/gearboxRewards/index.ts +3 -0
  223. package/src/sdk/sdk-legacy/gearboxRewards/merklAPI.ts +151 -0
  224. package/src/sdk/sdk-legacy/index.ts +21 -0
  225. package/src/sdk/sdk-legacy/pathfinder/core.ts +18 -0
  226. package/src/sdk/sdk-legacy/pathfinder/index.ts +1 -0
  227. package/src/sdk/sdk-legacy/payload/creditAccount.ts +48 -0
  228. package/src/sdk/sdk-legacy/payload/creditManager.ts +133 -0
  229. package/src/sdk/sdk-legacy/payload/creditSession.ts +143 -0
  230. package/src/sdk/sdk-legacy/payload/graphPayload.ts +10 -0
  231. package/src/sdk/sdk-legacy/payload/pool.ts +198 -0
  232. package/src/sdk/sdk-legacy/payload/token.ts +13 -0
  233. package/src/sdk/sdk-legacy/tokens/tokenData.ts +57 -0
  234. package/src/sdk/sdk-legacy/types/IAirdropDistributor.ts +103 -0
  235. package/src/sdk/sdk-legacy/types/IBaseRewardPool.ts +249 -0
  236. package/src/sdk/sdk-legacy/types/IDataCompressorV3.ts +957 -0
  237. package/src/sdk/sdk-legacy/types/IDegenDistributor.ts +70 -0
  238. package/src/sdk/sdk-legacy/types/IERC20Permit.ts +35 -0
  239. package/src/sdk/sdk-legacy/types/IERC20ZapperDeposits.ts +99 -0
  240. package/src/sdk/sdk-legacy/types/IETHZapperDeposits.ts +27 -0
  241. package/src/sdk/sdk-legacy/types/IFarmingPool.ts +229 -0
  242. package/src/sdk/sdk-legacy/types/IInterestRateModel.ts +23 -0
  243. package/src/sdk/sdk-legacy/types/IMulticall3.ts +242 -0
  244. package/src/sdk/sdk-legacy/types/IOffchainOracle.ts +31 -0
  245. package/src/sdk/sdk-legacy/types/index.ts +11 -0
  246. package/src/sdk/sdk-legacy/utils/formatter.ts +46 -0
  247. package/src/sdk/sdk-legacy/utils/index.ts +3 -0
  248. package/src/sdk/sdk-legacy/utils/math.ts +6 -0
  249. package/src/sdk/sdk-legacy/utils/price.ts +27 -0
  250. package/src/sdk/types/index.ts +5 -0
  251. package/src/sdk/types/logger.ts +13 -0
  252. package/src/sdk/types/state-human.ts +224 -0
  253. package/src/sdk/types/state.ts +8 -0
  254. package/src/sdk/types/transactions.ts +22 -0
  255. package/src/sdk/types/tvl.ts +4 -0
  256. package/src/sdk/utils/AddressMap.ts +111 -0
  257. package/src/sdk/utils/bytes32ToString.ts +6 -0
  258. package/src/sdk/utils/childLogger.ts +8 -0
  259. package/src/sdk/utils/createRawTx.ts +86 -0
  260. package/src/sdk/utils/etherscan.ts +42 -0
  261. package/src/sdk/utils/filterDust.ts +20 -0
  262. package/src/sdk/utils/formatter.ts +124 -0
  263. package/src/sdk/utils/index.ts +10 -0
  264. package/src/sdk/utils/internal/Hooks.ts +51 -0
  265. package/src/sdk/utils/internal/index.ts +1 -0
  266. package/src/sdk/utils/json.ts +27 -0
  267. package/src/sdk/utils/mappers.ts +38 -0
  268. package/src/sdk/utils/retry.ts +24 -0
  269. package/src/sdk/utils/viem/detectNetwork.ts +27 -0
  270. package/src/sdk/utils/viem/index.ts +3 -0
  271. package/src/sdk/utils/viem/sendRawTx.ts +36 -0
  272. package/src/sdk/utils/viem/simulateMulticall.ts +262 -0
  273. package/tsconfig.build.json +4 -0
  274. package/tsconfig.json +16 -0
  275. package/tsup.config.ts +77 -0
@@ -0,0 +1,816 @@
1
+ import type { Address } from "viem";
2
+
3
+ import {
4
+ MIN_INT96,
5
+ PERCENTAGE_DECIMALS,
6
+ PERCENTAGE_FACTOR,
7
+ PRICE_DECIMALS,
8
+ PRICE_DECIMALS_POW,
9
+ SECONDS_PER_YEAR,
10
+ WAD,
11
+ WAD_DECIMALS_POW,
12
+ } from "../../constants";
13
+ import type { Asset } from "../../router";
14
+ import type { TokensAPYList } from "../apy";
15
+ import type {
16
+ CaTokenBalance,
17
+ CreditAccountDataPayload,
18
+ } from "../payload/creditAccount";
19
+ import type { QuotaInfo } from "../payload/creditManager";
20
+ import type { TokenData } from "../tokens/tokenData";
21
+ import { rayToNumber } from "../utils/formatter";
22
+ import { BigIntMath } from "../utils/math";
23
+ import { PriceUtils } from "../utils/price";
24
+ import type { AssetWithAmountInTarget } from "./assets";
25
+
26
+ export interface CalcOverallAPYProps {
27
+ caAssets: Array<Asset>;
28
+ lpAPY: TokensAPYList | undefined;
29
+
30
+ quotas: Record<Address, Asset>;
31
+ quotaRates: Record<Address, Pick<QuotaInfo, "isActive" | "rate">>;
32
+ feeInterest: number;
33
+
34
+ prices: Record<Address, bigint>;
35
+
36
+ totalValue: bigint | undefined;
37
+ debt: bigint | undefined;
38
+ baseRateWithFee: number;
39
+ underlyingToken: Address;
40
+ tokensList: Record<Address, TokenData>;
41
+ }
42
+
43
+ export interface CalcMaxLendingDebtProps {
44
+ assets: Array<Asset>;
45
+
46
+ prices: Record<Address, bigint>;
47
+ liquidationThresholds: Record<Address, bigint>;
48
+ underlyingToken: Address;
49
+ tokensList: Record<Address, TokenData>;
50
+
51
+ targetHF?: bigint;
52
+ }
53
+
54
+ export interface CalcHealthFactorProps {
55
+ assets: Array<Asset>;
56
+ quotas: Record<Address, Asset>;
57
+ quotasInfo: Record<Address, Pick<QuotaInfo, "isActive">>;
58
+
59
+ prices: Record<Address, bigint>;
60
+ liquidationThresholds: Record<Address, bigint>;
61
+ underlyingToken: Address;
62
+ debt: bigint;
63
+ tokensList: Record<Address, TokenData>;
64
+ }
65
+
66
+ export interface CalcDefaultQuotaProps {
67
+ amount: bigint;
68
+ lt: bigint;
69
+ quotaReserve: bigint;
70
+ }
71
+
72
+ export interface CalcRecommendedQuotaProps {
73
+ amount: bigint;
74
+ debt: bigint;
75
+ lt: bigint;
76
+ quotaReserve: bigint;
77
+ }
78
+
79
+ export interface CalcQuotaUpdateProps {
80
+ quotas: Record<Address, Pick<QuotaInfo, "isActive" | "token">>;
81
+ initialQuotas: Record<Address, Pick<CaTokenBalance, "quota">>;
82
+ liquidationThresholds: Record<Address, bigint>;
83
+ assetsAfterUpdate: Record<Address, AssetWithAmountInTarget>;
84
+ maxDebt: bigint;
85
+ calcModification?: {
86
+ type: "recommendedQuota";
87
+ debt: bigint;
88
+ };
89
+
90
+ allowedToSpend: Record<Address, {}>;
91
+ allowedToObtain: Record<Address, {}>;
92
+
93
+ quotaReserve: bigint;
94
+ }
95
+
96
+ interface CalcQuotaUpdateReturnType {
97
+ desiredQuota: Record<Address, Asset>;
98
+ quotaIncrease: Array<Asset>;
99
+ quotaDecrease: Array<Asset>;
100
+ }
101
+
102
+ export interface CalcQuotaBorrowRateProps {
103
+ quotas: Record<Address, Asset>;
104
+ quotaRates: Record<Address, Pick<QuotaInfo, "isActive" | "rate">>;
105
+ }
106
+
107
+ export interface CalcRelativeBaseBorrowRateProps {
108
+ debt: bigint;
109
+ baseRateWithFee: number;
110
+ assetAmountInUnderlying: bigint;
111
+ }
112
+
113
+ export interface CalcAvgQuotaBorrowRateProps {
114
+ quotas: Record<Address, Asset>;
115
+ quotaRates: Record<Address, Pick<QuotaInfo, "isActive" | "rate">>;
116
+ }
117
+
118
+ interface LiquidationPriceProps {
119
+ liquidationThresholds: Record<Address, bigint>;
120
+
121
+ debt: bigint;
122
+ underlyingToken: Address;
123
+ targetToken: Address;
124
+ assets: Record<Address, Asset>;
125
+ tokensList: Record<Address, TokenData>;
126
+ }
127
+
128
+ export interface TimeToLiquidationProps {
129
+ totalBorrowRate_debt: bigint;
130
+ healthFactor: number;
131
+ }
132
+
133
+ const MAX_UINT16 = 65535;
134
+
135
+ export interface BotDataLegacy {
136
+ baseParams: {
137
+ addr: Address;
138
+ version: bigint;
139
+ contractType: Address;
140
+ serializedParams: Address;
141
+ };
142
+ permissions: bigint;
143
+ forbidden: boolean;
144
+ }
145
+
146
+ export class CreditAccountData_Legacy {
147
+ readonly isSuccessful: boolean;
148
+
149
+ readonly creditAccount: Address;
150
+ readonly borrower: Address;
151
+ readonly creditManager: Address;
152
+ readonly creditFacade: Address;
153
+ readonly underlying: Address;
154
+ readonly expirationDate: number;
155
+ readonly version: number;
156
+
157
+ readonly enabledTokensMask: bigint;
158
+ readonly healthFactor: number;
159
+ isDeleting: boolean;
160
+
161
+ readonly baseBorrowRateWithoutFee: number;
162
+
163
+ readonly borrowedAmount: bigint;
164
+ readonly accruedInterest: bigint;
165
+ readonly accruedFees: bigint;
166
+ readonly totalDebtUSD: bigint;
167
+ readonly borrowedAmountPlusInterestAndFees: bigint;
168
+ readonly debt: bigint;
169
+ readonly totalValue: bigint;
170
+ readonly totalValueUSD: bigint;
171
+ readonly twvUSD: bigint;
172
+
173
+ readonly activeBots: Record<Address, BotDataLegacy>;
174
+
175
+ readonly balances: Record<Address, bigint> = {};
176
+ readonly collateralTokens: Array<Address> = [];
177
+ readonly tokens: Record<Address, CaTokenBalance> = {};
178
+ readonly forbiddenTokens: Record<Address, true> = {};
179
+ readonly quotedTokens: Record<Address, true> = {};
180
+
181
+ constructor(payload: CreditAccountDataPayload) {
182
+ this.isSuccessful = payload.isSuccessful;
183
+
184
+ this.creditAccount = payload.addr.toLowerCase() as Address;
185
+ this.borrower = payload.borrower.toLowerCase() as Address;
186
+ this.creditManager = payload.creditManager.toLowerCase() as Address;
187
+ this.creditFacade = payload.creditFacade.toLowerCase() as Address;
188
+ this.underlying = payload.underlying.toLowerCase() as Address;
189
+ this.expirationDate = Number(payload.expirationDate);
190
+ this.version = Number(payload.cfVersion);
191
+
192
+ this.healthFactor = Number(payload.healthFactor || 0n);
193
+ this.enabledTokensMask = payload.enabledTokensMask;
194
+ this.isDeleting = false;
195
+
196
+ this.borrowedAmount = payload.debt;
197
+ this.accruedInterest = payload.accruedInterest || 0n;
198
+ this.accruedFees = payload.accruedFees || 0n;
199
+ this.debt = this.borrowedAmount;
200
+ this.borrowedAmountPlusInterestAndFees =
201
+ this.borrowedAmount + this.accruedInterest + this.accruedFees;
202
+ this.totalDebtUSD = payload.totalDebtUSD;
203
+ this.totalValue = payload.totalValue || 0n;
204
+ this.totalValueUSD = payload.totalValueUSD;
205
+ this.twvUSD = payload.twvUSD;
206
+
207
+ this.baseBorrowRateWithoutFee = rayToNumber(
208
+ payload.baseBorrowRate * PERCENTAGE_DECIMALS * PERCENTAGE_FACTOR,
209
+ );
210
+
211
+ this.activeBots = payload.activeBots.reduce<
212
+ CreditAccountData_Legacy["activeBots"]
213
+ >((acc, b) => {
214
+ const botLc = b.baseParams.addr.toLowerCase() as Address;
215
+ acc[botLc] = {
216
+ baseParams: {
217
+ ...b.baseParams,
218
+ addr: botLc,
219
+ },
220
+ permissions: b.permissions,
221
+ forbidden: b.forbidden,
222
+ };
223
+ return acc;
224
+ }, {});
225
+
226
+ payload.balances.forEach(b => {
227
+ const token = b.token.toLowerCase() as Address;
228
+ const balance: CaTokenBalance = {
229
+ success: b.success,
230
+ token,
231
+ balance: b.balance,
232
+ isForbidden: b.isForbidden,
233
+ isEnabled: b.isEnabled,
234
+ isQuoted: b.isQuoted,
235
+ quota: b.quota,
236
+ quotaRate: BigInt(b.quotaRate) * PERCENTAGE_DECIMALS,
237
+ mask: b.mask,
238
+ };
239
+
240
+ if (!b.isForbidden) {
241
+ this.balances[token] = balance.balance;
242
+ this.collateralTokens.push(token);
243
+ }
244
+ if (b.isForbidden) {
245
+ this.forbiddenTokens[token] = true;
246
+ }
247
+ if (b.isQuoted) {
248
+ this.quotedTokens[token] = true;
249
+ }
250
+
251
+ this.tokens[token] = balance;
252
+ });
253
+ }
254
+
255
+ setDeleteInProgress(d: boolean) {
256
+ this.isDeleting = d;
257
+ }
258
+
259
+ static sortBalances(
260
+ balances: Record<Address, bigint>,
261
+ prices: Record<Address, bigint>,
262
+ tokens: Record<Address, TokenData>,
263
+ ): Array<[Address, bigint]> {
264
+ return (Object.entries(balances) as Array<[Address, bigint]>).sort(
265
+ ([addr1, amount1], [addr2, amount2]) => {
266
+ const addr1Lc = addr1.toLowerCase() as Address;
267
+ const addr2Lc = addr2.toLowerCase() as Address;
268
+
269
+ const token1 = tokens[addr1Lc];
270
+ const token2 = tokens[addr2Lc];
271
+
272
+ const price1 = prices[addr1Lc] || PRICE_DECIMALS;
273
+ const price2 = prices[addr2Lc] || PRICE_DECIMALS;
274
+
275
+ const totalPrice1 = PriceUtils.calcTotalPrice(
276
+ price1,
277
+ amount1,
278
+ token1?.decimals,
279
+ );
280
+ const totalPrice2 = PriceUtils.calcTotalPrice(
281
+ price2,
282
+ amount2,
283
+ token2?.decimals,
284
+ );
285
+
286
+ if (totalPrice1 === totalPrice2) {
287
+ return amount1 === amount2
288
+ ? this.tokensAbcComparator(token1, token2)
289
+ : this.amountAbcComparator(amount1, amount2);
290
+ }
291
+
292
+ return this.amountAbcComparator(totalPrice1, totalPrice2);
293
+ },
294
+ );
295
+ }
296
+
297
+ static sortAssets(
298
+ balances: Array<Asset>,
299
+ prices: Record<Address, bigint>,
300
+ tokens: Record<Address, TokenData>,
301
+ ) {
302
+ return balances.sort(
303
+ (
304
+ { token: addr1, balance: amount1 },
305
+ { token: addr2, balance: amount2 },
306
+ ) => {
307
+ const addr1Lc = addr1.toLowerCase() as Address;
308
+ const addr2Lc = addr2.toLowerCase() as Address;
309
+
310
+ const token1 = tokens[addr1Lc];
311
+ const token2 = tokens[addr2Lc];
312
+
313
+ const price1 = prices[addr1Lc] || PRICE_DECIMALS;
314
+ const price2 = prices[addr2Lc] || PRICE_DECIMALS;
315
+
316
+ const totalPrice1 = PriceUtils.calcTotalPrice(
317
+ price1,
318
+ amount1,
319
+ token1?.decimals,
320
+ );
321
+ const totalPrice2 = PriceUtils.calcTotalPrice(
322
+ price2,
323
+ amount2,
324
+ token2?.decimals,
325
+ );
326
+
327
+ if (totalPrice1 === totalPrice2) {
328
+ return amount1 === amount2
329
+ ? this.tokensAbcComparator(token1, token2)
330
+ : this.amountAbcComparator(amount1, amount2);
331
+ }
332
+
333
+ return this.amountAbcComparator(totalPrice1, totalPrice2);
334
+ },
335
+ );
336
+ }
337
+
338
+ static tokensAbcComparator(t1?: TokenData, t2?: TokenData) {
339
+ const { symbol: symbol1 = "" } = t1 || {};
340
+ const { symbol: symbol2 = "" } = t2 || {};
341
+ const symbol1LC = symbol1.toLowerCase();
342
+ const symbol2LC = symbol2.toLowerCase();
343
+
344
+ if (symbol1LC === symbol2LC) return 0;
345
+ return symbol1LC > symbol2LC ? 1 : -1;
346
+ }
347
+
348
+ static amountAbcComparator(t1: bigint, t2: bigint) {
349
+ return t1 > t2 ? -1 : 1;
350
+ }
351
+
352
+ isForbidden(token: Address) {
353
+ return !!this.forbiddenTokens[token];
354
+ }
355
+
356
+ isQuoted(token: Address) {
357
+ return !!this.quotedTokens[token];
358
+ }
359
+
360
+ isTokenEnabled(token: Address) {
361
+ return this.tokens[token].isEnabled;
362
+ }
363
+
364
+ static calcMaxDebtIncrease(
365
+ healthFactor: number,
366
+ debt: bigint,
367
+ underlyingLT: number,
368
+ minHf = Number(PERCENTAGE_FACTOR),
369
+ ): bigint {
370
+ // HF = (TWV + d*lt) / (D + d) => d = (HF*D - TWV) / (l - HF)
371
+ // hf = TWV / D
372
+ // HF = (TVW * D / D + d*lt) / (D + d) = (hf*D + d*lt) / (d + D) => d = D * (hf-HF) / (HF - lt)
373
+ const result =
374
+ (debt * BigInt(healthFactor - minHf)) / BigInt(minHf - underlyingLT);
375
+
376
+ return BigIntMath.max(0n, result);
377
+ }
378
+
379
+ static calcMaxLendingDebt({
380
+ assets,
381
+
382
+ liquidationThresholds,
383
+ underlyingToken,
384
+
385
+ prices,
386
+ tokensList,
387
+
388
+ targetHF = PERCENTAGE_FACTOR,
389
+ }: CalcMaxLendingDebtProps) {
390
+ const assetsLTMoney = assets.reduce(
391
+ (acc, { token: tokenAddress, balance: amount }) => {
392
+ const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
393
+ const lt = liquidationThresholds[tokenAddress] || 0n;
394
+ const price = prices[tokenAddress] || 0n;
395
+
396
+ const tokenMoney = PriceUtils.calcTotalPrice(
397
+ price,
398
+ amount,
399
+ tokenDecimals,
400
+ );
401
+ const tokenLtMoney = tokenMoney * lt;
402
+ return acc + tokenLtMoney;
403
+ },
404
+ 0n,
405
+ );
406
+
407
+ const underlyingPrice = prices[underlyingToken] || 0n;
408
+ const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
409
+
410
+ // HF = TWV / D => D = TWV / HF; D = amount * price
411
+ // Debt_max = sum(LT_i * Asset_i * price_i) / (price_underlying * HF)
412
+ const max =
413
+ underlyingPrice > 0
414
+ ? (assetsLTMoney * 10n ** BigInt(underlyingDecimals)) /
415
+ underlyingPrice /
416
+ targetHF /
417
+ 10n ** BigInt(WAD_DECIMALS_POW - PRICE_DECIMALS_POW)
418
+ : 0n;
419
+
420
+ return max;
421
+ }
422
+
423
+ static calcOverallAPY({
424
+ caAssets,
425
+ lpAPY,
426
+ prices,
427
+ quotas,
428
+ quotaRates,
429
+ feeInterest,
430
+
431
+ totalValue,
432
+ debt,
433
+ baseRateWithFee,
434
+ underlyingToken,
435
+ tokensList,
436
+ }: CalcOverallAPYProps): bigint | undefined {
437
+ if (
438
+ !lpAPY ||
439
+ !totalValue ||
440
+ totalValue <= 0n ||
441
+ !debt ||
442
+ totalValue <= debt
443
+ )
444
+ return undefined;
445
+
446
+ const underlyingTokenDecimals = tokensList[underlyingToken]?.decimals || 18;
447
+ const underlyingPrice = prices[underlyingToken];
448
+
449
+ const assetAPYMoney = caAssets.reduce(
450
+ (acc, { token: tokenAddress, balance: amount }) => {
451
+ const apy = lpAPY[tokenAddress] || 0;
452
+
453
+ const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
454
+ const price = prices[tokenAddress] || 0n;
455
+
456
+ const money = PriceUtils.calcTotalPrice(price, amount, tokenDecimals);
457
+ const apyMoney = money * BigInt(apy);
458
+
459
+ const { rate: quotaAPY = 0n, isActive = false } =
460
+ quotaRates?.[tokenAddress] || {};
461
+ const { balance: quotaBalance = 0n } = quotas[tokenAddress] || {};
462
+
463
+ const quotaAmount = isActive ? quotaBalance : 0n;
464
+ const quotaMoney = PriceUtils.calcTotalPrice(
465
+ underlyingPrice || 0n,
466
+ quotaAmount,
467
+ underlyingTokenDecimals,
468
+ );
469
+
470
+ const quotaRate =
471
+ (quotaAPY * (BigInt(feeInterest) + PERCENTAGE_FACTOR)) /
472
+ PERCENTAGE_FACTOR;
473
+
474
+ const quotaAPYMoney = quotaMoney * quotaRate;
475
+
476
+ return acc + apyMoney - quotaAPYMoney;
477
+ },
478
+ 0n,
479
+ );
480
+
481
+ const assetAPYAmountInUnderlying = PriceUtils.convertByPrice(
482
+ assetAPYMoney,
483
+ {
484
+ price: underlyingPrice || PRICE_DECIMALS,
485
+ decimals: underlyingTokenDecimals,
486
+ },
487
+ );
488
+
489
+ const debtAPY = debt * BigInt(baseRateWithFee);
490
+
491
+ const yourAssets = totalValue - debt;
492
+
493
+ const apyInPercent = (assetAPYAmountInUnderlying - debtAPY) / yourAssets;
494
+
495
+ return apyInPercent;
496
+ }
497
+
498
+ hash(): string {
499
+ return CreditAccountData_Legacy.hash(this.creditManager, this.borrower);
500
+ }
501
+
502
+ static hash(creditManager: Address, borrower: Address): string {
503
+ return `${creditManager.toLowerCase()}:${borrower.toLowerCase()}`;
504
+ }
505
+
506
+ static calcHealthFactor({
507
+ assets,
508
+ quotas,
509
+ quotasInfo,
510
+
511
+ liquidationThresholds,
512
+ underlyingToken,
513
+ debt,
514
+
515
+ prices,
516
+ tokensList,
517
+ }: CalcHealthFactorProps): number {
518
+ if (debt === 0n) return MAX_UINT16;
519
+
520
+ const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
521
+ const underlyingPrice = prices[underlyingToken] || 0n;
522
+
523
+ const assetMoney = assets.reduce(
524
+ (acc, { token: tokenAddress, balance: amount }) => {
525
+ const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
526
+
527
+ const lt = liquidationThresholds[tokenAddress] || 0n;
528
+ const price = prices[tokenAddress] || 0n;
529
+
530
+ const tokenMoney = PriceUtils.calcTotalPrice(
531
+ price,
532
+ amount,
533
+ tokenDecimals,
534
+ );
535
+ const tokenLtMoney = (tokenMoney * lt) / PERCENTAGE_FACTOR;
536
+
537
+ const { isActive = false } = quotasInfo?.[tokenAddress] || {};
538
+ const quota = quotas[tokenAddress];
539
+ const quotaBalance = isActive ? quota?.balance || 0n : 0n;
540
+ const quotaMoney = PriceUtils.calcTotalPrice(
541
+ underlyingPrice,
542
+ quotaBalance,
543
+ underlyingDecimals,
544
+ );
545
+
546
+ // if quota is undefined, then it is not a quoted token
547
+ const money = quota
548
+ ? BigIntMath.min(quotaMoney, tokenLtMoney)
549
+ : tokenLtMoney;
550
+
551
+ return acc + money;
552
+ },
553
+ 0n,
554
+ );
555
+
556
+ const borrowedMoney = PriceUtils.calcTotalPrice(
557
+ underlyingPrice || PRICE_DECIMALS,
558
+ debt,
559
+ underlyingDecimals,
560
+ );
561
+
562
+ const hfInPercent =
563
+ borrowedMoney > 0n
564
+ ? (assetMoney * PERCENTAGE_FACTOR) / borrowedMoney
565
+ : 0n;
566
+
567
+ return Number(hfInPercent);
568
+ }
569
+
570
+ static roundUpQuota(quotaChange: bigint) {
571
+ return quotaChange !== MIN_INT96
572
+ ? (quotaChange / PERCENTAGE_FACTOR) * PERCENTAGE_FACTOR
573
+ : quotaChange;
574
+ }
575
+
576
+ static calcRecommendedQuota({
577
+ amount,
578
+ debt,
579
+ lt,
580
+ quotaReserve,
581
+ }: CalcRecommendedQuotaProps) {
582
+ const recommendedBaseQuota = BigIntMath.min(
583
+ debt,
584
+ (amount * lt) / PERCENTAGE_FACTOR,
585
+ );
586
+
587
+ const recommendedQuota =
588
+ (recommendedBaseQuota * (PERCENTAGE_FACTOR + quotaReserve)) /
589
+ PERCENTAGE_FACTOR;
590
+
591
+ return this.roundUpQuota(recommendedQuota);
592
+ }
593
+
594
+ static calcDefaultQuota({ amount, lt, quotaReserve }: CalcDefaultQuotaProps) {
595
+ const recommendedBaseQuota = (amount * lt) / PERCENTAGE_FACTOR;
596
+ const recommendedQuota =
597
+ (recommendedBaseQuota * (PERCENTAGE_FACTOR + quotaReserve)) /
598
+ PERCENTAGE_FACTOR;
599
+
600
+ return this.roundUpQuota(recommendedQuota);
601
+ }
602
+
603
+ static calcQuotaUpdate(
604
+ props: CalcQuotaUpdateProps,
605
+ ): CalcQuotaUpdateReturnType {
606
+ const { quotas, initialQuotas, maxDebt, allowedToSpend, allowedToObtain } =
607
+ props;
608
+ const quotaDecrease = Object.keys(allowedToSpend).reduce<
609
+ Record<Address, Asset>
610
+ >((acc, token) => {
611
+ const ch = this.getSingleQuotaChange(token as Address, 0n, props);
612
+ if (ch && ch.balance < 0) acc[ch.token] = ch;
613
+ return acc;
614
+ }, {});
615
+
616
+ const quotaCap = this.roundUpQuota(maxDebt * 2n);
617
+ const quotaBought = Object.values(initialQuotas).reduce(
618
+ (sum, q) => sum + this.roundUpQuota(q?.quota || 0n),
619
+ 0n,
620
+ );
621
+ const quotaReduced = Object.values(quotaDecrease).reduce((sum, q) => {
622
+ const quotaBalance = q.balance || 0n;
623
+ const safeBalance =
624
+ quotaBalance === MIN_INT96
625
+ ? BigIntMath.neg(
626
+ this.roundUpQuota(initialQuotas[q.token]?.quota || 0n),
627
+ )
628
+ : quotaBalance;
629
+
630
+ return sum + safeBalance;
631
+ }, 0n);
632
+ const maxQuotaIncrease = this.roundUpQuota(
633
+ BigIntMath.max(quotaCap - (quotaBought + quotaReduced), 0n),
634
+ );
635
+
636
+ const quotaIncrease = Object.keys(allowedToObtain).reduce<
637
+ Record<Address, Asset>
638
+ >((acc, token) => {
639
+ const ch = this.getSingleQuotaChange(
640
+ token as Address,
641
+ maxQuotaIncrease,
642
+ props,
643
+ );
644
+ if (ch && ch.balance > 0) acc[ch.token] = ch;
645
+ return acc;
646
+ }, {});
647
+
648
+ const quotaChange = {
649
+ ...quotaDecrease,
650
+ ...quotaIncrease,
651
+ };
652
+
653
+ const desiredQuota = Object.values(quotas).reduce<Record<Address, Asset>>(
654
+ (acc, cmQuota) => {
655
+ const { token, isActive } = cmQuota;
656
+ const { quota: initialQuota = 0n } = initialQuotas[token] || {};
657
+
658
+ if (!isActive) {
659
+ acc[token] = {
660
+ balance: initialQuota,
661
+ token,
662
+ };
663
+ } else {
664
+ const change = quotaChange[token]?.balance || 0n;
665
+ const quotaAfter = change === MIN_INT96 ? 0n : initialQuota + change;
666
+
667
+ acc[token] = {
668
+ balance: quotaAfter,
669
+ token,
670
+ };
671
+ }
672
+
673
+ return acc;
674
+ },
675
+ {},
676
+ );
677
+ return {
678
+ desiredQuota,
679
+ quotaDecrease: Object.values(quotaDecrease),
680
+ quotaIncrease: Object.values(quotaIncrease),
681
+ };
682
+ }
683
+
684
+ private static getSingleQuotaChange(
685
+ token: Address,
686
+ unsafeMaxQuotaIncrease: bigint,
687
+ props: CalcQuotaUpdateProps,
688
+ ) {
689
+ const { isActive = false } = props.quotas[token] || {};
690
+ const { quota: unsafeInitialQuota = 0n } = props.initialQuotas[token] || {};
691
+
692
+ if (!isActive) {
693
+ return undefined;
694
+ }
695
+
696
+ // min(debt,assetAmountInUnderlying*LT)*(1+buffer)
697
+ const assetAfter = props.assetsAfterUpdate[token];
698
+ const { amountInTarget = 0n } = assetAfter || {};
699
+ const lt = props.liquidationThresholds[token] || 0n;
700
+ const maxQuotaIncrease = this.roundUpQuota(unsafeMaxQuotaIncrease);
701
+ const initialQuota = this.roundUpQuota(unsafeInitialQuota);
702
+
703
+ const defaultQuota =
704
+ props.calcModification?.type === "recommendedQuota" &&
705
+ props.calcModification.debt > 0
706
+ ? this.calcRecommendedQuota({
707
+ lt,
708
+ quotaReserve: props.quotaReserve,
709
+ amount: amountInTarget,
710
+ debt: props.calcModification.debt,
711
+ })
712
+ : this.calcDefaultQuota({
713
+ lt,
714
+ quotaReserve: props.quotaReserve,
715
+ amount: amountInTarget,
716
+ });
717
+
718
+ const unsafeQuotaChange = this.roundUpQuota(defaultQuota - initialQuota);
719
+ const quotaChange =
720
+ unsafeQuotaChange > 0
721
+ ? BigIntMath.min(maxQuotaIncrease, unsafeQuotaChange)
722
+ : unsafeQuotaChange < 0 &&
723
+ BigIntMath.abs(unsafeQuotaChange) >= initialQuota
724
+ ? MIN_INT96
725
+ : unsafeQuotaChange;
726
+
727
+ const correctIncrease =
728
+ assetAfter && props.allowedToObtain[token] && quotaChange > 0;
729
+ const correctDecrease =
730
+ assetAfter && props.allowedToSpend[token] && quotaChange < 0;
731
+
732
+ if (correctIncrease || correctDecrease) {
733
+ return {
734
+ balance: quotaChange,
735
+ token,
736
+ };
737
+ }
738
+
739
+ return undefined;
740
+ }
741
+
742
+ static calcQuotaBorrowRate({ quotas, quotaRates }: CalcQuotaBorrowRateProps) {
743
+ const totalRateBalance = Object.values(quotas).reduce(
744
+ (acc, { token, balance }) => {
745
+ const { rate = 0, isActive = false } = quotaRates?.[token] || {};
746
+
747
+ const quotaBalance = isActive ? balance : 0n;
748
+ const rateBalance = quotaBalance * BigInt(rate);
749
+
750
+ return acc + rateBalance;
751
+ },
752
+ 0n,
753
+ );
754
+ return totalRateBalance;
755
+ }
756
+ static calcRelativeBaseBorrowRate({
757
+ debt,
758
+ baseRateWithFee,
759
+ assetAmountInUnderlying,
760
+ }: CalcRelativeBaseBorrowRateProps) {
761
+ return debt * BigInt(baseRateWithFee) * assetAmountInUnderlying;
762
+ }
763
+
764
+ static liquidationPrice({
765
+ liquidationThresholds,
766
+
767
+ debt,
768
+ underlyingToken,
769
+ targetToken,
770
+ assets,
771
+ tokensList,
772
+ }: LiquidationPriceProps) {
773
+ const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
774
+ const { balance: underlyingBalance = 0n } = assets[underlyingToken] || {};
775
+
776
+ // effectiveDebt = Debt - underlyingBalance*LTunderlying
777
+ const ltUnderlying = liquidationThresholds[underlyingToken] || 0n;
778
+ const effectiveDebt =
779
+ ((debt - (underlyingBalance * ltUnderlying) / PERCENTAGE_FACTOR) * WAD) /
780
+ 10n ** BigInt(underlyingDecimals);
781
+
782
+ const targetDecimals = tokensList[targetToken]?.decimals || 18;
783
+ const { balance: targetBalance = 0n } = assets[targetToken] || {};
784
+ const effectiveTargetBalance =
785
+ (targetBalance * WAD) / 10n ** BigInt(targetDecimals);
786
+
787
+ const lpLT = liquidationThresholds[targetToken] || 0n;
788
+
789
+ if (targetBalance <= 0n || lpLT <= 0n) return 0n;
790
+
791
+ // priceTarget = effectiveDebt / (lpLT*targetBalance)
792
+ return (
793
+ (effectiveDebt * PRICE_DECIMALS * PERCENTAGE_FACTOR) /
794
+ (effectiveTargetBalance * lpLT)
795
+ );
796
+ }
797
+
798
+ /**
799
+ * Calculates the time remaining until liquidation for a credit account.
800
+ * @returns The time remaining until liquidation in milliseconds.
801
+ */
802
+ static getTimeToLiquidation({
803
+ healthFactor,
804
+ totalBorrowRate_debt,
805
+ }: TimeToLiquidationProps) {
806
+ if (healthFactor <= PERCENTAGE_FACTOR || totalBorrowRate_debt === 0n)
807
+ return null;
808
+
809
+ // (HF - 1) / (br_D / year) or (HF - 1) * (year / br_D)
810
+ const HF_1 = BigInt(healthFactor) - PERCENTAGE_FACTOR;
811
+ const brPerYear =
812
+ (BigInt(SECONDS_PER_YEAR) * PERCENTAGE_FACTOR * PERCENTAGE_DECIMALS) /
813
+ totalBorrowRate_debt;
814
+ return (HF_1 * brPerYear * 1000n) / PERCENTAGE_FACTOR;
815
+ }
816
+ }