@morpho-org/blue-sdk 2.1.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { Market, type MaxBorrowOptions, type MaxWithdrawCollateralOptions } from "../market/index.js";
1
+ import { Market, type MaxBorrowOptions, type MaxPositionCapacities, type MaxWithdrawCollateralOptions } from "../market/index.js";
2
2
  import type { Address, BigIntish, MarketId } from "../types.js";
3
3
  export interface IPosition {
4
4
  user: Address;
@@ -98,8 +98,24 @@ export declare class AccrualPosition extends Position implements IAccrualPositio
98
98
  * If the collateral price is 0, usage is `MaxUint256`.
99
99
  */
100
100
  get borrowCapacityUsage(): bigint | undefined;
101
+ /**
102
+ * Returns the maximum amount of loan assets that can be borrowed given a certain borrow position
103
+ * and the reason for the limit.
104
+ * Returns `undefined` iff the market's price is undefined.
105
+ * @deprecated Use `getBorrowCapacityLimit` instead.
106
+ */
101
107
  get borrowCapacityLimit(): import("../market/Market.js").CapacityLimit | undefined;
108
+ /**
109
+ * Returns the maximum amount of loan assets that can be withdrawn given a certain supply position
110
+ * and a balance of loan assets, and the reason for the limit.
111
+ */
102
112
  get withdrawCapacityLimit(): import("../market/Market.js").CapacityLimit;
113
+ /**
114
+ * Returns the maximum amount of collateral assets that can be withdrawn given a certain borrow position
115
+ * and the reason for the limit.
116
+ * Returns `undefined` iff the market's price is undefined.
117
+ * @deprecated Use `getWithdrawCollateralCapacityLimit` instead.
118
+ */
103
119
  get withdrawCollateralCapacityLimit(): import("../market/Market.js").CapacityLimit | undefined;
104
120
  /**
105
121
  * Returns a new position derived from this position, whose interest has been accrued up to the given timestamp.
@@ -128,9 +144,11 @@ export declare class AccrualPosition extends Position implements IAccrualPositio
128
144
  assets: bigint;
129
145
  shares: bigint;
130
146
  };
147
+ getBorrowCapacityLimit(options?: MaxBorrowOptions): import("../market/Market.js").CapacityLimit | undefined;
148
+ getWithdrawCollateralCapacityLimit(options?: MaxWithdrawCollateralOptions): import("../market/Market.js").CapacityLimit | undefined;
131
149
  getRepayCapacityLimit(loanTokenBalance: bigint): import("../market/Market.js").CapacityLimit;
132
150
  getMaxCapacities(loanTokenBalance: bigint, collateralTokenBalance: bigint, options?: {
133
151
  borrow?: MaxBorrowOptions;
134
152
  withdrawCollateral?: MaxWithdrawCollateralOptions;
135
- }): import("../market/Market.js").MaxPositionCapacities;
153
+ }): MaxPositionCapacities;
136
154
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AccrualPosition = exports.Position = void 0;
4
4
  const errors_js_1 = require("../errors.js");
5
5
  const index_js_1 = require("../market/index.js");
6
+ const MathLib_js_1 = require("../math/MathLib.js");
6
7
  class Position {
7
8
  /**
8
9
  * The user holding this position.
@@ -67,7 +68,10 @@ class AccrualPosition extends Position {
67
68
  * `undefined` iff the market's oracle is undefined or reverts.
68
69
  */
69
70
  get maxBorrowableAssets() {
70
- return this.market.getMaxBorrowableAssets(this);
71
+ const { maxBorrowAssets } = this;
72
+ if (maxBorrowAssets == null)
73
+ return;
74
+ return MathLib_js_1.MathLib.zeroFloorSub(maxBorrowAssets, this.borrowAssets);
71
75
  }
72
76
  /**
73
77
  * The maximum amount of collateral that can be seized in exchange for the outstanding debt.
@@ -128,12 +132,28 @@ class AccrualPosition extends Position {
128
132
  get borrowCapacityUsage() {
129
133
  return this.market.getBorrowCapacityUsage(this);
130
134
  }
135
+ /**
136
+ * Returns the maximum amount of loan assets that can be borrowed given a certain borrow position
137
+ * and the reason for the limit.
138
+ * Returns `undefined` iff the market's price is undefined.
139
+ * @deprecated Use `getBorrowCapacityLimit` instead.
140
+ */
131
141
  get borrowCapacityLimit() {
132
142
  return this.market.getBorrowCapacityLimit(this);
133
143
  }
144
+ /**
145
+ * Returns the maximum amount of loan assets that can be withdrawn given a certain supply position
146
+ * and a balance of loan assets, and the reason for the limit.
147
+ */
134
148
  get withdrawCapacityLimit() {
135
149
  return this.market.getWithdrawCapacityLimit(this);
136
150
  }
151
+ /**
152
+ * Returns the maximum amount of collateral assets that can be withdrawn given a certain borrow position
153
+ * and the reason for the limit.
154
+ * Returns `undefined` iff the market's price is undefined.
155
+ * @deprecated Use `getWithdrawCollateralCapacityLimit` instead.
156
+ */
137
157
  get withdrawCollateralCapacityLimit() {
138
158
  return this.market.getWithdrawCollateralCapacityLimit(this);
139
159
  }
@@ -195,11 +215,30 @@ class AccrualPosition extends Position {
195
215
  throw new errors_js_1.BlueErrors.InsufficientPosition(position.user, position.marketId);
196
216
  return { position, assets, shares };
197
217
  }
218
+ getBorrowCapacityLimit(options) {
219
+ return this.market.getBorrowCapacityLimit(this, options);
220
+ }
221
+ getWithdrawCollateralCapacityLimit(options) {
222
+ return this.market.getWithdrawCollateralCapacityLimit(this, options);
223
+ }
198
224
  getRepayCapacityLimit(loanTokenBalance) {
199
225
  return this.market.getRepayCapacityLimit(this.borrowShares, loanTokenBalance);
200
226
  }
201
227
  getMaxCapacities(loanTokenBalance, collateralTokenBalance, options) {
202
- return this.market.getMaxCapacities(this, loanTokenBalance, collateralTokenBalance, options);
228
+ return {
229
+ supply: {
230
+ value: loanTokenBalance,
231
+ limiter: index_js_1.CapacityLimitReason.balance,
232
+ },
233
+ withdraw: this.withdrawCapacityLimit,
234
+ borrow: this.getBorrowCapacityLimit(options?.borrow),
235
+ repay: this.getRepayCapacityLimit(loanTokenBalance),
236
+ supplyCollateral: {
237
+ value: collateralTokenBalance,
238
+ limiter: index_js_1.CapacityLimitReason.balance,
239
+ },
240
+ withdrawCollateral: this.getWithdrawCollateralCapacityLimit(options?.withdrawCollateral),
241
+ };
203
242
  }
204
243
  }
