@gearbox-protocol/sdk 15.1.0-next.4 → 15.1.0-next.6

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 (35) hide show
  1. package/dist/cjs/dev/compareOpportunities.js +218 -0
  2. package/dist/cjs/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +2 -2
  3. package/dist/cjs/sdk/index.js +9 -5
  4. package/dist/cjs/sdk/market/credit/CreditManagerV310Contract.js +1 -12
  5. package/dist/cjs/sdk/market/credit/CreditSuite.js +18 -27
  6. package/dist/cjs/sdk/market/credit/index.js +3 -0
  7. package/dist/cjs/sdk/market/credit/isStrategyCollateral.js +50 -0
  8. package/dist/cjs/sdk/market/index.js +17 -0
  9. package/dist/cjs/sdk/market/math.js +57 -44
  10. package/dist/cjs/sdk/market/pool/PoolV310Contract.js +1 -1
  11. package/dist/cjs/sdk/opportunities/index.js +0 -13
  12. package/dist/esm/dev/compareOpportunities.js +216 -0
  13. package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +3 -3
  14. package/dist/esm/sdk/index.js +3 -2
  15. package/dist/esm/sdk/market/credit/CreditManagerV310Contract.js +2 -13
  16. package/dist/esm/sdk/market/credit/CreditSuite.js +19 -28
  17. package/dist/esm/sdk/market/credit/index.js +2 -1
  18. package/dist/esm/sdk/market/credit/isStrategyCollateral.js +48 -0
  19. package/dist/esm/sdk/market/index.js +3 -1
  20. package/dist/esm/sdk/market/math.js +52 -40
  21. package/dist/esm/sdk/market/pool/PoolV310Contract.js +2 -2
  22. package/dist/esm/sdk/opportunities/index.js +1 -2
  23. package/dist/types/dev/compareOpportunities.d.ts +153 -0
  24. package/dist/types/model/opportunities.d.ts +9 -9
  25. package/dist/types/model/positions.d.ts +3 -3
  26. package/dist/types/sdk/index.d.ts +3 -2
  27. package/dist/types/sdk/market/credit/CreditManagerV310Contract.d.ts +0 -4
  28. package/dist/types/sdk/market/credit/CreditSuite.d.ts +2 -16
  29. package/dist/types/sdk/market/credit/index.d.ts +2 -1
  30. package/dist/types/sdk/market/credit/isStrategyCollateral.d.ts +74 -0
  31. package/dist/types/sdk/market/credit/types.d.ts +2 -9
  32. package/dist/types/sdk/market/index.d.ts +3 -1
  33. package/dist/types/sdk/market/math.d.ts +44 -34
  34. package/dist/types/sdk/opportunities/index.d.ts +1 -2
  35. package/package.json +1 -1
@@ -16,7 +16,8 @@ const FULL = Number(require_sdk_constants_math.PERCENTAGE_FACTOR);
16
16
  *
17
17
  * @example
18
18
  * ```ts
19
- * rayToBps(50_000_000_000_000_000_000_000_000n) // 500, i.e. 5%
19
+ * // ray: 5% (0.05 × 10²⁷)
20
+ * rayToBps(50_000_000_000_000_000_000_000_000n) // 500 bps = 5%
20
21
  * ```
21
22
  **/
