@morpho-org/blue-sdk 4.9.0 → 4.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -11,3 +11,4 @@ export * from "./holding/index.js";
11
11
  export * from "./position/index.js";
12
12
  export * from "./vault/index.js";
13
13
  export * from "./preLiquidation.js";
14
+ export * from "./utils.js";
package/lib/index.js CHANGED
@@ -27,3 +27,4 @@ __exportStar(require("./holding/index.js"), exports);
27
27
  __exportStar(require("./position/index.js"), exports);
28
28
  __exportStar(require("./vault/index.js"), exports);
29
29
  __exportStar(require("./preLiquidation.js"), exports);
30
+ __exportStar(require("./utils.js"), exports);
@@ -99,7 +99,7 @@ class Market {
99
99
  get apyAtTarget() {
100
100
  if (this.rateAtTarget == null)
101
101
  return;
102
- return MarketUtils_js_1.MarketUtils.compoundRate(this.rateAtTarget);
102
+ return MarketUtils_js_1.MarketUtils.rateToApy(this.rateAtTarget);
103
103
  }
104
104
  /**
105
105
  * Returns the rate at which interest accrued for suppliers of this market,
@@ -218,7 +218,7 @@ class Market {
218
218
  */
219
219
  getBorrowApy(timestamp = morpho_ts_1.Time.timestamp()) {
220
220
  const borrowRate = this.getEndBorrowRate(timestamp);
221
- return MarketUtils_js_1.MarketUtils.compoundRate(borrowRate);
221
+ return MarketUtils_js_1.MarketUtils.rateToApy(borrowRate);
222
222
  }
223
223
  /**
224
224
  * The market's instantaneous supply-side Annual Percentage Yield (APY) at the given timestamp,
@@ -240,7 +240,7 @@ class Market {
240
240
  */
241
241
  getAvgBorrowApy(timestamp = morpho_ts_1.Time.timestamp()) {
242
242
  const borrowRate = this.getAvgBorrowRate(timestamp);
243
- return MarketUtils_js_1.MarketUtils.compoundRate(borrowRate);
243
+ return MarketUtils_js_1.MarketUtils.rateToApy(borrowRate);
244
244
  }
245
245
  /**
246
246
  * The market's experienced supply-side Annual Percentage Yield (APY),
@@ -38,11 +38,17 @@ export declare namespace MarketUtils {
38
38
  }): bigint;
39
39
  /**
40
40
  * Returns the per-second rate continuously compounded over the given period, as calculated in Morpho Blue (scaled by WAD).
41
- * If the period is 1 year, the compounded rate correspond to the Annual Percentage Yield (APY)
42
41
  * @param rate The per-second rate to compound (scaled by WAD).
43
42
  * @param period The period to compound the rate over (in seconds). Defaults to 1 year.
43
+ * @deprecated The compounded rate is inaccurate if rate * period >> 0. If interested in the APY, use `rateToApy` instead.
44
44
  */
45
45
  function compoundRate(rate: BigIntish, period?: BigIntish): bigint;
46
+ /**
47
+ * Returns the per-second rate continuously compounded over a year (scaled by WAD),
48
+ * as calculated in Morpho Blue assuming the market is frequently accrued onchain.
49
+ * @param rate The per-second rate to compound annually (scaled by WAD).
50
+ */
51
+ function rateToApy(rate: BigIntish): bigint;
46
52
  /**
47
53
  * Returns the interest accrued on both sides of the given market
48
54
  * as well as the supply shares minted to the fee recipient.
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MarketUtils = void 0;
4
4
  const sha3_1 = require("@noble/hashes/sha3");
5
5
  const utils_1 = require("@noble/hashes/utils");
6
+ const viem_1 = require("viem");
6
7
  const constants_js_1 = require("../constants.js");
7
8
  const index_js_1 = require("../math/index.js");
9
+ const utils_js_1 = require("../utils.js");
8
10
  /**
9
11
  * Namespace of utility functions to ease market-related calculations.
10
12
  */
@@ -63,14 +65,24 @@ var MarketUtils;
63
65
  MarketUtils.getSupplyRate = getSupplyRate;
64
66
  /**
65
67
  * Returns the per-second rate continuously compounded over the given period, as calculated in Morpho Blue (scaled by WAD).
66
- * If the period is 1 year, the compounded rate correspond to the Annual Percentage Yield (APY)
67
68
  * @param rate The per-second rate to compound (scaled by WAD).
68
69
  * @param period The period to compound the rate over (in seconds). Defaults to 1 year.
70
+ * @deprecated The compounded rate is inaccurate if rate * period >> 0. If interested in the APY, use `rateToApy` instead.
69
71
  */
70
72
  function compoundRate(rate, period = constants_js_1.SECONDS_PER_YEAR) {
71
73
  return index_js_1.MathLib.wTaylorCompounded(rate, period);
72
74
  }
73
75
  MarketUtils.compoundRate = compoundRate;
76
+ /**
77
+ * Returns the per-second rate continuously compounded over a year (scaled by WAD),
78
+ * as calculated in Morpho Blue assuming the market is frequently accrued onchain.
79
+ * @param rate The per-second rate to compound annually (scaled by WAD).
80
+ */
81
+ // TODO: return a Number for APYs.
82
+ function rateToApy(rate) {
83
+ return (0, utils_js_1.safeParseNumber)(Math.expm1(+(0, viem_1.formatEther)(BigInt(rate) * constants_js_1.SECONDS_PER_YEAR)));
84
+ }
85
+ MarketUtils.rateToApy = rateToApy;
74
86
  /**
75
87
  * Returns the interest accrued on both sides of the given market
76
88
  * as well as the supply shares minted to the fee recipient.
package/lib/utils.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const safeParseNumber: (value: number, decimals?: number) => bigint;
2
+ export declare const safeParseUnits: (strValue: string, decimals?: number) => bigint;
package/lib/utils.js ADDED
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.safeParseUnits = exports.safeParseNumber = void 0;
4
+ // Alternative to Number.toFixed that doesn't use scientific notation for excessively small or large numbers.
5
+ const toFixed = (x, decimals) => new Intl.NumberFormat("en-US", {
6
+ style: "decimal",
7
+ useGrouping: false,
8
+ maximumFractionDigits: decimals,
9
+ minimumFractionDigits: decimals,
10
+ }).format(x);
11
+ const safeParseNumber = (value, decimals = 18) => (0, exports.safeParseUnits)(toFixed(value, decimals), decimals);
12
+ exports.safeParseNumber = safeParseNumber;
13
+ const safeParseUnits = (strValue, decimals = 18) => {
14
+ if (!/[-+]?[0-9]*\.?[0-9]+/.test(strValue))
15
+ throw Error(`invalid number: ${strValue}`);
16
+ let [whole, dec = ""] = strValue.split(".");
17
+ dec = dec.slice(0, decimals);
18
+ return parseUnits([whole || "0", dec].filter((v) => v.length > 0).join("."), decimals);
19
+ };
20
+ exports.safeParseUnits = safeParseUnits;
21
+ /**
22
+ * Multiplies a string representation of a number by a given exponent of base 10 (10exponent).
23
+ *
24
+ * - Docs: https://viem.sh/docs/utilities/parseUnits
25
+ *
26
+ * @example
27
+ * import { parseUnits } from 'viem'
28
+ *
29
+ * parseUnits('420', 9)
30
+ * // 420000000000n
31
+ */
32
+ // TODO: get rid of this copy.
33
+ function parseUnits(value, decimals) {
34
+ let [integer, fraction = "0"] = value.split(".");
35
+ const negative = integer.startsWith("-");
36
+ if (negative)
37
+ integer = integer.slice(1);
38
+ // trim trailing zeros.
39
+ fraction = fraction.replace(/(0+)$/, "");
40
+ // round off if the fraction is larger than the number of decimals.
41
+ if (decimals === 0) {
42
+ if (Math.round(Number(`.${fraction}`)) === 1)
43
+ integer = `${BigInt(integer) + 1n}`;
44
+ fraction = "";
45
+ }
46
+ else if (fraction.length > decimals) {
47
+ const [left, unit, right] = [
48
+ fraction.slice(0, decimals - 1),
49
+ fraction.slice(decimals - 1, decimals),
50
+ fraction.slice(decimals),
51
+ ];
52
+ const rounded = Math.round(Number(`${unit}.${right}`));
53
+ if (rounded > 9)
54
+ fraction = `${BigInt(left) + BigInt(1)}0`.padStart(left.length + 1, "0");
55
+ else
56
+ fraction = `${left}${rounded}`;
57
+ if (fraction.length > decimals) {
58
+ fraction = fraction.slice(1);
59
+ integer = `${BigInt(integer) + 1n}`;
60
+ }
61
+ fraction = fraction.slice(0, decimals);
62
+ }
63
+ else {
64
+ fraction = fraction.padEnd(decimals, "0");
65
+ }
66
+ return BigInt(`${negative ? "-" : ""}${integer}${fraction}`);
67
+ }
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": "4.9.0",
4
+ "version": "4.9.1",
5
5
  "author": "Morpho Association <contact@morpho.org>",
6
6
  "contributors": [
7
7
  "Rubilmax <rmilon@gmail.com>"
@@ -32,7 +32,7 @@
32
32
  "viem": "^2.23.0",
33
33
  "vitest": "^3.0.5",
34
34
  "@morpho-org/morpho-ts": "^2.4.1",
35
- "@morpho-org/test": "^2.1.4"
35
+ "@morpho-org/test": "^2.1.5"
36
36
  },
37
37
  "scripts": {
38
38
  "prepublish": "$npm_execpath build",