205
244
  exports.AccrualPosition = AccrualPosition;
@@ -0,0 +1,55 @@
1
+ import type { Address } from "../types.js";
2
+ export declare const EIP_712_FIELDS: readonly ["name", "version", "chainId", "verifyingContract", "salt"];
3
+ export type Eip712Field = (typeof EIP_712_FIELDS)[number];
4
+ export interface IEip5267Domain {
5
+ fields: `0x${string}`;
6
+ name: string;
7
+ version: string;
8
+ chainId: bigint;
9
+ verifyingContract: Address;
10
+ salt: `0x${string}`;
11
+ extensions: readonly bigint[];
12
+ }
13
+ export declare class Eip5267Domain implements IEip5267Domain {
14
+ /**
15
+ * A bit map where bit i is set to 1 if and only if domain field i is present (0 ≤ i ≤ 4).
16
+ * Bits are read from least significant to most significant, and fields are indexed in the order that is specified by EIP-712, identical to the order in which they are listed in the function type.
17
+ */
18
+ readonly fields: `0x${string}`;
19
+ /**
20
+ * The user readable name of signing domain, i.e. the name of the DApp or the protocol.
21
+ */
22
+ readonly name: string;
23
+ /**
24
+ * The current major version of the signing domain.
25
+ * Signatures from different versions are not compatible.
26
+ */
27
+ readonly version: string;
28
+ /**
29
+ * The EIP-155 chain id.
30
+ */
31
+ readonly chainId: bigint;
32
+ /**
33
+ * The address of the contract that will verify the EIP-712 signature.
34
+ */
35
+ readonly verifyingContract: `0x${string}`;
36
+ /**
37
+ * A disambiguating salt for the protocol.
38
+ * This can be used as a domain separator of last resort.
39
+ */
40
+ readonly salt: `0x${string}`;
41
+ /**
42
+ * A list of EIP numbers, each of which MUST refer to an EIP that extends EIP-712 with new domain fields, along with a method to obtain the value for those fields, and potentially conditions for inclusion.
43
+ * The value of fields does not affect their inclusion.
44
+ */
45
+ readonly extensions: readonly bigint[];
46
+ readonly eip712Domain: {
47
+ name?: string | undefined;
48
+ chainId?: number | undefined;
49
+ version?: string | undefined;
50
+ verifyingContract?: `0x${string}` | undefined;
51
+ salt?: `0x${string}` | undefined;
52
+ };
53
+ constructor({ fields, name, version, chainId, verifyingContract, salt, extensions, }: IEip5267Domain);
54
+ private asEip712Domain;
55
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Eip5267Domain = exports.EIP_712_FIELDS = void 0;
4
+ exports.EIP_712_FIELDS = [
5
+ "name",
6
+ "version",
7
+ "chainId",
8
+ "verifyingContract",
9
+ "salt",
10
+ ];
11
+ class Eip5267Domain {
12
+ /**
13
+ * A bit map where bit i is set to 1 if and only if domain field i is present (0 ≤ i ≤ 4).
14
+ * Bits are read from least significant to most significant, and fields are indexed in the order that is specified by EIP-712, identical to the order in which they are listed in the function type.
15
+ */
16
+ fields;
17
+ /**
18
+ * The user readable name of signing domain, i.e. the name of the DApp or the protocol.
19
+ */
20
+ name;
21
+ /**
22
+ * The current major version of the signing domain.
23
+ * Signatures from different versions are not compatible.
24
+ */
25
+ version;
26
+ /**
27
+ * The EIP-155 chain id.
28
+ */
29
+ chainId;
30
+ /**
31
+ * The address of the contract that will verify the EIP-712 signature.
32
+ */
33
+ verifyingContract;
34
+ /**
35
+ * A disambiguating salt for the protocol.
36
+ * This can be used as a domain separator of last resort.
37
+ */
38
+ salt;
39
+ /**
40
+ * A list of EIP numbers, each of which MUST refer to an EIP that extends EIP-712 with new domain fields, along with a method to obtain the value for those fields, and potentially conditions for inclusion.
41
+ * The value of fields does not affect their inclusion.
42
+ */
43
+ extensions;
44
+ eip712Domain;
45
+ constructor({ fields, name, version, chainId, verifyingContract, salt, extensions, }) {
46
+ this.fields = fields;
47
+ this.name = name;
48
+ this.version = version;
49
+ this.chainId = chainId;
50
+ this.verifyingContract = verifyingContract;
51
+ this.salt = salt;
52
+ this.extensions = extensions;
53
+ this.eip712Domain = this.asEip712Domain();
54
+ }
55
+ asEip712Domain() {
56
+ const fields = BigInt(this.fields);
57
+ return exports.EIP_712_FIELDS.reduce((acc, field, i) => {
58
+ if (fields & (2n ** BigInt(i))) {
59
+ // @ts-expect-error Typescript doesn't infer value type based on field.
60
+ acc[field] =
61
+ field === "chainId"
62
+ ? // Signature does not correspond if chainId is a bigint.
63
+ Number(this.chainId)
64
+ : this[field];
65
+ }
66
+ return acc;
67
+ }, {});
68
+ }
69
+ }
70
+ exports.Eip5267Domain = Eip5267Domain;
@@ -1,12 +1,14 @@
1
1
  import { type ChainId } from "../chain.js";
2
2
  import { type RoundingDirection } from "../math/index.js";
3
3
  import type { Address, BigIntish } from "../types.js";
4
+ import type { Eip5267Domain } from "./Eip5267Domain.js";
4
5
  export interface IToken {
5
6
  address: Address;
6
7
  name?: string;
7
8
  symbol?: string;
8
9
  decimals?: BigIntish;
9
10
  price?: BigIntish;
11
+ eip5267Domain?: Eip5267Domain;
10
12
  }
11
13
  export declare class Token implements IToken {
12
14
  static native(chainId: ChainId): Token;
@@ -26,11 +28,15 @@ export declare class Token implements IToken {
26
28
  * The token's number of decimals. Defaults to 0.
27
29
  */
28
30
  readonly decimals: number;
31
+ /**
32
+ * The eip712 domain of the token if it can be directly queried onchain
33
+ */
34
+ readonly eip5267Domain?: Eip5267Domain;
29
35
  /**
30
36
  * Price of the token in USD (scaled by WAD).
31
37
  */
32
38
  price?: bigint;
33
- constructor({ address, name, symbol, decimals, price }: IToken);
39
+ constructor({ address, name, symbol, decimals, price, eip5267Domain, }: IToken);
34
40
  /**
35
41
  * Quotes an amount in USD (scaled by WAD) in this token.
36
42
  * Returns `undefined` iff the token's price is undefined.
@@ -25,15 +25,20 @@ class Token {
25
25
  * The token's number of decimals. Defaults to 0.
26
26
  */
27
27
  decimals;
28
+ /**
29
+ * The eip712 domain of the token if it can be directly queried onchain
30
+ */
31
+ eip5267Domain;
28
32
  /**
29
33
  * Price of the token in USD (scaled by WAD).
30
34
  */
31
35
  price;
32
- constructor({ address, name, symbol, decimals = 0, price }) {
36
+ constructor({ address, name, symbol, decimals = 0, price, eip5267Domain, }) {
33
37
  this.address = address;
34
38
  this.name = name;
35
39
  this.symbol = symbol;
36
40
  this.decimals = Number(decimals);
41
+ this.eip5267Domain = eip5267Domain;
37
42
  if (price != null)
38
43
  this.price = BigInt(price);
39
44
  }
@@ -3,3 +3,4 @@ export * from "./WrappedToken.js";
3
3
  export * from "./ConstantWrappedToken.js";
4
4
  export * from "./ExchangeRateWrappedToken.js";
5
5
  export * from "./VaultToken.js";
6
+ export * from "./Eip5267Domain.js";
@@ -19,3 +19,4 @@ __exportStar(require("./WrappedToken.js"), exports);
19
19
  __exportStar(require("./ConstantWrappedToken.js"), exports);
20
20
  __exportStar(require("./ExchangeRateWrappedToken.js"), exports);
21
21
  __exportStar(require("./VaultToken.js"), exports);
22
+ __exportStar(require("./Eip5267Domain.js"), exports);
@@ -38,6 +38,7 @@ export interface IVault extends IVaultConfig {
38
38
  totalSupply: bigint;
39
39
  totalAssets: bigint;
40
40
  lastTotalAssets: bigint;
41
+ lostAssets?: bigint;
41
42
  publicAllocatorConfig?: VaultPublicAllocatorConfig;
42
43
  }
43
44
  export declare class Vault extends VaultToken implements IVault {
@@ -101,11 +102,16 @@ export declare class Vault extends VaultToken implements IVault {
101
102
  * The MetaMorpho vault's last total assets used to calculate performance fees.
102
103
  */
103
104
  lastTotalAssets: bigint;
105
+ /**
106
+ * The MetaMorpho vault's lost assets due to realized bad debt.
107
+ * Only defined for MetaMorpho V1.1 vaults.
108
+ */
109
+ lostAssets?: bigint;
104
110
  /**
105
111
  * The MetaMorpho vault's public allocator configuration.
106
112
  */
107
113
  publicAllocatorConfig?: VaultPublicAllocatorConfig;
108
- constructor({ curator, owner, guardian, publicAllocatorConfig, fee, feeRecipient, skimRecipient, pendingTimelock, pendingGuardian, pendingOwner, timelock, supplyQueue, withdrawQueue, totalSupply, totalAssets, lastTotalAssets, ...config }: IVault);
114
+ constructor({ curator, owner, guardian, publicAllocatorConfig, fee, feeRecipient, skimRecipient, pendingTimelock, pendingGuardian, pendingOwner, timelock, supplyQueue, withdrawQueue, totalSupply, totalAssets, lastTotalAssets, lostAssets, ...config }: IVault);
109
115
  /**
110
116
  * The amount of interest in assets accrued since the last interaction with the vault.
111
117
  */
@@ -58,11 +58,16 @@ class Vault extends index_js_3.VaultToken {
58
58
  * The MetaMorpho vault's last total assets used to calculate performance fees.
59
59
  */
60
60
  lastTotalAssets;
61
+ /**
62
+ * The MetaMorpho vault's lost assets due to realized bad debt.
63
+ * Only defined for MetaMorpho V1.1 vaults.
64
+ */
65
+ lostAssets;
61
66
  /**
62
67
  * The MetaMorpho vault's public allocator configuration.
63
68
  */
64
69
  publicAllocatorConfig;
65
- constructor({ curator, owner, guardian, publicAllocatorConfig, fee, feeRecipient, skimRecipient, pendingTimelock, pendingGuardian, pendingOwner, timelock, supplyQueue, withdrawQueue, totalSupply, totalAssets, lastTotalAssets, ...config }) {
70
+ constructor({ curator, owner, guardian, publicAllocatorConfig, fee, feeRecipient, skimRecipient, pendingTimelock, pendingGuardian, pendingOwner, timelock, supplyQueue, withdrawQueue, totalSupply, totalAssets, lastTotalAssets, lostAssets, ...config }) {
66
71
  super(config, { totalAssets, totalSupply });
67
72
  this.curator = curator;
68
73
  this.owner = owner;
@@ -80,6 +85,7 @@ class Vault extends index_js_3.VaultToken {
80
85
  this.supplyQueue = supplyQueue;
81
86
  this.withdrawQueue = withdrawQueue;
82
87
  this.lastTotalAssets = lastTotalAssets;
88
+ this.lostAssets = lostAssets;
83
89
  this.publicAllocatorConfig = publicAllocatorConfig;
84
90
  }
85
91
  /**
@@ -214,6 +220,10 @@ class AccrualVault extends Vault {
214
220
  position: position.accrueInterest(timestamp),
215
221
  };
216
222
  }));
223
+ if (vault.lostAssets != null) {
224
+ vault.lostAssets += index_js_2.MathLib.max(vault.lastTotalAssets - vault.lostAssets - vault.totalAssets, 0n);
225
+ vault.totalAssets += vault.lostAssets;
226
+ }
217
227
  const feeAssets = index_js_2.MathLib.wMulDown(vault.totalInterest, vault.fee);
218
228
  vault.totalAssets -= feeAssets;
219
229
  const feeShares = vault.toShares(feeAssets, "Down");
@@ -1,21 +1,19 @@
1
- import type { ChainId } from "../chain.js";
1
+ import { type IToken, Token } from "../token/Token.js";
2
2
  import type { Address, BigIntish } from "../types.js";
3
- export interface IVaultConfig {
4
- address: Address;
3
+ export interface IVaultConfig extends Omit<IToken, "decimals"> {
5
4
  decimalsOffset: BigIntish;
6
- symbol: string;
7
- name: string;
8
5
  asset: Address;
9
6
  }
10
- export declare class VaultConfig implements IVaultConfig {
7
+ export declare class VaultConfig extends Token implements IVaultConfig {
8
+ /**
9
+ * @deprecated Kept for backward compatibility.
10
+ */
11
11
  readonly chainId?: number | undefined;
12
- protected static readonly _CACHE: Record<number, Record<Address, VaultConfig>>;
13
- static get(address: Address, chainId: ChainId): VaultConfig;
14
- readonly address: Address;
15
- readonly decimals: number;
16
12
  readonly decimalsOffset: bigint;
17
- readonly symbol: string;
18
- readonly name: string;
19
- readonly asset: Address;
20
- constructor({ address, decimalsOffset, symbol, name, asset }: IVaultConfig, chainId?: number | undefined);
13
+ readonly asset: `0x${string}`;
14
+ constructor({ decimalsOffset, asset, ...config }: IVaultConfig,
15
+ /**
16
+ * @deprecated Kept for backward compatibility.
17
+ */
18
+ chainId?: number | undefined);
21
19
  }
@@ -1,32 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VaultConfig = void 0;
4
- const errors_js_1 = require("../errors.js");
5
- class VaultConfig {
4
+ const Token_js_1 = require("../token/Token.js");
5
+ class VaultConfig extends Token_js_1.Token {
6
6
  chainId;
7
- static _CACHE = {};
8
- static get(address, chainId) {
9
- const config = VaultConfig._CACHE[chainId]?.[address];
10
- if (!config)
11
- throw new errors_js_1.UnknownVaultConfigError(address);
12
- return config;
13
- }
14
- address;
15
- decimals;
16
7
  decimalsOffset;
17
- symbol;
18
- name;
19
8
  asset;
20
- constructor({ address, decimalsOffset, symbol, name, asset }, chainId) {
9
+ constructor({ decimalsOffset, asset, ...config },
10
+ /**
11
+ * @deprecated Kept for backward compatibility.
12
+ */
13
+ chainId) {
14
+ super({ ...config, decimals: 18 });
21
15
  this.chainId = chainId;
22
- this.address = address;
23
- this.decimals = 18;
24
16
  this.decimalsOffset = BigInt(decimalsOffset);
25
- this.symbol = symbol;
26
- this.name = name;
27
17
  this.asset = asset;
28
- if (chainId != null)
29
- (VaultConfig._CACHE[chainId] ??= {})[address] = this;
30
18
  }
31
19
  }
32
20
  exports.VaultConfig = VaultConfig;
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": "2.1.2",
4
+ "version": "2.3.0",
5
5
  "author": "Morpho Association <contact@morpho.org>",
6
6
  "contributors": [
7
7
  "Rubilmax <rmilon@gmail.com>"
@@ -28,7 +28,7 @@
28
28
  "viem": "^2.22.2",
29
29
  "vitest": "^2.1.8",
30
30
  "@morpho-org/morpho-ts": "^2.0.0",
31
- "@morpho-org/test": "^2.0.2"
31
+ "@morpho-org/test": "^2.0.3"
32
32
  },
33
33
  "scripts": {
34
34
  "prepublish": "$npm_execpath build",