22
23
  function rayToBps(ray) {
@@ -27,6 +28,7 @@ function rayToBps(ray) {
27
28
  *
28
29
  * @example
29
30
  * ```ts
31
+ * // usd: $1500.50 in 8-decimal fixed point
30
32
  * usdToNumber(150_050_000_000n) // 1500.5
31
33
  * ```
32
34
  **/
@@ -39,56 +41,66 @@ function usdToNumber(usd) {
39
41
  *
40
42
  * @example
41
43
  * ```ts
42
- * utilizationBps(750n, 1000n) // 7500, i.e. 75%
44
+ * // borrowed: 750, total: 1000
45
+ * calcUtilization(750n, 1000n) // 750 / 1000 = 7500 bps = 75%
43
46
  * ```
44
47
  **/
45
- function utilizationBps(borrowed, total) {
48
+ function calcUtilization(borrowed, total) {
46
49
  if (total <= 0n || borrowed <= 0n) return 0;
47
50
  const utilization = Number(borrowed * require_sdk_constants_math.PERCENTAGE_FACTOR / total);
48
51
  return Math.min(utilization, FULL);
49
52
  }
50
53
  /**
51
- * Annual cost of debt for a credit manager, in basis points: the pool's base
52
- * rate plus the protocol's cut of the accrued interest.
54
+ * Annual cost of debt for a credit manager, in basis points:
55
+ * `baseInterestRate × (1 + feeInterest)` — the pool's base rate plus the
56
+ * protocol's cut of the accrued interest.
53
57
  *
54
58
  * @param baseInterestRate - Pool base rate in ray.
55
59
  * @param feeInterest - Credit manager interest fee in basis points.
56
60
  *
57
61
  * @example
58
62
  * ```ts
59
- * // 5% base rate, 50% interest fee
60
- * borrowApyBps(50_000_000_000_000_000_000_000_000n, 5000) // 750, i.e. 7.5%
63
+ * // baseInterestRate: 5% in ray, feeInterest: 5000 bps = 50%
64
+ * calcBorrowApy(50_000_000_000_000_000_000_000_000n, 5000) // 5% × 1.5 = 750 bps = 7.5%
61
65
  * ```
62
66
  **/
63
- function borrowApyBps(baseInterestRate, feeInterest) {
67
+ function calcBorrowApy(baseInterestRate, feeInterest) {
64
68
  return rayToBps(baseInterestRate * (require_sdk_constants_math.PERCENTAGE_FACTOR + BigInt(feeInterest)) / require_sdk_constants_math.PERCENTAGE_FACTOR);
65
69
  }
66
70
  /**
67
- * Highest leverage a liquidation threshold allows: `1 / (1 - lt)`.
68
- *
69
- * A threshold of 100% or more would allow unbounded leverage; such tokens are
70
- * not strategies and are filtered out before this is called, so the guard here
71
- * only exists to keep the function total.
71
+ * 5% safety margin subtracted from 100% in {@link calcMaxLeverage}, so a
72
+ * maxed position opens with HF slightly above 1.
73
+ **/
74
+ const MAX_LEVERAGE_BUFFER_BPS = 500;
75
+ /**
76
+ * Highest total-value leverage a liquidation threshold allows:
77
+ * `(100% − buffer) / (100% − liquidationThreshold)`. At HF = 1, debt is
78
+ * `liquidationThreshold × totalValue`, leaving `1 − liquidationThreshold` of
79
+ * equity per unit of exposure; the {@link MAX_LEVERAGE_BUFFER_BPS} buffer
80
+ * keeps the maxed position slightly away from that boundary.
72
81
  *
73
82
  * @example
74
83
  * ```ts
75
- * maxLeverage(9000) // 10
76
- * maxLeverage(8000) // 5
84
+ * // liquidationThreshold: 9000 bps = 90%
85
+ * calcMaxLeverage(9000) // (1 − 0.05) / (1 − 0.9) = 9.5x total exposure
77
86
  * ```
78
87
  **/
79
- function maxLeverage(liquidationThreshold) {
80
- const equity = FULL - liquidationThreshold;
81
- return equity > 0 ? FULL / equity : Number.POSITIVE_INFINITY;
88
+ function calcMaxLeverage(liquidationThreshold) {
89
+ if (liquidationThreshold >= FULL) return 0;
90
+ const leverage = (FULL - 500) / (FULL - liquidationThreshold);
91
+ return Math.max(leverage, 1);
82
92
  }
83
93
  /**
84
94
  * Converts a credit account's health factor from the 18-decimal fixed point the
85
95
  * contracts store to basis points.
86
96
  *
87
- * An account with no debt return MAX_UINT256 from contract, here we return 0
97
+ * Accounts with no debt store `MAX_UINT256` on-chain; for those this
98
+ * returns `0`.
88
99
  *
89
100
  * @example
90
101
  * ```ts
91
- * healthFactorBps(1_250_000_000_000_000_000n) // 12500, i.e. 1.25
102
+ * // healthFactor: 1.25 in 18-decimal fixed point
103
+ * healthFactorBps(1_250_000_000_000_000_000n) // 12500 bps = 1.25
92
104
  * ```
93
105
  **/
94
106
  function healthFactorBps(healthFactor) {
@@ -96,39 +108,39 @@ function healthFactorBps(healthFactor) {
96
108
  return Number(healthFactor * require_sdk_constants_math.PERCENTAGE_FACTOR / require_sdk_constants_math.WAD);
97
109
  }
98
110
  /**
99
- * Leverage of an open position: `totalDebt / equity`, where equity is what is
100
- * left of the position's value once its debt is repaid.
101
- *
102
- * Returns `0` for a position that carries no debt and for one that is
103
- * underwater, where there is no equity to lever.
111
+ * Total-value leverage of an open position:
112
+ * `totalValue / (totalValue totalDebt)`. `1` when unleveraged, `0` when
113
+ * underwater.
104
114
  *
105
- * @param totalDebt - Debt principal plus accrued interest and fees.
106
- * @param totalValue - Total value of the position, in the same token.
115
+ * @param totalValue - Total value of the position.
116
+ * @param totalDebt - Debt principal plus accrued interest and fees, same token.
107
117
  *
108
118
  * @example
109
119
  * ```ts
110
- * positionLeverage(800n, 1000n) // 4, i.e. 4x debt per unit of equity
120
+ * // totalValue: 100k, totalDebt: 80k equity: 100k 80k = 20k
121
+ * calcPositionLeverage(100_000n, 80_000n) // 100k / 20k = 5x
111
122
  * ```
112
123
  **/
113
- function positionLeverage(totalDebt, totalValue) {
124
+ function calcPositionLeverage(totalValue, totalDebt) {
114
125
  const equity = totalValue - totalDebt;
115
- if (equity <= 0n || totalDebt <= 0n) return 0;
116
- return Number(totalDebt) / Number(equity);
126
+ if (totalValue <= 0n || equity <= 0n) return 0;
127
+ if (totalDebt <= 0n) return 1;
128
+ return Number(totalValue) / Number(equity);
117
129
  }
118
130
  /**
119
- * Annual quota cost scaled to the debt a maximally leveraged position carries,
120
- * in basis points. Every unit of own capital carries `maxLeverage - 1` units of
121
- * debt, and the quota is paid on the whole quoted position.
131
+ * Annual quota cost on equity, in basis points:
132
+ * `quotaRate × (1 + feeInterest) × leverage`. Quota accrues on the whole
133
+ * quoted position, and the DAO takes `feeInterest` of it as with base interest.
122
134
  *
123
135
  * @example
124
136
  * ```ts
125
- * // 2.5% quota rate at 5x leverage
126
- * additionalBorrowApyBps(250, 5) // 1000, i.e. 10%
137
+ * // quotaRate: 200 bps = 2%, feeInterest: 2500 bps = 25%, leverage: 9.5x
138
+ * calcAdditionalBorrowApy(200, 2500, 9.5) // 2% × 1.25 × 9.5 = 2375 bps = 23.75%
127
139
  * ```
128
140
  **/
129
- function additionalBorrowApyBps(quotaRate, leverage) {
130
- if (!Number.isFinite(leverage)) return 0;
131
- return Math.round(quotaRate * Math.max(leverage - 1, 0));
141
+ function calcAdditionalBorrowApy(quotaRate, feeInterest, leverage) {
142
+ if (!Number.isFinite(leverage) || leverage <= 0) return 0;
143
+ return Math.round(quotaRate * (1 + feeInterest / FULL) * leverage);
132
144
  }
133
145
  /**
134
146
  * {@link PERCENTAGE_FACTOR} less a 0.1% safety buffer.
@@ -186,15 +198,16 @@ function optimalHFForPartialLiquidation(borrowRate) {
186
198
  return require_sdk_constants_math.PERCENTAGE_FACTOR + (borrowRate < 100n ? borrowRate : 100n);
187
199
  }
188
200
  //#endregion
201
+ exports.MAX_LEVERAGE_BUFFER_BPS = MAX_LEVERAGE_BUFFER_BPS;
189
202
  exports.PARTIAL_LIQUIDATION_BUFFER_BPS = PARTIAL_LIQUIDATION_BUFFER_BPS;
190
- exports.additionalBorrowApyBps = additionalBorrowApyBps;
191
- exports.borrowApyBps = borrowApyBps;
203
+ exports.calcAdditionalBorrowApy = calcAdditionalBorrowApy;
204
+ exports.calcBorrowApy = calcBorrowApy;
205
+ exports.calcMaxLeverage = calcMaxLeverage;
206
+ exports.calcPositionLeverage = calcPositionLeverage;
207
+ exports.calcUtilization = calcUtilization;
192
208
  exports.healthFactorBps = healthFactorBps;
193
- exports.maxLeverage = maxLeverage;
194
209
  exports.minSeizedAmount = minSeizedAmount;
195
210
  exports.optimalHFForPartialLiquidation = optimalHFForPartialLiquidation;
196
211
  exports.optimalRepaidAmount = optimalRepaidAmount;
197
- exports.positionLeverage = positionLeverage;
198
212
  exports.rayToBps = rayToBps;
199
213
  exports.usdToNumber = usdToNumber;
200
- exports.utilizationBps = utilizationBps;
@@ -51,7 +51,7 @@ var PoolV310Contract = class extends require_sdk_base_BaseContract.BaseContract
51
51
  * {@inheritDoc IPoolContract.utilization}
52
52
  */
53
53
  get utilization() {
54
- return require_sdk_market_math.utilizationBps(this.borrowed, this.expectedLiquidity);
54
+ return require_sdk_market_math.calcUtilization(this.borrowed, this.expectedLiquidity);
55
55
  }
56
56
  /**
57
57
  * {@inheritDoc IPoolContract.unwrappedUnderlying}
@@ -1,18 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sdk_market_math = require("../market/math.js");
3
2
  const require_sdk_opportunities_MultichainOpportunitiesService = require("./MultichainOpportunitiesService.js");
4
3
  const require_sdk_opportunities_OpportunitiesService = require("./OpportunitiesService.js");
5
4
  exports.MultichainOpportunitiesService = require_sdk_opportunities_MultichainOpportunitiesService.MultichainOpportunitiesService;
6
5
  exports.OpportunitiesService = require_sdk_opportunities_OpportunitiesService.OpportunitiesService;
7
- exports.PARTIAL_LIQUIDATION_BUFFER_BPS = require_sdk_market_math.PARTIAL_LIQUIDATION_BUFFER_BPS;
8
- exports.additionalBorrowApyBps = require_sdk_market_math.additionalBorrowApyBps;
9
- exports.borrowApyBps = require_sdk_market_math.borrowApyBps;
10
- exports.healthFactorBps = require_sdk_market_math.healthFactorBps;
11
- exports.maxLeverage = require_sdk_market_math.maxLeverage;
12
- exports.minSeizedAmount = require_sdk_market_math.minSeizedAmount;
13
- exports.optimalHFForPartialLiquidation = require_sdk_market_math.optimalHFForPartialLiquidation;
14
- exports.optimalRepaidAmount = require_sdk_market_math.optimalRepaidAmount;
15
- exports.positionLeverage = require_sdk_market_math.positionLeverage;
16
- exports.rayToBps = require_sdk_market_math.rayToBps;
17
- exports.usdToNumber = require_sdk_market_math.usdToNumber;
18
- exports.utilizationBps = require_sdk_market_math.utilizationBps;
@@ -0,0 +1,216 @@
1
+ import { opportunityId } from "../model/opportunities.js";
2
+ import "../model/index.js";
3
+ //#region src/dev/compareOpportunities.ts
4
+ /**
5
+ * Matches two opportunity listings by {@link opportunityId} and reports every
6
+ * field the two sources disagree on.
7
+ *
8
+ * Nothing is filtered out: a diff that is expected — a field only the backend
9
+ * can fill, a formula the two sides define differently, a USD value smoothed on
10
+ * one side — is reported like any other, tagged by {@link DiffKind} so that a
11
+ * reader can bucket it afterwards.
12
+ **/
13
+ function compareOpportunities(input) {
14
+ const onchainRows = indexById(input.onchain.data);
15
+ const offchainRows = indexById(input.offchain.data);
16
+ const onlyOnchain = [];
17
+ const onlyOffchain = [];
18
+ const matched = [];
19
+ for (const [id, row] of onchainRows) {
20
+ const counterpart = offchainRows.get(id);
21
+ if (!counterpart) {
22
+ onlyOnchain.push(toRef(row));
23
+ continue;
24
+ }
25
+ const diffs = diffOpportunity(row, counterpart);
26
+ matched.push({
27
+ id,
28
+ kind: row.kind,
29
+ chainId: row.chainId,
30
+ onchainName: row.name,
31
+ offchainName: counterpart.name,
32
+ identical: diffs.length === 0,
33
+ diffs
34
+ });
35
+ }
36
+ for (const [id, row] of offchainRows) if (!onchainRows.has(id)) onlyOffchain.push(toRef(row));
37
+ byId(onlyOnchain);
38
+ byId(onlyOffchain);
39
+ matched.sort((a, b) => a.id.localeCompare(b.id));
40
+ return {
41
+ generatedAt: input.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
42
+ backendUrl: input.backendUrl,
43
+ networks: [...input.networks],
44
+ onchainChains: input.onchain.meta.chains,
45
+ offchainChains: input.offchain.meta.chains,
46
+ summary: summarize(input.onchain.data, input.offchain.data, onlyOnchain, onlyOffchain, matched),
47
+ onlyOnchain,
48
+ onlyOffchain,
49
+ matched
50
+ };
51
+ }
52
+ function indexById(rows) {
53
+ return new Map(rows.map((row) => [opportunityId(row), row]));
54
+ }
55
+ function byId(refs) {
56
+ refs.sort((a, b) => a.id.localeCompare(b.id));
57
+ }
58
+ function toRef(row) {
59
+ const base = {
60
+ id: opportunityId(row),
61
+ kind: row.kind,
62
+ chainId: row.chainId,
63
+ name: row.name
64
+ };
65
+ return row.kind === "pool" ? {
66
+ ...base,
67
+ pool: row.pool
68
+ } : {
69
+ ...base,
70
+ creditManager: row.creditManager,
71
+ targetCollateral: row.targetCollateral.address
72
+ };
73
+ }
74
+ /**
75
+ * Every field two versions of one opportunity disagree on.
76
+ **/
77
+ function diffOpportunity(onchain, offchain) {
78
+ const diffs = [];
79
+ diffValue("", onchain, offchain, diffs);
80
+ return diffs;
81
+ }
82
+ function diffValue(path, onchain, offchain, out) {
83
+ if (isAbsent(onchain) && isAbsent(offchain)) return;
84
+ if (isAbsent(onchain) || isAbsent(offchain)) {
85
+ out.push({
86
+ path,
87
+ onchain,
88
+ offchain,
89
+ kind: "presence"
90
+ });
91
+ return;
92
+ }
93
+ if (Array.isArray(onchain) && Array.isArray(offchain)) {
94
+ diffArray(path, onchain, offchain, out);
95
+ return;
96
+ }
97
+ if (isRecord(onchain) && isRecord(offchain)) {
98
+ for (const key of union(Object.keys(onchain), Object.keys(offchain))) diffValue(join(path, key), onchain[key], offchain[key], out);
99
+ return;
100
+ }
101
+ if (!sameScalar(onchain, offchain)) out.push({
102
+ path,
103
+ onchain,
104
+ offchain,
105
+ kind: scalarKind(path, onchain)
106
+ });
107
+ }
108
+ /**
109
+ * Arrays whose elements identify themselves — collateral tokens, points
110
+ * programs — are matched by that identity, so a token present on one side only
111
+ * is reported as such rather than shifting every later element into a diff.
112
+ **/
113
+ function diffArray(path, onchain, offchain, out) {
114
+ const onchainKeyed = keyElements(onchain);
115
+ const offchainKeyed = keyElements(offchain);
116
+ if (!onchainKeyed || !offchainKeyed) {
117
+ if (onchain.length !== offchain.length) {
118
+ out.push({
119
+ path,
120
+ onchain,
121
+ offchain,
122
+ kind: "other"
123
+ });
124
+ return;
125
+ }
126
+ onchain.forEach((element, index) => {
127
+ diffValue(`${path}[${index}]`, element, offchain[index], out);
128
+ });
129
+ return;
130
+ }
131
+ for (const key of union([...onchainKeyed.keys()], [...offchainKeyed.keys()])) diffValue(`${path}[${key}]`, onchainKeyed.get(key), offchainKeyed.get(key), out);
132
+ }
133
+ /**
134
+ * The array indexed by each element's own identity, or `undefined` when its
135
+ * elements have none and order is all there is to go by.
136
+ **/
137
+ function keyElements(values) {
138
+ const keyed = /* @__PURE__ */ new Map();
139
+ for (const value of values) {
140
+ if (!isRecord(value)) return;
141
+ const identity = value.address ?? value.id ?? value.token;
142
+ if (typeof identity !== "string") return;
143
+ keyed.set(identity.toLowerCase(), value);
144
+ }
145
+ return keyed.size === values.length ? keyed : void 0;
146
+ }
147
+ const ADDRESS = /^0x[0-9a-f]{40}$/i;
148
+ /**
149
+ * Only addresses are compared case-insensitively: the backend lowercases them
150
+ * while the chain hands out checksummed ones, which is not a disagreement. A
151
+ * symbol or a name spelled differently is.
152
+ **/
153
+ function sameScalar(onchain, offchain) {
154
+ if (typeof onchain === "string" && typeof offchain === "string" && ADDRESS.test(onchain) && ADDRESS.test(offchain)) return onchain.toLowerCase() === offchain.toLowerCase();
155
+ return onchain === offchain;
156
+ }
157
+ function scalarKind(path, onchain) {
158
+ if (path.endsWith("valueUsd")) return "usd";
159
+ return typeof onchain === "number" || typeof onchain === "bigint" ? "numeric" : "other";
160
+ }
161
+ function summarize(onchain, offchain, onlyOnchain, onlyOffchain, matched) {
162
+ const byChain = union(onchain.map((row) => String(row.chainId)), offchain.map((row) => String(row.chainId))).map((chainId) => ({
163
+ chainId: Number(chainId),
164
+ ...count(onchain.filter((row) => String(row.chainId) === chainId), offchain.filter((row) => String(row.chainId) === chainId), onlyOnchain.filter((ref) => String(ref.chainId) === chainId), onlyOffchain.filter((ref) => String(ref.chainId) === chainId), matched.filter((match) => String(match.chainId) === chainId))
165
+ })).sort((a, b) => a.chainId - b.chainId);
166
+ return {
167
+ ...count(onchain, offchain, onlyOnchain, onlyOffchain, matched),
168
+ byChain,
169
+ diffsByPath: countPaths(matched)
170
+ };
171
+ }
172
+ function count(onchain, offchain, onlyOnchain, onlyOffchain, matched) {
173
+ const identical = matched.filter((match) => match.identical).length;
174
+ return {
175
+ onchainRows: onchain.length,
176
+ offchainRows: offchain.length,
177
+ matched: matched.length,
178
+ identical,
179
+ differing: matched.length - identical,
180
+ onlyOnchain: onlyOnchain.length,
181
+ onlyOffchain: onlyOffchain.length
182
+ };
183
+ }
184
+ /**
185
+ * How often each field differed, with array keys collapsed so that the same
186
+ * field of a hundred collateral tokens counts as one path.
187
+ **/
188
+ function countPaths(matched) {
189
+ const counts = /* @__PURE__ */ new Map();
190
+ for (const match of matched) for (const diff of match.diffs) {
191
+ const path = diff.path.replace(/\[[^\]]*\]/g, "[]");
192
+ const entry = counts.get(path) ?? {
193
+ path,
194
+ kinds: [],
195
+ count: 0
196
+ };
197
+ entry.count += 1;
198
+ if (!entry.kinds.includes(diff.kind)) entry.kinds.push(diff.kind);
199
+ counts.set(path, entry);
200
+ }
201
+ return [...counts.values()].sort((a, b) => b.count - a.count || a.path.localeCompare(b.path));
202
+ }
203
+ function isAbsent(value) {
204
+ return value === void 0 || value === null;
205
+ }
206
+ function isRecord(value) {
207
+ return typeof value === "object" && value !== null && !Array.isArray(value);
208
+ }
209
+ function union(left, right) {
210
+ return [.../* @__PURE__ */ new Set([...left, ...right])];
211
+ }
212
+ function join(path, key) {
213
+ return path ? `${path}.${key}` : key;
214
+ }
215
+ //#endregion
216
+ export { compareOpportunities, diffOpportunity };
@@ -9,7 +9,7 @@ import { hexEq } from "../../utils/hex.js";
9
9
  import "../../utils/index.js";
10
10
  import { SDKConstruct } from "../../base/SDKConstruct.js";
11
11
  import "../../base/index.js";
12
- import { borrowApyBps, healthFactorBps, positionLeverage, usdToNumber } from "../../market/math.js";
12
+ import { calcBorrowApy, calcPositionLeverage, healthFactorBps, usdToNumber } from "../../market/math.js";
13
13
  import { dominantCollateral } from "../../market/credit/dominantCollateral.js";
14
14
  import { simulateWithPriceUpdates } from "../../utils/viem/simulateWithPriceUpdates.js";
15
15
  import "../../utils/viem/index.js";
@@ -208,8 +208,8 @@ var CreditAccountCompressor = class extends SDKConstruct {
208
208
  creditAccount: ca.creditAccount,
209
209
  name: collateral ? suite.strategyName(collateral) : token.symbol,
210
210
  targetCollateral: collateral ? this.sdk.tokensMeta.mustGetToken(collateral) : null,
211
- leverage: positionLeverage(totalDebtValue, ca.totalValue),
212
- borrowApy: borrowApyBps(pool.baseInterestRate, suite.creditManager.feeInterest),
211
+ leverage: calcPositionLeverage(ca.totalValue, totalDebtValue),
212
+ borrowApy: calcBorrowApy(pool.baseInterestRate, suite.creditManager.feeInterest),
213
213
  totalDebt: {
214
214
  token,
215
215
  value: totalDebtValue,
@@ -49,9 +49,10 @@ import { createAdapter } from "./market/adapters/createAdapter.js";
49
49
  import { CreditConfiguratorV310Contract } from "./market/credit/CreditConfiguratorV310Contract.js";
50
50
  import { CreditFacadeV310BaseContract, creditFacadeV310Abi as abi } from "./market/credit/CreditFacadeV310BaseContract.js";
51
51
  import { CreditFacadeV310Contract } from "./market/credit/CreditFacadeV310Contract.js";
52
- import { PARTIAL_LIQUIDATION_BUFFER_BPS, additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount, positionLeverage, rayToBps, usdToNumber, utilizationBps } from "./market/math.js";
52
+ import { MAX_LEVERAGE_BUFFER_BPS, PARTIAL_LIQUIDATION_BUFFER_BPS, calcAdditionalBorrowApy, calcBorrowApy, calcMaxLeverage, calcPositionLeverage, calcUtilization, healthFactorBps, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount, rayToBps, usdToNumber } from "./market/math.js";
53
53
  import { CreditManagerV310Contract } from "./market/credit/CreditManagerV310Contract.js";
54
54
  import { dominantCollateral, mustGetDominantCollateral } from "./market/credit/dominantCollateral.js";
55
+ import { NON_STRATEGY_PHANTOM_TOKEN_TYPES, isStrategyCollateral } from "./market/credit/isStrategyCollateral.js";
55
56
  import { CreditSuite } from "./market/credit/CreditSuite.js";
56
57
  import { expectedBalanceDeltas } from "./market/credit/expectedBalanceDeltas.js";
57
58
  import { simulateMulticall } from "./utils/viem/simulateMulticall.js";
@@ -148,4 +149,4 @@ import { OnchainSDK, STATE_VERSION } from "./OnchainSDK.js";
148
149
  import { MultichainSDK } from "./MultichainSDK.js";
149
150
  import { attachOptionsSchema, onchainSDKOptionsSchema } from "./options.js";
150
151
  import "./types/index.js";
151
- export { ADDRESS_0X0, ADDRESS_PROVIDER_V310, AP_ACCOUNT_FACTORY, AP_ACL, AP_BOT_LIST, AP_BYTECODE_REPOSITORY, AP_CONTRACTS_REGISTER, AP_CONTROLLER_TIMELOCK, AP_CREDIT_ACCOUNT_COMPRESSOR, AP_CREDIT_SUITE_COMPRESSOR, AP_DATA_COMPRESSOR, AP_DELEVERAGE_BOT_HV, AP_DELEVERAGE_BOT_LV, AP_DELEVERAGE_BOT_PEGGED, AP_GAUGE_COMPRESSOR, AP_GEAR_STAKING, AP_GEAR_TOKEN, AP_INFLATION_ATTACK_BLOCKER, AP_INSOLVENCY_CHECKER, AP_MARKET_COMPRESSOR, AP_MARKET_CONFIGURATOR, AP_PARTIAL_LIQUIDATION_BOT, AP_PERIPHERY_COMPRESSOR, AP_PRICE_FEED_COMPRESSOR, AP_PRICE_FEED_STORE, AP_PRICE_ORACLE, AP_REDEMPTION_LOGGER, AP_REWARDS_COMPRESSOR, AP_ROUTER, AP_RWA_COMPRESSOR, AP_TOKEN_COMPRESSOR, AP_TREASURY, AP_WETH_GATEWAY, AP_WETH_TOKEN, AP_ZAPPER_REGISTER, AP_ZERO_PRICE_FEED, AbstractLPPriceFeedContract, AbstractPriceFeedContract, AbstractWithdrawalCompressorContract, AccountBotsService, AddressMap, AddressProviderV310Contract, AddressSet, AssetsMap, BLOCKS_PER_WEEK_BY_NETWORK, BalancerStablePriceFeedContract, BalancerWeightedPriceFeedContract, BaseContract, BasePlugin, BigIntMath, BotPermissions, BoundedPriceFeedContract, ChainContractsRegister, ChainNotConfiguredError, CompositePriceFeedContract, Construct, ContractParseError, CreditAccountCompressor, CreditAccountCompressorV310Contract, CreditAccountOperationsService, CreditAccountsServiceV310, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, Erc4626PriceFeedContract, ExternalPriceFeedContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, InvalidDelayedIntentError, LEVERAGE_DECIMALS, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LinearInterestRateModelContract, LiquidationsService, MAX_INT, MAX_UINT16, MAX_UINT256, MIN_INT96, MULTICALL_ADDRESS, MarketRegister, MarketSuite, MellowLRTPriceFeedContract, MidasLiquidatorContract, MissingSerializedParamsError, MultichainConstruct, MultichainLiquidationsService, MultichainOpportunitiesService, MultichainPositionsService, MultichainSDK, NATIVE_ADDRESS, NOT_DEPLOYED, NO_VERSION, NetworkType, OnchainSDK, OpportunitiesService, PARTIAL_LIQUIDATION_BUFFER_BPS, PERCENTAGE_DECIMALS, PERCENTAGE_FACTOR, PERCENTAGE_FACTOR_1KK, PERIPHERY_CONTRACTS, PHANTOM_TOKEN_CONTRACT_TYPES, PHANTOM_TOKEN_MIDAS_REDEMPTION, PHANTOM_TOKEN_SECURITIZE_REDEMPTION, PRICE_DECIMALS, PRICE_DECIMALS_POW, PartialPriceFeedInitError, PendleTWAPPTPriceFeed, PeripheryCompressorV310Contract, PlaceholderAdapterContract, PlaceholderContract, PluginStateVersionError, PoolService, PoolSuite, PoolV310Contract, PositionsService, PriceFeedRef, PriceFeedRegister, PriceOracleV310Contract, PythPriceFeed, RAMP_DURATION_BY_NETWORK, RAY, RAY_DECIMALS_POW, RWARegistry, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_LIQUIDATOR_MIDAS, RWA_LIQUIDATOR_SECURITIZE, RWA_ON_DEMAND_LP_MONOPOLIZED, RWA_UNDERLYING_DEFAULT, RWA_UNDERLYING_ON_DEMAND, RedemptionLoggerV310Contract, RedstonePriceFeedContract, RouterV310Contract, SDKConstruct, SECONDS_PER_YEAR, SECURITIZE_REGISTER_VAULT_TYPES, SLIPPAGE_DECIMALS, STATE_VERSION, SUPPORTED_NETWORKS, SdkAlreadyAttachedError, SdkChainMismatchError, SdkMissingChainStateError, SdkNotAttachedError, SdkStateVersionMismatchError, SdkSyncFailedError, SecuritizeLiquidatorContract, SecuritizeRWAFactory, SimulateWithPriceUpdatesError, SimulationError, TokensMeta, TypedObjectUtils, UnsupportedZapperFunctionError, VERSION_RANGE_310, VotingContractStatus, WAD, WAD_DECIMALS_POW, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, WstETHPriceFeedContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, ZodAddress, ZodBigInt, ZodHex, additionalBorrowApyBps, assetsMap, attachOptionsSchema, borrowApyBps, botPermissionsToString, bytes32ToString, chains, childLogger, createAdapter, createAddressProvider, createPriceOracle, createRawTx, createRedemptionLogger, createRouter, createWithdrawalCompressor, createZapper, abi as creditFacadeV310Abi, decodeDelayedIntent, detectNetwork, dominantCollateral, encodeDelayedIntent, estimateRawTxGas, etherscanApiUrl, etherscanUrl, executeDelegatedMulticalls, executeMulticallBatches, expectedBalanceDeltas, fetchRedstonePayloads, filterDust, filterDustUSD, findCuratorMarketConfigurator, fmtBinaryMask, formatBN, formatBNvalue, formatDuration, formatLeverage, formatNumberToString_, formatPercentage, formatTimestamp, functionArgsToMap, functionArgsToRecord, generateCastTraceCall, getAssetType, getCastTraceArgs, getChain, getCuratorName, getFunctionSignature, getNetworkType, getRawPriceUpdates, getSimulateWithPriceUpdatesError, getWithdrawalCompressorAddress, halfRAY, healthFactorBps, hexEq, hydrateAddressProvider, iCreditAccountAbi, isDust, isLPPriceFeed, isPublicNetwork, isRWAFactory, isRWAToken, isSunsetPool, isSunsetStrategy, isSupportedNetwork, isUpdatablePriceFeed, isV310, isVersionRange, json_parse, json_stringify, maxLeverage, minSeizedAmount, mustGetDominantCollateral, numberWithCommas, onchainSDKOptionsSchema, optimalHFForPartialLiquidation, optimalRepaidAmount, percentFmt, positionLeverage, primaryInstantOutput, rayToBps, rayToNumber, retry, sendRawTx, shortAddress, shortHash, simulateCall, simulateMulticall, simulateWithPriceUpdates, toAddress, toBN, toBigInt, toChainIds, toClaimableWithdrawal, toPendingWithdrawal, toRequestableWithdrawal, toSignificant, toWithdrawalStatus, usdToNumber, utilizationBps, watchBlocksAsync };
152
+ export { ADDRESS_0X0, ADDRESS_PROVIDER_V310, AP_ACCOUNT_FACTORY, AP_ACL, AP_BOT_LIST, AP_BYTECODE_REPOSITORY, AP_CONTRACTS_REGISTER, AP_CONTROLLER_TIMELOCK, AP_CREDIT_ACCOUNT_COMPRESSOR, AP_CREDIT_SUITE_COMPRESSOR, AP_DATA_COMPRESSOR, AP_DELEVERAGE_BOT_HV, AP_DELEVERAGE_BOT_LV, AP_DELEVERAGE_BOT_PEGGED, AP_GAUGE_COMPRESSOR, AP_GEAR_STAKING, AP_GEAR_TOKEN, AP_INFLATION_ATTACK_BLOCKER, AP_INSOLVENCY_CHECKER, AP_MARKET_COMPRESSOR, AP_MARKET_CONFIGURATOR, AP_PARTIAL_LIQUIDATION_BOT, AP_PERIPHERY_COMPRESSOR, AP_PRICE_FEED_COMPRESSOR, AP_PRICE_FEED_STORE, AP_PRICE_ORACLE, AP_REDEMPTION_LOGGER, AP_REWARDS_COMPRESSOR, AP_ROUTER, AP_RWA_COMPRESSOR, AP_TOKEN_COMPRESSOR, AP_TREASURY, AP_WETH_GATEWAY, AP_WETH_TOKEN, AP_ZAPPER_REGISTER, AP_ZERO_PRICE_FEED, AbstractLPPriceFeedContract, AbstractPriceFeedContract, AbstractWithdrawalCompressorContract, AccountBotsService, AddressMap, AddressProviderV310Contract, AddressSet, AssetsMap, BLOCKS_PER_WEEK_BY_NETWORK, BalancerStablePriceFeedContract, BalancerWeightedPriceFeedContract, BaseContract, BasePlugin, BigIntMath, BotPermissions, BoundedPriceFeedContract, ChainContractsRegister, ChainNotConfiguredError, CompositePriceFeedContract, Construct, ContractParseError, CreditAccountCompressor, CreditAccountCompressorV310Contract, CreditAccountOperationsService, CreditAccountsServiceV310, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, Erc4626PriceFeedContract, ExternalPriceFeedContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, InvalidDelayedIntentError, LEVERAGE_DECIMALS, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LinearInterestRateModelContract, LiquidationsService, MAX_INT, MAX_LEVERAGE_BUFFER_BPS, MAX_UINT16, MAX_UINT256, MIN_INT96, MULTICALL_ADDRESS, MarketRegister, MarketSuite, MellowLRTPriceFeedContract, MidasLiquidatorContract, MissingSerializedParamsError, MultichainConstruct, MultichainLiquidationsService, MultichainOpportunitiesService, MultichainPositionsService, MultichainSDK, NATIVE_ADDRESS, NON_STRATEGY_PHANTOM_TOKEN_TYPES, NOT_DEPLOYED, NO_VERSION, NetworkType, OnchainSDK, OpportunitiesService, PARTIAL_LIQUIDATION_BUFFER_BPS, PERCENTAGE_DECIMALS, PERCENTAGE_FACTOR, PERCENTAGE_FACTOR_1KK, PERIPHERY_CONTRACTS, PHANTOM_TOKEN_CONTRACT_TYPES, PHANTOM_TOKEN_MIDAS_REDEMPTION, PHANTOM_TOKEN_SECURITIZE_REDEMPTION, PRICE_DECIMALS, PRICE_DECIMALS_POW, PartialPriceFeedInitError, PendleTWAPPTPriceFeed, PeripheryCompressorV310Contract, PlaceholderAdapterContract, PlaceholderContract, PluginStateVersionError, PoolService, PoolSuite, PoolV310Contract, PositionsService, PriceFeedRef, PriceFeedRegister, PriceOracleV310Contract, PythPriceFeed, RAMP_DURATION_BY_NETWORK, RAY, RAY_DECIMALS_POW, RWARegistry, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_LIQUIDATOR_MIDAS, RWA_LIQUIDATOR_SECURITIZE, RWA_ON_DEMAND_LP_MONOPOLIZED, RWA_UNDERLYING_DEFAULT, RWA_UNDERLYING_ON_DEMAND, RedemptionLoggerV310Contract, RedstonePriceFeedContract, RouterV310Contract, SDKConstruct, SECONDS_PER_YEAR, SECURITIZE_REGISTER_VAULT_TYPES, SLIPPAGE_DECIMALS, STATE_VERSION, SUPPORTED_NETWORKS, SdkAlreadyAttachedError, SdkChainMismatchError, SdkMissingChainStateError, SdkNotAttachedError, SdkStateVersionMismatchError, SdkSyncFailedError, SecuritizeLiquidatorContract, SecuritizeRWAFactory, SimulateWithPriceUpdatesError, SimulationError, TokensMeta, TypedObjectUtils, UnsupportedZapperFunctionError, VERSION_RANGE_310, VotingContractStatus, WAD, WAD_DECIMALS_POW, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, WstETHPriceFeedContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, ZodAddress, ZodBigInt, ZodHex, assetsMap, attachOptionsSchema, botPermissionsToString, bytes32ToString, calcAdditionalBorrowApy, calcBorrowApy, calcMaxLeverage, calcPositionLeverage, calcUtilization, chains, childLogger, createAdapter, createAddressProvider, createPriceOracle, createRawTx, createRedemptionLogger, createRouter, createWithdrawalCompressor, createZapper, abi as creditFacadeV310Abi, decodeDelayedIntent, detectNetwork, dominantCollateral, encodeDelayedIntent, estimateRawTxGas, etherscanApiUrl, etherscanUrl, executeDelegatedMulticalls, executeMulticallBatches, expectedBalanceDeltas, fetchRedstonePayloads, filterDust, filterDustUSD, findCuratorMarketConfigurator, fmtBinaryMask, formatBN, formatBNvalue, formatDuration, formatLeverage, formatNumberToString_, formatPercentage, formatTimestamp, functionArgsToMap, functionArgsToRecord, generateCastTraceCall, getAssetType, getCastTraceArgs, getChain, getCuratorName, getFunctionSignature, getNetworkType, getRawPriceUpdates, getSimulateWithPriceUpdatesError, getWithdrawalCompressorAddress, halfRAY, healthFactorBps, hexEq, hydrateAddressProvider, iCreditAccountAbi, isDust, isLPPriceFeed, isPublicNetwork, isRWAFactory, isRWAToken, isStrategyCollateral, isSunsetPool, isSunsetStrategy, isSupportedNetwork, isUpdatablePriceFeed, isV310, isVersionRange, json_parse, json_stringify, minSeizedAmount, mustGetDominantCollateral, numberWithCommas, onchainSDKOptionsSchema, optimalHFForPartialLiquidation, optimalRepaidAmount, percentFmt, primaryInstantOutput, rayToBps, rayToNumber, retry, sendRawTx, shortAddress, shortHash, simulateCall, simulateMulticall, simulateWithPriceUpdates, toAddress, toBN, toBigInt, toChainIds, toClaimableWithdrawal, toPendingWithdrawal, toRequestableWithdrawal, toSignificant, toWithdrawalStatus, usdToNumber, watchBlocksAsync };
@@ -8,8 +8,7 @@ import { BaseContract } from "../../base/BaseContract.js";
8
8
  import "../../base/index.js";
9
9
  import { createAdapter } from "../adapters/createAdapter.js";
10
10
  import "../adapters/index.js";
11
- import { maxLeverage } from "../math.js";
12
- import { isAddressEqual } from "viem";
11
+ import { calcMaxLeverage } from "../math.js";
13
12
  //#region src/sdk/market/credit/CreditManagerV310Contract.ts
14
13
  const abi = iCreditManagerV310Abi;
15
14
  var CreditManagerV310Contract = class extends BaseContract {
@@ -64,20 +63,10 @@ var CreditManagerV310Contract = class extends BaseContract {
64
63
  return this.liquidationThresholds.keys();
65
64
  }
66
65
  /**
67
- * {@inheritDoc ICreditManagerContract.leverageableCollaterals}
68
- */
69
- get leverageableCollaterals() {
70
- return this.collateralTokens.filter((token) => {
71
- if (isAddressEqual(token, this.underlying)) return false;
72
- const lt = this.liquidationThresholds.get(token);
73
- return !!lt && lt > 0 && lt < Number(10000n);
74
- });
75
- }
76
- /**
77
66
  * {@inheritDoc ICreditManagerContract.maxLeverage}
78
67
  */
79
68
  maxLeverage(collateral) {
80
- return maxLeverage(this.liquidationThresholds.mustGet(collateral));
69
+ return calcMaxLeverage(this.liquidationThresholds.mustGet(collateral));
81
70
  }
82
71
  /**
83
72
  * {@inheritDoc ICreditManagerContract.liquidationPremium}
@@ -6,12 +6,12 @@ import "../../constants/index.js";
6
6
  import "../../utils/index.js";
7
7
  import { SDKConstruct } from "../../base/SDKConstruct.js";
8
8
  import "../../base/index.js";
9
- import { additionalBorrowApyBps, borrowApyBps, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount } from "../math.js";
9
+ import { calcAdditionalBorrowApy, calcBorrowApy, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount } from "../math.js";
10
10
  import createCreditConfigurator from "./createCreditConfigurator.js";
11
11
  import createCreditFacade from "./createCreditFacade.js";
12
12
  import createCreditManager from "./createCreditManager.js";
13
13
  import { mustGetDominantCollateral } from "./dominantCollateral.js";
14
- import { isAddressEqual } from "viem";
14
+ import { isStrategyCollateral } from "./isStrategyCollateral.js";
15
15
  //#region src/sdk/market/credit/CreditSuite.ts
16
16
  /**
17
17
  * SDK aggregate for one credit-manager branch inside a market.
@@ -171,22 +171,8 @@ var CreditSuite = class extends SDKConstruct {
171
171
  return this.creditFacade.isPaused || this.market.pool.isPaused;
172
172
  }
173
173
  /**
174
- * Collateral tokens a leveraged position can be built around in this suite:
175
- * the ones the credit manager can lever up, narrowed to the tokens that can
176
- * still be entered. A token qualifies when it
177
- *
178
- * - has a liquidation threshold above `0` and below `100%`, and is not the
179
- * suite's underlying, see
180
- * {@link ICreditManagerContract.leverageableCollaterals};
181
- * - is not the token the market's underlying wraps, which for an RWA market
182
- * is the same exposure as the underlying itself;
183
- * - is not a phantom token, which only ever appears as the intermediate step
184
- * of a withdrawal and cannot be acquired;
185
- * - is not an expired token, e.g. a matured Pendle PT;
186
- * - has a non-zero main price in the market's oracle — a zero or failed
187
- * answer (e.g. a zero price feed) means the position cannot be valued;
188
- * - the market still accepts quota for, see
189
- * {@link PoolQuotaKeeperContract.hasActiveQuota}.
174
+ * Collateral tokens a leveraged position can be built around in this suite,
175
+ * see {@link isStrategyCollateral} for the per-token criteria.
190
176
  *
191
177
  * A suite where no debt can be drawn at all ({@link maxBorrowAmount} is `0`,
192
178
  * e.g. its debt limit is exhausted or zeroed out) offers no strategies,
@@ -196,14 +182,19 @@ var CreditSuite = class extends SDKConstruct {
196
182
  if (this.maxBorrowAmount === 0n) return [];
197
183
  const { pqk, unwrappedUnderlying } = this.market.pool;
198
184
  const { mainPrices } = this.market.priceOracle;
199
- const { tokensMeta } = this;
200
- return this.creditManager.leverageableCollaterals.filter((token) => {
201
- if (isAddressEqual(token, unwrappedUnderlying)) return false;
185
+ const { tokensMeta, creditManager } = this;
186
+ return creditManager.collateralTokens.filter((token) => {
202
187
  const meta = tokensMeta.mustGet(token);
203
- if (tokensMeta.isPhantomToken(meta) || meta.isExpired) return false;
204
- const mainPrice = mainPrices.get(token);
205
- if (!mainPrice?.success || mainPrice.price === 0n) return false;
206
- return pqk.hasActiveQuota(token);
188
+ return isStrategyCollateral({
189
+ token,
190
+ underlying: creditManager.underlying,
191
+ unwrappedUnderlying,
192
+ liquidationThreshold: creditManager.liquidationThresholds.mustGet(token),
193
+ contractType: meta.contractType,
194
+ isExpired: meta.isExpired,
195
+ mainPrice: mainPrices.get(token)?.price,
196
+ hasActiveQuota: pqk.hasActiveQuota(token)
197
+ });
207
198
  });
208
199
  }
209
200
  /**
@@ -248,7 +239,7 @@ var CreditSuite = class extends SDKConstruct {
248
239
  curator: market.curator,
249
240
  underlyingToken: market.underlyingToken,
250
241
  totalBorrow: oracle.toAmount(pool.underlying, borrowed),
251
- collateralTokens: market.collateralTokens,
242
+ collateralTokens: this.strategyCollaterals.map((t) => this.tokensMeta.mustGetToken(t)),
252
243
  paused: this.isPaused,
253
244
  rwa: market.rwa,
254
245
  sunset: market.sunset || isSunsetStrategy(cm.address, collateral, this.sdk.networkType),
@@ -256,8 +247,8 @@ var CreditSuite = class extends SDKConstruct {
256
247
  liquidationPremium: cm.liquidationPremium,
257
248
  liquidationFee: cm.feeLiquidation,
258
249
  expirationDate: this.expirationDate,
259
- borrowApy: borrowApyBps(pool.baseInterestRate, cm.feeInterest),
260
- additionalBorrowApy: additionalBorrowApyBps(market.pool.pqk.quotaRate(collateral), maxLeverage),
250
+ borrowApy: calcBorrowApy(pool.baseInterestRate, cm.feeInterest),
251
+ additionalBorrowApy: calcAdditionalBorrowApy(market.pool.pqk.quotaRate(collateral), cm.feeInterest, maxLeverage),
261
252
  maxBorrowAmount: oracle.toAmount(pool.underlying, this.maxBorrowAmount),
262
253
  maxLeverage
263
254
  };
@@ -3,7 +3,8 @@ import { CreditFacadeV310BaseContract, creditFacadeV310Abi as abi } from "./Cred
3
3
  import { CreditFacadeV310Contract } from "./CreditFacadeV310Contract.js";
4
4
  import { CreditManagerV310Contract } from "./CreditManagerV310Contract.js";
5
5
  import { dominantCollateral, mustGetDominantCollateral } from "./dominantCollateral.js";
6
+ import { NON_STRATEGY_PHANTOM_TOKEN_TYPES, isStrategyCollateral } from "./isStrategyCollateral.js";
6
7
  import { CreditSuite } from "./CreditSuite.js";
7
8
  import { expectedBalanceDeltas } from "./expectedBalanceDeltas.js";
8
9
  import "./types.js";
9
- export { CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, abi as creditFacadeV310Abi, dominantCollateral, expectedBalanceDeltas, mustGetDominantCollateral };
10
+ export { CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, NON_STRATEGY_PHANTOM_TOKEN_TYPES, abi as creditFacadeV310Abi, dominantCollateral, expectedBalanceDeltas, isStrategyCollateral, mustGetDominantCollateral };