@morpho-org/blue-sdk 3.0.3 → 3.0.5

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.
@@ -104,21 +104,63 @@ export declare class Market implements IMarket {
104
104
  /**
105
105
  * Returns the rate at which interest accrued for suppliers of this market,
106
106
  * since the last time the market was updated (scaled by WAD).
107
+ * @deprecated There's no such thing as a supply rate in Morpho. Only the supply APY is meaningful.
107
108
  */
108
109
  get supplyRate(): bigint;
109
110
  /**
110
- * Returns the rate at which interest accrued for borrowers of this market,
111
- * since the last time the market was updated (scaled by WAD).
111
+ * Returns the average rate at which interest _would_ accrue from `lastUpdate`
112
+ * till now, if `accrueInterest` was called immediately onchain (scaled by WAD).
113
+ * If `accrueInterest` was just called, the average rate equals the instantaneous rate,
114
+ * so it is equivalent to `getBorrowRate(lastUpdate)`.
115
+ *
116
+ * In most cases, `accrueInterest` will not be called immediately onchain, so the
117
+ * average rate doesn't correspond to anything "real".
118
+ *
119
+ * If interested in the instantaneous rate experienced by existing market actors at a specific timestamp,
120
+ * use `getBorrowRate(timestamp)`, `getBorrowApy(timestamp)`, or `getSupplyApy(timestamp)` instead.
112
121
  */
113
122
  get borrowRate(): bigint;
114
123
  /**
115
- * The market's supply-side Annual Percentage Yield (APY) (scaled by WAD).
124
+ * The market's current, instantaneous supply-side Annual Percentage Yield (APY) (scaled by WAD).
125
+ * If interested in the APY at a specific timestamp, use `getSupplyApy(timestamp)` instead.
116
126
  */
117
127
  get supplyApy(): bigint;
118
128
  /**
119
- * The market's borrow-side Annual Percentage Yield (APY) (scaled by WAD).
129
+ * The market's current, instantaneous borrow-side Annual Percentage Yield (APY) (scaled by WAD).
130
+ * If interested in the APY at a specific timestamp, use `getBorrowApy(timestamp)` instead.
120
131
  */
121
132
  get borrowApy(): bigint;
133
+ /**
134
+ * Returns the instantaneous rate at which interest accrues for borrowers of this market,
135
+ * at the given timestamp, if the state remains unchanged (not accrued) (scaled by WAD).
136
+ * It is fundamentally different from the rate at which interest is paid by borrowers to lenders in the case of an interest accrual,
137
+ * as in the case of the AdaptiveCurveIRM, the (approximated) average rate since the last update is used instead.
138
+ * @param timestamp The timestamp at which to calculate the borrow rate. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow rate).
139
+ */
140
+ getBorrowRate(timestamp?: BigIntish): bigint;
141
+ /**
142
+ * Returns the rate at which interest accrues for borrowers of this market,
143
+ * at the given timestamp, if the state remains unchanged (not accrued) (scaled by WAD).
144
+ * @param timestamp The timestamp at which to calculate the accrual borrow rate. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow rate).
145
+ */
146
+ protected getAccrualBorrowRate(timestamp?: BigIntish): {
147
+ elapsed: bigint;
148
+ avgBorrowRate: bigint;
149
+ endBorrowRate: bigint;
150
+ endRateAtTarget?: bigint;
151
+ };
152
+ /**
153
+ * The market's instantaneous borrow-side Annual Percentage Yield (APY) at the given timestamp,
154
+ * if the state remains unchanged (not accrued) (scaled by WAD).
155
+ * @param timestamp The timestamp at which to calculate the borrow APY. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow APY).
156
+ */
157
+ getBorrowApy(timestamp?: BigIntish): bigint;
158
+ /**
159
+ * The market's instantaneous supply-side Annual Percentage Yield (APY) at the given timestamp,
160
+ * if the state remains unchanged (not accrued) (scaled by WAD).
161
+ * @param timestamp The timestamp at which to calculate the supply APY. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current supply APY).
162
+ */
163
+ getSupplyApy(timestamp?: BigIntish): bigint;
122
164
  /**
123
165
  * Returns a new market derived from this market, whose interest has been accrued up to the given timestamp.
124
166
  * @param timestamp The timestamp at which to accrue interest. Must be greater than or equal to `lastUpdate`. Defaults to `lastUpdate` (returns a copy of the market).
@@ -103,57 +103,111 @@ class Market {
103
103
  /**
104
104
  * Returns the rate at which interest accrued for suppliers of this market,
105
105
  * since the last time the market was updated (scaled by WAD).
106
+ * @deprecated There's no such thing as a supply rate in Morpho. Only the supply APY is meaningful.
106
107
  */
107
108
  get supplyRate() {
108
109
  return MarketUtils_js_1.MarketUtils.getSupplyRate(this.borrowRate, this);
109
110
  }
110
111
  /**
111
- * Returns the rate at which interest accrued for borrowers of this market,
112
- * since the last time the market was updated (scaled by WAD).
112
+ * Returns the average rate at which interest _would_ accrue from `lastUpdate`
113
+ * till now, if `accrueInterest` was called immediately onchain (scaled by WAD).
114
+ * If `accrueInterest` was just called, the average rate equals the instantaneous rate,
115
+ * so it is equivalent to `getBorrowRate(lastUpdate)`.
116
+ *
117
+ * In most cases, `accrueInterest` will not be called immediately onchain, so the
118
+ * average rate doesn't correspond to anything "real".
119
+ *
120
+ * If interested in the instantaneous rate experienced by existing market actors at a specific timestamp,
121
+ * use `getBorrowRate(timestamp)`, `getBorrowApy(timestamp)`, or `getSupplyApy(timestamp)` instead.
113
122
  */
114
123
  get borrowRate() {
115
- if (this.rateAtTarget == null)
116
- return 0n;
117
- return index_js_1.AdaptiveCurveIrmLib.getBorrowRate(this.utilization, this.rateAtTarget, 0n).avgBorrowRate;
124
+ return this.getAccrualBorrowRate().avgBorrowRate;
118
125
  }
119
126
  /**
120
- * The market's supply-side Annual Percentage Yield (APY) (scaled by WAD).
127
+ * The market's current, instantaneous supply-side Annual Percentage Yield (APY) (scaled by WAD).
128
+ * If interested in the APY at a specific timestamp, use `getSupplyApy(timestamp)` instead.
121
129
  */
122
130
  get supplyApy() {
123
- return MarketUtils_js_1.MarketUtils.compoundRate(this.supplyRate);
131
+ return this.getSupplyApy();
124
132
  }
125
133
  /**
126
- * The market's borrow-side Annual Percentage Yield (APY) (scaled by WAD).
134
+ * The market's current, instantaneous borrow-side Annual Percentage Yield (APY) (scaled by WAD).
135
+ * If interested in the APY at a specific timestamp, use `getBorrowApy(timestamp)` instead.
127
136
  */
128
137
  get borrowApy() {
129
- return MarketUtils_js_1.MarketUtils.compoundRate(this.borrowRate);
138
+ return this.getBorrowApy();
130
139
  }
131
140
  /**
132
- * Returns a new market derived from this market, whose interest has been accrued up to the given timestamp.
133
- * @param timestamp The timestamp at which to accrue interest. Must be greater than or equal to `lastUpdate`. Defaults to `lastUpdate` (returns a copy of the market).
141
+ * Returns the instantaneous rate at which interest accrues for borrowers of this market,
142
+ * at the given timestamp, if the state remains unchanged (not accrued) (scaled by WAD).
143
+ * It is fundamentally different from the rate at which interest is paid by borrowers to lenders in the case of an interest accrual,
144
+ * as in the case of the AdaptiveCurveIRM, the (approximated) average rate since the last update is used instead.
145
+ * @param timestamp The timestamp at which to calculate the borrow rate. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow rate).
134
146
  */
135
- accrueInterest(timestamp = this.lastUpdate) {
147
+ getBorrowRate(timestamp = morpho_ts_1.Time.timestamp()) {
148
+ if (this.rateAtTarget == null)
149
+ return 0n;
136
150
  timestamp = BigInt(timestamp);
137
151
  const elapsed = timestamp - this.lastUpdate;
138
152
  if (elapsed < 0n)
139
153
  throw new errors_js_1.BlueErrors.InvalidInterestAccrual(this.id, timestamp, this.lastUpdate);
140
- if (elapsed === 0n)
141
- return new Market(this);
142
- let borrowRate = 0n;
143
- let { rateAtTarget } = this;
144
- if (rateAtTarget != null) {
145
- const { avgBorrowRate, endRateAtTarget } = index_js_1.AdaptiveCurveIrmLib.getBorrowRate(this.utilization, rateAtTarget, elapsed);
146
- borrowRate = avgBorrowRate;
147
- rateAtTarget = endRateAtTarget;
148
- }
149
- const { interest, feeShares } = MarketUtils_js_1.MarketUtils.getAccruedInterest(borrowRate, this, elapsed);
154
+ const { endBorrowRate } = index_js_1.AdaptiveCurveIrmLib.getBorrowRate(this.utilization, this.rateAtTarget, elapsed);
155
+ return endBorrowRate;
156
+ }
157
+ /**
158
+ * Returns the rate at which interest accrues for borrowers of this market,
159
+ * at the given timestamp, if the state remains unchanged (not accrued) (scaled by WAD).
160
+ * @param timestamp The timestamp at which to calculate the accrual borrow rate. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow rate).
161
+ */
162
+ getAccrualBorrowRate(timestamp = morpho_ts_1.Time.timestamp()) {
163
+ timestamp = BigInt(timestamp);
164
+ const elapsed = timestamp - this.lastUpdate;
165
+ if (elapsed < 0n)
166
+ throw new errors_js_1.BlueErrors.InvalidInterestAccrual(this.id, timestamp, this.lastUpdate);
167
+ if (this.rateAtTarget == null)
168
+ return {
169
+ elapsed,
170
+ avgBorrowRate: 0n,
171
+ endBorrowRate: 0n,
172
+ };
173
+ return {
174
+ elapsed,
175
+ ...index_js_1.AdaptiveCurveIrmLib.getBorrowRate(this.utilization, this.rateAtTarget, elapsed),
176
+ };
177
+ }
178
+ /**
179
+ * The market's instantaneous borrow-side Annual Percentage Yield (APY) at the given timestamp,
180
+ * if the state remains unchanged (not accrued) (scaled by WAD).
181
+ * @param timestamp The timestamp at which to calculate the borrow APY. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current borrow APY).
182
+ */
183
+ getBorrowApy(timestamp = morpho_ts_1.Time.timestamp()) {
184
+ const borrowRate = this.getBorrowRate(timestamp);
185
+ return MarketUtils_js_1.MarketUtils.compoundRate(borrowRate);
186
+ }
187
+ /**
188
+ * The market's instantaneous supply-side Annual Percentage Yield (APY) at the given timestamp,
189
+ * if the state remains unchanged (not accrued) (scaled by WAD).
190
+ * @param timestamp The timestamp at which to calculate the supply APY. Must be greater than or equal to `lastUpdate`. Defaults to `Time.timestamp()` (returns the current supply APY).
191
+ */
192
+ getSupplyApy(timestamp = morpho_ts_1.Time.timestamp()) {
193
+ const borrowApy = this.getBorrowApy(timestamp);
194
+ return index_js_1.MathLib.wMulUp(index_js_1.MathLib.wMulDown(borrowApy, this.utilization), index_js_1.MathLib.WAD - this.fee);
195
+ }
196
+ /**
197
+ * Returns a new market derived from this market, whose interest has been accrued up to the given timestamp.
198
+ * @param timestamp The timestamp at which to accrue interest. Must be greater than or equal to `lastUpdate`. Defaults to `lastUpdate` (returns a copy of the market).
199
+ */
200
+ accrueInterest(timestamp = this.lastUpdate) {
201
+ timestamp = BigInt(timestamp);
202
+ const { elapsed, avgBorrowRate, endRateAtTarget } = this.getAccrualBorrowRate(timestamp);
203
+ const { interest, feeShares } = MarketUtils_js_1.MarketUtils.getAccruedInterest(avgBorrowRate, this, elapsed);
150
204
  return new Market({
151
205
  ...this,
152
206
  totalSupplyAssets: this.totalSupplyAssets + interest,
153
207
  totalBorrowAssets: this.totalBorrowAssets + interest,
154
208
  totalSupplyShares: this.totalSupplyShares + feeShares,
155
209
  lastUpdate: timestamp,
156
- rateAtTarget,
210
+ rateAtTarget: endRateAtTarget,
157
211
  });
158
212
  }
159
213
  supply(assets, shares, timestamp) {
@@ -30,6 +30,7 @@ export declare namespace MarketUtils {
30
30
  * since the last time the market was updated (scaled by WAD).
31
31
  * @param borrowRate The average borrow rate since the last market update (scaled by WAD).
32
32
  * @param market The market state.
33
+ * @deprecated There's no such thing as a supply rate in Morpho. Only the supply APY is meaningful.
33
34
  */
34
35
  function getSupplyRate(borrowRate: BigIntish, { utilization, fee }: {
35
36
  utilization: BigIntish;
@@ -54,6 +54,7 @@ var MarketUtils;
54
54
  * since the last time the market was updated (scaled by WAD).
55
55
  * @param borrowRate The average borrow rate since the last market update (scaled by WAD).
56
56
  * @param market The market state.
57
+ * @deprecated There's no such thing as a supply rate in Morpho. Only the supply APY is meaningful.
57
58
  */
58
59
  function getSupplyRate(borrowRate, { utilization, fee }) {
59
60
  const borrowRateWithoutFees = index_js_1.MathLib.wMulUp(borrowRate, utilization);
@@ -33,6 +33,7 @@ export declare namespace AdaptiveCurveIrmLib {
33
33
  function wExp(x: BigIntish): bigint;
34
34
  function getBorrowRate(startUtilization: BigIntish, startRateAtTarget: BigIntish, elapsed: BigIntish): {
35
35
  avgBorrowRate: bigint;
36
+ endBorrowRate: bigint;
36
37
  endRateAtTarget: bigint;
37
38
  };
38
39
  function getUtilizationAtBorrowRate(borrowRate: BigIntish, rateAtTarget: BigIntish): bigint;
@@ -109,9 +109,11 @@ var AdaptiveCurveIrmLib;
109
109
  const coeff = err < 0
110
110
  ? MathLib_js_1.MathLib.WAD - MathLib_js_1.MathLib.wDivDown(MathLib_js_1.MathLib.WAD, AdaptiveCurveIrmLib.CURVE_STEEPNESS)
111
111
  : AdaptiveCurveIrmLib.CURVE_STEEPNESS - MathLib_js_1.MathLib.WAD;
112
+ const _curve = (rateAtTarget) => MathLib_js_1.MathLib.wMulDown(MathLib_js_1.MathLib.wMulDown(coeff, err) + MathLib_js_1.MathLib.WAD, rateAtTarget);
112
113
  // Non negative if avgRateAtTarget >= 0 because if err < 0, coeff <= 1.
113
114
  return {
114
- avgBorrowRate: MathLib_js_1.MathLib.wMulDown(MathLib_js_1.MathLib.wMulDown(coeff, err) + MathLib_js_1.MathLib.WAD, avgRateAtTarget),
115
+ avgBorrowRate: _curve(avgRateAtTarget),
116
+ endBorrowRate: _curve(endRateAtTarget),
115
117
  endRateAtTarget,
116
118
  };
117
119
  }
@@ -148,13 +148,29 @@ export declare class AccrualVault extends Vault implements IAccrualVault {
148
148
  */
149
149
  get liquidity(): bigint;
150
150
  /**
151
- * The MetaMorpho vault's APY on its assets averaged over its market deposits, before deducting the performance fee.
151
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
152
+ * before deducting the performance fee, at the time of each market's last update (scaled by WAD).
153
+ * If interested in the APY at a specific timestamp, use `getApy(timestamp)` instead.
152
154
  */
153
155
  get apy(): bigint;
154
156
  /**
155
- * The MetaMorpho vault's APY on its assets averaged over its market deposits, after deducting the performance fee.
157
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
158
+ * after deducting the performance fee, at the time of each market's last update (scaled by WAD).
159
+ * If interested in the APY at a specific timestamp, use `getApy(timestamp)` instead.
156
160
  */
157
161
  get netApy(): bigint;
162
+ /**
163
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
164
+ * before deducting the performance fee, at the given timestamp,
165
+ * if the state of all the markets remains unchanged (not accrued) (scaled by WAD).
166
+ */
167
+ getApy(timestamp: BigIntish): bigint;
168
+ /**
169
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
170
+ * after deducting the performance fee, at the given timestamp,
171
+ * if the state of all the markets remains unchanged (not accrued) (scaled by WAD).
172
+ */
173
+ getNetApy(timestamp: BigIntish): bigint;
158
174
  getAllocationProportion(marketId: MarketId): bigint;
159
175
  getDepositCapacityLimit(assets: bigint): CapacityLimit;
160
176
  getWithdrawCapacityLimit(shares: bigint): CapacityLimit;
@@ -153,7 +153,9 @@ class AccrualVault extends Vault {
153
153
  .reduce((total, { position }) => total + position.withdrawCapacityLimit.value, 0n);
154
154
  }
155
155
  /**
156
- * The MetaMorpho vault's APY on its assets averaged over its market deposits, before deducting the performance fee.
156
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
157
+ * before deducting the performance fee, at the time of each market's last update (scaled by WAD).
158
+ * If interested in the APY at a specific timestamp, use `getApy(timestamp)` instead.
157
159
  */
158
160
  get apy() {
159
161
  if (this.totalAssets === 0n)
@@ -163,11 +165,34 @@ class AccrualVault extends Vault {
163
165
  .reduce((total, { position }) => total + position.market.supplyApy * position.supplyAssets, 0n) / this.totalAssets);
164
166
  }
165
167
  /**
166
- * The MetaMorpho vault's APY on its assets averaged over its market deposits, after deducting the performance fee.
168
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
169
+ * after deducting the performance fee, at the time of each market's last update (scaled by WAD).
170
+ * If interested in the APY at a specific timestamp, use `getApy(timestamp)` instead.
167
171
  */
168
172
  get netApy() {
169
173
  return index_js_2.MathLib.wMulDown(this.apy, index_js_2.MathLib.WAD - this.fee);
170
174
  }
175
+ /**
176
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
177
+ * before deducting the performance fee, at the given timestamp,
178
+ * if the state of all the markets remains unchanged (not accrued) (scaled by WAD).
179
+ */
180
+ getApy(timestamp) {
181
+ if (this.totalAssets === 0n)
182
+ return 0n;
183
+ return (this.allocations
184
+ .values()
185
+ .reduce((total, { position }) => total +
186
+ position.market.getSupplyApy(timestamp) * position.supplyAssets, 0n) / this.totalAssets);
187
+ }
188
+ /**
189
+ * The MetaMorpho vault's APY on its assets averaged over its market deposits,
190
+ * after deducting the performance fee, at the given timestamp,
191
+ * if the state of all the markets remains unchanged (not accrued) (scaled by WAD).
192
+ */
193
+ getNetApy(timestamp) {
194
+ return index_js_2.MathLib.wMulDown(this.getApy(timestamp), index_js_2.MathLib.WAD - this.fee);
195
+ }
171
196
  getAllocationProportion(marketId) {
172
197
  if (this.totalAssets === 0n)
173
198
  return 0n;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@morpho-org/blue-sdk",
3
3
  "description": "Framework-agnostic package that defines Morpho-related entity classes (such as `Market`, `Token`, `Vault`).",
4
- "version": "3.0.3",
4
+ "version": "3.0.5",
5
5
  "author": "Morpho Association <contact@morpho.org>",
6
6
  "contributors": [
7
7
  "Rubilmax <rmilon@gmail.com>"