@morpho-org/blue-sdk 1.0.3 → 1.0.4

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 (158) hide show
  1. package/lib/addresses.d.ts +156 -0
  2. package/lib/addresses.js +160 -0
  3. package/lib/chain/chain.constants.d.ts +3 -0
  4. package/lib/chain/chain.constants.js +232 -0
  5. package/lib/chain/chain.test.d.ts +1 -0
  6. package/lib/chain/chain.test.js +37 -0
  7. package/lib/chain/chain.types.d.ts +20 -0
  8. package/lib/chain/chain.types.js +30 -0
  9. package/lib/chain/chain.utils.d.ts +14 -0
  10. package/lib/chain/chain.utils.js +30 -0
  11. package/lib/chain/index.js +18 -0
  12. package/lib/constants.d.ts +8 -0
  13. package/lib/constants.js +13 -0
  14. package/lib/errors.d.ts +37 -0
  15. package/lib/errors.js +71 -0
  16. package/lib/ethers/ethers.test.d.ts +1 -0
  17. package/lib/ethers/ethers.test.js +11 -0
  18. package/lib/ethers/index.js +18 -0
  19. package/lib/ethers/safeGetAddress.d.ts +1 -0
  20. package/lib/ethers/safeGetAddress.js +6 -0
  21. package/lib/ethers/safeParseUnits.d.ts +2 -0
  22. package/lib/ethers/safeParseUnits.js +25 -0
  23. package/lib/evm.d.ts +36 -0
  24. package/lib/evm.js +113 -0
  25. package/lib/helpers/format/format.d.ts +98 -0
  26. package/lib/helpers/format/format.js +301 -0
  27. package/lib/helpers/format/format.test.d.ts +1 -0
  28. package/lib/helpers/format/format.test.js +257 -0
  29. package/lib/helpers/format/index.js +17 -0
  30. package/lib/helpers/getChecksumedAddress.d.ts +7 -0
  31. package/lib/helpers/getChecksumedAddress.js +17 -0
  32. package/lib/helpers/index.js +20 -0
  33. package/{src/helpers/isZeroAddressOrUnset.ts → lib/helpers/isZeroAddressOrUnset.d.ts} +1 -7
  34. package/lib/helpers/isZeroAddressOrUnset.js +14 -0
  35. package/lib/helpers/locale.d.ts +36 -0
  36. package/lib/helpers/locale.js +86 -0
  37. package/lib/holding/Holding.d.ts +60 -0
  38. package/lib/holding/Holding.js +31 -0
  39. package/lib/holding/index.js +17 -0
  40. package/{src/index.ts → lib/index.d.ts} +0 -1
  41. package/lib/market/Market.d.ts +159 -0
  42. package/lib/market/Market.js +240 -0
  43. package/lib/market/MarketConfig.d.ts +44 -0
  44. package/lib/market/MarketConfig.js +56 -0
  45. package/lib/market/MarketUtils.d.ts +165 -0
  46. package/lib/market/MarketUtils.js +182 -0
  47. package/lib/market/MarketUtils.test.d.ts +1 -0
  48. package/lib/market/MarketUtils.test.js +19 -0
  49. package/lib/market/index.js +19 -0
  50. package/lib/maths/AdaptiveCurveIrmLib.d.ts +37 -0
  51. package/lib/maths/AdaptiveCurveIrmLib.js +116 -0
  52. package/lib/maths/MathLib.d.ts +94 -0
  53. package/lib/maths/MathLib.js +153 -0
  54. package/lib/maths/MathUtils.d.ts +15 -0
  55. package/lib/maths/MathUtils.js +33 -0
  56. package/lib/maths/SharesMath.d.ts +12 -0
  57. package/lib/maths/SharesMath.js +22 -0
  58. package/lib/maths/index.js +20 -0
  59. package/lib/notifications.d.ts +98 -0
  60. package/lib/notifications.js +52 -0
  61. package/lib/position/Position.d.ts +118 -0
  62. package/lib/position/Position.js +145 -0
  63. package/lib/position/index.js +17 -0
  64. package/lib/signatures/index.d.ts +12 -0
  65. package/lib/signatures/index.js +39 -0
  66. package/lib/signatures/manager.d.ts +10 -0
  67. package/lib/signatures/manager.js +37 -0
  68. package/lib/signatures/permit.d.ts +21 -0
  69. package/lib/signatures/permit.js +101 -0
  70. package/lib/signatures/permit2.d.ts +20 -0
  71. package/lib/signatures/permit2.js +91 -0
  72. package/lib/signatures/types.d.ts +13 -0
  73. package/lib/signatures/types.js +2 -0
  74. package/lib/signatures/utils.d.ts +6 -0
  75. package/lib/signatures/utils.js +44 -0
  76. package/lib/tests/mocks/markets.d.ts +17 -0
  77. package/lib/tests/mocks/markets.js +108 -0
  78. package/lib/token/ERC20Metadata.d.ts +249 -0
  79. package/lib/token/ERC20Metadata.js +81 -0
  80. package/lib/token/Token.d.ts +45 -0
  81. package/lib/token/Token.js +39 -0
  82. package/lib/token/TokenNamespace.d.ts +18 -0
  83. package/lib/token/TokenNamespace.js +55 -0
  84. package/lib/token/WrappedToken.d.ts +42 -0
  85. package/lib/token/WrappedToken.js +87 -0
  86. package/lib/token/index.js +18 -0
  87. package/lib/types.d.ts +29 -0
  88. package/lib/types.js +23 -0
  89. package/lib/user/User.d.ts +20 -0
  90. package/lib/user/User.js +11 -0
  91. package/lib/user/index.js +18 -0
  92. package/lib/user/user.types.d.ts +18 -0
  93. package/lib/user/user.types.js +2 -0
  94. package/lib/vault/Vault.d.ts +167 -0
  95. package/lib/vault/Vault.js +156 -0
  96. package/lib/vault/VaultAllocation.d.ts +38 -0
  97. package/lib/vault/VaultAllocation.js +18 -0
  98. package/lib/vault/VaultConfig.d.ts +23 -0
  99. package/lib/vault/VaultConfig.js +26 -0
  100. package/lib/vault/VaultUtils.d.ts +17 -0
  101. package/lib/vault/VaultUtils.js +17 -0
  102. package/lib/vault/index.js +20 -0
  103. package/package.json +6 -9
  104. package/src/addresses.ts +0 -247
  105. package/src/chain/chain.constants.ts +0 -235
  106. package/src/chain/chain.test.ts +0 -51
  107. package/src/chain/chain.types.ts +0 -42
  108. package/src/chain/chain.utils.ts +0 -44
  109. package/src/constants.ts +0 -18
  110. package/src/errors.ts +0 -75
  111. package/src/ethers/ethers.test.ts +0 -17
  112. package/src/ethers/safeGetAddress.ts +0 -4
  113. package/src/ethers/safeParseUnits.ts +0 -29
  114. package/src/evm.ts +0 -172
  115. package/src/helpers/format/format.test.ts +0 -340
  116. package/src/helpers/format/format.ts +0 -416
  117. package/src/helpers/getChecksumedAddress.ts +0 -15
  118. package/src/helpers/locale.ts +0 -108
  119. package/src/holding/Holding.ts +0 -109
  120. package/src/market/Market.ts +0 -479
  121. package/src/market/MarketConfig.ts +0 -108
  122. package/src/market/MarketUtils.test.ts +0 -25
  123. package/src/market/MarketUtils.ts +0 -467
  124. package/src/maths/AdaptiveCurveIrmLib.ts +0 -143
  125. package/src/maths/MathLib.ts +0 -208
  126. package/src/maths/MathUtils.ts +0 -31
  127. package/src/maths/SharesMath.ts +0 -40
  128. package/src/notifications.ts +0 -167
  129. package/src/position/Position.ts +0 -251
  130. package/src/signatures/index.ts +0 -18
  131. package/src/signatures/manager.ts +0 -50
  132. package/src/signatures/permit.ts +0 -126
  133. package/src/signatures/permit2.ts +0 -120
  134. package/src/signatures/types.ts +0 -18
  135. package/src/signatures/utils.ts +0 -83
  136. package/src/tests/mocks/markets.ts +0 -110
  137. package/src/token/ERC20Metadata.ts +0 -124
  138. package/src/token/Token.ts +0 -83
  139. package/src/token/TokenNamespace.ts +0 -76
  140. package/src/token/WrappedToken.ts +0 -142
  141. package/src/types.ts +0 -37
  142. package/src/user/User.ts +0 -32
  143. package/src/user/user.types.ts +0 -25
  144. package/src/vault/Vault.ts +0 -370
  145. package/src/vault/VaultAllocation.ts +0 -58
  146. package/src/vault/VaultConfig.ts +0 -55
  147. package/src/vault/VaultUtils.ts +0 -47
  148. /package/{src/chain/index.ts → lib/chain/index.d.ts} +0 -0
  149. /package/{src/ethers/index.ts → lib/ethers/index.d.ts} +0 -0
  150. /package/{src/helpers/format/index.ts → lib/helpers/format/index.d.ts} +0 -0
  151. /package/{src/helpers/index.ts → lib/helpers/index.d.ts} +0 -0
  152. /package/{src/holding/index.ts → lib/holding/index.d.ts} +0 -0
  153. /package/{src/market/index.ts → lib/market/index.d.ts} +0 -0
  154. /package/{src/maths/index.ts → lib/maths/index.d.ts} +0 -0
  155. /package/{src/position/index.ts → lib/position/index.d.ts} +0 -0
  156. /package/{src/token/index.ts → lib/token/index.d.ts} +0 -0
  157. /package/{src/user/index.ts → lib/user/index.d.ts} +0 -0
  158. /package/{src/vault/index.ts → lib/vault/index.d.ts} +0 -0
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarketConfig = void 0;
4
+ const ethers_1 = require("ethers");
5
+ const ethers_types_1 = require("ethers-types");
6
+ const addresses_1 = require("../addresses");
7
+ const chain_1 = require("../chain");
8
+ const errors_1 = require("../errors");
9
+ const MarketUtils_1 = require("./MarketUtils");
10
+ class MarketConfig {
11
+ static get(id) {
12
+ const marketConfig = MarketConfig._CACHE[id];
13
+ if (!marketConfig)
14
+ throw new errors_1.UnknownMarketConfigError(id);
15
+ return marketConfig;
16
+ }
17
+ static async fetch(id, runner, chainId) {
18
+ let config = (0, errors_1._try)(() => MarketConfig.get(id), errors_1.UnknownMarketConfigError);
19
+ if (!config) {
20
+ chainId ?? (chainId = chain_1.ChainUtils.parseSupportedChainId((await runner.provider.getNetwork()).chainId));
21
+ const { morpho } = (0, addresses_1.getChainAddresses)(chainId);
22
+ config = new MarketConfig(
23
+ // Always fetch at latest block because config is immutable.
24
+ await ethers_types_1.MorphoBlue__factory.connect(morpho, runner).idToMarketParams(id));
25
+ }
26
+ return config;
27
+ }
28
+ static idle(token) {
29
+ return new MarketConfig({
30
+ collateralToken: ethers_1.ZeroAddress,
31
+ loanToken: token,
32
+ oracle: ethers_1.ZeroAddress,
33
+ irm: ethers_1.ZeroAddress,
34
+ lltv: 0n,
35
+ });
36
+ }
37
+ constructor({ collateralToken, loanToken, oracle, irm, lltv }) {
38
+ this.collateralToken = collateralToken;
39
+ this.loanToken = loanToken;
40
+ this.oracle = oracle;
41
+ this.irm = irm;
42
+ this.lltv = (0, ethers_1.toBigInt)(lltv);
43
+ MarketConfig._CACHE[this.id] = this;
44
+ }
45
+ /**
46
+ * The market's hex-encoded id, defined as the hash of the market's params.
47
+ */
48
+ get id() {
49
+ return MarketUtils_1.MarketUtils.getMarketId(this);
50
+ }
51
+ get liquidationIncentiveFactor() {
52
+ return MarketUtils_1.MarketUtils.getLiquidationIncentiveFactor(this);
53
+ }
54
+ }
55
+ exports.MarketConfig = MarketConfig;
56
+ MarketConfig._CACHE = {};
@@ -0,0 +1,165 @@
1
+ import { BigNumberish } from "ethers";
2
+ import { MarketParamsStruct } from "ethers-types/dist/protocols/morpho/blue/MorphoBlue";
3
+ import { RoundingDirection } from "../maths";
4
+ import { MarketId } from "../types";
5
+ export declare namespace MarketUtils {
6
+ function getMarketId(market: MarketParamsStruct): MarketId;
7
+ function getLiquidationIncentiveFactor({ lltv, }: {
8
+ lltv: BigNumberish;
9
+ }): bigint;
10
+ function getUtilization({ totalSupplyAssets, totalBorrowAssets, }: {
11
+ totalSupplyAssets: BigNumberish;
12
+ totalBorrowAssets: BigNumberish;
13
+ }): bigint;
14
+ function getSupplyRate(borrowRate: BigNumberish, { utilization, fee }: {
15
+ utilization: BigNumberish;
16
+ fee: BigNumberish;
17
+ }): bigint;
18
+ function getApy(rate: BigNumberish): bigint;
19
+ function getAccruedInterest(borrowRate: BigNumberish, { totalSupplyAssets, totalBorrowAssets, totalSupplyShares, fee, }: {
20
+ totalSupplyAssets: BigNumberish;
21
+ totalBorrowAssets: BigNumberish;
22
+ totalSupplyShares: BigNumberish;
23
+ fee: BigNumberish;
24
+ }, elapsed?: bigint): {
25
+ interest: bigint;
26
+ feeShares: bigint;
27
+ };
28
+ function getLiquidityToUtilization({ totalSupplyAssets, totalBorrowAssets, }: {
29
+ totalSupplyAssets: BigNumberish;
30
+ totalBorrowAssets: BigNumberish;
31
+ }, utilization: BigNumberish): bigint;
32
+ function getCollateralPower(collateral: BigNumberish, { lltv }: {
33
+ lltv: BigNumberish;
34
+ }): bigint;
35
+ function getCollateralValue(collateral: BigNumberish, { price }: {
36
+ price: BigNumberish;
37
+ }): bigint;
38
+ function getMaxBorrowAssets(collateral: BigNumberish, market: {
39
+ price: BigNumberish;
40
+ }, { lltv }: {
41
+ lltv: BigNumberish;
42
+ }): bigint;
43
+ function getMaxBorrowableAssets({ collateral, borrowShares, }: {
44
+ collateral: BigNumberish;
45
+ borrowShares: BigNumberish;
46
+ }, market: {
47
+ totalBorrowAssets: BigNumberish;
48
+ totalBorrowShares: BigNumberish;
49
+ price: BigNumberish;
50
+ }, marketConfig: {
51
+ lltv: BigNumberish;
52
+ }): bigint;
53
+ function getLiquidationSeizedAssets(repaidShares: BigNumberish, market: {
54
+ totalBorrowAssets: BigNumberish;
55
+ totalBorrowShares: BigNumberish;
56
+ price: BigNumberish;
57
+ }, config: {
58
+ lltv: BigNumberish;
59
+ }): bigint;
60
+ function getLiquidationRepaidShares(seizedAssets: BigNumberish, market: {
61
+ totalBorrowAssets: BigNumberish;
62
+ totalBorrowShares: BigNumberish;
63
+ price: BigNumberish;
64
+ }, config: {
65
+ lltv: BigNumberish;
66
+ }): bigint;
67
+ function getSeizableCollateral(position: {
68
+ collateral: BigNumberish;
69
+ borrowShares: BigNumberish;
70
+ }, market: {
71
+ totalBorrowAssets: BigNumberish;
72
+ totalBorrowShares: BigNumberish;
73
+ price: BigNumberish;
74
+ }, config: {
75
+ lltv: BigNumberish;
76
+ }): bigint;
77
+ function getWithdrawableCollateral({ collateral, borrowShares, }: {
78
+ collateral: BigNumberish;
79
+ borrowShares: BigNumberish;
80
+ }, market: {
81
+ totalBorrowAssets: BigNumberish;
82
+ totalBorrowShares: BigNumberish;
83
+ price: BigNumberish;
84
+ }, { lltv }: {
85
+ lltv: BigNumberish;
86
+ }): bigint;
87
+ function isHealthy({ collateral, borrowShares, }: {
88
+ collateral: BigNumberish;
89
+ borrowShares: BigNumberish;
90
+ }, market: {
91
+ totalBorrowAssets: BigNumberish;
92
+ totalBorrowShares: BigNumberish;
93
+ price: BigNumberish;
94
+ }, marketConfig: {
95
+ lltv: BigNumberish;
96
+ }): boolean;
97
+ /**
98
+ * Returns the price of the collateral quoted in the loan token (e.g. ETH/DAI)
99
+ * that set the user's position to be liquidatable.
100
+ * Returns null if the user is not a borrower
101
+ */
102
+ function getLiquidationPrice({ collateral, borrowShares, }: {
103
+ collateral: BigNumberish;
104
+ borrowShares: BigNumberish;
105
+ }, market: {
106
+ totalBorrowAssets: BigNumberish;
107
+ totalBorrowShares: BigNumberish;
108
+ }, marketConfig: {
109
+ lltv: BigNumberish;
110
+ }): bigint | null;
111
+ function getPriceVariationToLiquidation(position: {
112
+ collateral: BigNumberish;
113
+ borrowShares: BigNumberish;
114
+ }, market: {
115
+ totalBorrowAssets: BigNumberish;
116
+ totalBorrowShares: BigNumberish;
117
+ price: BigNumberish;
118
+ }, marketConfig: {
119
+ lltv: BigNumberish;
120
+ }): bigint | null;
121
+ function getHealthFactor({ collateral, borrowShares, }: {
122
+ collateral: BigNumberish;
123
+ borrowShares: BigNumberish;
124
+ }, market: {
125
+ totalBorrowAssets: BigNumberish;
126
+ totalBorrowShares: BigNumberish;
127
+ price: BigNumberish;
128
+ }, marketConfig: {
129
+ lltv: BigNumberish;
130
+ }): bigint | null;
131
+ function getLtv({ collateral, borrowShares, }: {
132
+ collateral: BigNumberish;
133
+ borrowShares: BigNumberish;
134
+ }, market: {
135
+ totalBorrowAssets: BigNumberish;
136
+ totalBorrowShares: BigNumberish;
137
+ price: BigNumberish;
138
+ }): bigint | null;
139
+ function getBorrowCapacityUsage(position: {
140
+ collateral: BigNumberish;
141
+ borrowShares: BigNumberish;
142
+ }, market: {
143
+ totalBorrowAssets: BigNumberish;
144
+ totalBorrowShares: BigNumberish;
145
+ price: BigNumberish;
146
+ }, marketConfig: {
147
+ lltv: BigNumberish;
148
+ }): bigint | null;
149
+ function toSupplyAssets(shares: BigNumberish, market: {
150
+ totalSupplyAssets: BigNumberish;
151
+ totalSupplyShares: BigNumberish;
152
+ }, rounding?: RoundingDirection): bigint;
153
+ function toSupplyShares(assets: BigNumberish, market: {
154
+ totalSupplyAssets: BigNumberish;
155
+ totalSupplyShares: BigNumberish;
156
+ }, rounding?: RoundingDirection): bigint;
157
+ function toBorrowAssets(shares: BigNumberish, market: {
158
+ totalBorrowAssets: BigNumberish;
159
+ totalBorrowShares: BigNumberish;
160
+ }, rounding?: RoundingDirection): bigint;
161
+ function toBorrowShares(assets: BigNumberish, market: {
162
+ totalBorrowAssets: BigNumberish;
163
+ totalBorrowShares: BigNumberish;
164
+ }, rounding?: RoundingDirection): bigint;
165
+ }
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarketUtils = void 0;
4
+ const ethers_1 = require("ethers");
5
+ const constants_1 = require("../constants");
6
+ const maths_1 = require("../maths");
7
+ var MarketUtils;
8
+ (function (MarketUtils) {
9
+ function getMarketId(market) {
10
+ const encodedMarket = ethers_1.AbiCoder.defaultAbiCoder().encode(["address", "address", "address", "address", "uint256"], [
11
+ market.loanToken,
12
+ market.collateralToken,
13
+ market.oracle,
14
+ market.irm,
15
+ market.lltv,
16
+ ]);
17
+ return (0, ethers_1.keccak256)(encodedMarket);
18
+ }
19
+ MarketUtils.getMarketId = getMarketId;
20
+ function getLiquidationIncentiveFactor({ lltv, }) {
21
+ return maths_1.MathLib.min(constants_1.MAX_LIQUIDATION_INCENTIVE_FACTOR, maths_1.MathLib.wDivDown(maths_1.MathLib.WAD, maths_1.MathLib.WAD -
22
+ maths_1.MathLib.wMulDown(constants_1.LIQUIDATION_CURSOR, maths_1.MathLib.WAD - (0, ethers_1.toBigInt)(lltv))));
23
+ }
24
+ MarketUtils.getLiquidationIncentiveFactor = getLiquidationIncentiveFactor;
25
+ function getUtilization({ totalSupplyAssets, totalBorrowAssets, }) {
26
+ totalSupplyAssets = (0, ethers_1.toBigInt)(totalSupplyAssets);
27
+ if (totalSupplyAssets === 0n)
28
+ return 0n;
29
+ return maths_1.MathLib.wDivDown(totalBorrowAssets, totalSupplyAssets);
30
+ }
31
+ MarketUtils.getUtilization = getUtilization;
32
+ function getSupplyRate(borrowRate, { utilization, fee }) {
33
+ const borrowRateWithoutFees = maths_1.MathLib.wMulUp(borrowRate, utilization);
34
+ return maths_1.MathLib.wMulUp(borrowRateWithoutFees, maths_1.MathLib.WAD - (0, ethers_1.toBigInt)(fee));
35
+ }
36
+ MarketUtils.getSupplyRate = getSupplyRate;
37
+ function getApy(rate) {
38
+ return maths_1.MathLib.wTaylorCompounded(rate, constants_1.SECONDS_PER_YEAR);
39
+ }
40
+ MarketUtils.getApy = getApy;
41
+ function getAccruedInterest(borrowRate, { totalSupplyAssets, totalBorrowAssets, totalSupplyShares, fee, }, elapsed = 0n) {
42
+ const interest = maths_1.MathLib.wMulDown(totalBorrowAssets, maths_1.MathLib.wTaylorCompounded(borrowRate, elapsed));
43
+ const feeAmount = maths_1.MathLib.wMulDown(interest, fee);
44
+ const feeShares = toSupplyShares(feeAmount, {
45
+ totalSupplyAssets: (0, ethers_1.toBigInt)(totalSupplyAssets) - feeAmount,
46
+ totalSupplyShares,
47
+ }, "Down");
48
+ return { interest, feeShares };
49
+ }
50
+ MarketUtils.getAccruedInterest = getAccruedInterest;
51
+ function getLiquidityToUtilization({ totalSupplyAssets, totalBorrowAssets, }, utilization) {
52
+ utilization = (0, ethers_1.toBigInt)(utilization);
53
+ totalSupplyAssets = (0, ethers_1.toBigInt)(totalSupplyAssets);
54
+ totalBorrowAssets = (0, ethers_1.toBigInt)(totalBorrowAssets);
55
+ if (utilization === 0n) {
56
+ if (totalBorrowAssets === 0n)
57
+ return totalSupplyAssets;
58
+ return 0n;
59
+ }
60
+ return maths_1.MathUtils.zeroFloorSub(totalSupplyAssets, maths_1.MathLib.wDivUp(totalBorrowAssets, utilization));
61
+ }
62
+ MarketUtils.getLiquidityToUtilization = getLiquidityToUtilization;
63
+ function getCollateralPower(collateral, { lltv }) {
64
+ return maths_1.MathLib.wMulDown(collateral, lltv);
65
+ }
66
+ MarketUtils.getCollateralPower = getCollateralPower;
67
+ function getCollateralValue(collateral, { price }) {
68
+ return maths_1.MathLib.mulDivDown(collateral, price, constants_1.ORACLE_PRICE_SCALE);
69
+ }
70
+ MarketUtils.getCollateralValue = getCollateralValue;
71
+ function getMaxBorrowAssets(collateral, market, { lltv }) {
72
+ return maths_1.MathLib.wMulDown(getCollateralValue(collateral, market), lltv);
73
+ }
74
+ MarketUtils.getMaxBorrowAssets = getMaxBorrowAssets;
75
+ function getMaxBorrowableAssets({ collateral, borrowShares, }, market, marketConfig) {
76
+ return maths_1.MathUtils.zeroFloorSub(getMaxBorrowAssets(collateral, market, marketConfig), toBorrowAssets(borrowShares, market));
77
+ }
78
+ MarketUtils.getMaxBorrowableAssets = getMaxBorrowableAssets;
79
+ function getLiquidationSeizedAssets(repaidShares, market, config) {
80
+ market.price = (0, ethers_1.toBigInt)(market.price);
81
+ if (market.price === 0n)
82
+ return 0n;
83
+ return maths_1.MathLib.mulDivDown(maths_1.MathLib.wMulDown(toBorrowAssets(repaidShares, market, "Down"), getLiquidationIncentiveFactor(config)), constants_1.ORACLE_PRICE_SCALE, market.price);
84
+ }
85
+ MarketUtils.getLiquidationSeizedAssets = getLiquidationSeizedAssets;
86
+ function getLiquidationRepaidShares(seizedAssets, market, config) {
87
+ return toBorrowShares(maths_1.MathLib.wDivUp(maths_1.MathLib.mulDivUp(seizedAssets, market.price, constants_1.ORACLE_PRICE_SCALE), getLiquidationIncentiveFactor(config)), market, "Up");
88
+ }
89
+ MarketUtils.getLiquidationRepaidShares = getLiquidationRepaidShares;
90
+ function getSeizableCollateral(position, market, config) {
91
+ market.price = (0, ethers_1.toBigInt)(market.price);
92
+ if (market.price === 0n || isHealthy(position, market, config))
93
+ return 0n;
94
+ return maths_1.MathLib.min(position.collateral, getLiquidationSeizedAssets(position.borrowShares, market, config));
95
+ }
96
+ MarketUtils.getSeizableCollateral = getSeizableCollateral;
97
+ function getWithdrawableCollateral({ collateral, borrowShares, }, market, { lltv }) {
98
+ market.price = (0, ethers_1.toBigInt)(market.price);
99
+ if (market.price === 0n)
100
+ return 0n;
101
+ return maths_1.MathUtils.zeroFloorSub((0, ethers_1.toBigInt)(collateral), maths_1.MathLib.wDivUp(maths_1.MathLib.mulDivUp(toBorrowAssets(borrowShares, market), constants_1.ORACLE_PRICE_SCALE, market.price), lltv));
102
+ }
103
+ MarketUtils.getWithdrawableCollateral = getWithdrawableCollateral;
104
+ function isHealthy({ collateral, borrowShares, }, market, marketConfig) {
105
+ return (getMaxBorrowAssets(collateral, market, marketConfig) >=
106
+ toBorrowAssets(borrowShares, market));
107
+ }
108
+ MarketUtils.isHealthy = isHealthy;
109
+ /**
110
+ * Returns the price of the collateral quoted in the loan token (e.g. ETH/DAI)
111
+ * that set the user's position to be liquidatable.
112
+ * Returns null if the user is not a borrower
113
+ */
114
+ function getLiquidationPrice({ collateral, borrowShares, }, market, marketConfig) {
115
+ borrowShares = (0, ethers_1.toBigInt)(borrowShares);
116
+ market.totalBorrowShares = (0, ethers_1.toBigInt)(market.totalBorrowShares);
117
+ if (borrowShares === 0n || market.totalBorrowShares === 0n)
118
+ return null;
119
+ const collateralPower = getCollateralPower(collateral, marketConfig);
120
+ if (collateralPower === 0n)
121
+ return ethers_1.MaxUint256;
122
+ const borrowAssets = toBorrowAssets(borrowShares, market);
123
+ return maths_1.MathLib.mulDivUp(borrowAssets, constants_1.ORACLE_PRICE_SCALE, collateralPower);
124
+ }
125
+ MarketUtils.getLiquidationPrice = getLiquidationPrice;
126
+ function getPriceVariationToLiquidation(position, market, marketConfig) {
127
+ market.price = (0, ethers_1.toBigInt)(market.price);
128
+ const liquidationPrice = getLiquidationPrice(position, market, marketConfig);
129
+ if (market.price === 0n || liquidationPrice == null)
130
+ return null;
131
+ return maths_1.MathLib.WAD - maths_1.MathLib.wDivUp(liquidationPrice, market.price);
132
+ }
133
+ MarketUtils.getPriceVariationToLiquidation = getPriceVariationToLiquidation;
134
+ function getHealthFactor({ collateral, borrowShares, }, market, marketConfig) {
135
+ borrowShares = (0, ethers_1.toBigInt)(borrowShares);
136
+ market.totalBorrowShares = (0, ethers_1.toBigInt)(market.totalBorrowShares);
137
+ if (borrowShares === 0n || market.totalBorrowShares === 0n)
138
+ return null;
139
+ const borrowAssets = toBorrowAssets(borrowShares, market);
140
+ if (borrowAssets === 0n)
141
+ return ethers_1.MaxUint256;
142
+ const maxBorrowAssets = getMaxBorrowAssets(collateral, market, marketConfig);
143
+ return maths_1.MathLib.wDivDown(maxBorrowAssets, borrowAssets);
144
+ }
145
+ MarketUtils.getHealthFactor = getHealthFactor;
146
+ function getLtv({ collateral, borrowShares, }, market) {
147
+ borrowShares = (0, ethers_1.toBigInt)(borrowShares);
148
+ market.totalBorrowShares = (0, ethers_1.toBigInt)(market.totalBorrowShares);
149
+ if (borrowShares === 0n || market.totalBorrowShares === 0n)
150
+ return null;
151
+ const collateralValue = getCollateralValue(collateral, market);
152
+ if (collateralValue === 0n)
153
+ return ethers_1.MaxUint256;
154
+ return maths_1.MathLib.wDivUp(toBorrowAssets(borrowShares, market), collateralValue);
155
+ }
156
+ MarketUtils.getLtv = getLtv;
157
+ function getBorrowCapacityUsage(position, market, marketConfig) {
158
+ const hf = getHealthFactor(position, market, marketConfig);
159
+ if (hf === null)
160
+ return null;
161
+ if (hf === 0n)
162
+ return ethers_1.MaxUint256;
163
+ return maths_1.MathLib.wDivUp(maths_1.MathLib.WAD, hf);
164
+ }
165
+ MarketUtils.getBorrowCapacityUsage = getBorrowCapacityUsage;
166
+ function toSupplyAssets(shares, market, rounding = "Down") {
167
+ return maths_1.SharesMath.toAssets(shares, market.totalSupplyAssets, market.totalSupplyShares, rounding);
168
+ }
169
+ MarketUtils.toSupplyAssets = toSupplyAssets;
170
+ function toSupplyShares(assets, market, rounding = "Up") {
171
+ return maths_1.SharesMath.toShares(assets, market.totalSupplyAssets, market.totalSupplyShares, rounding);
172
+ }
173
+ MarketUtils.toSupplyShares = toSupplyShares;
174
+ function toBorrowAssets(shares, market, rounding = "Up") {
175
+ return maths_1.SharesMath.toAssets(shares, market.totalBorrowAssets, market.totalBorrowShares, rounding);
176
+ }
177
+ MarketUtils.toBorrowAssets = toBorrowAssets;
178
+ function toBorrowShares(assets, market, rounding = "Down") {
179
+ return maths_1.SharesMath.toShares(assets, market.totalBorrowAssets, market.totalBorrowShares, rounding);
180
+ }
181
+ MarketUtils.toBorrowShares = toBorrowShares;
182
+ })(MarketUtils || (exports.MarketUtils = MarketUtils = {}));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ethers_1 = require("ethers");
4
+ const MarketUtils_1 = require("./MarketUtils");
5
+ const market = {
6
+ loanToken: "0x0000000000000000000000000000000000000001",
7
+ collateralToken: "0x0000000000000000000000000000000000000002",
8
+ oracle: "0x0000000000000000000000000000000000000003",
9
+ irm: "0x0000000000000000000000000000000000000004",
10
+ lltv: (0, ethers_1.parseEther)("0.86"),
11
+ };
12
+ describe("MarketUtils", () => {
13
+ it("should calculate the correct market id", () => {
14
+ expect(MarketUtils_1.MarketUtils.getMarketId(market)).toEqual("0x625e29dff74826b71c1f4c74b208a896109cc8ac9910192ce2927a982b0809e6");
15
+ });
16
+ it("should calculate the correct liquidation incentive factor", () => {
17
+ expect(MarketUtils_1.MarketUtils.getLiquidationIncentiveFactor(market)).toEqual(1043841336116910229n);
18
+ });
19
+ });
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./MarketUtils"), exports);
18
+ __exportStar(require("./MarketConfig"), exports);
19
+ __exportStar(require("./Market"), exports);
@@ -0,0 +1,37 @@
1
+ /**
2
+ * JS implementation of {@link https://github.com/morpho-org/morpho-blue-irm/blob/main/src/libraries/adaptive-curve/ExpLib.sol ExpLib} used by the Adaptive Curve IRM.
3
+ */
4
+ export declare namespace AdaptiveCurveIrmLib {
5
+ const CURVE_STEEPNESS: bigint;
6
+ const TARGET_UTILIZATION: bigint;
7
+ const INITIAL_RATE_AT_TARGET: bigint;
8
+ const ADJUSTMENT_SPEED: bigint;
9
+ const MIN_RATE_AT_TARGET: bigint;
10
+ const MAX_RATE_AT_TARGET: bigint;
11
+ /**
12
+ * ln(2), scaled by WAD.
13
+ */
14
+ const LN_2_INT = 693147180559945309n;
15
+ /**
16
+ * ln(1e-18), scaled by WAD.
17
+ */
18
+ const LN_WEI_INT = -41446531673892822312n;
19
+ /**
20
+ * Above this bound, `wExp` is clipped to avoid overflowing when multiplied with 1 ether.
21
+ * This upper bound corresponds to: ln(type(int256).max / 1e36) (scaled by WAD, floored).
22
+ */
23
+ const WEXP_UPPER_BOUND = 93859467695000404319n;
24
+ /**
25
+ * The value of wExp(`WEXP_UPPER_BOUND`).
26
+ */
27
+ const WEXP_UPPER_VALUE = 57716089161558943949701069502944508345128422502756744429568n;
28
+ /**
29
+ * Returns an approximation of exp(x) used by the Adaptive Curve IRM.
30
+ * @param x
31
+ */
32
+ function wExp(x: bigint): bigint;
33
+ function getBorrowRate(startUtilization: bigint, startRateAtTarget: bigint, elapsed: bigint): {
34
+ avgBorrowRate: bigint;
35
+ endRateAtTarget: bigint;
36
+ };
37
+ }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AdaptiveCurveIrmLib = void 0;
4
+ const ethers_1 = require("ethers");
5
+ const constants_1 = require("../constants");
6
+ const MathLib_1 = require("./MathLib");
7
+ /**
8
+ * JS implementation of {@link https://github.com/morpho-org/morpho-blue-irm/blob/main/src/libraries/adaptive-curve/ExpLib.sol ExpLib} used by the Adaptive Curve IRM.
9
+ */
10
+ var AdaptiveCurveIrmLib;
11
+ (function (AdaptiveCurveIrmLib) {
12
+ AdaptiveCurveIrmLib.CURVE_STEEPNESS = (0, ethers_1.parseUnits)("4");
13
+ AdaptiveCurveIrmLib.TARGET_UTILIZATION = (0, ethers_1.parseUnits)("0.9");
14
+ AdaptiveCurveIrmLib.INITIAL_RATE_AT_TARGET = (0, ethers_1.parseUnits)("0.04") / constants_1.SECONDS_PER_YEAR;
15
+ AdaptiveCurveIrmLib.ADJUSTMENT_SPEED = (0, ethers_1.parseUnits)("50") / constants_1.SECONDS_PER_YEAR;
16
+ AdaptiveCurveIrmLib.MIN_RATE_AT_TARGET = (0, ethers_1.parseUnits)("0.001") / constants_1.SECONDS_PER_YEAR;
17
+ AdaptiveCurveIrmLib.MAX_RATE_AT_TARGET = (0, ethers_1.parseUnits)("2") / constants_1.SECONDS_PER_YEAR;
18
+ /**
19
+ * ln(2), scaled by WAD.
20
+ */
21
+ AdaptiveCurveIrmLib.LN_2_INT = 693147180559945309n;
22
+ /**
23
+ * ln(1e-18), scaled by WAD.
24
+ */
25
+ AdaptiveCurveIrmLib.LN_WEI_INT = -41446531673892822312n;
26
+ /**
27
+ * Above this bound, `wExp` is clipped to avoid overflowing when multiplied with 1 ether.
28
+ * This upper bound corresponds to: ln(type(int256).max / 1e36) (scaled by WAD, floored).
29
+ */
30
+ AdaptiveCurveIrmLib.WEXP_UPPER_BOUND = 93859467695000404319n;
31
+ /**
32
+ * The value of wExp(`WEXP_UPPER_BOUND`).
33
+ */
34
+ AdaptiveCurveIrmLib.WEXP_UPPER_VALUE = 57716089161558943949701069502944508345128422502756744429568n;
35
+ /**
36
+ * Returns an approximation of exp(x) used by the Adaptive Curve IRM.
37
+ * @param x
38
+ */
39
+ function wExp(x) {
40
+ // If x < ln(1e-18) then exp(x) < 1e-18 so it is rounded to zero.
41
+ if (x < AdaptiveCurveIrmLib.LN_WEI_INT)
42
+ return 0n;
43
+ // `wExp` is clipped to avoid overflowing when multiplied with 1 ether.
44
+ if (x >= AdaptiveCurveIrmLib.WEXP_UPPER_BOUND)
45
+ return AdaptiveCurveIrmLib.WEXP_UPPER_VALUE;
46
+ // Decompose x as x = q * ln(2) + r with q an integer and -ln(2)/2 <= r <= ln(2)/2.
47
+ // q = x / ln(2) rounded half toward zero.
48
+ const roundingAdjustment = x < 0n ? -(AdaptiveCurveIrmLib.LN_2_INT / 2n) : AdaptiveCurveIrmLib.LN_2_INT / 2n;
49
+ const q = (x + roundingAdjustment) / AdaptiveCurveIrmLib.LN_2_INT;
50
+ const r = x - q * AdaptiveCurveIrmLib.LN_2_INT;
51
+ // Compute e^r with a 2nd-order Taylor polynomial.
52
+ const expR = MathLib_1.MathLib.WAD + r + (r * r) / MathLib_1.MathLib.WAD / 2n;
53
+ // Return e^x = 2^q * e^r.
54
+ if (q === 0n)
55
+ return expR << q;
56
+ return expR >> -q;
57
+ }
58
+ AdaptiveCurveIrmLib.wExp = wExp;
59
+ function getBorrowRate(startUtilization, startRateAtTarget, elapsed) {
60
+ const errNormFactor = startUtilization > AdaptiveCurveIrmLib.TARGET_UTILIZATION
61
+ ? MathLib_1.MathLib.WAD - AdaptiveCurveIrmLib.TARGET_UTILIZATION
62
+ : AdaptiveCurveIrmLib.TARGET_UTILIZATION;
63
+ const err = MathLib_1.MathLib.wDivDown(startUtilization - AdaptiveCurveIrmLib.TARGET_UTILIZATION, errNormFactor);
64
+ let avgRateAtTarget;
65
+ let endRateAtTarget;
66
+ if (startRateAtTarget === 0n) {
67
+ // First interaction.
68
+ avgRateAtTarget = AdaptiveCurveIrmLib.INITIAL_RATE_AT_TARGET;
69
+ endRateAtTarget = AdaptiveCurveIrmLib.INITIAL_RATE_AT_TARGET;
70
+ }
71
+ else {
72
+ // The speed is assumed constant between two updates, but it is in fact not constant because of interest.
73
+ // So the rate is always underestimated.
74
+ const speed = MathLib_1.MathLib.wMulDown(AdaptiveCurveIrmLib.ADJUSTMENT_SPEED, err);
75
+ const linearAdaptation = speed * elapsed;
76
+ if (linearAdaptation === 0n) {
77
+ // If linearAdaptation == 0, avgRateAtTarget = endRateAtTarget = startRateAtTarget;
78
+ avgRateAtTarget = startRateAtTarget;
79
+ endRateAtTarget = startRateAtTarget;
80
+ }
81
+ else {
82
+ // Non negative because MIN_RATE_AT_TARGET > 0.
83
+ const _newRateAtTarget = (linearAdaptation) => MathLib_1.MathLib.min(MathLib_1.MathLib.max(MathLib_1.MathLib.wMulDown(startRateAtTarget, wExp(linearAdaptation)), AdaptiveCurveIrmLib.MIN_RATE_AT_TARGET), AdaptiveCurveIrmLib.MAX_RATE_AT_TARGET);
84
+ // Formula of the average rate that should be returned to Morpho Blue:
85
+ // avg = 1/T * ∫_0^T curve(startRateAtTarget*exp(speed*x), err) dx
86
+ // The integral is approximated with the trapezoidal rule:
87
+ // avg ~= 1/T * Σ_i=1^N [curve(f((i-1) * T/N), err) + curve(f(i * T/N), err)] / 2 * T/N
88
+ // Where f(x) = startRateAtTarget*exp(speed*x)
89
+ // avg ~= Σ_i=1^N [curve(f((i-1) * T/N), err) + curve(f(i * T/N), err)] / (2 * N)
90
+ // As curve is linear in its first argument:
91
+ // avg ~= curve([Σ_i=1^N [f((i-1) * T/N) + f(i * T/N)] / (2 * N), err)
92
+ // avg ~= curve([(f(0) + f(T))/2 + Σ_i=1^(N-1) f(i * T/N)] / N, err)
93
+ // avg ~= curve([(startRateAtTarget + endRateAtTarget)/2 + Σ_i=1^(N-1) f(i * T/N)] / N, err)
94
+ // With N = 2:
95
+ // avg ~= curve([(startRateAtTarget + endRateAtTarget)/2 + startRateAtTarget*exp(speed*T/2)] / 2, err)
96
+ // avg ~= curve([startRateAtTarget + endRateAtTarget + 2*startRateAtTarget*exp(speed*T/2)] / 4, err)
97
+ endRateAtTarget = _newRateAtTarget(linearAdaptation);
98
+ avgRateAtTarget =
99
+ (startRateAtTarget +
100
+ endRateAtTarget +
101
+ 2n * _newRateAtTarget(linearAdaptation / 2n)) /
102
+ 4n;
103
+ }
104
+ }
105
+ // Non negative because 1 - 1/C >= 0, C - 1 >= 0.
106
+ const coeff = err < 0
107
+ ? MathLib_1.MathLib.WAD - MathLib_1.MathLib.wDivDown(MathLib_1.MathLib.WAD, AdaptiveCurveIrmLib.CURVE_STEEPNESS)
108
+ : AdaptiveCurveIrmLib.CURVE_STEEPNESS - MathLib_1.MathLib.WAD;
109
+ // Non negative if avgRateAtTarget >= 0 because if err < 0, coeff <= 1.
110
+ return {
111
+ avgBorrowRate: MathLib_1.MathLib.wMulDown(MathLib_1.MathLib.wMulDown(coeff, err) + MathLib_1.MathLib.WAD, avgRateAtTarget),
112
+ endRateAtTarget,
113
+ };
114
+ }
115
+ AdaptiveCurveIrmLib.getBorrowRate = getBorrowRate;
116
+ })(AdaptiveCurveIrmLib || (exports.AdaptiveCurveIrmLib = AdaptiveCurveIrmLib = {}));